glibc 知:构建机制

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)
	$(AWK) -f $< \
	       -v subdirs='$(all-subdirs)' \
	       -v srcpfx='$(..)' \
	       $(filter %/Subdirs %/Depend,$^) > $@-tmp
	mv -f $@-tmp $@
$(all-Depend-files): ;
endif

构建顺序是按照sorted-subdirs列表的顺序,如下所示:

[maminjie@fedora glibc]$ grep "make  subdir" build.log
make  subdir=csu -C csu ..=../ subdir_lib
make  subdir=iconv -C iconv ..=../ subdir_lib
make  subdir=locale -C locale ..=../ subdir_lib
make  subdir=localedata -C localedata ..=../ subdir_lib
make  subdir=iconvdata -C iconvdata ..=../ subdir_lib
make  subdir=assert -C assert ..=../ subdir_lib
make  subdir=ctype -C ctype ..=../ subdir_lib
make  subdir=intl -C intl ..=../ subdir_lib
make  subdir=catgets -C catgets ..=../ subdir_lib
make  subdir=math -C math ..=../ subdir_lib
make  subdir=setjmp -C setjmp ..=../ subdir_lib
make  subdir=signal -C signal ..=../ subdir_lib
make  subdir=stdlib -C stdlib ..=../ subdir_lib
make  subdir=stdio-common -C stdio-common ..=../ subdir_lib
make  subdir=libio -C libio ..=../ subdir_lib
make  subdir=dlfcn -C dlfcn ..=../ subdir_lib
make  subdir=nptl -C nptl ..=../ subdir_lib
make  subdir=rt -C rt ..=../ subdir_lib
make  subdir=malloc -C malloc ..=../ subdir_lib
make  subdir=string -C string ..=../ subdir_lib
make  subdir=wcsmbs -C wcsmbs ..=../ subdir_lib
make  subdir=timezone -C timezone ..=../ subdir_lib
make  subdir=time -C time ..=../ subdir_lib
make  subdir=dirent -C dirent ..=../ subdir_lib
make  subdir=grp -C grp ..=../ subdir_lib
make  subdir=pwd -C pwd ..=../ subdir_lib
make  subdir=posix -C posix ..=../ subdir_lib
make  subdir=io -C io ..=../ subdir_lib
make  subdir=termios -C termios ..=../ subdir_lib
make  subdir=resource -C resource ..=../ subdir_lib
make  subdir=misc -C misc ..=../ subdir_lib
make  subdir=socket -C socket ..=../ subdir_lib
make  subdir=sysvipc -C sysvipc ..=../ subdir_lib
make  subdir=gmon -C gmon ..=../ subdir_lib
make  subdir=gnulib -C gnulib ..=../ subdir_lib
make  subdir=wctype -C wctype ..=../ subdir_lib
make  subdir=manual -C manual ..=../ subdir_lib
make  subdir=shadow -C shadow ..=../ subdir_lib
make  subdir=gshadow -C gshadow ..=../ subdir_lib
make  subdir=po -C po ..=../ subdir_lib
make  subdir=argp -C argp ..=../ subdir_lib
make  subdir=conform -C conform ..=../ subdir_lib
make  subdir=debug -C debug ..=../ subdir_lib
make  subdir=mathvec -C mathvec ..=../ subdir_lib
make  subdir=support -C support ..=../ subdir_lib
make  subdir=crypt -C crypt ..=../ subdir_lib
make  subdir=nptl_db -C nptl_db ..=../ subdir_lib
make  subdir=inet -C inet ..=../ subdir_lib
make  subdir=resolv -C resolv ..=../ subdir_lib
make  subdir=nss -C nss ..=../ subdir_lib
make  subdir=hesiod -C hesiod ..=../ subdir_lib
make  subdir=sunrpc -C sunrpc ..=../ subdir_lib
make  subdir=nis -C nis ..=../ subdir_lib
make  subdir=nscd -C nscd ..=../ subdir_lib
make  subdir=login -C login ..=../ subdir_lib
make  subdir=elf -C elf ..=../ subdir_lib
make  subdir=csu -C csu ..=../ others
make  subdir=iconv -C iconv ..=../ others
make  subdir=locale -C locale ..=../ others
make  subdir=localedata -C localedata ..=../ others
make  subdir=iconvdata -C iconvdata ..=../ others
make  subdir=assert -C assert ..=../ others
make  subdir=ctype -C ctype ..=../ others
make  subdir=intl -C intl ..=../ others
make  subdir=catgets -C catgets ..=../ others
make  subdir=math -C math ..=../ others
make  subdir=setjmp -C setjmp ..=../ others
make  subdir=signal -C signal ..=../ others
make  subdir=stdlib -C stdlib ..=../ others
make  subdir=stdio-common -C stdio-common ..=../ others
make  subdir=libio -C libio ..=../ others
make  subdir=dlfcn -C dlfcn ..=../ others
make  subdir=nptl -C nptl ..=../ others
make  subdir=rt -C rt ..=../ others
make  subdir=malloc -C malloc ..=../ others
make  subdir=string -C string ..=../ others
make  subdir=wcsmbs -C wcsmbs ..=../ others
make  subdir=timezone -C timezone ..=../ others
make  subdir=time -C time ..=../ others
make  subdir=dirent -C dirent ..=../ others
make  subdir=grp -C grp ..=../ others
make  subdir=pwd -C pwd ..=../ others
make  subdir=posix -C posix ..=../ others
make  subdir=io -C io ..=../ others
make  subdir=termios -C termios ..=../ others
make  subdir=resource -C resource ..=../ others
make  subdir=misc -C misc ..=../ others
make  subdir=socket -C socket ..=../ others
make  subdir=sysvipc -C sysvipc ..=../ others
make  subdir=gmon -C gmon ..=../ others
make  subdir=gnulib -C gnulib ..=../ others
make  subdir=wctype -C wctype ..=../ others
make  subdir=manual -C manual ..=../ others
make  subdir=shadow -C shadow ..=../ others
make  subdir=gshadow -C gshadow ..=../ others
make  subdir=po -C po ..=../ others
make  subdir=argp -C argp ..=../ others
make  subdir=conform -C conform ..=../ others
make  subdir=debug -C debug ..=../ others
make  subdir=mathvec -C mathvec ..=../ others
make  subdir=support -C support ..=../ others
make  subdir=crypt -C crypt ..=../ others
make  subdir=nptl_db -C nptl_db ..=../ others
make  subdir=inet -C inet ..=../ others
make  subdir=resolv -C resolv ..=../ others
make  subdir=nss -C nss ..=../ others
make  subdir=hesiod -C hesiod ..=../ others
make  subdir=sunrpc -C sunrpc ..=../ others
make  subdir=nis -C nis ..=../ others
make  subdir=nscd -C nscd ..=../ others
make  subdir=login -C login ..=../ others
make  subdir=elf -C elf ..=../ others

