Cmake && Ninja

8 篇文章 0 订阅

CMake

install

Get the Software,下载对应平台上的压缩包即可。
eg. linux 平台上用

wget https://github.com/Kitware/CMake/releases/download/v3.22.1/cmake-3.22.1-linux-x86_64.tar.gz        //下载资源,速度慢的话直接从其他渠道获取也一样
tar -vxf cmake-3.21.1-linux-x86_64.tar.gz                   //解压
ln -s /usr/bin/cmake /home/chen/cmake_project/cmake-3.21.1-linux-x86_64/bin/cmake           //做软链接

测试

>cmake -version
cmake version 3.21.1
CMake suite maintained and supported by Kitware (kitware.com/cmake).

cmake 命令行的可配置参数如下

Usage

  cmake [options] <path-to-source>
  cmake [options] <path-to-existing-build>
  cmake [options] -S <path-to-source> -B <path-to-build>

Specify a source directory to (re-)generate a build system for it in the
current working directory.  Specify an existing build directory to
re-generate its build system.

Options
  -S <path-to-source>          = Explicitly specify a source directory.
  -B <path-to-build>           = Explicitly specify a build directory.
  -C <initial-cache>           = Pre-load a script to populate the cache.
  -D <var>[:<type>]=<value>    = Create or update a cmake cache entry.
  -U <globbing_expr>           = Remove matching entries from CMake cache.
  -G <generator-name>          = Specify a build system generator.
  -T <toolset-name>            = Specify toolset name if supported by
                                 generator.
  -A <platform-name>           = Specify platform name if supported by
                                 generator.
  --toolchain <file>           = Specify toolchain file
                                 [CMAKE_TOOLCHAIN_FILE].
  --install-prefix <directory> = Specify install directory
                                 [CMAKE_INSTALL_PREFIX].
  -Wdev                        = Enable developer warnings.
  -Wno-dev                     = Suppress developer warnings.
  -Werror=dev                  = Make developer warnings errors.
  -Wno-error=dev               = Make developer warnings not errors.
  -Wdeprecated                 = Enable deprecation warnings.
  -Wno-deprecated              = Suppress deprecation warnings.
  -Werror=deprecated           = Make deprecated macro and function warnings
                                 errors.
  -Wno-error=deprecated        = Make deprecated macro and function warnings
                                 not errors.
  --preset <preset>,--preset=<preset>
                               = Specify a configure preset.
  --list-presets               = List available presets.
  -E                           = CMake command mode.
  -L[A][H]                     = List non-advanced cached variables.
  --build <dir>                = Build a CMake-generated project binary tree.
  --install <dir>              = Install a CMake-generated project binary
                                 tree.
  --open <dir>                 = Open generated project in the associated
                                 application.
  -N                           = View mode only.
  -P <file>                    = Process script mode.
  --find-package               = Legacy pkg-config like mode.  Do not use.
  --graphviz=[file]            = Generate graphviz of dependencies, see
                                 CMakeGraphVizOptions.cmake for more.
  --system-information [file]  = Dump information about this system.
  --log-level=<ERROR|WARNING|NOTICE|STATUS|VERBOSE|DEBUG|TRACE>
                               = Set the verbosity of messages from CMake
                                 files.  --loglevel is also accepted for
                                 backward compatibility reasons.
  --log-context                = Prepend log messages with context, if given
  --debug-trycompile           = Do not delete the try_compile build tree.
                                 Only useful on one try_compile at a time.
  --debug-output               = Put cmake in a debug mode.
  --debug-find                 = Put cmake find in a debug mode.
  --trace                      = Put cmake in trace mode.
  --trace-expand               = Put cmake in trace mode with variable
                                 expansion.
  --trace-format=<human|json-v1>
                               = Set the output format of the trace.
  --trace-source=<file>        = Trace only this CMake file/module.  Multiple
                                 options allowed.
  --trace-redirect=<file>      = Redirect trace output to a file instead of
                                 stderr.
  --warn-uninitialized         = Warn about uninitialized values.
  --no-warn-unused-cli         = Don't warn about command line options.
  --check-system-vars          = Find problems with variable usage in system
                                 files.
  --profiling-format=<fmt>     = Output data for profiling CMake scripts.
                                 Supported formats: google-trace
  --profiling-output=<file>    = Select an output path for the profiling data
                                 enabled through --profiling-format.
  --help,-help,-usage,-h,-H,/? = Print usage information and exit.
  --version,-version,/V [<f>]  = Print version number and exit.
  --help-full [<f>]            = Print all help manuals and exit.
  --help-manual <man> [<f>]    = Print one help manual and exit.
  --help-manual-list [<f>]     = List help manuals available and exit.
  --help-command <cmd> [<f>]   = Print help for one command and exit.
  --help-command-list [<f>]    = List commands with help available and exit.
  --help-commands [<f>]        = Print cmake-commands manual and exit.
  --help-module <mod> [<f>]    = Print help for one module and exit.
  --help-module-list [<f>]     = List modules with help available and exit.
  --help-modules [<f>]         = Print cmake-modules manual and exit.
  --help-policy <cmp> [<f>]    = Print help for one policy and exit.
  --help-policy-list [<f>]     = List policies with help available and exit.
  --help-policies [<f>]        = Print cmake-policies manual and exit.
  --help-property <prop> [<f>] = Print help for one property and exit.
  --help-property-list [<f>]   = List properties with help available and
                                 exit.
  --help-properties [<f>]      = Print cmake-properties manual and exit.
  --help-variable var [<f>]    = Print help for one variable and exit.
  --help-variable-list [<f>]   = List variables with help available and exit.
  --help-variables [<f>]       = Print cmake-variables manual and exit.

