英文:
Use CMake to build dependency (oneTBB as git submodule) as dynamic library?
问题
我有一个依赖于Intel的oneTBB的项目。我的项目结构如下:
external/
| - CMakeLists.txt
| - oneTBB/ (这是一个git子模块)
| - ...
include/
lib/
include/
CMakeLists.txt
我目前通过手动构建oneTBB
并将其安装在external/oneTBB/prefix
目录中,通过运行以下(bash)命令来使项目编译:
cd oneTBB
mkdir -p prefix
mkdir -p build
cd build
cmake -DCMAKE_INSTALL_PREFIX=../prefix -DTBB_TEST=OFF ..
cmake --build .
cmake --install .
然后,我只需使用这个前缀进行包含和链接。(我是根据oneTBB的README中的说明完成的)
虽然这个方法可以正常工作,但我目前正在尝试优化我的CMake,以便更容易在Windows上构建。理想情况下,我希望能够简单运行:
mkdir build
cd build
cmake ..
cmake --build .
然后我的项目将自动构建自身和所有依赖项。
我已经通过在external/
的CMakeLists.txt中简单添加以下内容来使其他依赖项(如glfw和eigen)正常工作:
add_subdirectory(glfw)
add_subdirectory(eigen)
但是,添加add_subdirectory(oneTBB)
会引发大量警告,从以下警告开始:
CMake Warning at external/oneTBB/CMakeLists.txt:116 (message):
You are building oneTBB as a static library. This is highly discouraged
and such configuration is not supported. Consider building a dynamic
library to avoid unforeseen issues.
-- TBBBind build targets are disabled due to unsupported environment
-- Configuring done
CMake Warning (dev) at external/oneTBB/src/tbb/CMakeLists.txt:15 (add_library):
Policy CMP0069 is not set: INTERPROCEDURAL_OPTIMIZATION is enforced when
enabled. Run "cmake --help-policy CMP0069" for policy details. Use the
cmake_policy command to set the policy and suppress this warning.
INTERPROCEDURAL_OPTIMIZATION property will be ignored for target 'tbb'.
This warning is for project developers. Use -Wno-dev to suppress it.
我不需要将oneTBB构建为静态库。我在尝试时是否做错了什么?实际上,我只需要oneTBB作为动态库构建,并将其放在可以链接的地方(而无需在整个系统上安装它)。
类似的问题:
我还包括了METIS库,它依赖于GKlib。目前,我正在以与我为oneTBB
做的方式类似的方式手动构建每个库,使用以下脚本:
# 设置GKlib库:
cd GKlib
mkdir -p prefix
mkdir -p build
cd build
cmake -DCMAKE_INSTALL_PREFIX=../prefix ..
cmake --build . -j
cmake --install .
cd ../../
# 设置METIS库:
cd METIS
mkdir -p prefix
make config prefix=../prefix gklib_path=../GKlib/prefix #(GKLib路径从根目录开始,安装路径相对于构建目录)
make install -j
cd ../
当我尝试使用以下方式添加它们时:
add_subdirectory(GKlib)
add_subdirectory(METIS)
它会引发错误,METIS找不到GKlib:
CMake Error at external/METIS/CMakeLists.txt:50 (add_subdirectory):
add_subdirectory given source "build/xinclude" which is not an existing
directory.
尽管我意识到这是一个不同的问题,但我认为将其包含在这里是因为它与我的add_subdirectory()
问题相关。
英文:
I have a project that depends on Intel's oneTBB. My project is structured as follows:
external/
| - CMakeLists.txt
| - oneTBB/ (this is a git submodule)
| - ...
include/
lib/
include/
CMakeLists.txt
I currently get things to compile by manually building oneTBB
and installing it inside a prefix
directory located at external/oneTBB/prefix
by running the following (bash) commands:
cd oneTBB
mkdir -p prefix
mkdir -p build
cd build
cmake -DCMAKE_INSTALL_PREFIX=../prefix -DTBB_TEST=OFF ..
cmake --build .
cmake --install .
I then simply include and link using this prefix. (I got this from following the oneTBB READMEs)
While this works without issue, I'm currently trying to clean up my CMake such that its easier to build on Windows as well. Ideally, I'm looking to get to a point where I can simply run:
mkdir build
cd build
cmake ..
cmake --build .
and my project will build itself and all dependencies.
I got this working with other dependencies such as glfw and eigen by simply adding (to the CMakeLists.txt in external/
:
add_subdirectory(glfw)
add_subdirectory(eigen)
But adding add_subdirectory(oneTBB)
throws a LOT of warnings, starting with:
CMake Warning at external/oneTBB/CMakeLists.txt:116 (message):
You are building oneTBB as a static library. This is highly discouraged
and such configuration is not supported. Consider building a dynamic
library to avoid unforeseen issues.
-- TBBBind build targets are disabled due to unsupported environment
-- Configuring done
CMake Warning (dev) at external/oneTBB/src/tbb/CMakeLists.txt:15 (add_library):
Policy CMP0069 is not set: INTERPROCEDURAL_OPTIMIZATION is enforced when
enabled. Run "cmake --help-policy CMP0069" for policy details. Use the
cmake_policy command to set the policy and suppress this warning.
INTERPROCEDURAL_OPTIMIZATION property will be ignored for target 'tbb'.
This warning is for project developers. Use -Wno-dev to suppress it.
I have no need to build oneTBB as a static library.
Am I doing something wrong in my attempt? Really all I need is for oneTBB to be built as a dynamic library and placed somewhere I can link it to (without installing it on the system overall)
Similar question:
I am also including the METIS library which depends on GKlib. Currently I'm doing this in a similar way to what I did for oneTBB
where I manually build each using the following script:
# Setup the GKlib library:
cd GKlib
mkdir -p prefix
mkdir -p build
cd build
cmake -DCMAKE_INSTALL_PREFIX=../prefix ..
cmake --build . -j
cmake --install .
cd ../../
# Setup the METIS library:
cd METIS
mkdir -p prefix
make config prefix=../prefix gklib_path=../GKlib/prefix #(GKLib path is done from root, install path done relative to build)
make install -j
cd ../
When I try to add them using:
add_subdirectory(GKlib)
add_subdirectory(METIS)
it throws errors that METIS cannot find GKlib:
CMake Error at external/METIS/CMakeLists.txt:50 (add_subdirectory):
add_subdirectory given source "build/xinclude" which is not an existing
directory.
While I recognize this is a separate issue, I figured to include it here as it is related to my issues with add_subdirectory()
答案1
得分: 1
许多项目希望您单独调用CMake,而不是将它们添加到现有项目中使用add_subdirectory
。虽然可能有办法让add_subdirectory
与oneTBB一起工作,但有一种更简单的方法。
CMake有一个函数,允许您在构建时下载、构建和安装外部项目:ExternalProject_Add。
这是一个关于spdlog的示例,直接取自我的一个项目:
# project_root/thirdparty/spdlog/CMakeLists.txt
string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_UPPER)
ExternalProject_Add(spdlog-project
GIT_REPOSITORY https://github.com/gabime/spdlog
GIT_TAG edc51df1bdad8667b628999394a1e7c4dc6f3658
GIT_SUBMODULES_RECURSE ON
GIT_REMOTE_UPDATE_STRATEGY CHECKOUT
INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/install"
LIST_SEPARATOR |
CMAKE_CACHE_ARGS
"-DCMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE_UPPER}:STRING=${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE_UPPER}}"
"-DCMAKE_C_FLAGS_${CMAKE_BUILD_TYPE_UPPER}:STRING=${CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE_UPPER}}"
"-DCMAKE_EXE_LINKER_FLAGS_${CMAKE_BUILD_TYPE_UPPER}:STRING=${CMAKE_EXE_LINKER_FLAGS_${CMAKE_BUILD_TYPE_UPPER}}"
"-DCMAKE_SHARED_LINKER_FLAGS_${CMAKE_BUILD_TYPE_UPPER}:STRING=${CMAKE_SHARED_LINKER_FLAGS_${CMAKE_BUILD_TYPE_UPPER}}"
"-DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}"
"-DCMAKE_INSTALL_PREFIX:STRING=<INSTALL_DIR>"
"-SPDLOG_BUILD_EXAMPLE:BOOL=OFF"
)
add_library(ext-spdlog INTERFACE)
add_dependencies(ext-spdlog spdlog-project)
ExternalProject_Get_property(spdlog-project INSTALL_DIR)
target_include_directories(ext-spdlog SYSTEM INTERFACE "${INSTALL_DIR}/include")
target_link_directories(ext-spdlog INTERFACE "${INSTALL_DIR}/lib")
target_link_libraries(ext-spdlog INTERFACE spdlog$<$<CONFIG:Debug>:d>)
之后,我的项目只需链接到创建的库目标:
target_link_libraries(my_project ext-spdlog)
要适应oneTBB,您需要更改存储库URL和提交哈希,并添加自己的CMake定义(例如,"-DTBB_TEST=OFF"
)。根据oneTBB的包含和库目录设置方式,您还可能需要更改target_include_directories
和/或target_link_directories
行。我还没有查找过这个,但我相信您可以自行解决。
无论外部项目是作为静态库还是共享库构建,这都可以正常工作。不过,您不应该使用git子模块 - 反而应该让CMake执行下载操作(如果外部项目已经构建且是最新的,它只会下载并构建一次,后续构建不会重新构建外部项目)。
英文:
Many projects expect that you invoke CMake on them separately instead of adding them into an existing project with add_subdirectory
. While there might be a way to make add_subdirectory
work with oneTBB, there is an easier way.
CMake has a function that allows you to download, build, and install external projects at build time: ExternalProject_Add.
Here's an example for spdlog, taken straight from one of my own projects:
# project_root/thirdparty/spdlog/CMakeLists.txt
string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_UPPER)
ExternalProject_Add(spdlog-project
GIT_REPOSITORY https://github.com/gabime/spdlog
GIT_TAG edc51df1bdad8667b628999394a1e7c4dc6f3658
GIT_SUBMODULES_RECURSE ON
GIT_REMOTE_UPDATE_STRATEGY CHECKOUT
INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/install"
LIST_SEPARATOR |
CMAKE_CACHE_ARGS
"-DCMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE_UPPER}:STRING=${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE_UPPER}}"
"-DCMAKE_C_FLAGS_${CMAKE_BUILD_TYPE_UPPER}:STRING=${CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE_UPPER}}"
"-DCMAKE_EXE_LINKER_FLAGS_${CMAKE_BUILD_TYPE_UPPER}:STRING=${CMAKE_EXE_LINKER_FLAGS_${CMAKE_BUILD_TYPE_UPPER}}"
"-DCMAKE_SHARED_LINKER_FLAGS_${CMAKE_BUILD_TYPE_UPPER}:STRING=${CMAKE_SHARED_LINKER_FLAGS_${CMAKE_BUILD_TYPE_UPPER}}"
"-DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}"
"-DCMAKE_INSTALL_PREFIX:STRING=<INSTALL_DIR>"
"-DSPDLOG_BUILD_EXAMPLE:BOOL=OFF"
)
add_library(ext-spdlog INTERFACE)
add_dependencies(ext-spdlog spdlog-project)
ExternalProject_Get_property(spdlog-project INSTALL_DIR)
target_include_directories(ext-spdlog SYSTEM INTERFACE "${INSTALL_DIR}/include")
target_link_directories(ext-spdlog INTERFACE "${INSTALL_DIR}/lib")
target_link_libraries(ext-spdlog INTERFACE spdlog$<$<CONFIG:Debug>:d>)
After that, my project simply links against the created library target:
target_link_libraries(my_project ext-spdlog)
To adapt this for oneTBB, you have to switch out the repository URL and commit hash, and add your own CMake definitions (i.e. "-DTBB_TEST=OFF"
). Depending on how oneTBB has its include and library directories set up, you may also have to change the target_include_directories
and/or target_link_directories
lines. I haven't looked this up yet, but I'm sure you can figure it out.
This works regardless of whether the external project is built as a static or shared library. You shouldn't use git submodules, though - instead, let CMake do the downloading. (It'll only download and build once; subsequent builds will not re-build the external project if it's already built and up-to-date.)
答案2
得分: 0
我无需构建一个静态库的需求。我在尝试中是否有做错什么?我只需要将oneTBB构建为动态库,并将其放在可以链接的位置(而无需在整个系统上安装它)。
所有您的诊断消息都表明它实际上正在配置为构建为静态库,并且其他线索表明,您可能已将BUILD_SHARED_LIBS
设置为false
,在您的作用域内执行add_subdirectory(oneTBB)
。
CMake Warning at external/oneTBB/CMakeLists.txt:116 (message):
You are building oneTBB as a static library. This is highly discouraged
and such configuration is not supported. Consider building a dynamic
library to avoid unforeseen issues.
如果您查看oneTBB的CMakeLists.txt文件,您会看到以下内容:
if (NOT DEFINED BUILD_SHARED_LIBS)
set(BUILD_SHARED_LIBS ON)
endif()
if (NOT BUILD_SHARED_LIBS)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
message(WARNING "You are building oneTBB as a static library. This is highly discouraged and such configuration is not supported. Consider building a dynamic library to avoid unforeseen issues.")
endif()
然后紧接着,您会得到
-- TBBBind build targets are disabled due to unsupported environment
oneTBB的CMakeLists.txt文件中的相应部分如下:
if (TBB_FIND_PACKAGE OR TBB_DIR)
...
else()
if (APPLE OR NOT BUILD_SHARED_LIBS)
message(STATUS "TBBBind build targets are disabled due to unsupported environment")
else()
add_subdirectory(src/tbbbind)
endif()
...
这两个线索都表明,在您执行add_subdirectory(oneTBB)
的变量范围内,BUILD_SHARED_LIBS
被设置为假值。
在执行add_subdirectory(oneTBB)
之前,将BUILD_SHARED_LIBS
设置为真值(例如1
,TRUE
,YES
,ON
等),然后在之后恢复先前的值。
例如:
set(BUILD_SHARED_LIBS_TEMP "${BUILD_SHARED_LIBS}")
set(BUILD_SHARED_LIBS YES)
add_subdirectory(oneTBB)
set(BUILD_SHARED_LIBS "${BUILD_SHARED_LIBS_TEMP}")
unset(BUILD_SHARED_LIBS_TEMP)
英文:
> I have no need to build oneTBB as a static library. Am I doing something wrong in my attempt? Really all I need is for oneTBB to be built as a dynamic library and placed somewhere I can link it to (without installing it on the system overall)
All your diagnostic messages indicate that it's actually being configured to be built as a static library, and additional clues point to the probability that you've set BUILD_SHARED_LIBS
to false in the scope where you add_subdirectory(oneTBB)
.
CMake Warning at external/oneTBB/CMakeLists.txt:116 (message):
You are building oneTBB as a static library. This is highly discouraged
and such configuration is not supported. Consider building a dynamic
library to avoid unforeseen issues.
If you look in oneTBB's CMakeLists.txt file, you'll the following:
if (NOT DEFINED BUILD_SHARED_LIBS)
set(BUILD_SHARED_LIBS ON)
endif()
if (NOT BUILD_SHARED_LIBS)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
message(WARNING "You are building oneTBB as a static library. This is highly discouraged and such configuration is not supported. Consider building a dynamic library to avoid unforeseen issues.")
endif()
And then right after that, you get
-- TBBBind build targets are disabled due to unsupported environment
The corresponding section of oneTBB's CMakeLists.txt file is:
if (TBB_FIND_PACKAGE OR TBB_DIR)
...
else()
if (APPLE OR NOT BUILD_SHARED_LIBS)
message(STATUS "TBBBind build targets are disabled due to unsupported environment")
else()
add_subdirectory(src/tbbbind)
endif()
...
Both of these clues indicate that in the variable scope at which you add_subdirectory(oneTBB)
, BUILD_SHARED_LIBS
is set to a falsy value.
Set BUILD_SHARED_LIBS
it to a truthy value (Ex. 1
, TRUE
, YES
, ON
, etc.) before doing add_subdirectory(oneTBB)
and then restore the previous value afterward.
Ex.
set(BUILD_SHARED_LIBS_TEMP "${BUILD_SHARED_LIBS}")
set(BUILD_SHARED_LIBS YES)
add_subdirectory(oneTBB)
set(BUILD_SHARED_LIBS "${BUILD_SHARED_LIBS_TEMP}")
unset(BUILD_SHARED_LIBS_TEMP)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论