2.1.5. libtypes规则

$ grep -n libtypes Makeconfig Makerules Makefile
Makeconfig:1035:libtypes = $(foreach o,$(object-suffixes-for-libc),$(libtype$o))
Makerules:820:.PRECIOUS: $(foreach l,$(libtypes),$(patsubst %,$(common-objpfx)$l,c))
Makerules:835:lib: lib-noranlib $(foreach l,$(libtypes),$(patsubst %,$(common-objpfx)$l,c))

Makeconfig文件中关于libtypes的内容如下:

# Enable object files for different versions of the library.
# Various things use $(object-suffixes) to know what all to make.
# The compilation rules use $(CPPFLAGS-${SUFFIX}) and $(CFLAGS-${SUFFIX})
# to pass different flags for each flavor.
libtypes = $(foreach o,$(object-suffixes-for-libc),$(libtype$o))
# .op may be added to all-object-suffixes below.
all-object-suffixes := .o .os .oS
object-suffixes :=
CPPFLAGS-.o = $(pic-default)
# libc.a must be compiled with -fPIE/-fpie for static PIE.
CFLAGS-.o = $(filter %frame-pointer,$(+cflags)) $(pie-default)
libtype.o := lib%.a
object-suffixes += .o
ifeq (yes,$(build-shared))
# Under --enable-shared, we will build a shared library of PIC objects.
# The PIC object files are named foo.os.
object-suffixes += .os
CPPFLAGS-.os = -DPIC -DSHARED
CFLAGS-.os = $(filter %frame-pointer,$(+cflags)) $(pic-ccflag)
libtype.os := lib%_pic.a
...

# Convenience variable for when we want to treat shared-library cases
# differently from the rest.
object-suffixes-noshared := $(filter-out .os,$(object-suffixes))

object-suffixes-for-libc := $(object-suffixes)

ifeq (yes,$(build-shared))
# Build special library that contains the static-only routines for libc.
object-suffixes-for-libc += .oS

# Must build the routines as PIC, though, because they can end up in (users')
# shared objects.  We don't want to use CFLAGS-os because users may, for
# example, make that processor-specific.
CFLAGS-.oS = $(CFLAGS-.o) $(PIC-ccflag) $(extra-nonshared-cflags)
CPPFLAGS-.oS = $(CPPFLAGS-.o) -DPIC -DLIBC_NONSHARED=1
libtype.oS = lib%_nonshared.a
endif

