1. 前言
文本结合glibc-2.34的构建过程,解读其Makefile是如何工作的。
参考“glibc 知:构建2.34版本”的构建方法:
mkdir -p glibc-2.34/build
cd glibc-2.34/build
/xxxx/glibc-2.34/configure --prefix=/usr
make -j8 2>&1 | tee ../build.log
作者水平有限,只能渐进明细,本文会不断更新迭代。
1.1. 执行配置命令
执行configure之后,构建目录下生成如下一些文件:
[maminjie@fedora build]$ /mnt/hgfs/projects/opensrc/glibc/glibc-2.34/configure --prefix=/usr
[maminjie@fedora build]$ ls
bits config.h config.log config.make config.status Makefile
在当前目录下,直接执行make命令就可以进行构建glibc了。不过,这里我们先不构建,先来看一下配置生成的Makefile内容:
srcdir = /mnt/hgfs/projects/opensrc/glibc/glibc-2.34
# Uncomment the line below if you want to do parallel build.
# PARALLELMFLAGS = -j 4
.PHONY: all install bench
all .DEFAULT:
$(MAKE) -r PARALLELMFLAGS="$(PARALLELMFLAGS)" -C $(srcdir) objdir=`pwd` $@
install:
LC_ALL=C; export LC_ALL; \
$(MAKE) -r PARALLELMFLAGS="$(PARALLELMFLAGS)" -C $(srcdir) objdir=`pwd` $@
bench bench-clean bench-build:
$(MAKE) -C $(srcdir)/benchtests $(PARALLELMFLAGS) objdir=`pwd` $@
# Convenience target to rebuild ULPs for all math tests.
regen-ulps:
$(MAKE) -C $(srcdir)/math $(PARALLELMFLAGS) objdir=`pwd` $@
该Makefile内容很简单,终极目标all的执行命令是到glibc的源码目录下执行真正的Makefile。
1.2. 生成构建日志
执行make生成构建日志,如下所示:
$ make -j8 2>&1 | tee ../build.log
$ ls
abi-versions.h jmp_buf-ssp.h linkobj soversions.mk
argp jmp_buf-ssp.h.d locale stamp.o
assert ldbl-compat-choose.h localedata stamp.os
bits ld.map locale-defines.h stamp.oS
catgets libanl.map locale-defines.h.d stdio-common
config.h libBrokenLocale.map login stdlib
config.log libc.a Makefile string
config.make libc-abis.h malloc sunrpc
config.status libc-abis.stamp manual support
conform libc_malloc_debug.map math sysd-rules
cpu-features-offsets.h libc.map mathvec sysd-sorted
cpu-features-offsets.h.d libc-modules.h misc sysd-syscalls
crypt libc-modules.stmp nis sysd-versions
csu libc_nonshared.a nptl sysvipc
ctype libc_pic.a nptl_db tcb-offsets.h
debug libc_pic.opts nscd tcb-offsets.h.d
debugglibc.sh libc_pic.os nss termios
dirent libc_pic.os.clean po testrun.sh
dlfcn libcrypt.map posix time
dl-tunable-list.h libc.so pthread-pi-defines.h time64-compat.mk
dl-tunable-list.stmp libc.so.6 pthread-pi-defines.h.d time64-compat.mk.i
dummy.c libdl.map pwd timezone
dummy.o libio resolv tlsdesc.h
dummy.o.dt libm.map resource tlsdesc.h.d
elf libmvec.map rt ucontext_i.h
first-versions.h libnsl.map rtld-offsets.h ucontext_i.h.d
format.lds libnss_compat.map rtld-offsets.h.d unwindbuf.h
gmon libnss_db.map runtime-linker.h unwindbuf.h.d
gnu libnss_dns.map runtime-linker.stamp Versions.all
gnulib libnss_files.map setjmp Versions.def
grp libnss_hesiod.map shadow Versions.mk
gshadow libpthread.map shlib-versions.v versions.stmp
hesiod libresolv.map shlib-versions.v.i Versions.tmp
iconv librt.map sigaltstack-offsets.h Versions.v
iconvdata libthread_db.map sigaltstack-offsets.h.d Versions.v.i
inet libutil.map signal wcsmbs
intl link-defines.h socket wctype
io link-defines.h.d soversions.i
build.log日志文件的前面内容如下所示:
ake -r PARALLELMFLAGS="" -C /mnt/hgfs/projects/opensrc/glibc/glibc-2.34 objdir=`pwd` all
make[1]: Entering directory '/mnt/hgfs/projects/opensrc/glibc/glibc-2.34'
LC_ALL=C gawk -f scripts/sysd-rules.awk > /home/maminjie/glibc-2.34/build/sysd-rulesT \
-v all_object_suffixes='.o .os .oS' \
-v inhibit_sysdep_asm='' \
-v sysd_rules_patterns='%:% rtld-%:rtld-% rtld-%:% m_%:s_%' \
-v config_sysdirs='sysdeps/unix/sysv/linux/x86_64/64 sysdeps/unix/sysv/linux/x86_64 sysdeps/unix/sysv/linux/x86 sysdeps/x86/nptl sysdeps/unix/sysv/linux/wordsize-64 sysdeps/x86_64/nptl sysdeps/unix/sysv/linux sysdeps/nptl sysdeps/pthread sysdeps/gnu sysdeps/unix/inet sysdeps/unix/sysv sysdeps/unix/x86_64 sysdeps/unix sysdeps/posix sysdeps/x86_64/64 sysdeps/x86_64/fpu/multiarch sysdeps/x86_64/fpu sysdeps/x86/fpu sysdeps/x86_64/multiarch sysdeps/x86_64 sysdeps/x86 sysdeps/ieee754/float128 sysdeps/ieee754/ldbl-96 sysdeps/ieee754/dbl-64 sysdeps/ieee754/flt-32 sysdeps/wordsize-64 sysdeps/ieee754 sysdeps/generic'
mv -f /home/maminjie/glibc-2.34/build/sysd-rulesT /home/maminjie/glibc-2.34/build/sysd-rules
gawk -f scripts/gen-sorted.awk \
-v subdirs='csu assert ctype locale intl catgets math setjmp signal stdlib stdio-common libio malloc string wcsmbs time dirent grp pwd posix io termios resource misc socket sysvipc gmon gnulib iconv iconvdata wctype manual shadow gshadow po argp localedata timezone rt conform debug mathvec support dlfcn elf crypt' \
-v srcpfx='' \
sysdeps/nptl/Subdirs sysdeps/un
...
2. 构建
2.1. 总体机制
下面将通过分析glibc源码目录下的顶层Makefile,Makeconfig,Makerules,Rules等来解读glibc的构建机制。
2.1.1. 默认规则
$ grep -n "^include" Makefile
25:include Makeconfig
89:include Makerules
$ grep -nw "all:" Makeconfig Makerules Makefile
Makeconfig:26:all: # Make this the default goal
Makeconfig:1237:$(common-objpfx)Versions.all: $(..)scripts/firstversions.awk \
Makefile:30:all: minihelp lib others
2.1.2. lib规则
$ grep -nw "lib:" Makeconfig Makerules Makefile
Makerules:835:lib: lib-noranlib $(foreach l,$(libtypes),$(patsubst %,$(common-objpfx)$l,c))
Makerules:981:install-lib.so := $(filter %.so,$(install-lib:%_pic.a=%.so))
Makefile:131:lib: $(common-objpfx)libc.so $(common-objpfx)linkobj/libc.so
$ grep -nw "lib-noranlib:" Makeconfig Makerules Makefile
Makerules:836:lib-noranlib: libobjs
Makefile:127:lib-noranlib: subdir_lib
$ grep -nw "libobjs:" Makeconfig Makerules Makefile
Makerules:896:libobjs: $(foreach o,$(object-suffixes-for-libc),$(objpfx)stamp$o)
目标lib的依赖分别是:stamp$o,subdir_lib,libtypes,libc.so几个。
2.1.3. stamp规则
stamp%o是glibc中间目标文件的时间戳文件
$ grep -n stamp Makeconfig Makerules Makefile
Makerules:294:# We use a stamp file to avoid unnecessary recompilations.
Makerules:849:# Create the stamp$o files to keep the parent makefile happy.
Makerules:850:subdir_lib: $(foreach o,$(object-suffixes-for-libc),$(objpfx)stamp$o)
Makerules:851:$(foreach o,$(object-suffixes-for-libc),$(objpfx)stamp$o):
Makerules:856:# Define explicit rules to update each $(objpfx)stamp.SUFFIX
Makerules:857:# timestamp file; these rules (one explicit rule is generated for each
Makerules:858:# object suffix) write a list of objects to update in the stamp file.
Makerules:862:$(objpfx)stamp$o: $(o-objects); $$(do-stamp)
Makerules:864:define do-stamp
Makerules:875:# on the stamp files built above.
Makerules:878: $(subdirs-stamp-o) $(common-objpfx)stamp$o; $$(do-makelib)
Makerules:884:subdirs-stamps := $(foreach d,$(subdirs),$(common-objpfx)$d/stamp%)
Makerules:885:subdirs-stamp-o = $(subst %,$o,$(subdirs-stamps))
Makerules:887:$(subdirs-stamps): subdir_lib;
Makerules:896:libobjs: $(foreach o,$(object-suffixes-for-libc),$(objpfx)stamp$o)
Makerules:1464:-rm -f $(objpfx)stamp$o $(o-objects))
Makerules文件中关于stamp内容如下:
# For object-suffix $o, the list of objects with that suffix.
# Makefiles can define `elide-routines.so = foo' to leave foo.so out.
o-objects = $(patsubst %.o,%$o,$(filter-out $(patsubst %,$(objpfx)%.o,\
$(elide-routines$o)),\
$(objects))) \
$(addprefix $(objpfx),$(o-objects$o))
others: $(addprefix $(objpfx),$(install-lib))
ifndef objects
# Create the stamp$o files to keep the parent makefile happy.
subdir_lib: $(foreach o,$(object-suffixes-for-libc),$(objpfx)stamp$o)
$(foreach o,$(object-suffixes-for-libc),$(objpfx)stamp$o):
$(make-target-directory)
rm -f $@; > $@
else
# Define explicit rules to update each $(objpfx)stamp.SUFFIX
# timestamp file; these rules (one explicit rule is generated for each
# object suffix) write a list of objects to update in the stamp file.
# The parent will then actually add them all to the archive in the
# archive rule, below.
define o-iterator-doit
$(objpfx)stamp$o: $(o-objects); $$(do-stamp)
endef
define do-stamp
$(make-target-directory)
echo '$(patsubst $(objpfx)%,$(addsuffix /,$(subdir))%,$^)' > $@T
mv -f $@T $@
endef
object-suffixes-left := $(object-suffixes-for-libc)
include $(o-iterator)
endif
根据构建过程,结合构建规则,实际glibc各子目录下生成的stamp%o文件内容为各子目录编译的中间o文件列表。
以csu子目录为例:
[maminjie@fedora csu]$ ls
abi-note.o dso_handle.o.dt gmon-start.os.dt Mcrt1.o sysdep.o
abi-note.o.dt dso_handle.os init-first.o Scrt1.o sysdep.o.dt
abi-tag.h dso_handle.os.dt init-first.o.dt stamp.o sysdep.os
check_fds.o errno-loc.o init-first.os stamp.os sysdep.os.dt
check_fds.o.dt errno-loc.o.dt init-first.os.dt stamp.oS unwind-resume.os
check_fds.os errno-loc.os init.o start.o unwind-resume.os.dt
check_fds.os.dt errno-loc.os.dt init.o.dt start.o.dt version.o
crt1.o errno.o libc-start.o start.os version.o.dt
crti.o errno.o.dt libc-start.o.dt start.os.dt version.os
crti.o.dt errno.os libc-start.os static-reloc.o version.os.dt
crtn.o errno.os.dt libc-start.os.dt static-reloc.o.dt
crtn.o.dt gcrt1.o libc-tls.o static-reloc.os
dso_handle.o gmon-start.os libc-tls.o.dt static-reloc.os.dt
[maminjie@fedora csu]$ cat stamp.o
csu/init-first.o csu/libc-start.o csu/sysdep.o csu/version.o csu/check_fds.o csu/libc-tls.o csu/dso_handle.o csu/errno.o csu/errno-loc.o
[maminjie@fedora csu]$ cat stamp.os
csu/init-first.os csu/libc-start.os csu/sysdep.os csu/version.os csu/check_fds.os csu/dso_handle.os csu/unwind-resume.os csu/errno.os csu/errno-loc.os
2.1.4. subdir_lib规则
$ grep -nw "subdir_lib" Makeconfig Makerules Makefile
Makerules:850:subdir_lib: $(foreach o,$(object-suffixes-for-libc),$(objpfx)stamp$o)
Makerules:887:$(subdirs-stamps): subdir_lib;
Makefile:61:+subdir_targets := subdir_lib objects objs others subdir_mostlyclean \
Makefile:127:lib-noranlib: subdir_lib
Makefile文件中关于subdir_lib的主要内容如下:
# These are the targets that are made by making them in each subdirectory.
+subdir_targets := subdir_lib objects objs others subdir_mostlyclean \
subdir_clean subdir_distclean subdir_realclean \
tests xtests \
subdir_update-abi subdir_check-abi \
subdir_update-all-abi \
subdir_echo-headers \
subdir_install \
subdir_objs subdir_stubs subdir_testclean \
$(addprefix install-, no-libc.a bin lib data headers others)
...
# For each target, make it depend on DIR/target for each subdirectory DIR.
$(+subdir_targets): %: $(addsuffix /%,$(subdirs))
# Compute a list of all those targets.
all-subdirs-targets := $(foreach dir,$(subdirs),\
$(addprefix $(dir)/,$(+subdir_targets)))
# The action for each of those is to cd into the directory and make the
# target there.
$(all-subdirs-targets):
$(MAKE) $(PARALLELMFLAGS) $(subdir-target-args) $(@F)
define subdir-target-args
subdir=$(@D)$(if $($(@D)-srcdir),\
-C $($(@D)-srcdir) ..=`pwd`/,\
-C $(@D) ..=../)
endef
subdir_lib目标实际上是递归glibc的源码子目录,编译每个子目录的subdir_lib目标,其它子目录目标类比,简单的解析如下:
subdirs := csu iconv locale ...
subdir_lib: csu/subdir_lib iconv/subdir_lib locale/subdir_lib
all-subdirs-targets := csu/subdir_lib csu/objects ... iconv/subdir_lib iconv/objects ..
csu/subdir_lib:
$(MAKE) $(PARALLELMFLAGS) $(subdir-target-args) subdir_lib
iconv/subdir_lib:
$(MAKE) $(PARALLELMFLAGS) $(subdir-target-args) subdir_lib
2.1.4.1. subdirs列表
subdirs的内容如下所示:
$ grep -nw "subdirs" Makeconfig Makerules Makefile
Makeconfig:1103:subdirs = $(sorted-subdirs)
$ grep -rn sorted-subdirs
build/sysd-sorted:6:sorted-subdirs := csu iconv locale localedata iconvdata assert ctype intl catgets math setjmp signal stdlib stdio-common libio dlfcn nptl rt malloc string wcsmbs timezone time dirent grp pwd posix io termios resource misc socket sysvipc gmon gnulib wctype manual shadow gshadow po argp conform debug mathvec support crypt nptl_db inet resolv nss hesiod sunrpc nis nscd login elf
$ $ grep -n sysd-sorted Makeconfig Makerules Makefile
Makeconfig:1102:-include $(common-objpfx)sysd-sorted
...
Makeconfig:1342:$(common-objpfx)sysd-sorted: $(..)scripts/gen-sorted.awk \
Makefile:507: $(addprefix $(objpfx),sysd-sorted soversions.mk soversions.i)
Makeconfig文件中生成sysd-sorted文件的主要内容如下:
# This is a partial list of subdirectories containing the library source.
# The order is more or less arbitrary. The sorting step will take care of the
# dependencies and generate sorted-subdirs dynamically.
all-subdirs = csu assert ctype locale intl catgets math setjmp signal \
stdlib stdio-common libio malloc string wcsmbs time dirent \
grp pwd posix io termios resource misc socket sysvipc gmon \
gnulib iconv iconvdata wctype manual shadow gshadow po argp \
localedata timezone rt conform debug mathvec support \
dlfcn elf
ifeq ($(build-crypt),yes)
all-subdirs += crypt
rpath-dirs += crypt
endif
ifndef avoid-generated
# sysd-sorted itself will contain rules making the sysd-sorted target
# depend on Depend files. But if you just added a Depend file to an
# existing directory not in all-subdirs, then sysd-sorted needs to
# be regenerated, so it depends on existing $(sorted-subdirs:=/Depend) files.
all-Depend-files := $(wildcard $(sort \
$(foreach dir,$(all-subdirs),\
$(firstword $($(dir)-srcdir) \
$(..)$(dir))/Depend) \
$(sorted-subdirs:=/Depend)))
$(common-objpfx)sysd-sorted: $(..)scripts/gen-sorted.awk \
$(common-objpfx)config.make $(..)Makeconfig \
$(wildcard $(sysdirs:=/Subdirs)) \
$(all-Depend-files)

最低0.47元/天 解锁文章
2万+

被折叠的 条评论
为什么被折叠?



