CMake Visual Studio 将构建的 dll 和来自 Conan 的依赖 dll 组合在一起
CMake Visual Studio Group together builded dll and dependend dlls from Conan
我有一个项目,我用 CMake
管理并用 MSVC
构建它。
对于依赖管理,我使用 Conan
和 cmake_find_package
生成器。
Build it 自行运行没有任何问题。但我不能 运行 例如测试可执行文件,无需将创建的 dll
和 dll
从依赖项复制到 Test Executable
.
的位置
这是我的 conanfile.txt
:
[requires]
gtest/1.10.0
[generators]
cmake_find_package
[options]
gtest:shared=True
gtest:build_gmock=True
这是我的 CMakeLists.txt
文件 DLL
:
cmake_minimum_required(VERSION 3.14)
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
message(FATAL_ERROR "Do not build in-source. Please remove CMakeCache.txt and the CMakeFiles/ directory. Then build out-of-source")
endif()
project("CommandDispatcher" VERSION 1.0.0 LANGUAGES CXX)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_BINARY_DIR})
list(APPEND CMAKE_PREFIX_PATH ${CMAKE_BINARY_DIR})
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
option(BUILD_SHARED_LIBS "Build shared (dynamic) libraries." ON)
option(ENABLE_TESTING "Build with Tests enabled." ON)
include(generate_product_version)
generate_product_version(
VersionFilesOutputVariable
ICON ${CMAKE_CURRENT_SOURCE_DIR}/resources/Product.ico
NAME ${PROJECT_NAME}
VERSION_MAJOR 1
VERSION_MINOR 0
VERSION_PATCH 0
VERSION_REVISION 0
)
add_library(${PROJECT_NAME})
add_library("Product::CommandDispatcher" ALIAS ${PROJECT_NAME})
target_sources(${PROJECT_NAME}
PUBLIC
include/${PROJECT_NAME}/export.hpp
include/${PROJECT_NAME}/command_dispatcher.hpp
PRIVATE
src/command_dispatcher.cpp
src/test.hpp
src/test.cpp
${VersionFilesOutputVariable}
)
target_include_directories(${PROJECT_NAME} PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
"$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>"
PRIVATE "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>")
set_target_properties(${PROJECT_NAME} PROPERTIES SOVERSION 1 VERSION 1.0.0)
if (MSVC)
set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "d")
endif()
include(GenerateExportHeader)
string(TOUPPER ${PROJECT_NAME} PROJECT_NAME_UPPER)
generate_export_header(${PROJECT_NAME}
EXPORT_FILE_NAME ${CMAKE_CURRENT_SOURCE_DIR}/include/${PROJECT_NAME}/export.hpp
EXPORT_MACRO_NAME ${PROJECT_NAME_UPPER}_EXPORT
STATIC_DEFINE ${PROJECT_NAME_UPPER}_STATIC
)
if(ENABLE_TESTING)
message(STATUS "Build Library as Static Version for testing purpose")
set(PROJECT_NAME_STATIC ${PROJECT_NAME}_static)
add_library(${PROJECT_NAME_STATIC} STATIC)
target_sources(${PROJECT_NAME_STATIC}
PUBLIC
include/${PROJECT_NAME}/export.hpp
include/${PROJECT_NAME}/command_dispatcher.hpp
PRIVATE
src/command_dispatcher.cpp
src/test.hpp
src/test.cpp
)
target_include_directories(${PROJECT_NAME_STATIC} PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
"$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>"
PRIVATE "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>")
string(TOUPPER ${PROJECT_NAME} PROJECT_NAME_UPPER)
set_target_properties(${PROJECT_NAME_STATIC} PROPERTIES COMPILE_FLAGS -D${PROJECT_NAME_UPPER}_STATIC)
if (MSVC)
# set_target_properties(${PROJECT_NAME_STATIC} PROPERTIES DEBUG_POSTFIX "d")
endif()
message(STATUS "Running Tests for Library ${PROJECT_NAME}")
include(CTest)
enable_testing()
add_subdirectory(tests)
endif()
我首先将库构建为 DLL
和 static
库用于测试目的(也测试库的私有部分。
这是tests
目录里面的CMakeLists.txt
:
set(TEST_TARGET_NAME ${PROJECT_NAME}_TEST)
add_executable(${TEST_TARGET_NAME})
target_sources(${TEST_TARGET_NAME}
PRIVATE
ExampleTest.cpp
TestRunner.cpp
)
find_package(GTest)
if(TARGET GTest::GTest)
message(STATUS "Target Found")
target_link_libraries(${TEST_TARGET_NAME} PRIVATE GTest::GTest)
endif()
target_link_libraries(${TEST_TARGET_NAME} PRIVATE ${PROJECT_NAME_STATIC})
add_test(NAME ${TEST_TARGET_NAME}
COMMAND ${TEST_TARGET_NAME}
WORKING_DIRECTORY $<TARGET_FILE_DIR:${TEST_TARGET_NAME}>)
target_include_directories(${TEST_TARGET_NAME} PRIVATE $<TARGET_PROPERTY:${PROJECT_NAME_STATIC},INCLUDE_DIRECTORIES>)
这里我 Link 与 GTest
库相对应 Conan
.
如果我 运行 构建结果位于 Build
目录中的以下文件夹结构中:
+---build
|
+---Debug
| CommandDispatcherd.dll
+---tests
| |
| \---Debug
| CommandDispatcher_TEST.exe
GTest DLLs
在我的 Userfolder/.conan
下方某处。
将这些东西组合在一起的好方法是什么?例如。在 build
目录中的 bin/test
文件夹中构建 DLL
、Test Exe
和 Dependencies DLL
?
我的第一个猜测是将以下内容添加到 Conanfile.txt
:
[imports]
bin, gmockd.dll -> ./bin/test
bin, gmock_maind.dll -> ./bin/test
bin, gtestd.dll -> ./bin/test
bin, gtest_maind.dll -> ./bin/test
但是为此我需要知道构建的名称 dlls
。
并且还将以下内容添加到 Main CMakeFile.txt
:
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR}/bin)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR}/lib)
或者我应该根据 target
和 set_target_properties
进行更改吗?
或者有更好的解决方案吗?柯南部分还要将 DLL 复制到正确的位置吗?
也欢迎对我的 CMakeFile.txt
进行任何改进 =)。
But for this i need to know the name of the builded dlls.
我认为您不需要知道 dll 的名称。您可以像这样设置导入:
bin, *.dll -> ./bin/test @ root_package=gtest
注意 root_package
参数,它将告诉柯南从哪个包中复制 dll。
更多信息在这里:https://docs.conan.io/en/latest/reference/conanfile_txt.html#imports
或者在conanfile.py
中可以实现为:
def imports(self):
self.copy("*.dll", f"bin\tests", "bin", root_package='gtest')
我有一个项目,我用 CMake
管理并用 MSVC
构建它。
对于依赖管理,我使用 Conan
和 cmake_find_package
生成器。
Build it 自行运行没有任何问题。但我不能 运行 例如测试可执行文件,无需将创建的 dll
和 dll
从依赖项复制到 Test Executable
.
这是我的 conanfile.txt
:
[requires]
gtest/1.10.0
[generators]
cmake_find_package
[options]
gtest:shared=True
gtest:build_gmock=True
这是我的 CMakeLists.txt
文件 DLL
:
cmake_minimum_required(VERSION 3.14)
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
message(FATAL_ERROR "Do not build in-source. Please remove CMakeCache.txt and the CMakeFiles/ directory. Then build out-of-source")
endif()
project("CommandDispatcher" VERSION 1.0.0 LANGUAGES CXX)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_BINARY_DIR})
list(APPEND CMAKE_PREFIX_PATH ${CMAKE_BINARY_DIR})
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
option(BUILD_SHARED_LIBS "Build shared (dynamic) libraries." ON)
option(ENABLE_TESTING "Build with Tests enabled." ON)
include(generate_product_version)
generate_product_version(
VersionFilesOutputVariable
ICON ${CMAKE_CURRENT_SOURCE_DIR}/resources/Product.ico
NAME ${PROJECT_NAME}
VERSION_MAJOR 1
VERSION_MINOR 0
VERSION_PATCH 0
VERSION_REVISION 0
)
add_library(${PROJECT_NAME})
add_library("Product::CommandDispatcher" ALIAS ${PROJECT_NAME})
target_sources(${PROJECT_NAME}
PUBLIC
include/${PROJECT_NAME}/export.hpp
include/${PROJECT_NAME}/command_dispatcher.hpp
PRIVATE
src/command_dispatcher.cpp
src/test.hpp
src/test.cpp
${VersionFilesOutputVariable}
)
target_include_directories(${PROJECT_NAME} PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
"$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>"
PRIVATE "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>")
set_target_properties(${PROJECT_NAME} PROPERTIES SOVERSION 1 VERSION 1.0.0)
if (MSVC)
set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "d")
endif()
include(GenerateExportHeader)
string(TOUPPER ${PROJECT_NAME} PROJECT_NAME_UPPER)
generate_export_header(${PROJECT_NAME}
EXPORT_FILE_NAME ${CMAKE_CURRENT_SOURCE_DIR}/include/${PROJECT_NAME}/export.hpp
EXPORT_MACRO_NAME ${PROJECT_NAME_UPPER}_EXPORT
STATIC_DEFINE ${PROJECT_NAME_UPPER}_STATIC
)
if(ENABLE_TESTING)
message(STATUS "Build Library as Static Version for testing purpose")
set(PROJECT_NAME_STATIC ${PROJECT_NAME}_static)
add_library(${PROJECT_NAME_STATIC} STATIC)
target_sources(${PROJECT_NAME_STATIC}
PUBLIC
include/${PROJECT_NAME}/export.hpp
include/${PROJECT_NAME}/command_dispatcher.hpp
PRIVATE
src/command_dispatcher.cpp
src/test.hpp
src/test.cpp
)
target_include_directories(${PROJECT_NAME_STATIC} PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
"$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>"
PRIVATE "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>")
string(TOUPPER ${PROJECT_NAME} PROJECT_NAME_UPPER)
set_target_properties(${PROJECT_NAME_STATIC} PROPERTIES COMPILE_FLAGS -D${PROJECT_NAME_UPPER}_STATIC)
if (MSVC)
# set_target_properties(${PROJECT_NAME_STATIC} PROPERTIES DEBUG_POSTFIX "d")
endif()
message(STATUS "Running Tests for Library ${PROJECT_NAME}")
include(CTest)
enable_testing()
add_subdirectory(tests)
endif()
我首先将库构建为 DLL
和 static
库用于测试目的(也测试库的私有部分。
这是tests
目录里面的CMakeLists.txt
:
set(TEST_TARGET_NAME ${PROJECT_NAME}_TEST)
add_executable(${TEST_TARGET_NAME})
target_sources(${TEST_TARGET_NAME}
PRIVATE
ExampleTest.cpp
TestRunner.cpp
)
find_package(GTest)
if(TARGET GTest::GTest)
message(STATUS "Target Found")
target_link_libraries(${TEST_TARGET_NAME} PRIVATE GTest::GTest)
endif()
target_link_libraries(${TEST_TARGET_NAME} PRIVATE ${PROJECT_NAME_STATIC})
add_test(NAME ${TEST_TARGET_NAME}
COMMAND ${TEST_TARGET_NAME}
WORKING_DIRECTORY $<TARGET_FILE_DIR:${TEST_TARGET_NAME}>)
target_include_directories(${TEST_TARGET_NAME} PRIVATE $<TARGET_PROPERTY:${PROJECT_NAME_STATIC},INCLUDE_DIRECTORIES>)
这里我 Link 与 GTest
库相对应 Conan
.
如果我 运行 构建结果位于 Build
目录中的以下文件夹结构中:
+---build
|
+---Debug
| CommandDispatcherd.dll
+---tests
| |
| \---Debug
| CommandDispatcher_TEST.exe
GTest DLLs
在我的 Userfolder/.conan
下方某处。
将这些东西组合在一起的好方法是什么?例如。在 build
目录中的 bin/test
文件夹中构建 DLL
、Test Exe
和 Dependencies DLL
?
我的第一个猜测是将以下内容添加到 Conanfile.txt
:
[imports]
bin, gmockd.dll -> ./bin/test
bin, gmock_maind.dll -> ./bin/test
bin, gtestd.dll -> ./bin/test
bin, gtest_maind.dll -> ./bin/test
但是为此我需要知道构建的名称 dlls
。
并且还将以下内容添加到 Main CMakeFile.txt
:
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR}/bin)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR}/lib)
或者我应该根据 target
和 set_target_properties
进行更改吗?
或者有更好的解决方案吗?柯南部分还要将 DLL 复制到正确的位置吗?
也欢迎对我的 CMakeFile.txt
进行任何改进 =)。
But for this i need to know the name of the builded dlls.
我认为您不需要知道 dll 的名称。您可以像这样设置导入:
bin, *.dll -> ./bin/test @ root_package=gtest
注意 root_package
参数,它将告诉柯南从哪个包中复制 dll。
更多信息在这里:https://docs.conan.io/en/latest/reference/conanfile_txt.html#imports
或者在conanfile.py
中可以实现为:
def imports(self):
self.copy("*.dll", f"bin\tests", "bin", root_package='gtest')