libtypes为:libtype.o,libtype.os等。
libtype$o为:lib%.a,lib%_pic.a等静态库

Makerules文件中关于libtype$o的内容如下:

# Now define explicit rules to build the library archives; these depend
# on the stamp files built above.
define o-iterator-doit
$(common-objpfx)$(patsubst %,$(libtype$o),c): \
		$(subdirs-stamp-o) $(common-objpfx)stamp$o; $$(do-makelib)
endef
define do-makelib
cd $(common-objdir) && \
$(AR) $(CREATE_ARFLAGS) $(@F) `cat $(patsubst $(common-objpfx)%,%,$^)`
endef
subdirs-stamps := $(foreach d,$(subdirs),$(common-objpfx)$d/stamp%)
subdirs-stamp-o = $(subst %,$o,$(subdirs-stamps))
ifndef subdir
$(subdirs-stamps): subdir_lib;
endif
object-suffixes-left = $(object-suffixes-for-libc)
include $(o-iterator)
2.1.5.1. o-iterator

o-iterator-doit在o-iterator.mk中调用展开:

$ grep -rn o-iterator-doit
o-iterator.mk:9:$(o-iterator-doit)

o-iterator.mk内容如下:

o := $(firstword $(object-suffixes-left))
object-suffixes-left := $(filter-out $o,$(object-suffixes-left))

$(o-iterator-doit)

o-iterator.mk通过include $(o-iterator)包含进Makerules中,如下所示:

$ grep -nw "o-iterator" Makeconfig Makerules Makefile
Makerules:62:o-iterator = $(patsubst %,$(..)o-iterator.mk,$(object-suffixes-left))

Makerules文件中关于o-iterator的内容如下:

# This variable is used in ``include $(o-iterator)'' after defining
# $(o-iterator-doit) to produce some desired rule using $o for the object
# suffix, and setting $(object-suffixes-left) to $(object-suffixes); a copy
# is produced for each object suffix in use.
o-iterator = $(patsubst %,$(..)o-iterator.mk,$(object-suffixes-left))

libtype$o最后被转为:libc.a,libc_pic.a等静态库,这些静态库基于各子目录subdirs中的时间戳stamp$o文件取出中间目标文件,然后通过ar命令归档。

[maminjie@fedora glibc]$ grep libc_pic.a build.log
cd /home/maminjie/glibc-2.34/build && ar cruv libc_pic.a `cat csu/stamp.os iconv/stamp.os locale/stamp.os localedata/stamp.os iconvdata/stamp.os assert/stamp.os ctype/stamp.os intl/stamp.os catgets/stamp.os math/stamp.os setjmp/stamp.os signal/stamp.os stdlib/stamp.os stdio-common/stamp.os libio/stamp.os dlfcn/stamp.os nptl/stamp.os rt/stamp.os malloc/stamp.os string/stamp.os wcsmbs/stamp.os timezone/stamp.os time/stamp.os dirent/stamp.os grp/stamp.os pwd/stamp.os posix/stamp.os io/stamp.os termios/stamp.os resource/stamp.os misc/stamp.os socket/stamp.os sysvipc/stamp.os gmon/stamp.os gnulib/stamp.os wctype/stamp.os manual/stamp.os shadow/stamp.os gshadow/stamp.os po/stamp.os argp/stamp.os conform/stamp.os debug/stamp.os mathvec/stamp.os support/stamp.os crypt/stamp.os nptl_db/stamp.os inet/stamp.os resolv/stamp.os nss/stamp.os hesiod/stamp.os sunrpc/stamp.os nis/stamp.os nscd/stamp.os login/stamp.os elf/stamp.os stamp.os`
...

2.1.6. libc.so规则

$ grep -nw "libc.so:" Makeconfig Makerules Makefile
Makerules:686:$(common-objpfx)libc.so: link-libc-deps = # empty
Makerules:687:$(common-objpfx)linkobj/libc.so: link-libc-deps = # empty
Makerules:691:$(common-objpfx)libc.so: $(common-objpfx)libc_pic.os$(libc_pic_clean) \
Makerules:699:$(common-objpfx)linkobj/libc.so: $(common-objpfx)linkobj/libc_pic.a \
Makerules:708:$(common-objpfx)libc.so: $(common-objpfx)libc.map
Makerules:1056:$(inst_libdir)/libc.so: $(common-objpfx)format.lds \
Makerules:1075:$(inst_slibdir)/libc.so: $(common-objpfx)libc.so $(+force)

libc.so依赖libc_pic.a。

由上面libtypes规则知道libc_pic.a由各个子目录编译出的中间目标文件归档而来。

