使用CMake构建依赖项(将oneTBB作为git子模块)作为动态库?

huangapple go评论70阅读模式
英文:

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 &quot;${CMAKE_CURRENT_BINARY_DIR}/install&quot;
        LIST_SEPARATOR |
        CMAKE_CACHE_ARGS
        &quot;-DCMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE_UPPER}:STRING=${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE_UPPER}}&quot;
        &quot;-DCMAKE_C_FLAGS_${CMAKE_BUILD_TYPE_UPPER}:STRING=${CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE_UPPER}}&quot;
        &quot;-DCMAKE_EXE_LINKER_FLAGS_${CMAKE_BUILD_TYPE_UPPER}:STRING=${CMAKE_EXE_LINKER_FLAGS_${CMAKE_BUILD_TYPE_UPPER}}&quot;
        &quot;-DCMAKE_SHARED_LINKER_FLAGS_${CMAKE_BUILD_TYPE_UPPER}:STRING=${CMAKE_SHARED_LINKER_FLAGS_${CMAKE_BUILD_TYPE_UPPER}}&quot;
        &quot;-DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}&quot;
        &quot;-DCMAKE_INSTALL_PREFIX:STRING=&lt;INSTALL_DIR&gt;&quot;
        &quot;-DSPDLOG_BUILD_EXAMPLE:BOOL=OFF&quot;
        )

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 &quot;${INSTALL_DIR}/include&quot;)
target_link_directories(ext-spdlog INTERFACE &quot;${INSTALL_DIR}/lib&quot;)
target_link_libraries(ext-spdlog INTERFACE spdlog$&lt;$&lt;CONFIG:Debug&gt;:d&gt;)

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. &quot;-DTBB_TEST=OFF&quot;). 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设置为真值(例如1TRUEYESON等),然后在之后恢复先前的值。

例如:

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 &quot;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.&quot;)
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 &quot;TBBBind build targets are disabled due to unsupported environment&quot;)
    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 &quot;${BUILD_SHARED_LIBS}&quot;)
set(BUILD_SHARED_LIBS YES)
add_subdirectory(oneTBB)
set(BUILD_SHARED_LIBS &quot;${BUILD_SHARED_LIBS_TEMP}&quot;)
unset(BUILD_SHARED_LIBS_TEMP)

huangapple
  • 本文由 发表于 2023年2月6日 03:24:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/75354917.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定