网站公告列表

  没有公告

加入收藏
设为首页
联系本站
您现在的位置: AnalogCN安诺电子 >> 文章 >> 技术交流 >> 文章正文
  host-i686-pc-cygwin/gcc/Makefile分析           ★★★ 【字体:
host-i686-pc-cygwin/gcc/Makefile分析
作者:快乐虾    文章来源:http://blog.csdn.net/lights_joy    点击数:    更新时间:2008-8-27    

这个Makefilegcc-4.3.1/gcc/configure脚本生成,并在主控的Makefile中进行make操作,要求生成的目标为all,它有如下依赖关系:

# 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) $@

注释中已经比较清楚地说明了这段脚本的作用,它将创建includeinclude-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