Makerules文件中关于libc.so的主要内容如下所示:


define build-shlib-helper
$(LINK.o) -shared -static-libgcc -Wl,-O1 $(sysdep-LDFLAGS) \
	  $(if $($(@F)-no-z-defs)$(no-z-defs),,-Wl,-z,defs) $(rtld-LDFLAGS) \
	  $(extra-B-$(@F:lib%.so=%).so) -B$(csu-objpfx) \
	  $(extra-B-$(@F:lib%.so=%).so) $(load-map-file) \
	  -Wl,-soname=lib$(libprefix)$(@F:lib%.so=%).so$($(@F)-version) \
	  $(LDFLAGS.so) $(LDFLAGS-lib.so) $(LDFLAGS-$(@F:lib%.so=%).so) \
	  -L$(subst :, -L,$(rpath-link)) -Wl,-rpath-link=$(rpath-link)
endef
...

define build-shlib
$(build-shlib-helper) -o $@ $(shlib-lds-flags) \
	  $(csu-objpfx)abi-note.o $(build-shlib-objlist)
endef
...
# Clear link-libc-deps for the libc.so libraries so build-shlibs does not
# filter ld.so out of the list of linked objects.
$(common-objpfx)libc.so: link-libc-deps = # empty
$(common-objpfx)linkobj/libc.so: link-libc-deps = # empty

# Use our own special initializer and finalizer files for the libc.so
# libraries.
$(common-objpfx)libc.so: $(common-objpfx)libc_pic.os$(libc_pic_clean) \
			 $(elf-objpfx)sofini.os \
			 $(elf-objpfx)interp.os \
			 $(elf-objpfx)ld.so \
			 $(shlib-lds)
	$(build-shlib)
	$(call after-link,$@)

$(common-objpfx)linkobj/libc.so: $(common-objpfx)linkobj/libc_pic.a \
			 $(elf-objpfx)sofini.os \
			 $(elf-objpfx)interp.os \
			 $(elf-objpfx)ld.so \
			 $(shlib-lds)
	$(build-shlib)
	$(call after-link,$@)

ifeq ($(build-shared),yes)
$(common-objpfx)libc.so: $(common-objpfx)libc.map
endif
common-generated += libc.so libc_pic.os
ifdef libc.so-version
$(common-objpfx)libc.so$(libc.so-version): $(common-objpfx)libc.so
	$(make-link)
common-generated += libc.so$(libc.so-version)
endif
...

2.2. 系统调用的选择机制

在“glibc 知:系统调用”中作者发现glibc中对于系统调用会有很多同名c文件(实现文件),这些文件最终使用的是哪个,作者当时没有找到直接依据,只是大胆猜测其使用顺序:优先使用特定架构下的,其次是linux下的,再是generic下面的,最后是glibc自实现的(往往是空函数)。本次,作者根据构建机制再探究竟。

glibc提供的系统调用一般与平台相关,不同的平台有不同的实现。glibc的做法是平台无关目录下提供一个默认的实现,返回ENOSYS;在具体的平台目录下再有一个真正的实现。

2.2.1. strcpy实现

以strcpy为例,其它系统调用读者可以根据机制自行推导。

$ $ find -name strcpy.*
./string/strcpy.c
./sysdeps/aarch64/strcpy.S
./sysdeps/alpha/strcpy.S
./sysdeps/arm/armv6/strcpy.S
./sysdeps/csky/abiv2/strcpy.S
./sysdeps/i386/i586/strcpy.S
./sysdeps/i386/i686/multiarch/strcpy.c
./sysdeps/ia64/strcpy.S
./sysdeps/powerpc/powerpc32/405/strcpy.S
./sysdeps/powerpc/powerpc32/strcpy.S
./sysdeps/powerpc/powerpc64/le/power9/strcpy.S
./sysdeps/powerpc/powerpc64/multiarch/strcpy.c
./sysdeps/powerpc/powerpc64/power8/strcpy.S
./sysdeps/s390/strcpy.c
./sysdeps/sparc/sparc32/sparcv9/strcpy.S
./sysdeps/sparc/sparc32/strcpy.S
./sysdeps/sparc/sparc64/strcpy.S
./sysdeps/x86_64/multiarch/strcpy.c
./sysdeps/x86_64/strcpy.S

2.2.2. 系统依赖规则

Makerules文件中关于系统依赖规则的内容如下:

###############################################################################
# NOTE!  Everything adding to before-compile needs to come before this point! #
###############################################################################

# Generate an ordered list of implicit rules which find the source files in
# each sysdep directory.  The old method was to use vpath to search all the
# sysdep directories.  However, that had the problem that a .S file in a
# later directory would be chosen over a .c file in an earlier directory,
# which does not preserve the desired sysdeps ordering behavior.

