Cmake-5

Step5:系统检测机制

如果系统有log和exp,我们在mysqrt方法中使用它们。在MathFunctions/CMakeLists.txt中,首先检测它们是否存在,使用的语法是CheckSymbolExits。如果log和exp没有被发现,需要m库。

include(CheckSymbolExists)
check_symbol_exists(log "math.h" HAVE_LOG)
check_symbol_exists(exp "math.h" HAVE_EXP)
if(NOT (HAVE_LOG AND HAVE_EXP))
  unset(HAVE_LOG CACHE)
  unset(HAVE_EXP CACHE)
  set(CMAKE_REQUIRED_LIBRARIES "m")
  check_symbol_exists(log "math.h" HAVE_LOG)
  check_symbol_exists(exp "math.h" HAVE_EXP)
  if(HAVE_LOG AND HAVE_EXP)
    target_link_libraries(MathFunctions PRIVATE m)
  endif()
endif()

如果存在,使用 target_compile_definitions() 来指定 HAVE_LOG and HAVE_EXP as PRIVATE 的编译定义.

if(HAVE_LOG AND HAVE_EXP)
  target_compile_definitions(MathFunctions
                             PRIVATE "HAVE_LOG" "HAVE_EXP")
endif()

命令解释:

target_compile_definitions(<target>
  <INTERFACE|PUBLIC|PRIVATE> [items1...]
  [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])

The INTERFACEPUBLIC and PRIVATE 的关键字指定了下面参数的作用域。PRIVATE and PUBLIC items will populate the COMPILE_DEFINITIONS property of <target>PUBLIC and INTERFACE items will populate the INTERFACE_COMPILE_DEFINITIONS property of <target>. The following arguments specify compile definitions. Repeated calls for the same <target> append items in the order called.

COMPLIE_DEFINITIONS:编译定义

 

在mysqrt方法中,可以使用:

#if defined(HAVE_LOG) && defined(HAVE_EXP)
  double result = exp(log(x) * 0.5);
  std::cout << "Computing sqrt of " << x << " to be " << result
            << " using log and exp" << std::endl;
#else
  double result = x;

修改mysqrt.cxx 来包含 cmath.

#include <cmath>

Step 6:增加一个客制化的命令和产生的文件

在MathFunctions的目录中,一个新的源文件MakeTable.cxx,被用来产生已经计算出来的值。接下来在Math/CMakeLists.txt中,增加恰当的命令来编译可执行的MakeTable和运行它。

MathFunctions/CMakeLists.txt的头部增加:

add_executable(MakeTable MakeTable.cxx)

然后,我们增加一个客制化的命令,运行MakeTable,来产生Table.h.

Then we add a custom command that specifies how to produce Table.h by running MakeTable.

add_custom_command(
  OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
  COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
  DEPENDS MakeTable
  )

接下来,必须让CMake直到mysqrt.cxxx依赖于这个Table.h.This is done by adding the generated Table.h to the list of sources for the library MathFunctions.

add_library(MathFunctions
            mysqrt.cxx
            ${CMAKE_CURRENT_BINARY_DIR}/Table.h
            )

我们也必须增加Table.h到目前的二进制目录中,以便于它可以被找到。

target_include_directories(MathFunctions
          INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
          PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
          )

修改mysqrt.cxx来包含Table.h,接下来就可以重写mysqrt方法来使用这个表。

step 7: 编译和安装

如果我们想发布我们程序给其他人使用。使用CPacke来创建平台指定的安装器,来编译不同平台的二进制安装包等。需要在上一级的CMakeLists.txt中增加:

include(InstallRequiredSystemLibraries)
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}")
set(CPACK_PACKAGE_VERSION_MINOR "${Tutorial_VERSION_MINOR}")
include(CPack)

这个module将会包含当前平台项目所需要的任何运行时库。

cpack -G ZIP -C Debug
cpack --config CPackSourceConfig.cmake

step 8:Adding Support for a Dashboard

为了支持输出dashboards,在顶级的CMakeLists.txt中,做修改如下:

 

Replace:

# enable testing
enable_testing()

With:

# enable dashboard scripting
include(CTest)

在顶级目录,我们需要创建一个CTestConfig.cmake的文件,可以指定项目的名称和要提供的dashboard。

set(CTEST_PROJECT_NAME "CMakeTutorial")
set(CTEST_NIGHTLY_START_TIME "00:00:00 EST")

