本文是CMake Tutorial的心得, CMake是一個用於build, test與package的cross-platform tool, 基本上是透過撰寫CMakeLists來描述如何build, test與package專案,接著會產生makefile, 再透過makefile產生最終的target(executable, library, or both)
讓我們從最簡單的CMakeLists.txt開始,基本上CMakeLists.txt的指令是不分大小寫的
# Require a minimum version of cmake. # cmake_minimum_required(VERSION <min>>[...<policy_max>] [FATAL_ERROR]) cmake_minimum_required(VERSION 3.10) # Set the name of the project. # project(<PROJECT-NAME< [<anguage-name>...]) # project(<PROJECT-NAME> # [VERSION <major>[.<minor>[.<patch>[.<tweak>]]]] # [DESCRIPTION <project-description-string>] # [HOMEPAGE_URL <url-string>] # [LANGUAGES <language-name>...]) project(Tutorial VERSION 0.1.2 DESCRIPTION "This is Brook 1st CMake") # Add an executable to the project using the specified source files. # add_executable(<name> [WIN32] [MACOSX_BUNDLE] # [EXCLUDE_FROM_ALL] # [source1] [source2 ...]) add_executable(Tutorial hello.c)
hello.c
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
printf("hello world\n");
return 0;
}
有了CMakeLists.txt與source code, 就可以使用cmake [options] <path-to-source>建立Makefile, 並使用cmake --build <dir>去build targe
[brook@:~/Projects/cmake]$ tree
.
`-- src
|-- CMakeLists.txt
`-- hello.c
1 directory, 2 files
[brook@:~/Projects/cmake]$ mkdir build && cd build
[brook@:~/Projects/cmake/build]$ cmake ../src/
-- The C compiler identification is GNU 7.5.0
-- The CXX compiler identification is GNU 7.5.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /build/brook/Projects/cmake/build
[brook@:~/Projects/cmake/build]$ ls
CMakeCache.txt CMakeFiles Makefile cmake_install.cmake
[brook@:~/Projects/cmake/build]$ cmake --build .
Scanning dependencies of target Tutorial
[ 50%] Building C object CMakeFiles/Tutorial.dir/hello.c.o
[100%] Linking C executable Tutorial
[100%] Built target Tutorial
[brook@:~/Projects/cmake/build]$ ls
CMakeCache.txt CMakeFiles Makefile Tutorial cmake_install.cmake
[brook@:~/Projects/cmake/build]$ ./Tutorial
hello world
Adding a Version Number and Configured Header File
前面的CMakeLists.txt中描述了project(Tutorial VERSION 0.1.2 DESCRIPTION "This is Brook 1st CMake"), 但是沒在C code中被用到, 所以, 我們將這些變數加入configure a header file 並傳遞給source code
# Require a minimum version of cmake.
# cmake_minimum_required(VERSION <min>>[...<policy_max>] [FATAL_ERROR])
cmake_minimum_required(VERSION 3.10)
# Set the name of the project.
# project(<PROJECT-NAME< [<anguage-name>...])
# project(<PROJECT-NAME>
# [VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]
# [DESCRIPTION <project-description-string>]
# [LANGUAGES <language-name>...])
project(Tutorial VERSION 0.1.2 DESCRIPTION "This is Brook 1st CMake")
# Add an executable to the project using the specified source files.
# add_executable(<name> [WIN32] [MACOSX_BUNDLE]
# [EXCLUDE_FROM_ALL]
# [source1] [source2 ...])
add_executable(Tutorial hello.c)
# Copy a file to another location and modify its contents.
# configure_file(<input> <output>
# [NO_SOURCE_PERMISSIONS | USE_SOURCE_PERMISSIONS |
# FILE_PERMISSIONS <permissions>...]
# [COPYONLY] [ESCAPE_QUOTES] [@ONLY]
# [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])
configure_file(Config.h.in Config.h)
# Add include directories to a target.
# target_include_directories(&;lt;target> [SYSTEM] [AFTER|BEFORE]
# &;lt;INTERFACE|PUBLIC|PRIVATE> [items1...]
# [&;lt;INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
target_include_directories(Tutorial PUBLIC "${PROJECT_BINARY_DIR}")
首先先透過configure_file()設定configure file的input與output, 在CMake建立Makefile過程中, 就會將configure的input變數取代後, 產生configure的output檔. 由於configure header file要被source code給include進來, 所以還得透過target_include_directories()設定對應的include path. 相關執行步驟如下:
[brook@:~/Projects/cmake]$ tree
.
`-- src
|-- CMakeLists.txt
|-- Config.h.in
`-- hello.c
1 directory, 3 files
[brook@:~/Projects/cmake]$ cat src/Config.h.in
// the configured options and settings for Tutorial
#define VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define VERSION_MINOR @Tutorial_VERSION_MINOR@
[brook@:~/Projects/cmake]$ cat src/hello.c
#include <stdio.h>
#include <stdlib.h>
#include "Config.h"
int main(int argc, char *argv[])
{
printf("hello world(version: %d.%d)\n", VERSION_MAJOR, VERSION_MINOR);
return 0;
}
[brook@:~/Projects/cmake]$ mkdir build && cd build
[brook@:~/Projects/cmake/build]$ cmake ../src/
-- The C compiler identification is GNU 7.5.0
-- The CXX compiler identification is GNU 7.5.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /build/brook/Projects/cmake/build
[brook@:~/Projects/cmake/build]$ ls
CMakeCache.txt CMakeFiles Config.h Makefile cmake_install.cmake
[brook@:~/Projects/cmake/build]$ cmake --build .
Scanning dependencies of target Tutorial
[ 50%] Building C object CMakeFiles/Tutorial.dir/hello.c.o
[100%] Linking C executable Tutorial
[100%] Built target Tutorial
[brook@:~/Projects/cmake/build]$ ./Tutorial
hello world(version: 0.1)
[brook@:~/Projects/cmake/build]$ cat Config.h
// the configured options and settings for Tutorial
#define VERSION_MAJOR 0
#define VERSION_MINOR 1
在這裡我們有用到幾個CMake的變數, 包含PROJECT_BINARY_DIR, <PROJECT-NAME>_VERSION_MAJOR, PROJECT_BINARY_DIR等等, 這些都可以參考cmake-variables(7)取得更多的變數與相關細節, 我這裡就簡單介紹幾個基本的, 並透過Configure header file讓大家稍微理解一下對應的值
[brook@:~/Projects/cmake/build]$ cat ../src/Config.h.in // the configured options and settings for Tutorial #define VERSION_MAJOR @Tutorial_VERSION_MAJOR@ #define VERSION_MINOR @Tutorial_VERSION_MINOR@ // <PROJECT-NAME>_BINARY_DIR // A variable is created with the name used in the project() command, // and is the binary directory for the project. #define Tutorial_BINARY_DIR @Tutorial_BINARY_DIR@ // <PROJECT-NAME>_SOURCE_DIR // Top level source directory for the named project. // A variable is created with the name used in the project() command, // and is the source directory for the project. #define Tutorial_SOURCE_DIR @Tutorial_SOURCE_DIR@ // <PROJECT-NAME>_VERSION // Value given to the VERSION option of the most recent call // to the project() command with project name <PROJECT-NAME> #define Tutorial_VERSION "@Tutorial_VERSION@" #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@ #define Tutorial_VERSION_PATCH @Tutorial_VERSION_PATCH@ #define Tutorial_VERSION_TWEAK @Tutorial_VERSION_TWEAK@ // Full path to build directory for project. // This is the binary directory of the most recent project() command. #define PROJECT_BINARY_DIR @PROJECT_BINARY_DIR@ // Short project description given to the project command. // This is the description given to the most recent project() command. #define PROJECT_DESCRIPTION "@PROJECT_DESCRIPTION@" // Name of the project given to the project command. // This is the name given to the most recent project() command. #define PROJECT_NAME @PROJECT_NAME@ // Top level source directory for the current project. // This is the source directory of the most recent project() command. #define PROJECT_SOURCE_DIR @PROJECT_SOURCE_DIR@ // Value given to the VERSION option of the most recent call to the project() command #define PROJECT_VERSION "@PROJECT_VERSION@" #define PROJECT_VERSION_MAJOR @PROJECT_VERSION_MAJOR@ #define PROJECT_VERSION_MINOR @PROJECT_VERSION_MINOR@ #define PROJECT_VERSION_PATCH @PROJECT_VERSION_PATCH@ #define PROJECT_VERSION_TWEAK @PROJECT_VERSION_TWEAK@ [brook@:~/Projects/cmake/build]$ cmake ../src/ -- Configuring done -- Generating done -- Build files have been written to: /build/brook/Projects/cmake/build [brook@:~/Projects/cmake/build]$ cat Config.h // the configured options and settings for Tutorial #define VERSION_MAJOR 0 #define VERSION_MINOR 1 // <PROJECT-NAME>_BINARY_DIR // A variable is created with the name used in the project() command, // and is the binary directory for the project. #define Tutorial_BINARY_DIR /build/brook/Projects/cmake/build // <PROJECT-NAME>_SOURCE_DIR // Top level source directory for the named project. // A variable is created with the name used in the project() command, // and is the source directory for the project. #define Tutorial_SOURCE_DIR /build/brook/Projects/cmake/src // <PROJECT-NAME>_VERSION // Value given to the VERSION option of the most recent call // to the project() command with project name <PROJECT-NAME> #define Tutorial_VERSION "0.1.2" #define Tutorial_VERSION_MAJOR 0 #define Tutorial_VERSION_MINOR 1 #define Tutorial_VERSION_PATCH 2 #define Tutorial_VERSION_TWEAK // Full path to build directory for project. // This is the binary directory of the most recent project() command. #define PROJECT_BINARY_DIR /build/brook/Projects/cmake/build // Short project description given to the project command. // This is the description given to the most recent project() command. #define PROJECT_DESCRIPTION "This is Brook 1st CMake" // Name of the project given to the project command. // This is the name given to the most recent project() command. #define PROJECT_NAME Tutorial // Top level source directory for the current project. // This is the source directory of the most recent project() command. #define PROJECT_SOURCE_DIR /build/brook/Projects/cmake/src // Value given to the VERSION option of the most recent call to the project() command #define PROJECT_VERSION "0.1.2" #define PROJECT_VERSION_MAJOR 0 #define PROJECT_VERSION_MINOR 1 #define PROJECT_VERSION_PATCH 2 #define PROJECT_VERSION_TWEAK

沒有留言:
張貼留言