# System-dependent makefiles can put in `inhibit-sysdep-asm' regexps
# matching sysdep directories whose assembly source files should be
# suppressed.

-include $(common-objpfx)sysd-rules
ifneq ($(sysd-rules-sysdirs),$(config-sysdirs))
# The value of $(+sysdep_dirs) the sysd-rules was computed for
# differs from the one we are using now.  So force a rebuild of sysd-rules.
sysd-rules-force = FORCE
FORCE:
endif
$(common-objpfx)sysd-rules: $(..)scripts/sysd-rules.awk \
			    $(common-objpfx)config.make $(..)Makerules \
			    $(sysdep-makefiles) $(sysdep-makeconfigs) \
			    $(sysd-rules-force)
	-@rm -f $@T
	LC_ALL=C $(AWK) -f $< > $@T \
			-v all_object_suffixes='$(all-object-suffixes)' \
			-v inhibit_sysdep_asm='$(inhibit-sysdep-asm)' \
			-v sysd_rules_patterns='$(sysd-rules-patterns)' \
			-v config_sysdirs='$(config-sysdirs)'
	mv -f $@T $@

ifndef sysd-rules-done
# Don't do deps until this exists, because it provides rules to make the deps.
no_deps=t
endif

define o-iterator-doit
$(objpfx)%$o: %.S $(before-compile); $$(compile-command.S)
endef
object-suffixes-left := $(all-object-suffixes)
include $(o-iterator)

define o-iterator-doit
$(objpfx)%$o: %.c $(before-compile); $$(compile-command.c)
endef
object-suffixes-left := $(all-object-suffixes)
include $(o-iterator)

define o-iterator-doit
$(objpfx)%$o: %.cc $(before-compile); $$(compile-command.cc)
endef
object-suffixes-left := $(all-object-suffixes)
include $(o-iterator)
...

生成隐式规则的有序列表,这些规则在每个sysdep目录中查找源文件。旧方法是使用vpath搜索所有sysdep目录。然而,它有一个问题,即在一个更后的目录中选择一个.S文件,而不是在一个更前的目录中选择一个.c文件,这不会保留所需的sysdeps排序行为。

1)sysd-rules中处理的是系统依赖目录下的实现。
2)o-iterator处理的是当前目录下的实现。

疑问:这里对于多实现的文件,其目标都是一个,Makefile中对于多规则目标的约定,此处的用法似乎有点问题,莫非高版本的make支持这种用法??

before-compile和compile-command的定义如下:

