# set the project name and version # 设置项目名称和版本 project(Tutorial VERSION 1.0)
# specify the C++ standard # 指定C ++标准 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 # 控制静态和共享库的构建位置,以便在Windows上我们无需修改运行可执行文件的路径 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 # 添加MathFunctions库 add_subdirectory(MathFunctions)
# add the executable # 添加一个可执行文件 add_executable(Tutorial tutorial.cxx) target_link_libraries(Tutorial PUBLIC MathFunctions)
# add the binary tree to the search path for include files # so that we will find TutorialConfig.h # 将二进制目录添加到包含文件的搜索路径中,以便我们找到TutorialConfig.h target_include_directories(Tutorial PUBLIC "${PROJECT_BINARY_DIR}" )
# 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. # 说明与我们链接的任何人都需要包括当前源目录才能找到MathFunctions.h,而我们不需要。 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 # 只包含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 # 声明我们依靠二进制目录找到Table.h target_include_directories(SqrtLibrary PRIVATE ${CMAKE_CURRENT_BINARY_DIR} )
# define the symbol stating we are using the declspec(dllexport) when # building on windows # 定义标记在Windows上构建时使用declspec(dllexport) target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH")
// a hack square root calculation using simple operations doublemysqrt(double x){ if (x <= 0) { return0; }
double result = x; if (x >= 1 && x < 10) { std::cout << "Use the table to help find an initial value " << std::endl; result = sqrtTable[static_cast<int>(x)]; }
// do ten iterations for (int i = 0; i < 10; ++i) { if (result <= 0) { result = 0.1; } double delta = x - (result * result); result = result + 0.5 * delta / result; std::cout << "Computing sqrt of " << x << " to be " << result << std::endl; }
# state that SqrtLibrary need PIC when the default is shared libraries # 声明默认为共享库时,SqrtLibrary需要PIC set_target_properties(SqrtLibrary PROPERTIES POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS} ) target_link_libraries(MathFunctions PRIVATE SqrtLibrary)
使用 cmake-gui 构建项目,勾选 BUILD_SHARED_LIBS
在项目根目录运行命令生成可执行文件:
1
cmake --build cmake-build-debug
在项目根目录运行生成的可执行文件:
1
./cmake-build-debug/Tutorial 2
终端输出:
1 2 3 4 5 6 7 8 9 10 11 12
Use the table to help find an initial value Computing sqrt of 2 to be 1.41421 Computing sqrt of 2 to be 1.41421 Computing sqrt of 2 to be 1.41421 Computing sqrt of 2 to be 1.41421 Computing sqrt of 2 to be 1.41421 Computing sqrt of 2 to be 1.41421 Computing sqrt of 2 to be 1.41421 Computing sqrt of 2 to be 1.41421 Computing sqrt of 2 to be 1.41421 Computing sqrt of 2 to be 1.41421 The square root of 2 is 1.41421
使用 cmake-gui 重新构建项目,取消勾选 BUILD_SHARED_LIBS
在项目根目录运行命令生成可执行文件:
1
cmake --build cmake-build-debug
在项目根目录运行生成的可执行文件:
1
./cmake-build-debug/Tutorial 2
终端输出:
1 2 3 4 5 6 7 8 9 10 11 12
Use the table to help find an initial value Computing sqrt of 2 to be 1.41421 Computing sqrt of 2 to be 1.41421 Computing sqrt of 2 to be 1.41421 Computing sqrt of 2 to be 1.41421 Computing sqrt of 2 to be 1.41421 Computing sqrt of 2 to be 1.41421 Computing sqrt of 2 to be 1.41421 Computing sqrt of 2 to be 1.41421 Computing sqrt of 2 to be 1.41421 Computing sqrt of 2 to be 1.41421 The square root of 2 is 1.41421
接下来,我们为项目添加所需的编译器警告标志。由于警告标志根据编译器的不同而不同,因此我们使用 COMPILE_LANG_AND_ID 生成器表达式来控制在给定一种语言和一组编译器 ID 的情况下应应用的标志,如下所示:
1 2 3 4 5 6 7 8 9
# add compiler warning flags just when building this project via # the BUILD_INTERFACE genex # 仅当通过BUILD_INTERFACE生成此项目时添加编译器警告标志 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>>" )
# state that anybody linking to us needs to include the current source dir # to find MathFunctions.h, while we don't. # 说明与我们链接的任何人都需要包括当前源目录才能找到MathFunctions.h,而我们不需要。 target_include_directories(MathFunctions INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> $<INSTALL_INTERFACE:include> )
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 )
# generate the export targets for the build tree # needs to be after the install(TARGETS ) command # 在install(TARGETS)命令之后生成生成树的导出目标 export(EXPORT MathFunctionsTargets FILE"${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsTargets.cmake" )