编译,链接和构建
《程序员的自我修养–链接,装载与库》这本书是在读研时才看的,印象很深,现在想想这本书讲的都是程序员,尤其是从事系统编程的必备素养。这里我将平时使用的跟编译,链接和构建应用程序及库相关的知识记录下来,希望以后能温故知新。
编译与链接
-
gcc
-
clang
-
bfd (使用 Binary File Descriptor 库构建的 Linker, Ubuntu 上默认的 ld)
-
gold (google loader)
-
mold (modern loader)
Note:
- ld 这个名字是历史遗留,实际上面这些 ld 并不负责加载程序或库,它们负责在编译阶段生成可执行程序 ELF 时符号和地址的"拼装"
- 负责运行时链接和加载库的是
/lib32/ld-linux.so.2
或/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
,它们即是所谓的动态链接器
gcc 的优化级别
-O
和 -O1
是等价的。 -O
会对目标文件大小和执行时间进行优化,但不会进行非常耗时的优化,以下是 -O
打开的优化: (其中红色的是 -Og
关闭的)
- -fauto-inc-dec
- -fbranch-count-reg
- -fcombine-stack-adjustments
- -fcompare-elim
- -fcprop-registers
- -fdce
- -fdefer-pop
- -fdelayed-branch
- -fdse
- -fforward-propagate
- -fguess-branch-probability
- -fif-conversion
- -fif-conversion2
- -finline-functions-called-once
- -fipa-modref
- -fipa-profile
- -fipa-reference
- -fipa-reference-addressable
- -fmerge-constants
- -fmove-loop-invariants
- -fmove-loop-stores
- -fomit-frame-pointer
- -freorder-blocks
- -fshrink-wrap
- -fshrink-wrap-separate
- -fsplit-wide-types
- -fssa-backprop
- -fssa-phiopt
- -ftree-bit-ccp
- -ftree-ccp
- -ftree-ch
- -ftree-coalesce-vars
- -ftree-copy-prop
- -ftree-dce
- -ftree-dominator-opts
- -ftree-dse
- -ftree-forwprop
- -ftree-fre
- -ftree-phiprop
- -ftree-pta
- -ftree-scev-cprop
- -ftree-sink
- -ftree-slsr
- -ftree-sra
- -ftree-ter
- -funit-at-a-time
动态库都去哪儿呢
- pkg-config
pkg-config (symbolic link to /usr/bin/pkgconf
) 是用来获取系统上安装的库的信息的程序。cmake, meson 这些构建系统底层都是靠它来解析依赖包的。 下面的命令可以查看 pkg-config 工作时所搜索的路径和优先次序, 用户也可以通过环境变量 PKG_CONFIG_PATH
来指定自己想要优先搜索的路径。
1 | pkg-config --variable pc_path pkg-config | sed 's/:/\n/g' |
1 | /usr/local/lib/x86_64-linux-gnu/pkgconfig |
pkg-config
是二进制可执行程序 /usr/bin/pkgconf
的一个符号链接文件,它是 CMake, meson 等构建系统主要使用的系统动态库检测的工具。pkg-config
本质上是在解析 *.pc
文件。下面是常见的 Mesa OpenGL Library 的 .pc 文件。
1 | ➜ piglit git:(main) ✗ find /usr -name 'gl.pc' -ls |
lib*-dev
与lib*
的区别
1 | $ dpkg -L libxcb1 |
1 | $ dpkg -L libxcb1-dev |
/usr/sbin/ldconfig
Configure Dynamic Linker Run Time Bindings
1 |
|
GOT, PLT & PIC
- GOT Global Offset Table
- PLT Procedure Linkage Table
- PIC Position Independent Code
构建系统
- autotools
- cmake
- make
- meson
- ninja
- scons
autotools
flowchart LR
autoreconf(("autoreconf<br>[Perl script]"))
autoconf(autoconf)
aclocal(aclocal)
automake(automake)
autoheader(autoheader)
gettextize(gettextize)
libtoolize(libtoolize)
am@{shape: docs, label: "Makefile.am"}
in@{shape: docs, label: "Makefile.in"}
mk@{shape: docs, label: "Makefile"}
ac@{shape: paper-tape, label: "configure.ac"}
co@{shape: paper-tape, label: "configure<br>[Shell script]"}
autoreconf --> autoconf
autoreconf -.-> aclocal
autoreconf -.-> automake
autoreconf -.-> autoheader
autoreconf -.-> gettextize
autoreconf -.-> libtoolize
am --> automake --> in
ac --> autoconf --> co
in --> co --> mk
autotools 的唯一的可取处就是 GNU 项目广泛使用它。使用它的项目的构建步骤一般是
1 | ./autogen.sh |
当你遇到 ./autogen.sh: 13: autoreconf: not found
这样的错误时,你可能需要安装这些软件包
1 | sudo apt-get install autoconf automake libtool gettext |
cmake
- use
gold
1 | cmake -B build -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=On -DCMAKE_EXE_LINKER_FLAGS=-fuse-ld=gold |
meson
meson 的 buildtype 是用来设定编译优化级别 (optimization levels: -O0, -O1, -O2, -O3, -Os) 和是否有调试信息 (debug: -g)。 实际上,meson 提供两个分开的选项分别控制编译优化级别和调试信息
-
-Doptimization (plain|0|2|3|s, plain 指不设置任何 optimization flags)
-
-Ddebug (true|false)
-
只编译某个 target
1 | ninja -C build target |
- meson install --tags tag1,tag2
Installation tags 是专门为打包 (packaging) 设计的,因为打包时开发文件包(头文件),文档包 (mannul) 和二进制包 (shared libraries) 一般是分开的 3 个包。所以 meson install --tags
可以让用户分 3 次安装,每次只安装这个包所需的文件。meson 有几个预定义的 tags (不用用户自己使用 install_tag
关键字去指定 tag 名)
tags | files |
---|---|
devel | static_library(), install_headers(), .a, .pc |
runtime | executable(), shared_library(), shared_module(), .so, .dll |
man | install_man() |
doc | hotdoc.generate_doc() |
i18n | i18n.gettext(), files installed into localedir |
bin | scripts and executables bundled with a library used by end users |
bin-devel | scripts and executables bundled with a library used by developers |
- use
gold
1 | meson build --prefix=/usr -D{c,cpp}_args=-fuse-ld=gold -Dflavors=x11-gl,x11-glesv2 |