英文:
Strange behavior from CMake when importing a STATIC library
问题
以下是要翻译的内容:
主要问题:
我在使用CMake导入yaml-cpp静态库时遇到了一个奇怪的问题(错误?)。
main.cpp
#include "yaml-cpp/yaml.h"
CMakeLists.txt(可行)
add_library(yaml-cpp ${PROJECT_BINARY_DIR}/path/to/libyaml-cpp.a)
target_link_libraries(main yaml-cpp)
CMakeLists.txt(不可行)
add_library(yaml-cpp STATIC IMPORTED)
set_target_properties(yaml-cpp PROPERTIES IMPORTED_LOCATION ${PROJECT_BINARY_DIR}/path/to/libyaml-cpp.a)
target_link_libraries(main yaml-cpp)
当我使用第二个CMakeLists.txt时,main.cpp 无法找到 yaml-cpp/yaml.h。但当我使用第一个CMakeLists.txt时,虽然能够找到,但每次配置项目时都会收到 "ar: no archive members specified" 的消息,这很烦人。我想以第二种方式导入它,以摆脱这个消息。
英文:
I'm experiencing a strange (bug?) when importing the yaml-cpp static library with CMake.
main.cpp
#include "yaml-cpp/yaml.h"
CMakeLists.txt (working)
add_library(yaml-cpp ${PROJECT_BINARY_DIR}/path/to/libyaml-cpp.a)
target_link_libraries(main yaml-cpp)
CMakeLists.txt (not working)
add_library(yaml-cpp STATIC IMPORTED)
set_target_properties(yaml-cpp PROPERTIES IMPORTED_LOCATION ${PROJECT_BINARY_DIR}/path/to/libyaml-cpp.a)
target_link_libraries(main yaml-cpp)
When I use the second CMakeLists.txt, my main.cpp cannot find yaml-cpp/yaml.h. When I use the first CMakeLists.txt, it can, however, I get the "ar: no archive members specified" message every time I configure the project, which is annoying. Would like to import it the second way to get rid of that message.
答案1
得分: 0
你的第一个片段没有意义。
第二个片段缺少INTERFACE_INCLUDE_DIRECTORIES
属性。
add_library(yaml-cpp STATIC IMPORTED)
set_target_properties(yaml-cpp PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "<path/to/includedir>"
IMPORTED_LOCATION "<path/to/static_lib>"
)
但正如答案中提到的,为什么不使用find_package()
呢,因为yaml-cpp提供了一个CMake配置文件?
英文:
Your first snippet doesn't make sense.
The second one is missing INTERFACE_INCLUDE_DIRECTORIES
property.
add_library(yaml-cpp STATIC IMPORTED)
set_target_properties(yaml-cpp PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "<path/to/includedir>"
IMPORTED_LOCATION "<path/to/static_lib>"
)
But as mentioned in an answer, why don't you use find_package()
since yaml-cpp provides a CMake config file?
答案2
得分: 0
I'm not aware of "add_library(yaml-cpp ${PROJECT_BINARY_DIR}/path/to/libyaml-cpp.a)
" being a valid usage of add_library
. See the docs. You can use absolute paths to library binaries in target_link_libraries
(but I'd consider that an antipattern here and I'll explain why).
I'm pretty sure the problem is that you haven't done target_include_directories(yaml-cpp INTERFACE <path to include directory for yaml-cpp>)
(or equivalently, set the INTERFACE_INCLUDE_DIRECTORIES
target property).
But I'd suggest you just use find_package
. From what I see in yaml-cpp's CMakeLists.txt, it does create a find-config script. Build and install yaml-cpp, and then call find_package(yaml-cpp ...)
, which will make available the yaml-cpp::yaml-cpp
target with correct configuration for include directory options and import location.
英文:
I'm not aware of "add_library(yaml-cpp ${PROJECT_BINARY_DIR}/path/to/libyaml-cpp.a)
" being a valid usage of add_library
. see the docs. You can use absolute paths to library binaries in target_link_libraries
(but I'd consider that an antipattern here and I'll explain why).
I'm pretty sure the problem is that you haven't done target_include_directories(yaml-cpp INTERFACE <path to include directory for yaml-cpp>)
(or equivalently, set the INTERFACE_INCLUDE_DIRECTORIES
target property).
But I'd suggest you just use find_package
. From what I see in yaml-cpp's CMakeLists.txt, it does create a find-config script. Build and install yaml-cpp, and then call find_package(yaml-cpp ...)
, which will make available the yaml-cpp::yaml-cpp
target with correct configuration for include directory options and import location.
答案3
得分: -1
对于你们两位的回答,我很感激。事实证明我应该在我的问题中提供更多信息。问题基本上是因为我试图创建一个便携式安装,将每个依赖项的整个源代码放在项目文件夹结构中,这是我以前从未尝试过的。对我来说,似乎逻辑上库文件(.a,.dylib等)应该包含所有的头文件,但显然并非如此。我将提供一些我是如何解决这个问题的细节。
- 在其余项目之前构建库是正确的选择,但我忘记了安装它们。cmake -> make -> make install
BuildLibraries.txt(cmake 文件)
set(yaml-cpp_cmakelists "${CMAKE_SOURCE_DIR}/external/yaml-cpp-master")
set(yaml-cpp_build_location "${CMAKE_BINARY_DIR}/external/yaml-cpp-master")
file(MAKE_DIRECTORY ${yaml-cpp_build_location})
execute_process(
COMMAND ${CMAKE_COMMAND} -S ${yaml-cpp_cmakelists} -B ${yaml-cpp_build_location} -D CMAKE_INSTALL_PREFIX=${CMAKE_LIBRARY_OUTPUT_DIRECTORY} -D BUILD_SHARED_LIBS=OFF
WORKING_DIRECTORY ${yaml-cpp_build_location}
RESULT_VARIABLE result
)
if(NOT result EQUAL 0)
message(FATAL_ERROR "Failed to configure yaml-cpp")
endif()
execute_process(
COMMAND make -C ${yaml-cpp_build_location} -j4
WORKING_DIRECTORY ${yaml-cpp_build_location}
RESULT_VARIABLE result
)
if(NOT result EQUAL 0)
message(FATAL_ERROR "Failed to generate yaml-cpp")
endif()
execute_process(
COMMAND make install -C ${yaml-cpp_build_location} -j4
WORKING_DIRECTORY ${yaml-cpp_build_location}
RESULT_VARIABLE result
)
if(NOT result EQUAL 0)
message(FATAL_ERROR "Failed to install yaml-cpp")
endif()
- 在项目根目录的 CMakeLists.txt 中:
- 确保 find_package() 知道在哪里查找你使用 set(CMAKE_PREFIX_PATH ...) 安装的库
- 接着使用 find_package()。就像这些用户建议的那样,这样做会更容易。
CMakeLists.txt(在根项目目录中)
cmake_minimum_required(VERSION 3.26.0)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(REBUILD_LIBS ON) # 选择在生成阶段重新构建库
set(PROJECT_BINARY_DIR "${CMAKE_SOURCE_DIR}/build") # 根构建目录
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") # 静态库
set(CMAKE_INSTALL_LIBDIR ${PROJECT_BINARY_DIR}/lib)
set(CMAKE_INSTALL_BINDIR ${PROJECT_BINARY_DIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") # 共享库
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") # 可执行文件
set(CMAKE_PREFIX_PATH # 定义 find_package() 的搜索路径
"${PROJECT_BINARY_DIR}/lib/cmake"
)
if(REBUILD_LIBS)
include(${CMAKE_SOURCE_DIR}/CMakeFiles/BuildLibraries.txt) # 使用 BuildLibraries.txt CMakeLists.txt 文件构建外部库
endif()
project(myProject)
add_executable(main main.cpp)
find_package (yaml-cpp)
target_link_libraries(main yaml-cpp)
英文:
For both of you who answered, I appreciate it. Turns out I should have provided more information in my question. The issue was arising basically from the fact that I am attempting to create a portable installation, with the entire source of each of the dependencies within the project folder-structure, which is something that I haven't attempted before. It seemed logical to me that the library files (.a, .dylib, etc..) would contain all of the headers within them, but apparently that is not the case. I will provide a few details on how I was able to fix the issue.
- Building the libraries before the rest of the project was the right move, but I forgot to install them. cmake -> make -> make install
BuildLibraries.txt (cmake file)
set(yaml-cpp_cmakelists "${CMAKE_SOURCE_DIR}/external/yaml-cpp-master")
set(yaml-cpp_build_location "${CMAKE_BINARY_DIR}/external/yaml-cpp-master")
file(MAKE_DIRECTORY ${yaml-cpp_build_location})
execute_process(
COMMAND ${CMAKE_COMMAND} -S ${yaml-cpp_cmakelists} -B ${yaml-cpp_build_location} -D CMAKE_INSTALL_PREFIX=${CMAKE_LIBRARY_OUTPUT_DIRECTORY} -D BUILD_SHARED_LIBS=OFF
WORKING_DIRECTORY ${yaml-cpp_build_location}
RESULT_VARIABLE result
)
if(NOT result EQUAL 0)
message(FATAL_ERROR "Failed to configure yaml-cpp")
endif()
execute_process(
COMMAND make -C ${yaml-cpp_build_location} -j4
WORKING_DIRECTORY ${yaml-cpp_build_location}
RESULT_VARIABLE result
)
if(NOT result EQUAL 0)
message(FATAL_ERROR "Failed to generate yaml-cpp")
endif()
execute_process(
COMMAND make install -C ${yaml-cpp_build_location} -j4
WORKING_DIRECTORY ${yaml-cpp_build_location}
RESULT_VARIABLE result
)
if(NOT result EQUAL 0)
message(FATAL_ERROR "Failed to install yaml-cpp")
endif()
- Inside project-root directory CMakeLists.txt:
- ensure that find_package() knows where to look for the libraries that you installed using set(CMAKE_PREFIX_PATH ...)
- go ahead and use find_package(). It is, as these users suggested, much easier.
CMakeLists.txt (in root project directory)
cmake_minimum_required(VERSION 3.26.0)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(REBUILD_LIBS ON) # choose wether to rebuild libraries during the generate phase
set(PROJECT_BINARY_DIR "${CMAKE_SOURCE_DIR}/build") # root build directory
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") # static libraries
set(CMAKE_INSTALL_LIBDIR ${PROJECT_BINARY_DIR}/lib)
set(CMAKE_INSTALL_BINDIR ${PROJECT_BINARY_DIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") # shared libraries
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") # executables
set(CMAKE_PREFIX_PATH # define search-paths for find_package()
"${PROJECT_BINARY_DIR}/lib/cmake"
)
if(REBUILD_LIBS)
include(${CMAKE_SOURCE_DIR}/CMakeFiles/BuildLibraries.txt) # Build external libraries using the BuildLibraries.txt CMakeLists.txt file
endif()
project(myProject)
add_executable(main main.cpp)
find_package (yaml-cpp)
target_link_libraries(main yaml-cpp)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论