Проблемы при связывании моей основной выходной библиотеки с моим тестовым исполняемым файлом - PullRequest
0 голосов
/ 01 мая 2018

Я создаю библиотеку "framework", в которую я пытаюсь интегрировать Google Tests. Это довольно маленькая библиотека, которая в конце дает мне файл .so или .dll.

Когда я начинал тестировать свою библиотеку, я нашел конфигурацию (подробности ниже), которая отлично работает на моем CMakeFile в моей среде linux. Но когда я пытаюсь запустить тот же проект, используя MSBuild для MSVC14, это дает мне ошибку ссылки LINK : fatal error LNK1104: cannot open file '..\src\Debug\foobar.lib'

Я думаю, что мой cmake угадывает имя lib неправильно (foobar.lib вместо foobar.dll), но я не мог найти, почему и как это исправить.

Кроме того, я не знаю, действительно ли это лучший способ для меня это проверить. То, что я хочу, - это способ протестировать весь фреймворк (инициализация, создание материалов, проверка возврата и т. Д.) Без файла main.cpp, а между тем начать создавать модульные тесты.

Итак, мой вопрос ... Что я делаю не так, что в среде Windows компоновщик не находит foobar lib, созданный src/CMakeLists.txt? (Я проверил, и библиотека создана в "src / Debug / foobar.dll", тот же каталог, который появляется при ошибке и работает нормально)

Кроме того, мой метод настолько неверен, что окна просто не хотят иметь дело? LOL Я имею в виду, это неправильно делать что-то, как я пытаюсь сделать? Дело не в том, что я не хочу делать модульные тесты, что я буду делать в ближайшее время, но мне действительно нравится собирать и пробовать мою lib без использования какого-либо внешнего исполняемого файла, прежде чем я начну это делать.

Спасибо!

OBS:

  • Мои тесты Google работают нормально как в Linux, так и в Windows;

  • Я могу запустить тест FooA, если уберу тест FooBar, который ссылается на foobar lib.

  • При использовании моей среды linux эта конфигурация работает отлично.

Обновление:

Как подсказал @vre, я нашел макрос __declspec(dllexport) и поместил его перед именем FooBar класса и пройденной компиляцией, но он вылетает при запуске и выдает это предупреждение при компиляции:

warning C4251: 'FooBar::_impl': class 'std::unique_ptr<FooBar::FooBarImpl,
std::default_delete<_Ty>>' needs to have dll-interface to be used by clients of class 'FooBar'

Это потому, что у меня есть реализация PImp класса FooBar. Итак, у меня есть это:

class __declspec(dllexport) FooBar
{
    ...

    private:
        class FooBarImpl;
        std::unique_ptr<FooBarImpl> _impl;
}

Я пока не знаю, что это значит. Пытаюсь выяснить, почему происходит сбой.


Мой проект имеет это дерево файлов:

├── CMakeLists.txt
├── include
|   ├── FooBar.hpp
├── src
│   ├── CMakeLists.txt
│   ├── FooBar.cpp
│   ├── FooA
│   │   └── CMakeLists.txt
│   ├── FooB
│   │   └── CMakeLists.txt
│   └── FooC
│       └── CMakeLists.txt
└── test
    ├── CMakeLists.txt
    ├── FooBar
    │   └── FooBarTest.hpp
    ├── FooA
    │   ├── FakeBar.hpp
    │   ├── FooATest.hpp
    │   └── mockObj.hpp

Мой основной CMakeLists.txt такой:

...
set(FOOBAR_INCLUDE "${PROJECT_SOURCE_DIR}/include/FooBar.hpp")

# Include src main CMakeLists
add_subdirectory("${PROJECT_SOURCE_DIR}/src")

# Include tests if enabled
if (test)
 add_subdirectory("${PROJECT_SOURCE_DIR}/test")
endif ()

Мой src/CMakeLists.txt:

...
set(FOOBAR_SOURCES "FooBar.cpp")

# Build
add_library(foobar SHARED ${FOOBAR_SOURCES} ${FOOBAR_INCLUDE})

# Links the library with components.
target_link_libraries(foobar FooA FooB FooC)

А мой test/CMakeLists.txt выглядит примерно так:

enable_testing()

# Include directories used for testing.
include_directories("${CMAKE_SOURCE_DIR}/src"
                    "${CMAKE_SOURCE_DIR}/include"
                    "FooA/"
                    "FooBar/")

# Include the files for testing.
set(INCLUDE_TESTS "${CMAKE_SOURCE_DIR}/src/FooA/FooA.cpp"
                  "${CMAKE_SOURCE_DIR}/src/FooA/Bar.cpp")

# Include the test source files.
set(TEST_SOURCES  "main.cpp"
                  "FooBar/JepluTest.hpp"
                  "FooA/FakeBar.hpp"
                  "FooA/FooATest.hpp")

# Build
add_executable(foobar-test ${TEST_SOURCES} ${INCLUDE_TESTS})

# Links the library with components. (HERE IS WHERE OCCURS THE PROBLEM)
target_link_libraries(foobar-test gtest foobar)

# Not really important right now
add_test(NAME foobar-test COMMAND foobar-test)

1 Ответ

0 голосов
/ 02 мая 2018

Переформулировка и улучшение моих предыдущих комментариев:

Вам необходимо экспортировать символы из DLL в Windows, иначе библиотека импорта не будет создана, и MSBuild жалуется на это.

Сначала вы должны добавить в заголовок FooBar.hpp следующую конструкцию:

#ifdef WIN32
    #ifdef FOOBARLIB_EXPORTS
        #define FOOBARLIB_API __declspec(dllexport)
    #else
        #define FOOBARLIB_API __declspec(dllimport)
    #endif
#else
    #define FOOBARLIB_API
#endif

Позже отметьте ваши классы, функции и символы для экспорта следующим образом:

void FOOBARLIB_API foobar(char*)
{
}

В вашем CMakeLists.txt после создания цели общей библиотеки foobar добавьте строку:

target_compile_definitions(foobar PRIVATE FOOBARLIB_EXPORTS)

EDIT: Как прокомментировал @vre, эти свойства CMake также необходимы, поскольку Windows не загружает DLL, расположенный в другой папке, вызывая сбой при попытке запустить исполняемый файл. Таким образом, когда DLL собирается и установлена ​​переменная CMAKE_RUNTIME_OUTPUT_DIRECTORY, выходная библиотека переходит в тот же каталог, что и тестовый файл .exe.

set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...