Generators

The following generators are available on this platform (* marks default):
  Green Hills MULTI            = Generates Green Hills MULTI files
                                 (experimental, work-in-progress).
* Unix Makefiles               = Generates standard UNIX makefiles.
  Ninja                        = Generates build.ninja files.
  Ninja Multi-Config           = Generates build-<Config>.ninja files.
  Watcom WMake                 = Generates Watcom WMake makefiles.
  CodeBlocks - Ninja           = Generates CodeBlocks project files.
  CodeBlocks - Unix Makefiles  = Generates CodeBlocks project files.
  CodeLite - Ninja             = Generates CodeLite project files.
  CodeLite - Unix Makefiles    = Generates CodeLite project files.
  Eclipse CDT4 - Ninja         = Generates Eclipse CDT 4.0 project files.
  Eclipse CDT4 - Unix Makefiles= Generates Eclipse CDT 4.0 project files.
  Kate - Ninja                 = Generates Kate project files.
  Kate - Unix Makefiles        = Generates Kate project files.
  Sublime Text 2 - Ninja       = Generates Sublime Text 2 project files.
  Sublime Text 2 - Unix Makefiles
                               = Generates Sublime Text 2 project files.

其中Generators是生成器,实际上cmake 的作用就是生成一个makefile(或者其他类型的最终编译文件(eg:build.ninja)),默认情况下,使用的生成器是Unix Makefiles,最终生成makefile文件,然后通过make 命令可以看是编译,但这个参数如上,可以通过-G 来指定。

搭建项目

CMake Tutorial

source code

source code
解压后,可以在cmake-3.22.1/Help/guide/tutorial/路径下找到官方的示例文件,再跟着Tutorial学就好了

Step1

cmake入门,初步编译一个文件

.
├── CMakeLists.txt
├── TutorialConfig.h.in
├── build
│   ├── CMakeCache.txt
│   ├── CMakeFiles
│   ├── Makefile
│   ├── Tutorial
│   ├── TutorialConfig.h
│   └── cmake_install.cmake
└── tutorial.cxx

build 文件夹自己创建一个,也可以不创建,只是为了方便区分。
相关文件内容如下
CMakeLists.txt

cmake_minimum_required(VERSION 3.10)

