cmake使用教程(四)-檔案生成器

saka發表於2018-02-01

【cmake系列使用教程】

cmake使用教程(一)-起步

cmake使用教程(二)-新增庫

cmake使用教程(三)-安裝、測試、系統自檢

cmake使用教程(四)-檔案生成器

cmake使用教程(五)-cpack生成安裝包

cmake使用教程(六)-蛋疼的語法

cmake使用教程(七)-流程和迴圈

cmake使用教程(八)-macro和function

這個系列的文章翻譯自官方cmake教程:cmake tutorial

示例程式地址: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系統構建的強大功能,一次編寫到處執行,我們忍一忍吧。

相關文章