set(CTEST_DROP_METHOD "http")
set(CTEST_DROP_SITE "my.cdash.org")
set(CTEST_DROP_LOCATION "/submit.php?project=CMakeTutorial")
set(CTEST_DROP_SITE_CDASH TRUE)
ctest [-VV] -C Debug -D Experimental

Step 9:混合静态和共享

使用option来定义一个开关,增加一个BUILD_SHARED_LIBS到顶级CMakeLists.txt中。

cmake_minimum_required(VERSION 3.10)

# set the project name and version
project(Tutorial VERSION 1.0)

# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

# control where the static and shared libraries are built so that on windows
# we don't need to tinker with the path to run the executable
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")

option(BUILD_SHARED_LIBS "Build using shared libraries" ON)

# configure a header file to pass the version number only
configure_file(TutorialConfig.h.in TutorialConfig.h)

# add the MathFunctions library
add_subdirectory(MathFunctions)

# add the executable
add_executable(Tutorial tutorial.cxx)
target_link_libraries(Tutorial PUBLIC MathFunctions)

在MathFunctions/CMakeLists.txt中,我们需要根据USE_MyMATH是否打开,来创建一个SqrtLibrary。

# add the library that runs
add_library(MathFunctions MathFunctions.cxx)

# state that anybody linking to us needs to include the current source dir
# to find MathFunctions.h, while we don't.
target_include_directories(MathFunctions
                           INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
                           )

# should we use our own math functions
option(USE_MYMATH "Use tutorial provided math implementation" ON)
if(USE_MYMATH)

  target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH")

  # first we add the executable that generates the table
  add_executable(MakeTable MakeTable.cxx)

  # add the command to generate the source code
  add_custom_command(
    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
    COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
    DEPENDS MakeTable
    )

  # library that just does sqrt
  add_library(SqrtLibrary STATIC
              mysqrt.cxx
              ${CMAKE_CURRENT_BINARY_DIR}/Table.h
              )

  # state that we depend on our binary dir to find Table.h
  target_include_directories(SqrtLibrary PRIVATE
                             ${CMAKE_CURRENT_BINARY_DIR}
                             )

  target_link_libraries(MathFunctions PRIVATE SqrtLibrary)
endif()

# define the symbol stating we are using the declspec(dllexport) when
# building on windows
target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH")

# install rules
set(installable_libs MathFunctions)
if(TARGET SqrtLibrary)
  list(APPEND installable_libs SqrtLibrary)
endif()
install(TARGETS ${installable_libs} DESTINATION lib)
install(FILES MathFunctions.h DESTINATION include)

最后更新 MathFunctions/MathFunctions.h to use dll export defines:

#if defined(_WIN32)
#  if defined(EXPORTING_MYMATH)
#    define DECLSPEC __declspec(dllexport)
#  else
#    define DECLSPEC __declspec(dllimport)
#  endif
#else // non windows
#  define DECLSPEC
#endif

namespace mathfunctions {
double DECLSPEC sqrt(double x);
}
 # state that SqrtLibrary need PIC when the default is shared libraries
  set_target_properties(SqrtLibrary PROPERTIES
                        POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS}
                        )

  target_link_libraries(MathFunctions PRIVATE SqrtLibrary)

Step 10:增加Generator 表达式

Generator expressions

在生成生成系统期间进行评估,以生成特定于每个生成配置的信息;

允许在许多目标属性的上下文中使用,例如链接\库、包含\目录、编译\定义等。在使用命令填充这些属性时,也可以使用它们,例如target\u link\u libraries()、target\u include\u directories()、target\u compile\u definitions()和其他命令。

可用于启用条件链接、编译时使用的条件定义、条件包含目录等。条件可能基于构建配置、目标属性、平台信息或任何其他可查询信息

包括逻辑,信息和输出表达式。

 A $<0:...> results in the empty string, and <1:...> results in the content of "...". They can also be nested.

下面的代码:

# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

可以被替换为:

add_library(tutorial_compiler_flags INTERFACE)
target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11)
set(gcc_like_cxx "$<COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU>")
set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>")
target_compile_options(tutorial_compiler_flags INTERFACE
  "$<${gcc_like_cxx}:$<BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused>>"
  "$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>"
)

Step 11. 增加导出配置

第一步,更新我们的install(TARGETS)命令不仅仅指定一个DESTINATION,而且指定EXPORT。这EXPORT关键字产生和安装一个CMake 文件包含代码来的导入被列在和安装安装命令在安装树。在MathFunctions/CMakeLists.txt,我们可以明确使用EXPORT,来导出MathFunctions库,通过更新安装命令。

