如何以跨平台的方式使用CMake ExternalProject_Add或替代方案?

时间:2013-05-30 17:16:19

标签: cmake cross-platform external-project

我想建立一个已经将CMake作为我项目的CMake条带的一部分的第三方项目。 ExternalProject_Add就是出于此目的,但我发现它只能用于特定的生成器,我想在很多平台上轻松工作。

例如,这里是zlib的外部项目添加脚本,它有自己的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")

这个问题是它适用于make,但不适用于Xcode或Visual Studio。也许有一些方法可以将传递给我的项目的cmake构建命令转发给ExternalProject_Add。

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

2 个答案:

答案 0 :(得分:25)

问题

-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}

这对于单配置项目来说已经足够了。但是对于Xcode和Visual Studio,您需要在构建阶段设置CMAKE_CONFIGURATION_TYPES加上调用build . --config。请参阅my answer

COMMAND cd <BINARY_DIR> && make install

这当然只适用于Makefile生成器。要成为跨平台的,您可以在--build . --target install --config的{​​{1}}内使用INSTALL_COMMAND

查看this模板文件,特别是following lines

ExternalProject_Add

替代

  

还是有更好的选择吗?

你见过Hunter吗?

您可以像this一样添加zlib:

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

此代码无处不在。将在配置步骤中自动下载第三方。使用不同的生成器/工具链构建示例(build.py只是设置hunter_add_package(ZLIB) find_package(ZLIB CONFIG REQUIRED) target_link_libraries(... ZLIB::zlib) CMAKE_TOOLCHAIN_FILE / -G的CMake包装器:

-B

您可以完全控制构建第三方软件包时想要拥有的optionsbuild typesnumber of jobs。例如,这就是如何为zlib构建4种类型的Debug,Release,MinSizeRel,RelWithDebInfo并将MinSizeRel链接到当前项目:

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

答案 1 :(得分:0)

默认情况下,CMake ExternalProject_Add调用跨平台工作,如果使用仅在操作系统子集上可用的特定命令,则无法执行此操作。通常,CMAKE_ARGS用于将信息传递到外部项目构建中的每个superbuild单元。控制整个构建的每个微型部分的CMakeLists.txt文件使用CMake的声明性语法(例如,“add_library(library_name SHARED filename1.hpp filename1.cpp)。”CMake将这种语法转换为特定于特定构建系统的命令你想使用(例如,制作,忍者)。

以上示例re:zlib无法跨平台,因为ExternalProject_Add_Step包含“COMMAND cd&amp;&amp; make install”,这必然仅适用于调用“cd”实际上是更改的正确方法的情况目录,以及调用“make”实际上是构建软件的正确方法。 CMake的-E选项提供了一种方法来调用基本操作,如更改/复制/制作/删除目录而不做出这样的假设。

(顺便说一下,如果你使用的是Visual Studio或XCode等IDE,你可能想在使用CMake时调用一个或多个IDE生成器。例如,设置

-G "Eclipse CDT4 - Unix Makefiles" -DCMAKE_ECLIPSE_GENERATE_SOURCE_PROJECT=TRUE

将导致在每个构建区域中生成Eclipse项目,并且还在所有构建共享的源代码区域中生成Eclipse项目。当然,如果您使用的是XCode或Visual Studio,则必须用适当的标志替换这些IDE。或者,您可以考虑在所有平台上使用Eclipse和Ninja,但在撰写本文时,我并不完全确定Ninja已准备好在非Linux,非Windows操作系统上进行黄金时段。)