生成依赖外部资源的header-only个库的.lib
Produce .lib of header-only library that depends on external resources
编辑: 我已经阅读并了解最初的问题是由于 scanning-header-only 没有 cpp 文件,因此没有生成 lib 文件。编辑问题以反映额外的理解:
我当前的项目文件夹结构和相关CMakeLists内容:
leveling
├── CMakeLists.txt: add_subdirectory(deps)
└── deps
├── CMakeLists.txt: add_subdirectory(scanning-header-only)
└── scanning
├── CMakeLists.txt: add_subdirectory(deps)
│ add_library(scanning-header-only file.h)
│ target_include_directories(scanning-header-only PUBLIC ${CMAKE_CURRENT_LIST_DIR}/deps/tinyxml2)
│ target_link_libraries(scanning-header-only PUBLIC tinyxml2)
└── deps
├── CMakeLists.txt: add_subdirectory(tinyxml2)
└── tinyxml2
但是没有生成scanning-header-only库文件,因此根项目不能target_link_libraries(升级scanning-header-only),不得不target_include_directories(leveling ${CMAKE_CURRENT_LIST_DIR}/deps/scanning-header-only/deps/tinyxml2
)
是否可以target_link_library一个依赖外部资源的header-only库?
我看到没有外部资源依赖的 header-only 库可能是 add_library(.. INTERFACE)
,但我没有这样做,因为依赖 tinyxml2
一个肮脏的解决方法是将 cpp 文件添加到 scanning-header-only 并生成一个 lib 文件,但是有正确的方法吗?
这是最小示例 v1:https://www.dropbox.com/s/r1lbajz3xoat1bg/leveling-header-only-test%20v1.zip?dl=0
练级CMakeLists.txt:
cmake_minimum_required(版本 3.8)
set(LEVELING_NAME leveling)
project(${LEVELING_NAME})
#
# To put tinyxml.dll next to the executable, to workaround having to make tinyxml2.dll reachable in PATH
#
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
math(EXPR platform_bits "${CMAKE_SIZEOF_VOID_P} * 8")
set(platform_dir bin/${CMAKE_SYSTEM_NAME}-${platform_bits})
foreach(config DEBUG RELEASE RELWITHDEBINFO MINSIZEREL)
foreach(var
CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${config}
CMAKE_LIBRARY_OUTPUT_DIRECTORY_${config}
CMAKE_RUNTIME_OUTPUT_DIRECTORY_${config}
)
set(${var} "${CMAKE_BINARY_DIR}/${platform_dir}/${config}")
string(TOLOWER "${${var}}" ${var})
endforeach()
endforeach()
#
# ----------------------------------------------------------------------
#
add_subdirectory(deps)
add_executable(${LEVELING_NAME} main.cpp)
target_include_directories(${LEVELING_NAME} PUBLIC
${CMAKE_CURRENT_LIST_DIR}/deps/scanning
)
target_link_libraries(${LEVELING_NAME}
xml-reading
)
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${LEVELING_NAME}) # Set Startup Project in VS. Implemented in CMake v3.6
set_target_properties(${LEVELING_NAME} PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}") # Set Working Directory of project in VS. Implemented in CMake v3.8
正在扫描CMakeLists.txt
cmake_minimum_required(VERSION 3.8)
set(XML_NAME xml-reading)
project(${XML_NAME})
#
# To put tinyxml.dll next to the executable, to workaround having to make tinyxml2.dll reachable in PATH
#
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
math(EXPR platform_bits "${CMAKE_SIZEOF_VOID_P} * 8")
set(platform_dir bin/${CMAKE_SYSTEM_NAME}-${platform_bits})
foreach(config DEBUG RELEASE RELWITHDEBINFO MINSIZEREL)
foreach(var
CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${config}
CMAKE_LIBRARY_OUTPUT_DIRECTORY_${config}
CMAKE_RUNTIME_OUTPUT_DIRECTORY_${config}
)
set(${var} "${CMAKE_BINARY_DIR}/${platform_dir}/${config}")
string(TOLOWER "${${var}}" ${var})
endforeach()
endforeach()
#
# ----------------------------------------------------------------------
#
add_subdirectory(deps)
add_library(${XML_NAME} INTERFACE CamerasXML.h)
target_include_directories(${XML_NAME} INTERFACE
${CMAKE_CURRENT_LIST_DIR}/deps/tinyxml2
)
target_link_libraries(${XML_NAME}
INTERFACE tinyxml2
)
产生
CMake Error at deps/scanning/CMakeLists.txt:33 (add_library):
add_library INTERFACE library requires no source arguments.
A .lib
是当您在 Windows 上创建 STATIC (.lib
) 或 SHARED(.lib
和 .dll
)库时。您想要的是一个 INTERFACE 库,它不生成任何文件。 http://mariobadr.com/creating-a-header-only-library-with-cmake.html has an example. Then you can use the following commands listed here, https://cmake.org/cmake/help/latest/command/add_library.html#interface-libraries,填充界面。请注意,它使用的是 INTERFACE 而不是 PUBLIC.
target_link_libraries(INTERFACE),
target_link_options(INTERFACE),
target_include_directories(INTERFACE),
target_compile_options(INTERFACE),
target_compile_definitions(INTERFACE), and
target_sources(INTERFACE),
我从来没有真正使用过这个,但我认为它可以像文档中描述的那样工作。
一个简单的 add_library(${XML_NAME} INTERFACE)
(不指定任何源文件),而 target_include_directories(${XML_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR}/deps/tinyxml2)
和 target_link_libraries(${XML_NAME} INTERFACE tinyxml2)
就可以了。
父项目可以使用 tinyxml2 包含的内容,并且在父项目中链接了 tinyxml2 库。
编辑: 我已经阅读并了解最初的问题是由于 scanning-header-only 没有 cpp 文件,因此没有生成 lib 文件。编辑问题以反映额外的理解:
我当前的项目文件夹结构和相关CMakeLists内容:
leveling
├── CMakeLists.txt: add_subdirectory(deps)
└── deps
├── CMakeLists.txt: add_subdirectory(scanning-header-only)
└── scanning
├── CMakeLists.txt: add_subdirectory(deps)
│ add_library(scanning-header-only file.h)
│ target_include_directories(scanning-header-only PUBLIC ${CMAKE_CURRENT_LIST_DIR}/deps/tinyxml2)
│ target_link_libraries(scanning-header-only PUBLIC tinyxml2)
└── deps
├── CMakeLists.txt: add_subdirectory(tinyxml2)
└── tinyxml2
但是没有生成scanning-header-only库文件,因此根项目不能target_link_libraries(升级scanning-header-only),不得不target_include_directories(leveling ${CMAKE_CURRENT_LIST_DIR}/deps/scanning-header-only/deps/tinyxml2
)
是否可以target_link_library一个依赖外部资源的header-only库?
我看到没有外部资源依赖的 header-only 库可能是 add_library(.. INTERFACE)
,但我没有这样做,因为依赖 tinyxml2
一个肮脏的解决方法是将 cpp 文件添加到 scanning-header-only 并生成一个 lib 文件,但是有正确的方法吗?
这是最小示例 v1:https://www.dropbox.com/s/r1lbajz3xoat1bg/leveling-header-only-test%20v1.zip?dl=0
练级CMakeLists.txt: cmake_minimum_required(版本 3.8)
set(LEVELING_NAME leveling)
project(${LEVELING_NAME})
#
# To put tinyxml.dll next to the executable, to workaround having to make tinyxml2.dll reachable in PATH
#
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
math(EXPR platform_bits "${CMAKE_SIZEOF_VOID_P} * 8")
set(platform_dir bin/${CMAKE_SYSTEM_NAME}-${platform_bits})
foreach(config DEBUG RELEASE RELWITHDEBINFO MINSIZEREL)
foreach(var
CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${config}
CMAKE_LIBRARY_OUTPUT_DIRECTORY_${config}
CMAKE_RUNTIME_OUTPUT_DIRECTORY_${config}
)
set(${var} "${CMAKE_BINARY_DIR}/${platform_dir}/${config}")
string(TOLOWER "${${var}}" ${var})
endforeach()
endforeach()
#
# ----------------------------------------------------------------------
#
add_subdirectory(deps)
add_executable(${LEVELING_NAME} main.cpp)
target_include_directories(${LEVELING_NAME} PUBLIC
${CMAKE_CURRENT_LIST_DIR}/deps/scanning
)
target_link_libraries(${LEVELING_NAME}
xml-reading
)
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${LEVELING_NAME}) # Set Startup Project in VS. Implemented in CMake v3.6
set_target_properties(${LEVELING_NAME} PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}") # Set Working Directory of project in VS. Implemented in CMake v3.8
正在扫描CMakeLists.txt
cmake_minimum_required(VERSION 3.8)
set(XML_NAME xml-reading)
project(${XML_NAME})
#
# To put tinyxml.dll next to the executable, to workaround having to make tinyxml2.dll reachable in PATH
#
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
math(EXPR platform_bits "${CMAKE_SIZEOF_VOID_P} * 8")
set(platform_dir bin/${CMAKE_SYSTEM_NAME}-${platform_bits})
foreach(config DEBUG RELEASE RELWITHDEBINFO MINSIZEREL)
foreach(var
CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${config}
CMAKE_LIBRARY_OUTPUT_DIRECTORY_${config}
CMAKE_RUNTIME_OUTPUT_DIRECTORY_${config}
)
set(${var} "${CMAKE_BINARY_DIR}/${platform_dir}/${config}")
string(TOLOWER "${${var}}" ${var})
endforeach()
endforeach()
#
# ----------------------------------------------------------------------
#
add_subdirectory(deps)
add_library(${XML_NAME} INTERFACE CamerasXML.h)
target_include_directories(${XML_NAME} INTERFACE
${CMAKE_CURRENT_LIST_DIR}/deps/tinyxml2
)
target_link_libraries(${XML_NAME}
INTERFACE tinyxml2
)
产生
CMake Error at deps/scanning/CMakeLists.txt:33 (add_library):
add_library INTERFACE library requires no source arguments.
A .lib
是当您在 Windows 上创建 STATIC (.lib
) 或 SHARED(.lib
和 .dll
)库时。您想要的是一个 INTERFACE 库,它不生成任何文件。 http://mariobadr.com/creating-a-header-only-library-with-cmake.html has an example. Then you can use the following commands listed here, https://cmake.org/cmake/help/latest/command/add_library.html#interface-libraries,填充界面。请注意,它使用的是 INTERFACE 而不是 PUBLIC.
target_link_libraries(INTERFACE),
target_link_options(INTERFACE),
target_include_directories(INTERFACE),
target_compile_options(INTERFACE),
target_compile_definitions(INTERFACE), and
target_sources(INTERFACE),
我从来没有真正使用过这个,但我认为它可以像文档中描述的那样工作。
一个简单的 add_library(${XML_NAME} INTERFACE)
(不指定任何源文件),而 target_include_directories(${XML_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR}/deps/tinyxml2)
和 target_link_libraries(${XML_NAME} INTERFACE tinyxml2)
就可以了。
父项目可以使用 tinyxml2 包含的内容,并且在父项目中链接了 tinyxml2 库。