各种构建系统各有优缺点,需要深入研究和使用才能了解。没有那个是最好的,只有最适合的。一般:
- 一两个源文件的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的过程可以分为配置和生成过程(如下图)。
配置的时候优先从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.gnu.org/software/make/
- http://www.cmake.org/
- http://scons.org/
- http://scons.org/doc/production/PDF/scons-design.pdf
- https://waf.io
- http://www.aosabook.org/en/500L/contingent-a-fully-dynamic-build-system.html (DIY一个构建系统)
基于:https://www.jianshu.com/p/31bf731fec22 整理本文。
来源:oschina
链接:https://my.oschina.net/u/916174/blog/4769726