如何以跨平台的方式使用 CMake ExternalProject_Add 或替代品? [英] How do I use CMake ExternalProject_Add or alternatives in a cross-platform way?

查看:24
本文介绍了如何以跨平台的方式使用 CMake ExternalProject_Add 或替代品?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想构建一个第三方项目,该项目已经将 CMake 作为我项目的 CMake 条带的一部分.ExternalProject_Add 就是为了这个目的,但我发现它只能与特定的生成器一起工作,我希望它可以轻松地在许多平台上工作.

例如,这是我的外部项目,为 zlib 添加了脚本,它有自己的 CMakeLists.txt:

set(USE_PROJECT_CMAKE_MODULE_PATH "-DCMAKE_MODULE_PATH=${MAKE_MODULE_PATH}")外部项目_添加(ZLIBSOURCE_DIR ${CMAKE_SOURCE_DIR}/external/zlib下载命令"更新命令"CMAKE_ARGS-DCMAKE_INSTALL_PREFIX=-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}-DCMAKE_C_FLAGS=${CMAKE_C_FLAGS}-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}${USE_PROJECT_CMAKE_MODULE_PATH}INSTALL_COMMAND "")ExternalProject_Add_Step(ZLIB 安装内部命令 cd &&进行安装依赖安装总是 1)ExternalProject_Get_Property(ZLIB install_dir)如果(UNIX)设置(ZLIB_NAME libz)其他(UNIX)设置(ZLIB_NAME zlib)结束(UNIX)add_library(zlib 未知导入)set_property(TARGET zlib PROPERTY IMPORTED_LOCATION ${install_dir}/lib/${ZLIB_NAME}.a)设置(ZLIB_LIBRARIES zlib)设置(ZLIB_LIBRARIES_OPTIONAL ${ZLIB_LIBRARIES})设置(ZLIB_DIR ${install_dir} 缓存内部zlib 根目录")设置(ZLIB_INCLUDE_DIRS ${install_dir}/include CACHE INTERNALzlib 包含目录")设置(ZLIB_DEFINES-msse2 -mfpmath=sse"缓存内部zlib定义")

问题在于它适用于 make,但不适用于 Xcode 或 Visual Studio.也许有某种方法可以将传递给我的项目的 CMake 构建命令转发给 ExternalProject_Add.

如何以跨平台的方式以最小的代码复杂性编写 ExternalProject_Add 调用,或者是否有更好的替代方法?

解决方案

问题

-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}

这对于单配置项目来说已经足够了.但是对于 Xcode 和 Visual Studio,您需要设置 CMAKE_CONFIGURATION_TYPES 并调用 build .--config 在构建阶段.请参阅我的答案.>

COMMAND cd &&进行安装

这当然只适用于 Makefile 生成器.要跨平台,您可以使用:

--build .--target install --configExternalProject_AddINSTALL_COMMAND 内.

看看这个模板文件>,特别是以下行>:

ExternalProject_Add(${current_project}"网址@HUNTER_PACKAGE_URL@URL_HASHSHA1=@HUNTER_PACKAGE_SHA1@下载目录"@HUNTER_PACKAGE_DOWNLOAD_DIR@"SOURCE_DIR"@HUNTER_PACKAGE_SOURCE_DIR@"安装目录"@HUNTER_PACKAGE_INSTALL_PREFIX@"# 没用,只是避免创建 Install/空目录BUILD_COMMAND ""# 此命令为空,因为所有必需的目标都将# 建立在安装阶段CMAKE_ARGS-G@CMAKE_GENERATOR@""-C@HUNTER_CACHE_FILE@""-C@HUNTER_ARGS_FILE@""-D${postfix_name}=${${postfix_name}}"-DCMAKE_BUILD_TYPE=${configuration}"-DCMAKE_CONFIGURATION_TYPES=${configuration}""-DCMAKE_INSTALL_PREFIX=@HUNTER_PACKAGE_INSTALL_PREFIX@"-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}"INSTALL_COMMAND@CMAKE_COMMAND@"- 建造 .--目标安装--config ${配置}——${jobs_option})

