Skip to content

编译系统

编译过程

自动化构建工具

在不同平台上编译项目,需要根据平台修改编译器、编译选项等。为了简化这个过程,可以使用自动化构建工具。

GNU Autotools

历史较为悠久的项目都会使用 GNU Autotools 来构建项目,标准流程为:

./configure && make && make install

需要熟悉的工具是 Autoconf 和 autoreconf,其他工具一般不需要直接操作。

文件结构

./configure 阶段可以使用 --prefix=/path/to/dir 参数指定安装路径,默认为 /usr/local

构建工具将在该目录下生成文件,标准架构如下:

prefix
├── bin
├── include
├── lib
├── share
│   ├── man
│   ├── info
│   ...
...   

Autoconf

./configure 自动检测系统中的环境变量、库、头文件等,基于 configure.ac 等文件生成 Makefile 等文件。

可以指定的变量:

CC
CFLAGS
CXX
CXXFLAGS
LDFLAGS
CPPFLAGS (for both C and C++)

使用 ./configure --help 查看帮助。

觉得在命令行中指定参数不方便?

如果觉得写命令行参数太长,可以把变量指定到 config.site 文件中:

config.site
test -z "$CC" && CC=gcc-3
test -z "$CPPFLAGS" && CPPFLAGS=-I$HOME/usr/include
test -z "$LDFLAGS" && LDFLAGS=-L$HOME/usr/lib

运行 ./configure 时应当会提示如 configure: loading site script /home/adl/usr/share/config.site

不需要在源文件目录中构建

./configure 在哪里运行,程序、目标文件和库文件就在哪里生成。因此,可以任何你希望的地方开始构建项目。

mkdir build && cd build
/nfs/src/amhello-1.0/configure
make

这样可以方便地使用一份源代码为多个平台构建项目。

交叉编译

使用 --host 参数指定目标体系结构。

./configure --host=i586-mingw32msvc

--target 参数用于构建编译工具,指定编译工具的目标体系结构。

Automake

automake 接受 Makefile.am 文件,生成 Makefile.in 文件。

可以指定的变量:

DESTDIR

一些通用的 target:

all
install
clean
distclean

Libtool

libtool 用于处理库文件,可以生成 .la (libtool archive)文件。和它有关的操作都会被翻译为真实的库文件。

库文件是可移植性的地狱

在不同平台上,库文件类型不同、编译选项不同。

在 Linux 上,静态库为 .a 文件,动态库为 .so 文件。编译选项 -fPIC 用于生成位置无关代码,-shared 用于生成动态库。

在安装时可以使用下面的参数控制库文件生成:

--enable-shared
--disable-shared
--enable-static
--disable-static

附:编写模板文件

为了使用 GNU Autotools 构建项目,至少需要编写下面的文件:

  • configure.ac
  • Makefile.am
  • src/Makefile.am

autoconf 会按合适的顺序执行所有自动化工具。

autoreconf --install

CMake

问题记录

动态链接库

error while loading shared libraries: libpthread_rt.so.1: cannot open shared object file: No such file or directory

.so 文件在运行时需要被加载,应当告诉系统在哪里找到它。

  • LD_LIBRARY_PATH 用于指定动态链接库的搜索路径。
  • ldconfig 用于更新动态链接库缓存。
  • ldd 用于查看动态链接库依赖。
  • rpath 用于指定运行时搜索路径。