【问题标题】:Produce .lib of header-only library that depends on external resources生成依赖于外部资源的仅标头库的 .lib
【发布时间】:2018-12-03 13:19:35
【问题描述】:

编辑:我已经阅读并理解最初的问题是由于仅扫描头没有 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

但是没有生成仅扫描头的库文件,因此根项目无法target_link_libraries(平整扫描头-only)并且不得不target_include_directories(leveling ${CMAKE_CURRENT_LIST_DIR}/deps/scanning-header-only/deps/tinyxml2

是否可以将 target_link_library 设置为依赖于外部资源的仅标头库?

我看到没有外部资源依赖的仅标头库可能是 add_library(.. INTERFACE),但我没有这样做,因为依赖于 tinyxml2

一个肮脏的解决方法是添加并清空 cpp 文件到仅扫描标头,以便生成一个 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. 

【问题讨论】:

  • target_include_directories 的 PUBLIC 关键字应该解决这个问题。任何与“扫描”链接的目标也应自动添加该包含目录。将您的示例归结为最小的 CMakeLists.txt 并发布...
  • 不,如果tinyxml2 库使用target_include_directories( tinyxml2 PUBLIC .) 将其头文件包含在目标定义中,则您不必为scanning 目标添加额外的target_include_directories。然后它应该填充使用它的所有内容的包含路径,例如target_link_libraries(scanning tinyxml2)
  • 另外include_directories 也不能这样工作。对于所有包含文件夹位置,您必须在顶层有一个 include_directories
  • 嗨,txs 指出这一点。因此,我对这个问题有了更多了解并编辑了问题以反映这一点

标签: cmake subdirectory


【解决方案1】:

.lib 是当您在 Windows 上创建 STATIC (.lib) 或 SHARED (.lib.dll) 库时。您想要的是一个 INTERFACE 库,它不会生成任何文件。 http://mariobadr.com/creating-a-header-only-library-with-cmake.html 有一个例子。然后,您可以使用此处列出的以下命令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(scanning-header-only INTERFACE file.h) target_link_libraries(scanning-header-only INTERFACE tinyxml2) 抱怨 tinyxml2 不是某种接口:/
  • 呵呵,在创建了最小示例之后,就成功了:/ :),txs 和抱歉
【解决方案2】:

一个简单的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 库链接在父项目中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-14
    • 1970-01-01
    • 1970-01-01
    • 2023-04-10
    • 2023-03-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多