替代方案

<块引用>

或者有更好的选择吗?

你见过猎人吗?

你可以像这个一样添加zlib:

hunter_add_package(ZLIB)find_package(需要 ZLIB 配置)target_link_libraries(... ZLIB::zlib)

此代码适用于任何地方.第三方依赖将在配置步骤中自动下载.使用不同生成器/工具链构建的示例(build.py 只是一个设置 CMAKE_TOOLCHAIN_FILE 的 CMake 包装器-G/-B):

build.py --toolchain mingw --config Release # MinGW Makefilesbuild.py --toolchain vs-12-2013 --config 调试 # Visual Studio 12 2013build.py --toolchain xcode --config Release # Xcodebuild.py --toolchain libcxx --config Release # Makefile with -stdlib=libc++ toolchainbuild.py --toolchain ios-8-2 --config Release # Xcode with iOS SDK 8.2 toolchain

您可以完全控制选项构建类型工作数量 在构建第三方软件包时您希望拥有.例如,您可以这样为 zlib 构建四种类型,Debug、Release、MinSizeRel 和 RelWithDebInfo,并将 MinSizeRel 链接到当前项目:

>build.py --toolchain xcode --verbose --config MinSizeRel --fwd "HUNTER_CONFIGURATION_TYPES=Release;Debug;MinSizeRel;RelWithDebInfo"/.../clang/.../lib/libz-MinSizeRel.a ... -o/.../_builds/xcode/MinSizeRel/foo>ls -la/.../.hunter/_Base/d1232c0/326318e/37e4682/Install/lib/libz*99056/.../.hunter/_Base/d1232c0/326318e/37e4682/Install/lib/libz-MinSizeRel.a307872/.../.hunter/_Base/d1232c0/326318e/37e4682/Install/lib/libz-RelWithDebInfo.a109536/.../.hunter/_Base/d1232c0/326318e/37e4682/Install/lib/libz.a258904/.../.hunter/_Base/d1232c0/326318e/37e4682/Install/lib/libzd.a

I would like to build a third-party project that already has CMake as part of my project's CMake strips. ExternalProject_Add is for this purpose, but I have found it can only be made to work with a specific generator, and I wanted it to work on many platforms easily.

For example, here is my external project with an added script for zlib, which has its own CMakeLists.txt:

set(USE_PROJECT_CMAKE_MODULE_PATH "-DCMAKE_MODULE_PATH=${MAKE_MODULE_PATH}")
ExternalProject_Add(ZLIB
                    SOURCE_DIR ${CMAKE_SOURCE_DIR}/external/zlib
                    DOWNLOAD_COMMAND ""
                    UPDATE_COMMAND ""
                    CMAKE_ARGS
                       -DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>
                       -DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}
                       -DCMAKE_C_FLAGS=${CMAKE_C_FLAGS}
                       -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
                       ${USE_PROJECT_CMAKE_MODULE_PATH}
                    INSTALL_COMMAND "")

ExternalProject_Add_Step(ZLIB installInternally
                         COMMAND cd <BINARY_DIR> && make install
                         DEPENDEES install
                         ALWAYS 1)
ExternalProject_Get_Property(ZLIB install_dir)

if(UNIX)
    set(ZLIB_NAME libz)
else(UNIX)
    set(ZLIB_NAME zlib)
endif(UNIX)

add_library(zlib UNKNOWN IMPORTED)
set_property(TARGET zlib PROPERTY IMPORTED_LOCATION ${install_dir}/lib/${ZLIB_NAME}.a)
set(ZLIB_LIBRARIES zlib)
set(ZLIB_LIBRARIES_OPTIONAL ${ZLIB_LIBRARIES})
set(ZLIB_DIR ${install_dir} CACHE INTERNAL "zlib ROOT dir")
set(ZLIB_INCLUDE_DIRS ${install_dir}/include CACHE INTERNAL "zlib include dirs")
set(ZLIB_DEFINES "-msse2 -mfpmath=sse" CACHE INTERNAL "zlib defines")

