常见的构建系统(Build System)

白昼怎懂夜的黑 提交于 2020-12-02 15:16:19

各种构建系统各有优缺点,需要深入研究和使用才能了解。没有那个是最好的,只有最适合的。一般:

  • 一两个源文件的C++代码,完全没必要用构建系统,直接使用编译器命令直接搞定;
  • 自己用的小项目,直接手动写Makefile即可
  • 大型C++项目建议使用CMake,GNU Build System比较年龄大了,规则有些复杂,写起来没有CMake那么舒服,不能跨平台的话就根本没戏。
  • 比较新的构建系统:SCons、Waf、B2

基于make的构建系统

GNU Make

GNU Make 是一个控制源码生成可执行文件或其他文件的工具。需要一个叫Makefile的文件来说明构建的目标和规则。

target:   dependencies ...
          commands
          ...

意思是:生成target,依赖于dependencies,如果dependencies有修改或者target不存在,就逐个执行下面的commands去生成target。

但是大型的项目中,Makefile文件不可能手工去编写,GNU Build System可以自动生成Makefile文件。主要包含三大模块:

  • Autoconf
  • Automake
  • Libtool

可以从使用者开发者两个角度来看:

使用者的角度

GNU Build System为我们提供了源码包编译安装的方式:

tar -xvzf package-name.version.tar.gz # tar -xvjf package-name.version.tar.bz2 
cd package-name.version
./configure --prefix=xxx
make
make install

其中的configure就是检测环境,生成Makefile的脚本,然后是构建和安装。configure的大概的过程如下:

开发者的角度

GNU Build System 为我们广大程序员提供了编写构建规则和检查安装环境的功能。

开发者要发布自己的源码时,首先需要一个Autoconf的configure.ac,最简单的长这样:

AC_INIT([hello], [1.0]) 
AC_CONFIG_SRCDIR([hello.c]) 
AC_CONFIG_HEADERS(config.h) 
AC_PROG_CC 
AC_CONFIG_FILES(Makefile) 
AC_PROG_INSTALL 
AC_OUTPUT

其次还需要一个Automake的Makefile.am来描述构建规则,看起来这这样的:

AC_INIT([hello], [1.0]) 
AC_CONFIG_SRCDIR([hello.c]) 
AC_CONFIG_HEADERS(config.h) 
AM_INIT_AUTOMAKE 
AC_PROG_CC 
AC_CONFIG_FILES(Makefile) 
AC_PROG_INSTALL 
AC_OUTPUT

定义好检查环境和配置的configure.ac和描述构建规则的Makefile.am,生成一个可以发布的源码包大概过程如下:

aclocal 
autoconf 
autoheader 
touch NEWS README AUTHORS ChangeLog 
automake -a 
./configure 
make 
make dist

CMake

CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程)。他能够输出各种各样的Makefile或者project文件,能检查编译器所支持的C++特性,类似UNIX下的automake。CMake 并不直接建构出最终的软件,而是产生标准的建构脚本(如Unix 的 Makefile 或 Windows Visual C++ 的 projects/workspaces),然后再使用相应的工具进行编译。

CMak的特点主要有:

  • 开放源代码, 使用类 BSD 许可发布。 http://cmake.org/HTML/Copyright.html
  • 跨平台, 并可生成 native 编译配置文件, 在 Linux/Unix 平台, 生成 makefile, 在苹果平台, 可以生成 xcode, 在 Windows 平台, - 可以生成 MSVC 的工程文件。
  • 能够管理大型项目, KDE4 就是最好的证明。
  • 简化编译构建过程和编译过程。 CMake 的工具链非常简单: cmake+make。
  • 可扩展, 可以为 cmake 编写特定功能的模块, 扩充 cmake 功能。
  • 其实CMake工具包不仅仅提供了编译,还有:支持单元测试的CTest,支持不同平台打包的CPack,自动化测试及其展示的CDash。有兴趣的访问官方网站学习:https://cmake.org/

一般,在每个源码目录下都有一个 CMakeLists.txt,看起来是这样的:

cmake_minimum_required (VERSION 2.6)
project (Tutorial)
# The version number.
set (Tutorial_VERSION_MAJOR 1)
set (Tutorial_VERSION_MINOR 0)
 
# 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 executable
add_executable(Tutorial tutorial.cxx)

使用的时候:

第一步:根据CMakeLists.txt生成Makefile,命令如下:

mkdir path-to-build
cd path-tob-build
cmake path-to-source

cmake的过程可以分为配置和生成过程(如下图)。

CMake的过程

配置的时候优先从CMakeCache.txt中读取设置,然后再扫一遍CMakeList.txt中的设置,该步骤会检查第三方库和构建过程的变量;生成步骤则根据当前的环境和平台,生成不同的构建脚本,如Linux的Makefile,Windows的VC工程文件。

第二步:编译。Linux下直接make -jxx,其他的操作系统的IDE直接打开点一下build按钮即可。

Microsoft NMake

在Windows下面做开发,Visual Studio基本上完全胜任。微软自己的IDE功能强大,对于项目构建的管理IDE帮着你搞定了。VS的构建的管理其实用的是微软自己的Make,叫NMAKE。脚本还是IDE,各有千秋:IDE好处就是它什么都帮你干了,简单方便;坏处就是对构建的方式和过程了解的比较浅,自由度没那么大,遇到大型项目的特殊需求时要各种查资料。