canpool@DESKTOP-ODCM7SC:~/projects/linux/glibc$ grep -rn ^before-compile
csu/Makefile:92:before-compile += $(objpfx)abi-tag.h
elf/Makefile:190:before-compile  += $(objpfx)trusted-dirs.h
iconvdata/Makefile:209:before-compile += $(addprefix $(objpfx),$(generated-modules:=.h))
intl/Makefile:37:before-compile += $(objpfx)msgs.h
locale/Makefile:42:before-compile       += $(objpfx)C-translit.h
mach/Machrules:196:before-compile += $(interface-headers:%=$(objpfx)%)
mach/Makefile:159:before-compile += $(objpfx)mach-shortcuts.h
Makeconfig:1174:before-compile += $(common-objpfx)libc-modules.h
Makeconfig:1193:before-compile += $(common-objpfx)dl-tunable-list.h
Makeconfig:1214:before-compile += $(common-objpfx)gcc-macros.h
Makerules:90:before-compile := $(filter $(common-objpfx)mach% $(common-objpfx)hurd%,\
Makerules:98:before-compile := $(common-objpfx)abi-versions.h $(before-compile)
Makerules:111:before-compile := $(common-objpfx)first-versions.h \
Makerules:129:before-compile := $(common-objpfx)cstdlib $(common-objpfx)cmath \
Makerules:140:before-compile := $(common-objpfx)bits/std_abs.h $(before-compile)
Makerules:147:before-compile := $(common-objpfx)libc-abis.h $(before-compile)
Makerules:174:before-compile += $(objpfx).
Makerules:185:before-compile := $(filter-out $(wildcard $(before-compile)),$(before-compile))
Makerules:281:before-compile += $(gen-as-const-headers:%.sym=$(common-objpfx)%.h)
Makerules:295:before-compile += $(common-objpfx)gnu/lib-names.h
Makerules:303:before-compile += $(common-objpfx)$(lib-names-h-abi)
posix/Makefile:144:before-compile       += $(objpfx)posix-conf-vars-def.h
Rules:64:before-compile += $(common-objpfx)bits/stdio_lim.h
Rules:417:before-compile: $(before-compile)
sysdeps/mach/hurd/Makefile:48:before-compile += $(patsubst %,$(hurd-objpfx)hurd/%.h,auth io fs process)
sysdeps/mach/Makefile:50:before-compile += $(mach-before-compile)
sysdeps/powerpc/powerpc64/le/Makefile:27:before-compile += $(common-objpfx)no_ldbl_gnu_attribute.bin
sysdeps/unix/sysv/linux/Makefile:187:before-compile += $(objpfx)bits/syscall.h

canpool@DESKTOP-ODCM7SC:~/projects/linux/glibc$ grep -rnE "^compile-command\.(S|c|cc)"
Makerules:437:compile-command.S = $(compile.S) $(OUTPUT_OPTION) $(compile-mkdep-flags)
Makerules:438:compile-command.c = $(compile.c) $(OUTPUT_OPTION) $(compile-mkdep-flags)
Makerules:439:compile-command.cc = $(compile.cc) $(OUTPUT_OPTION) $(compile-mkdep-flags)

canpool@DESKTOP-ODCM7SC:~/projects/linux/glibc$ grep -rnE "^compile\.(S|c|cc)"
Makerules:447:compile.c = $(CC) $< -c $(CFLAGS) $(CPPFLAGS)
Makerules:448:compile.cc = $(CXX) $< -c $(CXXFLAGS) $(CPPFLAGS)
Makerules:449:compile.S = $(CC) $< -c $(CPPFLAGS) $(S-CPPFLAGS) \

2.2.3. sysd-rules.awk

sysd-rules.awk文件内容如下:

# This is a GAWK script to generate the sysd-rules file.
# It does not read any input, but it requires that several variables
# be set on its command line (using -v) to their makefile counterparts:
#	all_object_suffixes	$(all-object-suffixes)
#	inhibit_sysdep_asm	$(inhibit-sysdep-asm)
#	config_sysdirs		$(config_sysdirs)
#	sysd_rules_patterns	$(sysd-rules-patterns)

BEGIN {
  print "sysd-rules-sysdirs :=", config_sysdirs;

  nsuffixes = split(all_object_suffixes, suffixes);
  ninhibit_asm = split(inhibit_sysdep_asm, inhibit_asm);
  nsysdirs = split(config_sysdirs, sysdirs);
  npatterns = split(sysd_rules_patterns, patterns);

  # Each element of $(sysd-rules-patterns) is a pair TARGET:DEP.
  # They are no in particular order.  We need to sort them so that
  # the longest TARGET is first, and, among elements with the same
  # TARGET, the longest DEP is first.
  for (i = 1; i <= npatterns; ++i) {
    if (split(patterns[i], td, ":") != 2) {
      msg = "bad sysd-rules-patterns element '" patterns[i] "'";
      print msg > "/dev/stderr";
      exit 2;
    }
    target_order = sprintf("%09d", npatterns + 1 - length(td[1]));
    dep_order = sprintf("%09d", npatterns - length(td[2]));
    sort_patterns[target_order SUBSEP dep_order] = patterns[i];
  }
  asorti(sort_patterns, map_patterns);
  for (i in map_patterns) {
    patterns[i] = sort_patterns[map_patterns[i]];
  }

  for (sysdir_idx = 1; sysdir_idx <= nsysdirs; ++sysdir_idx) {
    dir = sysdirs[sysdir_idx];
    if (dir !~ /^\//) dir = "$(..)" dir;
    asm_rules = 1;
    for (i = 1; i <= ninhibit_asm; ++i) {
      if (dir ~ ("^.*sysdeps/" inhibit_asm[i] "$")) {
        asm_rules = 0;
        break;
      }
    }
    for (suffix_idx = 1; suffix_idx <= nsuffixes; ++suffix_idx) {
      o = suffixes[suffix_idx];
      for (pattern_idx = 1; pattern_idx <= npatterns; ++pattern_idx) {
        pattern = patterns[pattern_idx];
        split(pattern, td, ":");
        target_pattern = td[1];
        dep_pattern = td[2];
        # rtld objects are always PIC.
        if (target_pattern ~ /^rtld/ && o != ".os") {
            continue;
        }
        if (target_pattern == "%") {
          command_suffix = "";
        } else {
          prefix = gensub(/%/, "", 1, target_pattern);
          command_suffix = " $(" prefix  "CPPFLAGS)" " $(" prefix  "CFLAGS)";
        }
        target = "$(objpfx)" target_pattern o ":";
        if (asm_rules) {
          dep = dir "/" dep_pattern ".S";
          print target, dep, "$(before-compile)";
          print "\t$(compile-command.S)" command_suffix;
        }
        dep = dir "/" dep_pattern ".c";
        print target, dep, "$(before-compile)";
        print "\t$(compile-command.c)" command_suffix;
      }
    }
    print "$(inst_includedir)/%.h:", dir "/%.h", "$(+force)";
    print "\t$(do-install)";
  }

  print "sysd-rules-done := t";
  exit 0;
}

$(sysd-rules-patterns)的每个元素都是一对TARGET:DEP。它们没有特定的顺序。我们需要对它们进行排序,以便最长的目标是第一个,并且在具有相同目标的元素中,最长的DEP是第一个。

sysd-rules-patterns的内容如下:

$ grep -rn sysd-rules-patterns
Makeconfig:1358:sysd-rules-patterns := %:% rtld-%:rtld-% rtld-%:% m_%:s_%

2.2.4. sysd-rules文件

生成的sysd-rules文件部分内容如下(长目标在前;目标相同时,长依赖在前;.S文件先于.c文件):

$ head -n10 sysd-rules
sysd-rules-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
$(objpfx)m_%.o: $(..)sysdeps/unix/sysv/linux/x86_64/64/s_%.S $(before-compile)
        $(compile-command.S) $(m_CPPFLAGS) $(m_CFLAGS)
$(objpfx)m_%.o: $(..)sysdeps/unix/sysv/linux/x86_64/64/s_%.c $(before-compile)
        $(compile-command.c) $(m_CPPFLAGS) $(m_CFLAGS)
$(objpfx)%.o: $(..)sysdeps/unix/sysv/linux/x86_64/64/%.S $(before-compile)
        $(compile-command.S)
$(objpfx)%.o: $(..)sysdeps/unix/sysv/linux/x86_64/64/%.c $(before-compile)
        $(compile-command.c)
$(objpfx)rtld-%.os: $(..)sysdeps/unix/sysv/linux/x86_64/64/rtld-%.S $(before-compile)

$ tail -n10 sysd-rules
        $(compile-command.S) $(m_CPPFLAGS) $(m_CFLAGS)
$(objpfx)m_%.oS: $(..)sysdeps/generic/s_%.c $(before-compile)
        $(compile-command.c) $(m_CPPFLAGS) $(m_CFLAGS)
$(objpfx)%.oS: $(..)sysdeps/generic/%.S $(before-compile)
        $(compile-command.S)
$(objpfx)%.oS: $(..)sysdeps/generic/%.c $(before-compile)
        $(compile-command.c)
$(inst_includedir)/%.h: $(..)sysdeps/generic/%.h $(+force)
        $(do-install)
sysd-rules-done := t

可以看出生成.o文件优先选择系统相关目录下的实现,如果没有才会选择当前目录下的实现。

2.2.5. config-sysdirs列表

系统依赖规则中有一个强制目标,判断条件是sysd-rules-sysdirs不等于config-sysdirs。

-include $(common-objpfx)sysd-rules
ifneq ($(sysd-rules-sysdirs),$(config-sysdirs))
# The value of $(+sysdep_dirs) the sysd-rules was computed for
# differs from the one we are using now.  So force a rebuild of sysd-rules.
sysd-rules-force = FORCE
FORCE:
endif

当sysd-rules文件未生成时,sysd-rules-sysdirs自然不等于config-sysdirs。当sysd-rules文件生成后,二者便相等了。

canpool@DESKTOP-ODCM7SC:~/projects/linux/glibc$ grep -rn config-sysdirs
build/config.make:38: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

文件config.make由configure命令生成的配置文件,被Makeconfig文件包含:

canpool@DESKTOP-ODCM7SC:~/projects/linux/glibc$ grep -rn config.make Makeconfig Makerules Makefile
Makeconfig:51:include $(common-objpfx)config.make
Makeconfig:60:# `configure' writes a definition of `config-sysdirs' in `config.make'.
Makeconfig:68:# Run config.status to update config.make and config.h.  We don't show the
Makeconfig:71:# config.make should suffice to force regeneration and re-exec, and the new
Makeconfig:73:$(common-objpfx)config.make: $(common-objpfx)config.status \
Makeconfig:74:                       $(..)config.make.in $(..)config.h.in
Makeconfig:1343:                             $(common-objpfx)config.make $(..)Makeconfig \
Makerules:163:$(common-objpfx)runtime-linker.stamp: $(common-objpfx)config.make
Makerules:377:                      $(common-objpfx)config.make $(..)Makerules \
Makerules:553:$(common-objpfx)shlib.lds: $(common-objpfx)config.make $(..)Makerules
Makerules:1040:$(common-objpfx)format.lds: $(common-objpfx)config.make \
Makerules:1300:$(objpfx)check-abi-%.out: $(common-objpfx)config.make %.abilist \
Makerules:1304:$(objpfx)check-abi-%.out: $(common-objpfx)config.make %.abilist \
Makerules:1381:            $(common-objpfx)config.make
Makefile:201:$(common-objpfx)testrun.sh: $(common-objpfx)config.make \
Makefile:407:$(common-objpfx)debugglibc.sh: $(common-objpfx)config.make \
Makefile:672:   -rm -f $(addprefix $(objpfx),config.make config-name.h config.h)

2.2.6. 小结

对于x86_64平台,strcpy根据系统依赖规则,其实现文件查找顺序如下:

$ $ find -name strcpy.*
./string/strcpy.c
./sysdeps/aarch64/strcpy.S
./sysdeps/alpha/strcpy.S
./sysdeps/arm/armv6/strcpy.S
./sysdeps/csky/abiv2/strcpy.S
./sysdeps/i386/i586/strcpy.S
./sysdeps/i386/i686/multiarch/strcpy.c
./sysdeps/ia64/strcpy.S
./sysdeps/powerpc/powerpc32/405/strcpy.S
./sysdeps/powerpc/powerpc32/strcpy.S
./sysdeps/powerpc/powerpc64/le/power9/strcpy.S
./sysdeps/powerpc/powerpc64/multiarch/strcpy.c
./sysdeps/powerpc/powerpc64/power8/strcpy.S
./sysdeps/s390/strcpy.c
./sysdeps/sparc/sparc32/sparcv9/strcpy.S
./sysdeps/sparc/sparc32/strcpy.S
./sysdeps/sparc/sparc64/strcpy.S
./sysdeps/x86_64/multiarch/strcpy.c
./sysdeps/x86_64/strcpy.S

==>
./sysdeps/x86_64/multiarch/strcpy.c
./sysdeps/x86_64/strcpy.S
./string/strcpy.c

结论:根据构建规则,似乎知道了对多实现是如何选择的,但又没有完全搞清楚。

2.3. 包含关系

canpool@DESKTOP-ODCM7SC:~/projects/linux/glibc$ grep -rnwE "^-*include\s*" Makefile Makeconfig Makerules Rules csu/Makefile
Makefile:25:include Makeconfig
Makefile:89:include Makerules
Makeconfig:51:include $(common-objpfx)config.make
Makeconfig:98:include $(..)configparms
Makeconfig:102:include $(common-objpfx)configparms
Makeconfig:1102:-include $(common-objpfx)sysd-sorted
Makeconfig:1144:-include $(common-objpfx)soversions.mk
Makeconfig:1219:-include $(common-objpfx)sysd-versions
Makeconfig:1220:-include $(common-objpfx)Versions.mk
Makeconfig:1270:-include $(common-objpfx)time64-compat.mk
Makeconfig:1363:include $(sysdep-makeconfigs)
Makerules:55:include $(..)Makeconfig
Makerules:82:include $(sysdep-makefiles)
Makerules:369:-include $(common-objpfx)sysd-rules
Makerules:397:include $(o-iterator)
Makerules:403:include $(o-iterator)
Makerules:409:include $(o-iterator)
Makerules:420:include $(o-iterator)
Makerules:426:include $(o-iterator)
Makerules:432:include $(o-iterator)
Makerules:740:include $(patsubst %,$(..)extra-lib.mk,$(extra-libs))
Makerules:751:include $(patsubst %,$(..)libof-iterator.mk,$(cpp-srcs-left))
Makerules:758:include $(patsubst %,$(..)libof-iterator.mk,$(cpp-srcs-left))
Makerules:799:-include $(+depfiles)
Makerules:870:include $(o-iterator)
Makerules:890:include $(o-iterator)
Makerules:1087:include $(o-iterator)
Makerules:1096:include $(o-iterator)
Makerules:1105:include $(o-iterator)
Makerules:1238:include $(o-iterator)
Makerules:1244:include $(o-iterator)
Makerules:1259:include $(patsubst %,$(..)libof-iterator.mk,$(cpp-srcs-left))
Makerules:1266:include $(patsubst %,$(..)libof-iterator.mk,$(cpp-srcs-left))
Makerules:1276:include $(patsubst %,$(..)libof-iterator.mk,$(cpp-srcs-left))
Makerules:1407:-include $(stdio_lim:h=d)
Rules:28:include $(firstword $(..) ../)Makeconfig
Rules:66:include $(..)Makerules
csu/Makefile:27:include ../Makeconfig
csu/Makefile:120:include ../Rules

3. 参考

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值