![]() |
|
||||||||||||||
| | 首页 | 新闻 | 文库 | 方案 | 技术 | 独家 | 座谈 | 下载 | 图库 | 开发板 | 仿真器 | 邮购 | VIP会员 | 芯片代购 | 客户评价 | | ||
|
||
|
|||||
| host-i686-pc-cygwin/gcc/Makefile分析 | |||||
作者:快乐虾 文章来源:http://blog.csdn.net/lights_joy 点击数: 更新时间:2008-8-27 ![]() |
|||||
|
这个Makefile由gcc- # This is the default target. # Set by autoconf to "all.internal" for a native build, or # "all.cross" to build a cross compiler. all: all.cross 而all.cross又有以下依赖关系: # This is what to compile if making a cross-compiler. all.cross: native gcc-cross$(exeext) cpp$(exeext) specs \ libgcc-support lang.all.cross doc # srcextra 1.1 native这个目标的依赖关系为: # This is what is made with the host's compiler # whether making a cross compiler or not. native: config.status auto-host.h build-po $(LANGUAGES) \ $(EXTRA_PASSES) $(EXTRA_PROGRAMS) $(COLLECT2) 这里有 LANGUAGES = c gcov$(exeext) gcov-dump$(exeext) $(CONFIG_LANGUAGES) CONFIG_LANGUAGES = c++ fortran java objc EXTRA_PASSES = EXTRA_PROGRAMS = COLLECT2 = collect2$(exeext) 这个目标将生成一系列在windows下运行的编译器,这些编译器生成的目标代码为blackfin cpu。 这部分的详细分析参见《bfin-xxx-gcc中native目标的生成》。 1.2 gcc-cross$(exeext)这条规则定义为: # We do want to create an executable named `xgcc', so we can use it to # compile libgcc2.a. # Also create gcc-cross, so that install-common will install properly. gcc-cross$(exeext): xgcc$(exeext) cp xgcc$(exeext) gcc-cross$(exeext) 这段脚本无非是将xgcc.exe复制一次变成gcc-cross.exe。它依赖于xgcc.exe,这个规则定义为: # We call this executable `xgcc' rather than `gcc' # to avoid confusion if the current directory is in the path # and CC is `gcc'. It is renamed to `gcc' when it is installed. xgcc$(exeext): $(GCC_OBJS) gccspec.o version.o intl.o prefix.o \ version.o $(LIBDEPS) $(EXTRA_GCC_OBJS) $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ $(GCC_OBJS) gccspec.o \ intl.o prefix.o version.o $(EXTRA_GCC_OBJS) $(LIBS) 在这个依赖关系中,除gccspec.o外,其余目标均已经生成,因此这个目标转而依赖gccspec.o: gccspec.o: gccspec.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H) (SHLIB_LINK='$(SHLIB_LINK)'; \ $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) \ $(DRIVER_DEFINES) \ -c $(srcdir)/gccspec.c $(OUTPUT_OPTION)) 没什么,直接编译即可。 1.3 cpp$(exeext)这条规则定义为: # cpp is to cpp0 as gcc is to cc1. # The only difference from xgcc is that it's linked with cppspec.o # instead of gccspec.o. cpp$(exeext): $(GCC_OBJS) cppspec.o version.o intl.o prefix.o \ version.o $(LIBDEPS) $(EXTRA_GCC_OBJS) $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ $(GCC_OBJS) cppspec.o \ intl.o prefix.o version.o $(EXTRA_GCC_OBJS) $(LIBS) 这段脚本无非是将目标文件链接为cpp.exe。 在这个依赖关系中,除cppspec.o外,其余目标均已经生成,因此这个目标转而依赖cppspec.o,这个文件的生成适用于通用规则: .c.o: $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $< $(OUTPUT_OPTION); 此外还定义了依赖关系: cppspec.o: cppspec.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H) 没什么,直接编译即可。 1.4 specs在Makefile中没有直接定义此规则,而是给出了一个定义: # This should name the specs file that we're going to install. Target # Makefiles may override it and name another file to be generated from # the built-in specs and installed as the default spec, as long as # they also introduce a rule to generate a file name specs, to be used # at build time. SPECS = specs 再往下有: # Dump a specs file to make -B./ read these specs over installed ones. $(SPECS): xgcc$(exeext) $(GCC_FOR_TARGET) -dumpspecs > tmp-specs mv tmp-specs $(SPECS) 所依赖的目标已经生成,直接运行脚本。 GCC_FOR_TARGET = $(STAGE_CC_WRAPPER) ./xgcc -B./ -B$(build_tooldir)/bin/ -isystem $(build_tooldir)/include -isystem $(build_tooldir)/sys-include -L$(objdir)/../ld STAGE_CC_WRAPPER的值没有定义,因而将调用xgcc生成specs文件。 1.5 libgcc-support这条规则定义为: libgcc-support: libgcc.mvars stmp-int-hdrs $(STMP_FIXPROTO) $(TCONFIG_H) \ $(MACHMODE_H) $(FPBIT) $(DPBIT) $(TPBIT) $(LIB2ADD) \ $(LIB2ADD_ST) $(LIB2ADDEH) $(srcdir)/emutls.c gcov-iov.h $(SFP_MACHINE) 它有以下依赖关系: 1.5.1 libgcc.mvars这条规则定义为: libgcc.mvars: config.status Makefile $(LIB2ADD) $(LIB2ADD_ST) specs \ xgcc$(exeext) : > tmp-libgcc.mvars echo LIB1ASMFUNCS = '$(LIB1ASMFUNCS)' >> tmp-libgcc.mvars echo LIB1ASMSRC = '$(LIB1ASMSRC)' >> tmp-libgcc.mvars echo LIB2FUNCS_ST = '$(LIB2FUNCS_ST)' >> tmp-libgcc.mvars echo LIB2FUNCS_EXCLUDE = '$(LIB2FUNCS_EXCLUDE)' >> tmp-libgcc.mvars echo LIBGCOV = '$(LIBGCOV)' >> tmp-libgcc.mvars echo LIB2ADD = '$(call srcdirify,$(LIB2ADD))' >> tmp-libgcc.mvars echo LIB2ADD_ST = '$(call srcdirify,$(LIB2ADD_ST))' >> tmp-libgcc.mvars echo LIB2ADDEH = '$(call srcdirify,$(LIB2ADDEH) $(srcdir)/emutls.c)' >> tmp-libgcc.mvars echo LIB2ADDEHSTATIC = '$(call srcdirify,$(LIB2ADDEHSTATIC) $(srcdir)/emutls.c)' >> tmp-libgcc.mvars echo LIB2ADDEHSHARED = '$(call srcdirify,$(LIB2ADDEHSHARED) $(srcdir)/emutls.c)' >> tmp-libgcc.mvars echo LIB2_SIDITI_CONV_FUNCS = '$(LIB2_SIDITI_CONV_FUNCS)' >> tmp-libgcc.mvars echo LIBUNWIND = '$(call srcdirify,$(LIBUNWIND))' >> tmp-libgcc.mvars echo SHLIBUNWIND_LINK = '$(SHLIBUNWIND_LINK)' >> tmp-libgcc.mvars echo SHLIBUNWIND_INSTALL = '$(SHLIBUNWIND_INSTALL)' >> tmp-libgcc.mvars echo FPBIT = '$(FPBIT)' >> tmp-libgcc.mvars echo FPBIT_FUNCS = '$(FPBIT_FUNCS)' >> tmp-libgcc.mvars echo LIB2_DIVMOD_FUNCS = '$(LIB2_DIVMOD_FUNCS)' >> tmp-libgcc.mvars echo DPBIT = '$(DPBIT)' >> tmp-libgcc.mvars echo DPBIT_FUNCS = '$(DPBIT_FUNCS)' >> tmp-libgcc.mvars echo TPBIT = '$(TPBIT)' >> tmp-libgcc.mvars echo TPBIT_FUNCS = '$(TPBIT_FUNCS)' >> tmp-libgcc.mvars echo DFP_ENABLE = '$(DFP_ENABLE)' >> tmp-libgcc.mvars echo DFP_CFLAGS='$(DFP_CFLAGS)' >> tmp-libgcc.mvars echo D32PBIT='$(D32PBIT)' >> tmp-libgcc.mvars echo D32PBIT_FUNCS='$(D32PBIT_FUNCS)' >> tmp-libgcc.mvars echo D64PBIT='$(D64PBIT)' >> tmp-libgcc.mvars echo D64PBIT_FUNCS='$(D64PBIT_FUNCS)' >> tmp-libgcc.mvars echo D128PBIT='$(D128PBIT)' >> tmp-libgcc.mvars echo D128PBIT_FUNCS='$(D128PBIT_FUNCS)' >> tmp-libgcc.mvars echo GCC_EXTRA_PARTS = '$(GCC_EXTRA_PARTS)' >> tmp-libgcc.mvars echo SHLIB_LINK = '$(subst $(GCC_FOR_TARGET),$$(GCC_FOR_TARGET),$(SHLIB_LINK))' >> tmp-libgcc.mvars echo SHLIB_INSTALL = '$(SHLIB_INSTALL)' >> tmp-libgcc.mvars echo SHLIB_EXT = '$(SHLIB_EXT)' >> tmp-libgcc.mvars echo SHLIB_MKMAP = '$(call srcdirify,$(SHLIB_MKMAP))' >> tmp-libgcc.mvars echo SHLIB_MKMAP_OPTS = '$(SHLIB_MKMAP_OPTS)' >> tmp-libgcc.mvars echo SHLIB_MAPFILES = '$(call srcdirify,$(SHLIB_MAPFILES))' >> tmp-libgcc.mvars echo SHLIB_NM_FLAGS = '$(SHLIB_NM_FLAGS)' >> tmp-libgcc.mvars echo LIBGCC2_CFLAGS = '$(LIBGCC2_CFLAGS)' >> tmp-libgcc.mvars echo CRTSTUFF_CFLAGS = '$(CRTSTUFF_CFLAGS)' >> tmp-libgcc.mvars echo CRTSTUFF_T_CFLAGS = '$(CRTSTUFF_T_CFLAGS)' >> tmp-libgcc.mvars echo CRTSTUFF_T_CFLAGS_S = '$(CRTSTUFF_T_CFLAGS_S)' >> tmp-libgcc.mvars mv tmp-libgcc.mvars libgcc.mvars 通过一个比较简单的方式生成libgcc.mvars文件。 1.5.2 stmp-int-hdrs这条规则定义为: # Build the include directories. stmp-int-hdrs: $(STMP_FIXINC) $(USER_H) $(UNWIND_H) fixinc_list # Copy in the headers provided with gcc. # The sed command gets just the last file name component; # this is necessary because VPATH could add a dirname. # Using basename would be simpler, but some systems don't have it. # The touch command is here to workaround an AIX/Linux NFS bug. -if [ -d include ] ; then true; else mkdir include; chmod a+rx include; fi -if [ -d include-fixed ] ; then true; else mkdir include-fixed; chmod a+rx include-fixed; fi for file in .. $(USER_H); do \ if [ X$$file != X.. ]; then \ realfile=`echo $$file | sed -e 's|.*/\([^/]*\)$$|\1|'`; \ $(STAMP) include/$$realfile; \ rm -f include/$$realfile; \ cp $$file include; \ chmod a+r include/$$realfile; \ fi; \ done rm -f include/unwind.h cp $(UNWIND_H) include/unwind.h set -e; for ml in `cat fixinc_list`; do \ sysroot_headers_suffix=`echo $${ml} | sed -e 's/;.*$$//'`; \ multi_dir=`echo $${ml} | sed -e 's/^[^;]*;//'`; \ fix_dir=include-fixed$${multi_dir}; \ if $(LIMITS_H_TEST) ; then \ cat $(srcdir)/limitx.h $(srcdir)/glimits.h $(srcdir)/limity.h > tmp-xlimits.h; \ else \ cat $(srcdir)/glimits.h > tmp-xlimits.h; \ fi; \ $(mkinstalldirs) $${fix_dir}; \ chmod a+rx $${fix_dir} || true; \ rm -f $${fix_dir}/limits.h; \ mv tmp-xlimits.h $${fix_dir}/limits.h; \ chmod a+r $${fix_dir}/limits.h; \ done # Install the README rm -f include-fixed/README cp $(srcdir)/../fixincludes/README-fixinc include-fixed/README chmod a+r include-fixed/README $(STAMP) $@ 注释中已经比较清楚地说明了这段脚本的作用,它将创建include和include-fixed两个目录,并在其中复制下一阶段所需要的一些头文件。 1.5.2.1 $(STMP_FIXINC)这个变量定义为: STMP_FIXINC = stmp-fixinc 因而有以下的依赖关系: # Build fixed copies of system files. # Abort if no system headers available, unless building a crosscompiler. # FIXME: abort unless building --without-headers would be more accurate and less ugly stmp-fixinc: gsyslimits.h macro_list fixinc_list \ $(build_objdir)/fixincludes/fixincl \ $(build_objdir)/fixincludes/fixinc.sh rm -rf include-fixed; mkdir include-fixed -chmod a+rx include-fixed if [ -d ../prev-gcc ]; then \ cd ../prev-gcc && \ $(MAKE) real-$(INSTALL_HEADERS_DIR) DESTDIR=`pwd`/../gcc/ \ libsubdir=. ; \ else \ set -e; for ml in `cat fixinc_list`; do \ sysroot_headers_suffix=`echo $${ml} | sed -e 's/;.*$$//'`; \ multi_dir=`echo $${ml} | sed -e 's/^[^;]*;//'`; \ fix_dir=include-fixed$${multi_dir}; \ if ! $(inhibit_libc) && test ! -d ${SYSTEM_HEADER_DIR}; then \ echo The directory that should contain system headers does not exist: >&2 ; \ echo " ${SYSTEM_HEADER_DIR}" >&2 ; \ tooldir_sysinc=`echo "${gcc_tooldir}/sys-include" | sed -e :a -e "s,[^/]*/\.\.\/,," -e ta`; \ if test "x${SYSTEM_HEADER_DIR}" = "x$${tooldir_sysinc}"; \ then sleep 1; else exit 1; fi; \ fi; \ $(mkinstalldirs) $${fix_dir}; \ chmod a+rx $${fix_dir} || true; \ (TARGET_MACHINE='$(target)'; srcdir=`cd $(srcdir); ${PWD_COMMAND}`; \ SHELL='$(SHELL)'; MACRO_LIST=`${PWD_COMMAND}`/macro_list ; \ export TARGET_MACHINE srcdir SHELL MACRO_LIST && \ cd $(build_objdir)/fixincludes && \ $(SHELL) ./fixinc.sh ../../gcc/$${fix_dir} \ $(SYSTEM_HEADER_DIR) $(OTHER_FIXINCLUDES_DIRS) ); \ rm -f $${fix_dir}/syslimits.h; \ if [ -f $${fix_dir}/limits.h ]; then \ mv $${fix_dir}/limits.h $${fix_dir}/syslimits.h; \ else \ cp $(srcdir)/gsyslimits.h $${fix_dir}/syslimits.h; \ fi; \ chmod a+r $${fix_dir}/syslimits.h; \ done; \ fi $(STAMP) stmp-fixinc 根据注释所说,这段脚本将创建include-fixed目录并在其中复制一些下个阶段所需要使用的头文件。 1.5.2.1.1 gsyslimits.h源文件,略过。 1.5.2.1.2 macro_list这条规则定义为: macro_list: s-macro_list; @true s-macro_list : $(GCC_PASSES) echo | $(GCC_FOR_TARGET) -E -dM - | \ sed -n -e 's/^#define \([^_][a-zA-Z0-9_]*\).*/\1/p' \ -e 's/^#define \(_[^_A-Z][a-zA-Z0-9_]*\).*/\1/p' | \ sort -u > tmp-macro_list $(SHELL) $(srcdir)/../move-if-change tmp-macro_list macro_list $(STAMP) s-macro_list 它将生成一个叫macro_list的文件。 $(GCC_PASSES)这个目标已经生成,直接执行这段脚本。 1.5.2.1.3 fixinc_list这条规则定义为: fixinc_list: s-fixinc_list; @true s-fixinc_list : $(GCC_PASSES) # Build up a list of multilib directories and corresponding sysroot # suffixes, in form sysroot;multilib. if $(GCC_FOR_TARGET) -print-sysroot-headers-suffix > /dev/null 2>&1; then \ set -e; for ml in `$(GCC_FOR_TARGET) -print-multi-lib`; do \ multi_dir=`echo $${ml} | sed -e 's/;.*$$//'`; \ flags=`echo $${ml} | sed -e 's/^[^;]*;//' -e 's/@/ -/g'`; \ sfx=`$(GCC_FOR_TARGET) $${flags} -print-sysroot-headers-suffix`; \ if [ "$${multi_dir}" = "." ]; \ then multi_dir=""; \ else \ multi_dir=/$${multi_dir}; \ fi; \ echo "$${sfx};$${multi_dir}"; \ done; \ else \ echo ";"; \ fi > tmp-fixinc_list $(SHELL) $(srcdir)/../move-if-change tmp-fixinc_list fixinc_list $(STAMP) s-fixinc_list 它将生成fixinc_list文件。 1.5.2.2 fixinc_list此前已经生成,略过。 1.5.3 $(STMP_FIXPROTO)这个变量定义为: STMP_FIXPROTO = 略过。 1.5.4 $(TCONFIG_H)这个变量定义为: TCONFIG_H = tconfig.h $(xm_file_list) 源文件,略过。 1.6 lang.all.cross这条规则定义为: lang.all.cross: c++.all.cross fortran.all.cross java.all.cross objc.all.cross 1.6.1 c++.all.cross这条规则定义在gcc/cp/Makelang.in中,其定义为: c++.all.cross: g++-cross$(exeext) g++-cross$(exeext): g++$(exeext) -rm -f g++-cross$(exeext) cp g++$(exeext) g++-cross$(exeext) 这段脚本很简单,无非是将g++.exe复制为g++-cross.exe,因而此目标转而依赖于g++.exe的生成: GXX_OBJS = $(GCC_OBJS) g++spec.o intl.o prefix.o version.o g++$(exeext): $(GXX_OBJS) $(EXTRA_GCC_OBJS) $(LIBDEPS) $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \ $(GXX_OBJS) $(EXTRA_GCC_OBJS) $(LIBS) 所有目标均已生成,直接编译链接即可。 1.6.2 fortran.all.cross这条规则定义在gcc/fortran/Makelang.in中,其定义为: fortran.all.cross: gfortran-cross$(exeext) gfortran-cross$(exeext): gfortran$(exeext) -rm -f gfortran-cross$(exeext) cp gfortran$(exeext) gfortran-cross$(exeext) 这段脚本很简单,无非是将gfortran.exe复制为gfortran-cross.exe,因而此目标转而依赖于gfortran.exe的生成: GFORTRAN_D_OBJS = $(GCC_OBJS) gfortranspec.o version.o prefix.o intl.o gfortran$(exeext): $(GFORTRAN_D_OBJS) $(EXTRA_GCC_OBJS) $(LIBDEPS) $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \ $(GFORTRAN_D_OBJS) $(EXTRA_GCC_OBJS) $(LIBS) 所有目标均已生成,直接编译链接即可。 1.6.3 java.all.cross这条规则定义在gcc/java/Makelang.in中,其定义为: java.all.cross: $(GCJ)-cross$(exeext) $(GCJ)-cross$(exeext): $(GCJ)$(exeext) -rm -f $(GCJ)-cross$(exeext) cp $(GCJ)$(exeext) $(GCJ)-cross$(exeext) 所依赖的目标gcj.exe此前已经生成,因此直接执行这段脚本,将gcj.exe复制为gcj-cross.exe。 1.6.4 objc.all.cross这条规则定义在gcc/objc/Makelang.in中,其定义为: objc.all.cross: 略过此目标。 1.7 doc这条规则定义为: doc: $(BUILD_INFO) $(GENERATED_MANPAGES) gccbug 1.7.1 $(BUILD_INFO)这个变量的定义为: BUILD_INFO = info 因而有依赖关系: info: $(INFOFILES) lang.info # srcinfo lang.srcinfo 1.7.1.1 $(INFOFILES)这个变量定义为: INFOFILES = doc/cpp.info doc/gcc.info doc/gccint.info \ doc/gccinstall.info doc/cppinternals.info 对于这此指定的info文件有以下的依赖关系: doc/cpp.info: $(TEXI_CPP_FILES) doc/gcc.info: $(TEXI_GCC_FILES) doc/gccint.info: $(TEXI_GCCINT_FILES) doc/cppinternals.info: $(TEXI_CPPINT_FILES) doc/gccinstall.info: $(TEXI_GCCINSTALL_FILES) if [ x$(BUILD_INFO) = xinfo ]; then \ $(MAKEINFO) $(MAKEINFOFLAGS) -I $(gcc_docdir) \ -I $(gcc_docdir)/include -o $@ $<; \ fi 这些info文件所依赖的都是源代码目录下的文件。因此将执行最后一段脚本,此时有: MAKEINFO = makeinfo --split-size=5000000 这段脚本执行的结果就是在doc目录下创建一些.info的文件。 1.7.1.2 lang.info这个变量定义为: lang.info: c++.info fortran.info java.info objc.info 1.7.1.2.1 c++.info这条规则的定义在cp/Makelang.in中: c++.info: 可略过。 1.7.1.2.2 fortran.info这条规则的定义在fortran/Makelang.in中: fortran.info: doc/gfortran.info doc/gfc-internals.info 1.7.1.2.2.1 doc/gfortran.info这条规则定义为: doc/gfortran.info: $(GFORTRAN_TEXI) if [ x$(BUILD_INFO) = xinfo ]; then \ rm -f doc/gfortran.info-*; \ $(MAKEINFO) -I $(srcdir)/doc/include -I $(srcdir)/fortran \ -o $@ $<; \ else true; fi 这段脚本将生成gfortran.info文件。 1.7.1.2.2.2 doc/gfc-internals.info这条规则定义为: doc/gfc-internals.info: $(GFC_INTERNALS_TEXI) if [ x$(BUILD_INFO) = xinfo ]; then \ rm -f doc/gfc-internals.info-*; \ $(MAKEINFO) -I $(srcdir)/doc/include -I $(srcdir)/fortran \ -o $@ $<; \ else true; fi 这段脚本将生成gfc-internals.info文件。 1.7.1.2.3 java.info这条规则的定义在java/Makelang.in中: java.info: doc/gcj.info doc/gcj.info: $(TEXI_JAVA_FILES) if test "x$(BUILD_INFO)" = xinfo; then \ rm -f doc/gcj.info*; \ $(MAKEINFO) $(MAKEINFOFLAGS) -I $(gcc_docdir) \ -I $(gcc_docdir)/include -o $@ $<; \ else true; fi 这段脚本将生成gcj.info | |||||