The problem with this is that it works with make, but not with Xcode or Visual Studio. Perhaps there is some way to take the CMake build commands passed to my project and forward them to ExternalProject_Add.

How can I write ExternalProject_Add calls in a cross-platform way with minimal code complexity, or is there a better alternative?

解决方案

Problems

-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}

This is enough for single-configuration projects. But for Xcode and Visual Studio, you need to set CMAKE_CONFIGURATION_TYPES plus call build . --config at the build stage. See my answer.

COMMAND cd <BINARY_DIR> && make install

This will work only for Makefile generators of course. To be cross-platform you can use:

--build . --target install --config inside INSTALL_COMMAND of ExternalProject_Add.

Take a look at this template file, and in particular the following lines:

ExternalProject_Add(
    "${current_project}"
    URL
    @HUNTER_PACKAGE_URL@
    URL_HASH
    SHA1=@HUNTER_PACKAGE_SHA1@
    DOWNLOAD_DIR
    "@HUNTER_PACKAGE_DOWNLOAD_DIR@"
    SOURCE_DIR
    "@HUNTER_PACKAGE_SOURCE_DIR@"
    INSTALL_DIR
    "@HUNTER_PACKAGE_INSTALL_PREFIX@"
        # Not used, just avoid creating Install/<name> empty directory
    BUILD_COMMAND ""
        # This command is empty because all necessary targets will
        # be built on install stage
    CMAKE_ARGS
    "-G@CMAKE_GENERATOR@"
    "-C@HUNTER_CACHE_FILE@"
    "-C@HUNTER_ARGS_FILE@"
    "-D${postfix_name}=${${postfix_name}}"
    "-DCMAKE_BUILD_TYPE=${configuration}"
    "-DCMAKE_CONFIGURATION_TYPES=${configuration}"
    "-DCMAKE_INSTALL_PREFIX=@HUNTER_PACKAGE_INSTALL_PREFIX@"
    "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}"
    INSTALL_COMMAND
        "@CMAKE_COMMAND@"
        --build .
        --target install
        --config ${configuration}
        --
        ${jobs_option}
)

Alternative

or is there a better alternative?

Have you seen Hunter?

You can add zlib just like this:

hunter_add_package(ZLIB)
find_package(ZLIB CONFIG REQUIRED)
target_link_libraries(... ZLIB::zlib)

This code works everywhere. Third party dependencies will be downloaded automatically in the configuration step. Example of building with different generator/toolchains (build.py is just a CMake wrapper that sets CMAKE_TOOLCHAIN_FILE and -G/-B):

build.py --toolchain mingw --config Release # MinGW Makefiles
build.py --toolchain vs-12-2013 --config Debug # Visual Studio 12 2013
build.py --toolchain xcode --config Release # Xcode
build.py --toolchain libcxx --config Release # Makefile with -stdlib=libc++ toolchain
build.py --toolchain ios-8-2 --config Release # Xcode with iOS SDK 8.2 toolchain

You got full control what options, build types or number of jobs you want to have while building third-party packages. For instance, this is how you can build four types, Debug, Release, MinSizeRel, and RelWithDebInfo for zlib and link MinSizeRel to the current project:

> build.py --toolchain xcode --verbose --config MinSizeRel --fwd "HUNTER_CONFIGURATION_TYPES=Release;Debug;MinSizeRel;RelWithDebInfo"
/.../clang  /.../lib/libz-MinSizeRel.a ... -o /.../_builds/xcode/MinSizeRel/foo

> ls -la /.../.hunter/_Base/d1232c0/326318e/37e4682/Install/lib/libz*
   99056 /.../.hunter/_Base/d1232c0/326318e/37e4682/Install/lib/libz-MinSizeRel.a
  307872 /.../.hunter/_Base/d1232c0/326318e/37e4682/Install/lib/libz-RelWithDebInfo.a
  109536 /.../.hunter/_Base/d1232c0/326318e/37e4682/Install/lib/libz.a
  258904 /.../.hunter/_Base/d1232c0/326318e/37e4682/Install/lib/libzd.a

这篇关于如何以跨平台的方式使用 CMake ExternalProject_Add 或替代品?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