增加一个生成文件和生成器
这一节里我们会像你展示如何在应用的构建过程中加入一个生成的源文件,比如说,我们会创建一个预先计算好的平方根表作为构建过程的一部分,然后将那个表编译进我们的应用中,为了完成这个部分,我们先要一个能生成表格的程序。在MathFunctions子目录下一个新的叫做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++代码产生的,输出结果的文件名称是通过一个参数传入的。下一步是在MathFunctions的CMakeLists文件中加入合适的命令来构建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 )
首先MakeTable的可执行文件会像其他任何可执行文件一样被加入到项目中,然后我们加入自定义的命令来指定如何通过运行MakeTable来产生Table.h。接下来我们必须要让CMake知道mysqrt.cxx依赖于生成的Table.h文件,这是通过在MathFunctions库的源文件列表中加入生成的Table.h来完成的,我们还需要把当前的二进制目录加入到头文件目录列表中,这样Table.h文件才能被找到并被mysqrt.cxx文件引用。当这个项目构建的时候,MakeFunctions可执行文件会被先构建,然后运行MakeTable来生成Table.h,最后,引入Table.h来编译mysqrt.cxx生成MathFunctions库。这个时候包含所有我们已经新加入功能的最顶层的CMakeLists文件会像下面这样:
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看起来像这样:
// 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
MathFunctions的CMakeLists文件看起来像这样:
# 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)