非基于make的构建系统

SCons

SCons 是一个开放源代码、以 Python 语言编写的下一代的程序建造工具。作为下一代的软件建造工具,SCons 的设计目标就是让开发人员更容易、更可靠和更快速的建造软件。与传统的 make 工具比较,SCons 具有以下优点:

  • 使用 Python 脚本做为配置文件。
  • 对于 C,C++,Fortran,内建支持可靠自动依赖分析 。不用像 make 工具那样需要 执行"make depends"和"make clean"就可以获得所有的依赖关系。
  • 内建支持 C, C++, D, Java, Fortran, Yacc, Lex, Qt,SWIG 以及 Tex/Latex。 用户还可以根据自己的需要进行扩展以获得对需要编程语言的支持。
  • 支持 make -j 风格的并行建造。相比 make -j, SCons 可以同时运行 N 个工作,而 不用担心代码的层次结构。
  • 使用 Autoconf 风格查找头文件,函数库,函数和类型定义。
  • 良好的夸平台性。SCons 可以运行在 Linux, AIX, BSD, HP/UX, IRIX, Solaris, Windows, Mac OS X 和 OS/2 上。

waf

SCons项目小的话还好,规模一大,依赖分析速度急速下降,而且自动配置功能很弱 (跨平台构建能力不足),Waf尝试去解决SCons所暴露的问题。Waf也是基于Python的配置、编译、安装程序。主要特性:

  • 构建顺序自动化:输入输出文件的构建顺序自动化识别。
  • 依赖自动分析:根据文件或命令自动进行依赖分析。
  • 性能:任务都是并发执行的。
  • 灵活性:可以方便地通过添加新的子类创建新的命令或任务,特定构建过程中的瓶颈可以动过方法的动态重载来消除。
  • 可扩展性:默认支持多种编程语言和编译器,有需求新加的也可以通过插件进行支持。
  • IDE支持:Eclipse, Visual Studio and Xcode project generators (waflib/extras/)
  • 文档详细:入门到深入可以阅读:《Waf Book》https://waf.io/book/
  • Python兼容:cPython 2.5 to 3.4, Jython 2.5, IronPython, and Pypy

一个简单的C++构建脚本wscript:

#! /usr/bin/env python
# encoding: utf-8
# Thomas Nagy, 2006-2010 (ita)
 
# the following two variables are used by the target "waf dist"
VERSION='0.0.1'
APPNAME='cxx_test'
 
# these variables are mandatory ('/' are converted automatically)
top = '.'
out = 'build'
 
def options(opt):
    opt.load('compiler_cxx')
 
def configure(conf):
    conf.load('compiler_cxx')
    conf.check(header_name='stdio.h', features='cxx cxxprogram', mandatory=False)
 
def build(bld):
    bld.shlib(source='a.cpp', target='mylib', vnum='9.8.7')
    bld.shlib(source='a.cpp', target='mylib2', vnum='9.8.7', cnum='9.8')
    bld.shlib(source='a.cpp', target='mylib3')
    bld.program(source='main.cpp', target='app', use='mylib')
    bld.stlib(target='foo', source='b.cpp')
 
    # just a test to check if the .c is compiled as c++ when no c compiler is found
    bld.program(features='cxx cxxprogram', source='main.c', target='app2')
 
    if bld.cmd != 'clean':
        from waflib import Logs
        bld.logger = Logs.make_logger('test.log', 'build') # just to get a clean output
        bld.check(header_name='sadlib.h', features='cxx cxxprogram', mandatory=False)
        bld.logger = None

Boost.Build(b2)

在编译Boost库的时候,会用到b2命令,其实就是Boost.Build的缩写。编译C++/C代码时,只需要指定要编译那些可执行文件或库,然后列出相关的源码,Boost.Build帮你搞定其他事情,支持Windows、OSX、Linux和商业的Unix系统。

HelloWorld项目的jamroot.jam脚本(Jamfiles,一种不同于Makefile的构建脚本):

exe hello : hello.cpp ;

Boost.Build是一个高级编译系统,它能尽可能容易的管理C++项目集。其思想是在配置文件中指定编译程序的要素。例如,它不需要告诉Boost.Build如何使用某个编译器。Boost.Build支持多个编译程序,并知道如何使用它们。如果你创建一个配置文件,你只需要告诉Boost.Build在何处寻找源文件,调用哪些可执行文件,Boost.Build使用哪个编译器。然后,Boost.Build将尝试查找编译器并自动生成程序。

Boost.Build支持许多不包含任何编译器特定选项的编译器的配置文件。配置文件完全是编译器独立的。当然,可以设置选项是否应该优化代码。这些选项都是boost.build语言写的。一旦选择编译器去编译程序, Boost.Build会将配置文件中的选项翻译成相应编译器的命令行选项。这样就有可能写一次配置文件,在不同的平台上用不同的编译器构建程序。

Boost.Build只支持C++和C项目。它是为在不同平台上用不同编译器编译和安装Boost C++库而创造的。

参考文献

基于:https://www.jianshu.com/p/31bf731fec22 整理本文。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!