ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

CMake基础教程二

CMake基础教程二
常用
环境变量 SET(ENV{VAR} VALUE) **常用变量:** | 变量名 | 含义 | | ----------------------------- | --------------------------------------------------------------------- | | **PROJECT_NAME** | `project`命令中写的项目名 | | **CMAKE_VERSION** | 当前使用 CMake 的版本 | | **CMAKE_SOURCE_DIR** | 工程顶层目录,即入口 CMakeLists 文件所在路径 | | **PROJECT_SOURCE_DIR** | 同**CMAKE_SOURCE_DIR** | | **CMAKE_BINARY_DIR** | 工程编译发生的目录,即执行 cmake 命令进行项目配置的目录,一般为 build | | **PROJECT_BINARY_DIR** | 同**CMAKE_BINARY_DIR** | | **CMAKE_CURRENT_SOURCE_DIR** | 当前处理的 CMakeLists.txt 所在的路径 | | **CMAKE_CURRRENT_BINARY_DIR** | 当前处理的 CMakeLists.txt 中生成目标文件所在编译目录 | | **CMAKE_CURRENT_LIST_FILE** | 输出调用这个变量的 CMakeLists.txt 文件的完整路径 | | **CMAKE_CURRENT_LIST_DIR** | 当前处理的 CMakeLists.txt 文件所在目录的路径 | | **CMAKE_INSTALL_PREFIX** | 指定`make install`命令执行时包安装路径 | | **CMAKE_MODULE_PATH** | `find_package`命令搜索包路径**之一**,默认为空 | **编译配置相关变量:** | 变量名 | 含义 | | ---------------------- | --------------------------------------------------------------------------------- | | **CMAKE_BUILD_TYPE** | 编译选项,Release 或者 Debug,如`set(CMAKE_BUILD_TYPE "Release")` | | **CMAKE_CXX_FLAGS** | 编译标志,设置 C++11 编译,`set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")` | | **CMAKE_CXX_STANDARD** | 也可以设置 C++11 编译,`set(CMAKE_CXX_STANDARD 11)` | list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") # 依赖库fetch include(FetchContent) FetchContent_Declare( googletest GIT_REPOSITORY https://github.com/google/googletest.git GIT_TAG release-1.8.0 ) FetchContent_GetProperties(googletest) if(NOT googletest_POPULATED) FetchContent_Populate(googletest) # ... # adds the targets: gtest, gtest_main, gmock, gmock_main add_subdirectory( ${googletest_SOURCE_DIR} ${googletest_BINARY_DIR} ) # ... endif() # 检测系统 if(CMAKE_SYSTEM_NAME STREQUAL "Linux") message(STATUS "Configuring on/for Linux") elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") message(STATUS "Configuring on/for macOS") elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows") message(STATUS "Configuring on/for Windows") elseif(CMAKE_SYSTEM_NAME STREQUAL "AIX") message(STATUS "Configuring on/for IBM AIX") else() message(STATUS "Configuring on/for ${CMAKE_SYSTEM_NAME}") endif() #ifdef IS_32_BIT_ARCH return arch_info + std::string("Compiled on a 32 bit host processor."); #elif IS_64_BIT_ARCH return arch_info + std::string("Compiled on a 64 bit host processor."); #else return arch_info + std::string("Neither 32 nor 64 bit, puzzling ..."); #endif if(CMAKE_SIZEOF_VOID_P EQUAL 8) target_compile_definitions(arch-dependent PUBLIC "IS_64_BIT_ARCH") message(STATUS "Target is 64 bits") else() target_compile_definitions(arch-dependent PUBLIC "IS_32_BIT_ARCH") message(STATUS "Target is 32 bits") endif() if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "i386") message(STATUS "i386 architecture detected") elseif(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "i686") message(STATUS "i686 architecture detected") elseif(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "x86_64") message(STATUS "x86_64 architecture detected") else() message(STATUS "host processor architecture is unknown") endif() target_compile_definitions(arch-dependent PUBLIC "ARCHITECTURE=${CMAKE_HOST_SYSTEM_PROCESSOR}" ) #外部检测 execute_process( COMMAND ${PYTHON_EXECUTABLE} "-c" "print('Hello, world!')" RESULT_VARIABLE _status OUTPUT_VARIABLE _hello_world ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE ) message(STATUS "RESULT_VARIABLE is: ${_status}") message(STATUS "OUTPUT_VARIABLE is: ${_hello_world}") cmake -D PYTHON_EXECUTABLE=/custom/location/python .. cmake -D BOOST_INCLUDEDIR=/custom/boost/include -DBOOST_LIBRARYDIR=/custom/boost/lib #配置生成源码 #include <stdio.h> #include <unistd.h> void print_info(void) { printf("\n"); printf("Configuration and build information\n"); printf("-----------------------------------\n"); printf("\n"); printf("Who compiled | %s\n", "@_user_name@"); printf("Compilation hostname | %s\n", "@_host_name@"); printf("Fully qualified domain name | %s\n", "@_fqdn@"); printf("Operating system | %s\n", "@_os_name@, @_os_release@, @_os_version@"); printf("Platform | %s\n", "@_os_platform@"); printf("Processor info | %s\n", "@_processor_name@, @_processor_description@"); printf("CMake version | %s\n", "@CMAKE_VERSION@"); printf("CMake generator | %s\n", "@CMAKE_GENERATOR@"); printf("Configuration time | %s\n", "@_configuration_time@"); printf("Fortran compiler | %s\n", "@CMAKE_Fortran_COMPILER@"); printf("C compiler | %s\n", "@CMAKE_C_COMPILER@"); printf("\n"); fflush(stdout); } configure_file(print_info.c.in print_info.c @ONLY) target_sources(example PRIVATE example.f90 ${CMAKE_CURRENT_BINARY_DIR}/print_info.c ) # 生成SDK include(GNUInstallDirs) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}) # Offer the user the choice of overriding the installation directories set(INSTALL_LIBDIR ${CMAKE_INSTALL_LIBDIR} CACHE PATH "Installation directory for libraries") set(INSTALL_BINDIR ${CMAKE_INSTALL_BINDIR} CACHE PATH "Installation directory for executables") set(INSTALL_INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR} CACHE PATH "Installation directory for header files") if(WIN32 AND NOT CYGWIN) set(DEF_INSTALL_CMAKEDIR CMake) else() set(DEF_INSTALL_CMAKEDIR share/cmake/${PROJECT_NAME}) endif() set(INSTALL_CMAKEDIR ${DEF_INSTALL_CMAKEDIR} CACHE PATH "Installation directory for CMake files") # Report to user foreach(p LIB BIN INCLUDE CMAKE) file(TO_NATIVE_PATH ${CMAKE_INSTALL_PREFIX}/${INSTALL_${p}DIR} _path ) message(STATUS "Installing ${p} components to ${_path}") unset(_path) endforeach() # rpath file(RELATIVE_PATH _rel ${CMAKE_INSTALL_PREFIX}/${INSTALL_BINDIR} ${CMAKE_INSTALL_PREFIX}) if(APPLE) set(_rpath "@loader_path/${_rel}") else() set(_rpath "\$ORIGIN/${_rel}") endif() file(TO_NATIVE_PATH "${_rpath}/${INSTALL_LIBDIR}" message_RPATH) set_target_properties(hello-world_wDSO PROPERTIES MACOSX_RPATH ON SKIP_BUILD_RPATH OFF BUILD_WITH_INSTALL_RPATH OFF INSTALL_RPATH "${message_RPATH}" INSTALL_RPATH_USE_LINK_PATH ON ) install( TARGETS message-shared hello-world_wDSO ARCHIVE DESTINATION ${INSTALL_LIBDIR} COMPONENT lib RUNTIME DESTINATION ${INSTALL_BINDIR} COMPONENT bin LIBRARY DESTINATION ${INSTALL_LIBDIR} COMPONENT lib PUBLIC_HEADER DESTINATION ${INSTALL_INCLUDEDIR}/message COMPONENT dev ) if(WIN32 OR MINGW) list(APPEND CPACK_GENERATOR "NSIS") set(CPACK_NSIS_PACKAGE_NAME "message") set(CPACK_NSIS_CONTACT "robertdr") set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON) endif() message(STATUS "CPack generators: ${CPACK_GENERATOR}") include(CPack) set(CPACK_SOURCE_GENERATOR "TGZ;ZIP") set(CPACK_SOURCE_IGNORE_FILES /.git /dist /.*build.* /\\\\.DS_Store ) set(CMAKE_EXPORT_PACKAGE_REGISTRY ON) export(PACKAGE MyLib) #交叉编译 set(CMAKE_SYSTEM_NAME Windows) set(CMAKE_SYSTEM_PROCESSOR arm) set(CMAKE_C_COMPILER i686-w64-mingw32-gcc) set(CMAKE_CXX_COMPILER i686-w64-mingw32-g++) set(CMAKE_C_COMPILER clang) set(CMAKE_CXX_COMPILER clang++) set(CMAKE_Fortran_COMPILER i686-w64-mingw32-gfortran) #submodule find_package(Git QUIET) if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git") # Update submodules as needed option(GIT_SUBMODULE "Check submodules during build" ON) if(GIT_SUBMODULE) message(STATUS "Submodule update") execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} RESULT_VARIABLE GIT_SUBMOD_RESULT) if(NOT GIT_SUBMOD_RESULT EQUAL "0") message(FATAL_ERROR "git submodule update --init --recursive failed with ${GIT_SUBMOD_RESULT}, please checkout submodules") endif() endif() endif() if(NOT EXISTS "${PROJECT_SOURCE_DIR}/extern/repo/CMakeLists.txt") message(FATAL_ERROR "The submodules were not downloaded! GIT_SUBMODULE was turned off or failed. Please update submodules and try again.") endif()
参考

https://github.com/wx-chevalier/CMake-Notes

CMake基础教程_cmake -b build-CSDN博客


创作不易,小小的支持一下吧!

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进