# set the project name
project(Tutorial VERSION 2.2)

#创建版本配置文件,*.in 文件最后会在build目录生成一个.h ,而这个.h又可以被包含在执行文件中,相当于可以全局配置版本号
configure_file(TutorialConfig.h.in TutorialConfig.h)

cmake_minimum_required(VERSION 3.10)

# set the project name and version
project(Tutorial VERSION 1.0)

# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

# add the executable(可执行文件名称 main文件名称)
add_executable(Tutorial tutorial.cxx)

# Since the configured file will be written into the binary tree,
# we must add that directory to the list of paths to search for include files.
# Add the following lines to the end of the CMakeLists.txt file:
# 其中target_include_directories 的参数为(project_name 目录影响范围 目录位置)
# 关于目录影响范围,实际上和文件调用相关,如果一个文件,被广范调用,则使用PUBLIC,否则使用PRIVATE
# 参考[cmake中 target_include_directories的用法](https://blog.csdn.net/weixin_45935219/article/details/120655782)
target_include_directories(Tutorial PUBLIC
                           "${PROJECT_BINARY_DIR}"
                           )

tutorial.cxx

// A simple program that computes the square root of a number
#include <cmath>
#include <iostream>
#include <string>
#include "TutorialConfig.h"

int main(int argc, char* argv[])
{
  if (argc < 2) {
    // report version
    std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
              << Tutorial_VERSION_MINOR << std::endl;
    std::cout << "Usage: " << argv[0] << " number" << std::endl;
    return 1;
  }

  // convert input to double
  const double inputValue = atof(argv[1]);

  // calculate square root
  const double outputValue = sqrt(inputValue);
  std::cout << "The square root of " << inputValue << " is " << outputValue
            << std::endl;
  return 0;
}

TutorialConfig.h.in

// the configured options and settings for Tutorial
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@

编译方式是cd到build,使用cmake ../命令后,没有报错再使用make
可以看到cmake命令需要跟CMakeLists.txt文件在同一个位置下使用,也是使用…/的原因,如果没有创建build文件夹,直接使用cmake 即可

Step2

主要是链接外部文件和动态配置

.
├── CMakeLists.txt
├── MathFunctions
│   ├── CMakeLists.txt
│   ├── MathFunctions.h
│   └── mysqrt.cxx
├── TutorialConfig.h.in
├── build
│   ├── CMakeCache.txt
│   ├── CMakeFiles
│   ├── Makefile
│   ├── MathFunctions
│   ├── TutorialConfig.h
│   └── cmake_install.cmake
└── tutorial.cxx

结构图的build目录内容可以忽略,执行cmake后自然会生成
按照官方的代码,最后修改的文件示例和注释如下
CMakeLists.txt

cmake_minimum_required(VERSION 3.10)

# set the project name and version
project(Tutorial VERSION 1.0)

# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

# configure a header file to pass some of the CMake settings
# to the source code
configure_file(TutorialConfig.h.in TutorialConfig.h)

# 设置配置开关,用于做特定编译时参数的选择(比如是否调用某个库),默认打开                        
option(USE_MYMATH "Use tutorial provided math implementation" ON)

# 判断是否打开配置
if(USE_MYMATH)
  # add the MathFunctions library
  add_subdirectory(MathFunctions)
  # EXTRA_LIBS 中附加 MathFunctions lib 路径
  list(APPEND EXTRA_LIBS MathFunctions)
  # EXTRA_INCLUDES 路径中附加链接库的路径 source 路径
  list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/MathFunctions")
endif()

# add the executable
add_executable(Tutorial tutorial.cxx)

# 添加链接库路径,并设置为PUBLIC
target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS})

# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
# 增加链接库文件相关的路径"${EXTRA_INCLUDES}"
target_include_directories(Tutorial PUBLIC
                           "${PROJECT_BINARY_DIR}"
                           ${EXTRA_INCLUDES}
                           )

tutorial.cxx

// A simple program that computes the square root of a number
#include <cmath>
#include <iostream>
#include <string>

