gcc交叉编译的实现

来源:互联网 发布:数据治理 英文 编辑:程序博客网 时间:2024/04/30 15:37
 
   
gcc支持多种不同的语言,也支持多种不同的CPU架构。
在它的实现上,不同语言编译的实现是通过
const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
这个结构体的不同定义来实现的。比如c语言的编译器就通过gcc/c-lang.c指定了lang_hooks这个结构体的一个实现。而C++语言编译器对此结构体的实现则放在gcc/cp/cp-lang.c中,同样在gcc目录下还可以发现gcc/objcp/objcp-lang.c和gcc/treelang/treetree.c这两个文件也提供了lang_hooks的不同实现。由此就可以很容易发现gcc所支持的编程语言。
而要生成不同目标CPU的代码,gcc则提供了另一个结构体:
struct gcc_target targetm = TARGET_INITIALIZER;
对此结构体的不同实现则是放在gcc/config/xxx/目录下的,其中xxx是具体的平台,如i386,bfin等等。
当然在后端,除了对gcc_target这个结构体提供不同的实现外,还必须重新定义一系列的宏,这些宏都是放在不同平台的config子目录下的,那么gcc如何知道要包含哪个目录下的头文件呢?
答案就在tm.h。以下是bf561交叉编译器下tm.h的内容:
#ifndef GCC_TM_H
#define GCC_TM_H
#ifdef IN_GCC
# include "options.h"
# include "config/bfin/bfin.h"
# include "config/dbxelf.h"
# include "config/elfos.h"
# include "config/bfin/elf.h"
# include "defaults.h"
#endif
#if defined IN_GCC && !defined GENERATOR_FILE && !defined USED_FOR_TARGET
# include "insn-constants.h"
# include "insn-flags.h"
#endif
#endif /* GCC_TM_H */
tm.h并不是gcc源码包的一部分,而是动态生成的,在gcc/gcc目录下的Makefile有这样的部分:
 
tm.h: cs-tm.h ; @true
cs-tm.h: Makefile
       TARGET_CPU_DEFAULT="$(target_cpu_default)" /
       HEADERS="$(tm_include_list)" DEFINES="$(tm_defines)" /
       $(SHELL) $(srcdir)/mkconfig.sh tm.h
 
这说明tm.h的生成要靠mkconfig.sh将tm_include_list这个变量中列出的文件。
再看看tm_include_list的定义:
tm_include_list=options.h config/bfin/bfin.h config/dbxelf.h config/elfos.h config/bfin/elf.h defaults.h
这个变量也是在Makefile中定义的,但是Makefile是由gcc/configure动态生成的,所以再看看gcc/configure中的相关部分:
tm_file_list="options.h"
tm_include_list="options.h"
for f in $tm_file; do
 case $f in
    defaults.h )
       tm_file_list="${tm_file_list} /$(srcdir)/$f"
       tm_include_list="${tm_include_list} $f"
       ;;
    * )
       tm_file_list="${tm_file_list} /$(srcdir)/config/$f"
       tm_include_list="${tm_include_list} config/$f"
       ;;
 esac
done
离目标越来越近了,顺藤摸瓜,看看在config.gcc中对$tm_file的定义:
tm_file=${cpu_type}/${cpu_type}.h
case ${target} in
# Support site-specific machine types.
bfin*-elf*)
     tm_file="${tm_file} dbxelf.h elfos.h bfin/elf.h"
        tmake_file=bfin/t-bfin-elf
        use_collect2=no
        ;;
bfin*-uclinux*)
     tm_file="${tm_file} dbxelf.h elfos.h bfin/elf.h bfin/uclinux.h"
        tmake_file=bfin/t-bfin-uclinux
        use_collect2=no
        ;;
bfin*-linux-uclibc*)
     tm_file="${tm_file} dbxelf.h elfos.h bfin/elf.h linux.h bfin/linux.h"
        tmake_file="t-slibgcc-elf-ver bfin/t-bfin-linux"
        use_collect2=no
        ;;
bfin*-*)
     tm_file="${tm_file} dbxelf.h elfos.h bfin/elf.h"
        tmake_file=bfin/t-bfin
        use_collect2=no
        ;;
呵呵,最后看看cpu_type的定义:
cpu_type=`echo ${target} | sed 's/-.*$//'`
case ${target} in
bfin*-*)
     cpu_type=bfin
     ;;
至此,终于真相大白!
 
原创粉丝点击