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

rvpgvaaj  于 2023-02-06  发布在  Git
关注(0)|答案(2)|浏览(489)

我有一个依赖于Intel's oneTBB的项目。我的项目结构如下:

external/
    | - CMakeLists.txt
    | - oneTBB/  (this is a git submodule)
    | - ...
include/
lib/
include/
CMakeLists.txt

目前,我通过手动构建oneTBB并通过运行以下(bash)命令将其安装在external/oneTBB/prefix目录中来进行编译:

cd oneTBB
mkdir -p prefix
mkdir -p build
cd build
cmake -DCMAKE_INSTALL_PREFIX=../prefix -DTBB_TEST=OFF ..
cmake --build .
cmake --install .

然后我简单地使用这个前缀包含和链接。(我从下面的oneTBB自述文件中得到这个)
虽然这没有问题,我目前正在尝试清理我的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构建为动态库,并放置在我可以链接到的地方(而不是在整个系统上安装它)
类似问题:
我还包含了依赖于GKlibMETIS库,目前我使用类似于oneTBB的方法来完成,在oneTBB中,我使用以下脚本手动构建每个库:

# 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 ../

当我尝试使用以下命令添加它们时:

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()问题相关

ljo96ir5

ljo96ir51#

我不需要将oneTBB构建为静态库。我的尝试是否做错了什么?实际上,我所需要的只是将oneTBB构建为动态库,并放置在我可以链接到的地方(而不是在整个系统上安装它)
所有的诊断消息都表明它实际上被配置为构建为一个静态库,并且其他线索指向在add_subdirectory(oneTBB)的作用域中将BUILD_SHARED_LIBS设置为false的可能性。

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's CMakeLists.txt file,您将看到以下内容:

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's CMakeLists.txt file的相应部分为:

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)
eqfvzcg8

eqfvzcg82#

许多项目希望您单独调用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>"
        "-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>)

之后,我的项目只链接到创建的库目标:

target_link_libraries(my_project ext-spdlog)

为了适应oneTBB,你必须切换出仓库URL和提交散列,并添加你自己的CMake定义(即"-DTBB_TEST=OFF")。根据oneTBB如何设置它的include和library目录,你可能还必须修改target_include_directories和/或target_link_directories行。我还没有查到这一点,但我相信你能弄清楚。
不管外部项目是以静态库还是共享库的形式构建的,都可以这样做。不过,你不应该使用git子模块,而是让CMake来下载。(它只会下载和构建一次;如果外部项目已经生成并且是最新的,则后续生成将不会重新生成该外部项目。)

相关问题