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(MathFunctionsPRIVATE "HAVE_LOG" "HAVE_EXP") endif()命令解釋:
target_compile_definitions(<target><INTERFACE|PUBLIC|PRIVATE> [items1...][<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])The?INTERFACE,?PUBLIC?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; #elsedouble 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.hCOMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.hDEPENDS 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(MathFunctionsmysqrt.cxx${CMAKE_CURRENT_BINARY_DIR}/Table.h)我們也必須增加Table.h到目前的二進制目錄中,以便于它可以被找到。
target_include_directories(MathFunctionsINTERFACE ${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.cmakestep 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 ExperimentalStep 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(MathFunctionsINTERFACE ${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 tableadd_executable(MakeTable MakeTable.cxx)# add the command to generate the source codeadd_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.hCOMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.hDEPENDS MakeTable)# library that just does sqrtadd_library(SqrtLibrary STATICmysqrt.cxx${CMAKE_CURRENT_BINARY_DIR}/Table.h)# state that we depend on our binary dir to find Table.htarget_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 #endifnamespace mathfunctions { double DECLSPEC sqrt(double x); } # state that SqrtLibrary need PIC when the default is shared librariesset_target_properties(SqrtLibrary PROPERTIESPOSITION_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 libEXPORT MathFunctionsTargets) install(FILES MathFunctions.h DESTINATION include)現在我們已經導出了MathFunctions,我們也需要明確安裝產生的MathFunctionsTargets.cmake文件。通過增加下面到頂層的CMakeLists.txt:
install(EXPORT MathFunctionsTargetsFILE MathFunctionsTargets.cmakeDESTINATION 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(MathFunctionsINTERFACE$<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 MathFunctionsTargetsFILE MathFunctionsTargets.cmakeDESTINATION 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_MACRONO_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.cmakeDESTINATION lib/cmake/MathFunctions)此時,我們已經產生了一個可以用于已經安裝或者打包的項目的relocatable的CMake配置文件。如果我們想我們的項目,從編譯的目錄可以被使用。我們在頂層的CMakeLists.txt的底部增加:
export(EXPORT MathFunctionsTargetsFILE "${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- releaseNow 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?
總結
- 上一篇: Cmake-4
- 下一篇: android-NDK-Opengl