#include "TutorialConfig.h"

//判断是否配置了开关,有就include
#ifdef USE_MYMATH
# include "MathFunctions.h"
#endif

int main(int argc, char* argv[])
{
  if (argc < 2) {
    // report version
    std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
              << Tutorial_VERSION_MINOR << std::endl;
    std::cout << "Usage: " << argv[0] << " number" << std::endl;
    return 1;
  }

  // convert input to double
  const double inputValue = std::stod(argv[1]);

  //判断是否配置开关,有就用链接库提供的函数实现,没有就用cpp提供的默认实现sqrt()
  #ifdef USE_MYMATH
    const double outputValue = mysqrt(inputValue);
  #else
    const double outputValue = sqrt(inputValue);
  #endif

  std::cout << "The square root of " << inputValue << " is " << outputValue
            << std::endl;
  return 0;
}

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     //用于引入命令行设置(eg:cmake ../ -DUSE_MYMATH=ON 开启mymath)

其中工具库放在 MathFunctions
里面的文件没什么变化,但需要自己增加一个CMakeLists.txt,内容为

# 添加库文件(库文件相关路径 源文件)
add_library(MathFunctions mysqrt.cxx)

重点
与上一章的编译方式不同,这次编译需要带上参数cmake ../ -DUSE_MYMATH=ON,设置OFF/ON可以对应配置是否使用外置文件,默认使用cmake的参数是ON

Step3

使用一些外部文件,在Step2中,总是要在最外层的配置文件(CMakeLists.txt)中添加 ${EXTRA_INCLUDES},cmake 可以使用诸如
target_compile_definitions()

target_compile_options()

target_include_directories()

target_link_libraries()
来做好被链接模块与main之间的编译关系。
相对于使用Step 2的代码,只需要在MathFunctions/CMakeLists.txt
中增加

target_include_directories(MathFunctions
          INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
          )

就可以把需要的链接文件链接到main 的source 路径上
此时就可以删除工程下CMakeLists.txt文件中的

list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/MathFunctions")

target_include_directories(Tutorial PUBLIC
                           "${PROJECT_BINARY_DIR}"
                           ${EXTRA_INCLUDES}
                           )

中的 ${EXTRA_INCLUDES}

在完成修改后按照Step2中的build flow即可实现同样的效果。

Step 4

关于instal和test

install

在编译结束后,可以install到平台上或者指定位置,这个操作相当于将关联文件打包并放在平台的某个位置
对于cmake 项目,只需要在有关联到的文件的CMakeLists.txt 中增加

install(TARGETS bin_file DESTINATION bin)
install(FILES "h_file"
  DESTINATION include
  )

即可保存相关的lib文件和.h文件。使用Step3的示例,则是要在
最上层CMakeLists.txt中增加

install(TARGETS Tutorial DESTINATION bin)
install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
  DESTINATION include
  )

在MathFunctions/CMakeLists.txt末尾增加

install(TARGETS Tutorial DESTINATION bin)
install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
  DESTINATION include
  )

然后回到/build 做

cmake ../
make install

默认情况下,make install 位置在/usr/local ,可以通过增加配置指定make install DESTDIR=/home/chen/output
运行后对应位置的tree为

output/
└── usr
    └── local
        ├── bin
        │   └── Tutorial
        ├── include
        │   ├── MathFunctions.h
        │   └── TutorialConfig.h
        └── lib
            └── libMathFunctions.a

test

稍微看了一下,包含一些cmake的语法,就不深入了,上面的示例,需要测试的话,只需要在顶层CMakeLists.txt中末尾添加如下

enable_testing()

# does the application run
add_test(NAME Runs COMMAND Tutorial 25)

# does the usage message work?
add_test(NAME Usage COMMAND Tutorial)
set_tests_properties(Usage
  PROPERTIES PASS_REGULAR_EXPRESSION "Usage:.*number"
  )