set(installable_libs MathFunctions tutorial_compiler_flags)
if(TARGET SqrtLibrary)
  list(APPEND installable_libs SqrtLibrary)
endif()
install(TARGETS ${installable_libs}
        DESTINATION lib
        EXPORT MathFunctionsTargets)
install(FILES MathFunctions.h DESTINATION include)

现在我们已经导出了MathFunctions,我们也需要明确安装产生的MathFunctionsTargets.cmake文件。通过增加下面到顶层的CMakeLists.txt:

install(EXPORT MathFunctionsTargets
  FILE MathFunctionsTargets.cmake
  DESTINATION lib/cmake/MathFunctions
)

它将导出一个路径和当前的机器绑定。这个解决方法是更新  MathFunctions target_include_directories() 来理解,它需要不同的INTERFACE位置,当在编译目录和来自一个install/packate。 This means converting the target_include_directories() call for MathFunctions to look like:

target_include_directories(MathFunctions
                           INTERFACE
                            $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
                            $<INSTALL_INTERFACE:include>
                           )

 

这时,CMake已经恰当的打包了目标信息,但是我们仍然需要产生一个MathFunctionsConfig.cmake,以至于CMake可以通过find_package命令来找到我们的项目。增加一个新文件Config.cmake.in,内容如下:

@PACKAGE_INIT@

include ( "${CMAKE_CURRENT_LIST_DIR}/MathFunctionsTargets.cmake" )

为了恰当的配置和安装这个文件,增加下面的内容到顶层的CMakeLists.txt:

install(EXPORT MathFunctionsTargets
  FILE MathFunctionsTargets.cmake
  DESTINATION lib/cmake/MathFunctions
)

include(CMakePackageConfigHelpers)
# generate the config file that is includes the exports
configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in
  "${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfig.cmake"
  INSTALL_DESTINATION "lib/cmake/example"
  NO_SET_AND_CHECK_MACRO
  NO_CHECK_REQUIRED_COMPONENTS_MACRO
  )
# generate the version file for the config file
write_basic_package_version_file(
  "${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfigVersion.cmake"
  VERSION "${Tutorial_VERSION_MAJOR}.${Tutorial_VERSION_MINOR}"
  COMPATIBILITY AnyNewerVersion
)

# install the configuration file
install(FILES
  ${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfig.cmake
  DESTINATION lib/cmake/MathFunctions
  )

此时,我们已经产生了一个可以用于已经安装或者打包的项目的relocatable的CMake配置文件。如果我们想我们的项目,从编译的目录可以被使用。我们在顶层的CMakeLists.txt的底部增加:

export(EXPORT MathFunctionsTargets
  FILE "${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsTargets.cmake"
)

Step 12:Debug和release

Set CMAKE_DEBUG_POSTFIX near the beginning of the top-level CMakeLists.txt file:

set(CMAKE_DEBUG_POSTFIX d)

add_library(tutorial_compiler_flags INTERFACE)

And the DEBUG_POSTFIX property on the tutorial executable:

add_executable(Tutorial tutorial.cxx)
set_target_properties(Tutorial PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})

target_link_libraries(Tutorial PUBLIC MathFunctions)

Let's also add version numbering to the MathFunctions library. In MathFunctions/CMakeLists.txt, set the VERSION and SOVERSION properties:

set_property(TARGET MathFunctions PROPERTY VERSION "1.0.0")
set_property(TARGET MathFunctions PROPERTY SOVERSION "1")

From the Step12 directory, create debug and release subbdirectories. The layout will look like:

- Step12
   - debug
   - release

Now we need to setup debug and release builds. We can use CMAKE_BUILD_TYPE to set the configuration type:

cd debug
cmake -DCMAKE_BUILD_TYPE=Debug ..
cmake --build .
cd ../release
cmake -DCMAKE_BUILD_TYPE=Release ..
cmake --build .

Now that both the debug and release builds are complete, we can use a custom configuration file to package both builds into a single release. In the Step12 directory, create a file called MultiCPackConfig.cmake. In this file, first include the default configuration file that was created by the cmake executable.

Next, use the CPACK_INSTALL_CMAKE_PROJECTS variable to specify which projects to install. In this case, we want to install both debug and release.

include("release/CPackConfig.cmake")

set(CPACK_INSTALL_CMAKE_PROJECTS
    "debug;Tutorial;ALL;/"
    "release;Tutorial;ALL;/"
    )

From the Step12 directory, run cpack specifying our custom configuration file with the config option:

cpack --config MultiCPackConfig.cmake

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值