[筆記]Modern CMake 3:基本介紹


Modern CMake 3:基本介紹

組織項目結構

CMake沒有統一的項目結構,一些常用原則可以幫助我們組織更好的項目結構:

  • 項目內部能夠十分方便的讀取其他工程;
  • 避免項目結構衝突;
  • 並行構建.

一個典型的例子(僅做參考),假設你的項目叫做project,你的庫名爲lib,可執行程序名爲app

- project
  - .gitignore
  - README.md
  - LICENCE.md
  - CMakeLists.txt
  - cmake
    - FindSomeLib.cmake
  - include
    - project
      - lib.hpp
  - src
    - CMakeLists.txt
    - project
      - CMakeLists.txt
      - lib.cpp
  - apps
    - CMakeLists.txt
    - app.cpp
  - tests
    - testlib.cpp
  - docs
    - Doxyfile.in
  - extern
    - googletest
  - scripts
    - helper.py
  1. 源文件中都應包含CMakeLists.txt文件。可以使用add_subdirectory添加包含CMakeLists.txt文件的子目錄到工程。
  2. 大多時候,我們需要cmake文件夾,所有Find*.cmake文件都應在此文件夾中找到。把cmake文件夾添加到CMake path的方法:
set(CMAKE_MOUDLE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKEMOUDLE_PATH})

如果你想使Build目錄在source目錄之外,添加以下代碼在你的CMakeLists.txt文件的頂部:

### Require out-of-source builds
file(TO_CMAKE_PATH "$PROJECT_BINARY_DIR/CMakeLists.txt" LOC_PATH)
if(EXISTS ${LOC_PATH})
	message(FATAL_ERROR "You cannot build in a source directory (or any directory with a CMakeLists.txt file). Please make a build subdirectory. Feel free to remove CMakeCache.txt and CMakeFiles.")
endif()

運行其他程序

在configure階段運行命令

CMake在configure階段運行命令相當的容易。使用execute_process運行進程並能得到結果。還可以使用${CMAKE_COMMAND},find_packaage(Git,或者find_program運行命令。使用RESULT_VARIABLE檢測返回值,OUTPUT_VARIABLE可以得到輸出結果。

舉一個更新git子模塊的例子:

find_package(Git QUIET)

if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git")
	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 failed with ${GIT_SUBMODE_RESULT}, please checkout submoudles")
	endif()
endif()

在build階段運行命令

在build階段運行命令需要一些技巧。我們需要考慮什麼時候需要運行命令?以及命令的輸出是否爲另外target的輸入?以下是一個調研Python腳本生成頭文件的例子:

find_package(PythonInterp REQUIRED)
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/include/Generated.hpp"
	COMMAND "${PYTHON_EXECUTABLE" "${CMAKE_CURRENT_SOURCE_DIR}/scripts/GenerateHeader.py" --argument
	DEPENDS some_target)

add_custom_target(generate_header ALL
	DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/include/Generated.hpp")

install(FILES ${CMAKE_CURRENT_BINARY_DIR}/include/GENERATED.hpp DESTINATION include)

一個完整的例子

# 所有的CMake files都是由此開始的。在新版本CMake中,給定最低版本號建議使用rang方式。
cmake_minimun_required(VERSION 3.1...3.14)

# 項目聲明。你應該表明項目使用的語言和版本,這都是非常有價值的信息
project(ModernCMakeExample VERSION 1.0 LANGUAGES CXX)

# 設置變量(尤其是c++語言,本例沒有變量聲明)

# Find packages 

add_library(MyLibExample simple_lib.cpp simple_lib.h)

# 應用程序,輸出名稱和target保持一致
add_executable(MyExample simple_example.cpp)

# 鏈接target
target_link_library(MyExample PRIVATE MyLibExample)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章