cmake入门系列总结五

本文是cmake入门系列总结五,主要介绍如何将生成的源文件添加到应用程序构建过程。通过创建预先计算的平方根表示例,展示了构建过程,包括创建生成表程序、修改CMakeLists.txt文件等,最后表示抛除非GUI系统未尝试通过部分,cmake基本学习完毕。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

cmake入门系列总结五


版本说明

版本作者日期备注
0.1loon2019.3.17初稿

目录

一、主旨

添加生成的文件和生成器。在本节中,我们将展示如何将生成的源文件添加到应用程序的构建过程中。

二、实例及运行

1、过程

对于此示例,我们将创建一个预先计算的平方根表,作为构建过程的一部分,然后将该表编译到我们的应用程序中。为此,我们首先需要一个生成表的程序。在MathFunctions子目录中,一个名为MakeTable.cpp的新源文件就是这样做的。

#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;

    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.txt文件以构建MakeTable可执行文件,然后在构建过程中运行它。完成此操作需要一些命令,如下所示。

# first we add the executable that generates the table
add_executable(MakeTable MakeTable.cpp)

# 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.cpp ${CMAKE_CURRENT_BINARY_DIR}/Table.h)

首先添加MakeTable的可执行文件,因为将添加任何其他可执行文件。然后我们添加一个自定义命令,指定如何通过运行MakeTable来生成Table.h。接下来我们要让CMake知道mysqrt.cpp依赖于生成的文件Table.h。这是通过将生成的Table.h添加到库MathFunctions的源列表中完成的。我们还必须将当前二进制目录添加到包含目录列表中,以便可以在mysqrt.cpp中找到并包含Table.h。构建此项目时,它将首先构建MakeTable可执行文件。然后它将运行MakeTable以生成Table.h。最后,它将编译包含Table.h的mysqrt.cpp以生成MathFunctions库。此时,顶级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(${CMKAE_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(EXIRA_LIBS ${EXIRA_LIBS} MathFunctions)
endif(USE_MYMATH)

#add the executable
add_executable(Tutorial tutorial.cpp)
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.346")
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

MathFunctions的CMakeLists.txt文件如下所示:

# first we add the executable that generates the table
add_executable(MakeTable MakeTable.cpp)

# 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.cpp ${CMAKE_CURRENT_BINARY_DIR}/Table.h)

install(TARGETS MathFunctions DESTINATIONS bin)
install(FILES MathFunctions.h DESTINATIONS include)

2、运行

目录结构:

loon@loon-virtual-machine:~/work/cmake_test/Tutorial$ tree .
.
├── build
├── CMakeLists.txt
├── MathFunctions
│   ├── CMakeLists.txt
│   ├── MakeTable.cpp
│   └── mysqrt.cpp
├── TutorialConfig.h.in
└── tutorial.cpp

2 directories, 6 files

顶级目录下的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(${CMKAE_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(EXIRA_LIBS ${EXIRA_LIBS} MathFunctions)
endif(USE_MYMATH)

#add the executable
add_executable(Tutorial tutorial.cpp)
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.346")
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")

tutorial.cpp:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "TutorialConfig.h"
#ifdef USE_MYMATH
#include "MathFunctions.h"
#endif

int main(int argc, char *argv[])
{
    if(argc < 2)
    {
        fprintf(stdout, "%s Version %d.%d\n", argv[0], Tutorial_VERSION_MAJOR,
                Tutorial_VERSION_MINOR);
        fprintf(stdout, "Usage:%s number\n", argv[0]);
        return 1;
    }
    double inputValue = atof(argv[1]);

#ifdef USE_MYMATH
    double outputValue = mysqrt(inputValue);
#else
    double outputValue = sqrt(inputValue);
#endif

    fprintf(stdout, "The square root of %g is %g\n", inputValue, outputValue);
    return 0;
}

TutorialConfig.h.in

#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.txt:

# first we add the executable that generates the table
add_executable(MakeTable MakeTable.cpp)

# 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.cpp ${CMAKE_CURRENT_BINARY_DIR}/Table.h)

install(TARGETS MathFunctions DESTINATIONS bin)
install(FILES MathFunctions.h DESTINATIONS include)

MakeTable.cpp

#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;

    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;
}

mysqrt.cpp:

#include <stdio.h>
#include <stdlib.h>

double mysqrt(double number)
{
    double newGuess;
    double lastGuess;

    if(number < 0)
    {
        printf("Cannot compute the square root of a negative number!\n");
        return -1;
    }

    if(0 == number)
        return 0;

    newGuess = 1;
    do{
        lastGuess = newGuess;
        newGuess = (lastGuess + number / lastGuess) / 2;
    }
    while(newGuess != lastGuess);

    return newGuess;
}

运行过程:

loon@loon-virtual-machine:~/work/cmake_test/Tutorial/build$ cmake ..
-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.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: /home/loon/work/cmake_test/Tutorial/build
loon@loon-virtual-machine:~/work/cmake_test/Tutorial/build$ make
Scanning dependencies of target Tutorial
[ 50%] Building CXX object CMakeFiles/Tutorial.dir/tutorial.cpp.o
[100%] Linking CXX executable Tutorial
[100%] Built target Tutorial
loon@loon-virtual-machine:~/work/cmake_test/Tutorial/build$ ./Tutorial 
./Tutorial Version 1.0
Usage:./Tutorial number
loon@loon-virtual-machine:~/work/cmake_test/Tutorial/build$ ctest 
Test project /home/loon/work/cmake_test/Tutorial/build
    Start 1: TutorialRuns
1/9 Test #1: TutorialRuns .....................   Passed    0.00 sec
    Start 2: TutorialUsage
2/9 Test #2: TutorialUsage ....................***Failed  Required regular expression not found.Regex=[usage:.*number
]  0.00 sec
    Start 3: TutorialComp4,
3/9 Test #3: TutorialComp4, ...................   Passed    0.00 sec
    Start 4: TutorialComp9,
4/9 Test #4: TutorialComp9, ...................   Passed    0.00 sec
    Start 5: TutorialComp5
5/9 Test #5: TutorialComp5 ....................***Failed  Required regular expression not found.Regex=[5 is 2.346
]  0.00 sec
    Start 6: TutorialComp7
6/9 Test #6: TutorialComp7 ....................   Passed    0.00 sec
    Start 7: TutorialComp25
7/9 Test #7: TutorialComp25 ...................   Passed    0.00 sec
    Start 8: TutorialComp-25
8/9 Test #8: TutorialComp-25 ..................***Failed  Required regular expression not found.Regex=[-25 is 0
]  0.00 sec
    Start 9: TutorialComp0.0001
9/9 Test #9: TutorialComp0.0001 ...............   Passed    0.00 sec

67% tests passed, 3 tests failed out of 9

Total Test time (real) =   0.05 sec

The following tests FAILED:
	  2 - TutorialUsage (Failed)
	  5 - TutorialComp5 (Failed)
	  8 - TutorialComp-25 (Failed)
Errors while running CTest

三、最后

这一节完了之后抛除我们暂时在非GUI系统下暂时没有尝试通过的部分,cmake已经基本上学习完了,我们日常能用到的基本也都学完了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

昵称系统有问题

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值