# define a function to simplify adding tests
function(do_test target arg result)
  add_test(NAME Comp${arg} COMMAND ${target} ${arg})
  set_tests_properties(Comp${arg}
    PROPERTIES PASS_REGULAR_EXPRESSION ${result}
    )
endfunction()

# do a bunch of result based tests
do_test(Tutorial 4 "4 is 2")
do_test(Tutorial 9 "9 is 3")
do_test(Tutorial 5 "5 is 2.236")
do_test(Tutorial 7 "7 is 2.645")
do_test(Tutorial 25 "25 is 5")
do_test(Tutorial -25 "-25 is (-nan|nan|0)")
do_test(Tutorial 0.0001 "0.0001 is 0.01")  

在/build 里面cmake ../ ;make;make test;

官网对这份测试的描述是

The first test simply verifies that the application runs, does not segfault or otherwise crash, and has a zero return value. This is the basic form of a CTest test.

The next test makes use of the PASS_REGULAR_EXPRESSION test property to verify that the output of the test contains certain strings. In this case, verifying that the usage message is printed when an incorrect number of arguments are provided.

Lastly, we have a function called do_test that runs the application and verifies that the computed square root is correct for given input. For each invocation of do_test, another test is added to the project with a name, input, and expected results based on the passed arguments.

单元测试用到了再学吧

Step7

Packaging an Installer

Step11

Adding Export Configuration

Ninja

install

ubuntu:sudo apt install ninja-build
version:ninja --version
官网
Ninja实际使用上类似与makefile,也是构建文件关系,编译相关的文件生成最终的执行文件

项目构建

CMake

在cmake项目中,可以直接使用ninja工具来加速编译速度。
使用Cmake Step3 的示例
项目结构为

.
├── CMakeLists.txt
├── MathFunctions
│   ├── CMakeLists.txt
│   ├── MathFunctions.h
│   └── mysqrt.cxx
├── TutorialConfig.h.in
└── tutorial.cxx

如前述,这部分主要增加自定义参数,来调节是否编译用户自己的库(USE_MYMATH)。
这里,我们用ninja 来进行编译。
cmake -B build -G Ninja -D USE_MYMATH=OFF
参考cmake 章节,上述的定义参数分别代表
-B = Explicitly specify a build directory.
-G = Specify a build system generator.
-D [:]= = Create or update a cmake cache entry.
运行指令后会生成build 目录,并在该目录下生成build.ninja文件(相当于makefile),同时传递了USE_MYMATH=OFF这个参数到配置中
注意: Ninja 不是用来替代cmake 的,它是作为cmake生成器的一部分,可选地参与cmake 构建
此时只需要再build目录下运行ninja即可完成编译。
ninja 编译过程只会打印一句log(官方认为这让用户感觉到快😂),一个好的特性是可以生成编译关系图,只需要使用
ninja -t graph all |dot -T png -o graph.png(需要安装graphviz=>apt install graphviz)
实际上只要有build.ninja 文件,即可运行ninja

编写自己的ninja 项目

前述,ninja 实际上是和make(makefile)做对比的,可以理解为ninja 是makefile的并行高速精简版本,编译速度比make 快。
我稍微看了语法,和make 差别不大,一个项目如下

.
├── build.ninja
└── foo.c

其中
build.ninja

cflags = -g

rule cc
  command = gcc $cflags -c $in -o $out

build foo.o: cc foo.c

foo.c

#include <stdio.h>

int main(int argc, char *argv[])
{
    printf("sandeepin poi!");
    return 0;
}

创建这两个文件后直接运行ninja即可,和前文类似,也可以生成graph。
这是简单不过的一个示例了,可以看到build.ninja 文件中只是创建了编译规则 rule cc 并在build 命令中传递编译文件和输入文件。这和makefile很类似。当然ninja 还有更多特性,比如利用缩进(shadowed)来覆盖某条规则可能会使用的参数,类似于全局变量和局部变量。其他特性就不展开了。
参考官网,国内转译

其他参考1
其他参考2
Cmake 语法与实战入门

  • 0
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值