简体   繁体   English

将 FetchContent_Declare 与 CMAKE_ARGS 一起使用

[英]Using FetchContent_Declare together with CMAKE_ARGS

I'm using cmake v3.13 and I want to change my ExternalProject_Add() for the SEAL library to:我正在使用cmake v3.13,我想将SEAL库的ExternalProject_Add()更改为:

include(FetchContent)
# Get the seal library
set(SEAL "seal")
FetchContent_Declare(
        ${SEAL}
        GIT_REPOSITORY  https://github.com/microsoft/SEAL
        GIT_TAG         v3.5.2

)
FetchContent_GetProperties(${SEAL})
if(NOT ${SEAL}_POPULATED)
    FetchContent_Populate(${SEAL})
    add_subdirectory(${${SEAL}_SOURCE_DIR} ${${SEAL}_BINARY_DIR})
endif()

When I was using ExternalProject_Add() I've used CMAKE_ARGS -DBUILD_SHARED_LIBS=ON and this doesn't work with FetchContent_Declare() that only downloads the library.当我使用ExternalProject_Add()时,我使用CMAKE_ARGS -DBUILD_SHARED_LIBS=ON ,这不适用于仅下载库的FetchContent_Declare()

The SEAL v3.5.2 CMakeLists.txt uses this to check if a shared library needs to be built: SEAL v3.5.2 CMakeLists.txt使用它来检查是否需要构建共享库:

# Should we build also the shared library?
set(BUILD_SHARED_LIBS_STR "Build shared library")
option(BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS_STR} OFF)
if(MSVC AND BUILD_SHARED_LIBS)
    message(WARNING "This build system only supports a static build; disabling `BUILD_SHARED_LIBS`")
    set(BUILD_SHARED_LIBS OFF CACHE BOOL ${BUILD_SHARED_LIBS_STR} FORCE)
endif()

# Conditionally build the shared library
if(BUILD_SHARED_LIBS)
    add_library(seal_shared SHARED $<TARGET_OBJECTS:seal_obj>)
    set_target_properties(seal_shared PROPERTIES OUTPUT_NAME seal)
    seal_set_version(seal_shared)
    seal_set_soversion(seal_shared)
    seal_set_language(seal_shared)
    seal_set_include_directories(seal_shared)
    seal_link_threads(seal_shared)

    # Conditionally add MSGSL include directory to build interface
    if(SEAL_USE_MSGSL AND NOT MSVC)
        target_include_directories(seal_shared PUBLIC $<BUILD_INTERFACE:${MSGSL_INCLUDE_DIR}>)
    endif()

    if(SEAL_USE_ZLIB AND NOT MSVC)
        # In the shared build we link zlibstatic into the shared library
        target_link_libraries(seal_shared PRIVATE zlibstatic)
    endif()

    seal_install_target(seal_shared SEALTargets)
endif()

Is there a way to download the SEAL library using FetchContent_Declare() and then use some CMakeLists setting to pass the CMAKE_ARGS -DBUILD_SHARED_LIBS=ON argument to the downloaded library when building it?有没有办法使用FetchContent_Declare()下载SEAL库,然后在构建它时使用一些CMakeLists设置将CMAKE_ARGS -DBUILD_SHARED_LIBS=ON参数传递给下载的库?

When build some project at the top-level , you may pass a parameter to it using command line option顶层构建一些项目时,您可以使用命令行选项将参数传递给它

-D<VARIABLE>=<VALUE>

( ExternalProject_Add builds the project "as if" top-level, so the option passing is technically the same). ExternalProject_Add构建项目“好像”顶级,因此选项传递在技术上是相同的)。

When build some project as a subproject using add_subdirectory approach, you may use the same command line option当使用add_subdirectory方法将某个项目构建为子项目时,您可以使用相同的命令行选项

-D<VARIABLE>=<VALUE>

for top-level project , and this parameter will be propagated to the subproject too.对于顶级项目,此参数也将传播子项目

If passing the parameter to the top-level project is not desired, then you may emulate the parameter setting inside CMakeLists.txt using set(CACHE INTERNAL) command flow:如果不需要将参数传递给顶级项目,那么您可以使用set(CACHE INTERNAL)命令流模拟CMakeLists.txt中的参数设置:

set(<PARAMETER> <VALUE> CACHE INTERNAL "<some description>")

Make sure this line is issued before add_subdirectory() call (otherwise it won't affect the subproject).确保在add_subdirectory()调用之前发出此行(否则它不会影响子项目)。

So in your case you may use following code:因此,在您的情况下,您可以使用以下代码:

if(NOT ${SEAL}_POPULATED)
    FetchContent_Populate(${SEAL})
    # Make subproject to use 'BUILD_SHARED_LIBS=ON' setting.
    set(BUILD_SHARED_LIBS ON CACHE INTERNAL "Build SHARED libraries")
    add_subdirectory(${${SEAL}_SOURCE_DIR} ${${SEAL}_BINARY_DIR})
endif()

All above works perfectly when top-level project doesn't use the parameter set for subproject.当顶级项目不使用子项目的参数集时,以上所有内容都可以完美运行。

If both top-level project and subproject are affected by the same parameter, and you want to hardcode the parameter for the subdproject only, then things become more complicated.如果顶级项目和子项目都受同一个参数影响,而您只想硬编码子项目的参数,那么事情会变得更加复杂。 You need to restore the parameter after add_subdirectory call:您需要在add_subdirectory调用后恢复参数:

if(NOT ${SEAL}_POPULATED)
    FetchContent_Populate(${SEAL})

    # Store the old value of the 'BUILD_SHARED_LIBS'
    set(BUILD_SHARED_LIBS_OLD ${BUILD_SHARED_LIBS})
    # Make subproject to use 'BUILD_SHARED_LIBS=ON' setting.
    set(BUILD_SHARED_LIBS ON CACHE INTERNAL "Build SHARED libraries")

    add_subdirectory(${${SEAL}_SOURCE_DIR} ${${SEAL}_BINARY_DIR})

    # Restore the old value of the parameter
    set(BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS_OLD} CACHE BOOL "Type of libraries to build" FORCE)
endif()

# ...

# The library will be created according to "original" value for BUILD_SHARED_LIBS option.
add_library(top_lib top_lib.c)

Note, that in case of restoring parameter, set(CACHE TYPE FORCE) command flow is used instead of set(CACHE INTERNAL) .请注意,在恢复参数的情况下,使用set(CACHE TYPE FORCE)命令流而不是set(CACHE INTERNAL) This restores not only a value of the CACHE variable, but also its type, which is shown in CMake GUI.这不仅会恢复 CACHE 变量的值,还会恢复其类型,如 CMake GUI 中所示。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM