【cmake系列使用教程】python
cmake使用教程(一)-起步linux
cmake使用教程(四)-文件生成器github
cmake使用教程(六)-蛋疼的語法macos
cmake使用教程(八)-macro和functionapp
這個系列的文章翻譯自官方cmake教程:cmake tutorial。ide
示例程序地址:github.com/rangaofei/t…
不會僅僅停留在官方教程。本人做爲一個安卓開發者,實在是沒有linux c程序開發經驗,望大佬們海涵。教程是在macos下完成,大部分linux我也測試過,有特殊說明的我會標註出來。本教程基於cmake-3.10.2,同時認爲你已經安裝好cmake。
有時候咱們的文件不是一開始就編寫好的,而是經過在編譯過程當中來生成文件好比某個日誌,構建時間等,等文件生成後咱們須要將這個文件再添加到應用程序的構建過程當中。
下邊,咱們將建立一個預先計算的平方根表做爲構建過程的一部分,程序能夠經過查詢這個表來輸出對應的數值,而後將該表編譯到咱們的應用程序中。爲了實現這一點,咱們首先須要一個生成該表的程序。在mathfunction
子目錄中,新建一個文件,名稱爲MakeTable.cxx,內容以下:
// A simple program that builds a sqrt table
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main (int argc, char *argv[])
{
int i;
double result;
// make sure we have enough arguments
if (argc < 2)
{
return 1;
}
// open the output file
FILE *fout = fopen(argv[1],"w");
if (!fout)
{
return 1;
}
// create a source file with a table of square roots
fprintf(fout,"double sqrtTable[] = {\n");
for (i = 0; i < 10; ++i)
{
result = sqrt(static_cast<double>(i));
fprintf(fout,"%g,\n",result);
}
// close the table with a zero
fprintf(fout,"0};\n");
fclose(fout);
return 0;
}
複製代碼
注意,該表是做爲有效的c++代碼生成的,輸出的文件名稱是以參數形式傳入的。下一步是將合適的命令添加到mathfunction
的CMakeLists.txt文件中來構建MakeTable的可執行文件,而後將其做爲構建過程的一部分運行。添加以下命令:
# 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
)
# add the binary tree directory to the search path for
# include files
include_directories( ${CMAKE_CURRENT_BINARY_DIR} )
# add the main library
add_library(MathFunctions mysqrt.cxx ${CMAKE_CURRENT_BINARY_DIR}/Table.h )
複製代碼
首先,add_executable(MakeTable MakeTable.cxx)
添加了MakeTable
這個可執行文件。而後咱們添加一個自定義命令來指定經過運行MakeTable
來生成平方根表(Table.h),注意add_custom_command
的第二個參數COMMAND
,至關於執行MakeTable並傳入參數${CMAKE_CURRENT_BINARY_DIR}/Table.h
。接下來咱們要讓CMake知道mysqrt.cxx依賴於生成的文件表(Table.h)。這是經過添加生成的Table.h文件到MathFunctions庫來實現的。咱們還必須將當前的二進制目錄添加到包含目錄的列表中,由於生成的表在二進制目錄中,這樣庫就能夠找到幷包含在mysqrt.cxx中。當這個項目被構建時,它將首先構建MakeTable
可執行文件。而後它將運行MakeTable
命令生成Table.h
文件。最後,它將編譯mysqrt.cxx和table.h生成mathfunction庫。
根目錄下的的CMakeLists.txt文件以下:
cmake_minimum_required (VERSION 2.6)
project (Tutorial)
include(CTest)
# The version number.
set (Tutorial_VERSION_MAJOR 1)
set (Tutorial_VERSION_MINOR 0)
# does this system provide the log and exp functions?
include (${CMAKE_ROOT}/Modules/CheckFunctionExists.cmake)
check_function_exists (log HAVE_LOG)
check_function_exists (exp HAVE_EXP)
# should we use our own math functions
option(USE_MYMATH
"Use tutorial provided math implementation" ON)
# configure a header file to pass some of the CMake settings
# to the source code
configure_file (
"${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
"${PROJECT_BINARY_DIR}/TutorialConfig.h"
)
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
include_directories ("${PROJECT_BINARY_DIR}")
# add the MathFunctions library?
if (USE_MYMATH)
include_directories ("${PROJECT_SOURCE_DIR}/MathFunctions")
add_subdirectory (MathFunctions)
set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)
endif (USE_MYMATH)
# add the executable
add_executable (Tutorial tutorial.cxx)
target_link_libraries (Tutorial ${EXTRA_LIBS})
# add the install targets
install (TARGETS Tutorial DESTINATION bin)
install (FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
DESTINATION include)
# does the application run
add_test (TutorialRuns Tutorial 25)
# does the usage message work?
add_test (TutorialUsage Tutorial)
set_tests_properties (TutorialUsage
PROPERTIES
PASS_REGULAR_EXPRESSION "Usage:.*number"
)
#define a macro to simplify adding tests
macro (do_test arg result)
add_test (TutorialComp${arg} Tutorial ${arg})
set_tests_properties (TutorialComp${arg}
PROPERTIES PASS_REGULAR_EXPRESSION ${result}
)
endmacro (do_test)
# do a bunch of result based tests
do_test (4 "4 is 2")
do_test (9 "9 is 3")
do_test (5 "5 is 2.236")
do_test (7 "7 is 2.645")
do_test (25 "25 is 5")
do_test (-25 "-25 is 0")
do_test (0.0001 "0.0001 is 0.01")
複製代碼
TutorialConfig.h.in文件以下:
// the configured options and settings for Tutorial
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
#cmakedefine USE_MYMATH
// does the platform provide exp and log functions?
#cmakedefine HAVE_LOG
#cmakedefine HAVE_EXP
複製代碼
MathFunction文件夾下的CMakeLists.txt文件內容以下:
# 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
DEPENDS MakeTable
COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
)
# add the binary tree directory to the search path
# for include files
include_directories( ${CMAKE_CURRENT_BINARY_DIR} )
# add the main library
add_library(MathFunctions mysqrt.cxx ${CMAKE_CURRENT_BINARY_DIR}/Table.h)
install (TARGETS MathFunctions DESTINATION bin)
install (FILES MathFunctions.h DESTINATION include)
複製代碼
完整的文件結構
~/Desktop/Tutorial/Step5/ tree -L 2
.
├── CMakeLists.txt
├── MathFunctions
│ ├── CMakeLists.txt
│ ├── MakeTable.cxx
│ ├── MathFunctions.h
│ └── mysqrt.cxx
├── TutorialConfig.h.in
├── build
└── tutorial.cxx
複製代碼
而後執行外部構建命令(第六個教程裏有說明如何外部構建):
mkdir build
cd build
cmake ..
make
複製代碼
構建成功後,咱們預期會在二進制文件夾中的MathFunction中生成一個Table.h文件,而且文件內容是一個簡單的平方根表。
來看一下結果:
~/Desktop/Tutorial/Step5/ tree -L 3 -I CMakeFiles
.
├── CMakeLists.txt
├── c
│ ├── CMakeLists.txt
│ ├── MakeTable.cxx
│ ├── MathFunctions.h
│ └── mysqrt.cxx
├── TutorialConfig.h.in
├── build
│ ├── CMakeCache.txt
│ ├── CTestTestfile.cmake
│ ├── Makefile
│ ├── MathFunctions
│ │ ├── MakeTable
│ │ ├── Makefile
│ │ ├── Table.h
│ │ ├── cmake_install.cmake
│ │ └── libMathFunctions.a
│ ├── Tutorial
│ ├── TutorialConfig.h
│ └── cmake_install.cmake
└── tutorial.cxx
複製代碼
能夠看到,確實有這個表。 而後看一下表的內容是否是0-9的平方根且最後以0結束,執行命令:
~/Desktop/Tutorial/Step5/ cat build/MathFunctions/Table.h
double sqrtTable[] = {
0,
1,
1.41421,
1.73205,
2,
2.23607,
2.44949,
2.64575,
2.82843,
3,
0};
複製代碼
結果正確。這種構建方式增長了蛋疼的操做,獲取用python腳本或者shell腳本更容易生成,可是爲了展現cmake系統構建的強大功能,一次編寫處處運行,咱們忍一忍吧。