交叉编译器原理
⑴ 交叉编译opencv 自动生成zlib吗
第一步,安装交叉编译工具arm-linux-gcc-4.3.2
xgy@ubuntu:~/toolchain$mkdir arm
xgy@ubuntu:~/toolchain$cd arm
xgy@ubuntu:~/toolchain/arm$tar xvf arm-linux-gcc-4.3.2
解压后,在当目录下会多一个usr目录,由于我不喜欢这目录太深,然后就执行如下命令:
xgy@ubuntu:~/toolchain/arm$cp -rv usr/local/* .
xgy@ubuntu:~/toolchain/arm$rm -rf usr
接下来设置环境变量PATH,执行命令如下:
xgy@ubuntu:~/toolchain/arm$cd
xgy@ubuntu:~$vi .bashrc
在.bashrc文件的最后加入:exportPATH=$PATH:/home/xgy/toolchain/arm/4.3.2/bin 保存退出(:wq)
xgy@ubuntu:~$source .bashrc //使刚设置的值生效
到此本来交叉编译工具就已经安装成功了的,可经过检查却发现下图中左列的arm-linux-g++,arm-linux-gcc是4.3.3版本的(用命令arm-linux-gcc -v 查看),而其它的确是版本的,4.3.2这是一个奇怪现象!
因为我曾试过用4.3.3版本的g++交叉编译opencv2.0总是出错如下:
在这里,我只好创建软链接,使它指向右侧的arm-none-linux-gnueabi-g++,arm-none-linux-gnueabi-gcc。在创建之前先对原来的两个文件做备份。执行命令如下:
在这里再次检查下arm-linux-gcc及arm-linux-g++的版本
命令arm-linux-gcc –v 输出的最后一行是应该是:gcc version 4.3.2 (Sourcery G++ Lite 2008q3-72)在这里说明下,这个很重要:现在所用的arm-linux-gcc实际上使用的是~./toolchain/arm/4.3.2/bin/目录下的arm-none-linux-gnueabi-gcc,而它的include为arm/4.3.2/arm-none-linux-gnueabi/include,对应的lib为arm/4.3.2/arm-none-linux-gnueabi/lib,也就是说,你如果用arm-linux-gcc编译程译的话,对头文件它缺省的就找arm/4.3.2/arm-none-linux-gnueabi/include,对库它缺省的就找 arm/4.3.2/arm-none-linux-gnueabi/lib,而不是/usr/include /usr/lib,所以如果你要加什么.h .a .so文件的话,记着一定要把这些文件加到这两个目录下去,不然这个交叉编译器会告你找不到所要的库或头文件。这里的原理对于其它交叉编译器也适应(主要指目录结构),只是可能目录名不一样。
OK,到此,交编译器安装成功!
2012-11-2 今天换了一个4.3.2版本的arm-linux-gcc没有发现上面的问题,也许是我以前在复制的时候出错了,用cp命令时最好使用-a选项。
由于opencv2.0依懒于zlib,png、jpeg图形库而我们的arm-linux-gcc 是不带这些库的,它只带了一些基本的库,所以这里我们首先就要交叉编译这些文件,安装到arm/4.3.2/arm-none-linux-gnueabi/include,arm/4.3.2/arm-none-linux-gnueabi/lib目录中。库不一定要最新的,库的版本太新了,opencv有可能不认识。
首先安装zlib库,这个是后面两个库的编译基础。
xgy@ubuntu:~/tmp$ tar zxvf zlib-1.2.3.tar.gz
在当前目录下会多一个zlib-1.2.3的目录。
由于 zlib 库的configure 脚本不支持交叉编译选项,只好自己手动临时把 gcc 修改成指向我们的交叉编译器 arm-linux-gcc 。执行如下命令:
xgy@ubuntu:~/tmp$ cd /usr/bin
xgy@ubuntu:/usr/bin$ sudo –i //这里得切换到root用户下才能有权限做下面的操作。
[sudo] password for xgy: //在这里输入xgy用户的密码
root@ubuntu:~# cd /usr/bin
root@ubuntu:/usr/bin# mv gcc gcc_back
root@ubuntu:/usr/bin# mv ld ld_back
root@ubuntu:/usr/bin# ln -sv/home/xgy/toolchain/arm/4.3.2/bin/arm-linux-gcc ./gcc
root@ubuntu:/usr/bin# ln -sv/home/xgy/toolchain/arm/4.3.2/bin/arm-linux-ld ./ld
下面检查下是否换过来了
root@ubuntu:/usr/bin#gcc –v
gcc version4.3.2 (Sourcery G++ Lite 2008q3-72) //为输出的最后一行
root@ubuntu:/usr/bin#ld -v
GNU ld (SourceryG++ Lite 2008q3-72) 2.18.50.20080215
接着切换到原来的目录~/tmp/zlib-1.2.3执行如下命令
root@ubuntu:/usr/bin#su – xgy //注意这里和用命令 suxgy是有区别的,-表示用xgy的环境
xgy@ubuntu:~$ cdtmp/zlib-1.2.3/
xgy@ubuntu:~/tmp/zlib-1.2.3$./configure --prefix=/home/xgy/toolchain/arm/4.3.2/arm-none-linux-gnueabi/--shared
xgy@ubuntu:~/tmp/zlib-1.2.3$make (如果以前在这个目录下执行过make ,那要先执行makeclean 然后执行make)
xgy@ubuntu:~/tmp/zlib-1.2.3$make install
然后可以去~/toolchain/arm/4.3.2/arm-none-linux-gnueabi/{include,lib}目录下是否多了一些文件(可以另外再开一个终端查看,这样方便点),如下图:
在这里记着把刚才改过的gcc再改回去,不然后面会出错!!!
接下来安装png库,这个是用来显示png图形的。
xgy@ubuntu:~/tmp$tar jxvf libpng-1.2.18.tar.bz2
xgy@ubuntu:~/tmp$cd libpng-1.2.18/
由于libpng不提供有效的configure脚本(可以查看INSTALL文件),所以只好自己动手改Makefile文件了。
xgy@ubuntu:~/tmp/libpng-1.2.18$cp scripts/makefile.linux Makefile
xgy@ubuntu:~/tmp/libpng-1.2.18$vi Makefile
CC=arm-linux-gcc //修改这里
MKDIR_P=mkdir -p
# where "make install" putslibpng12.a, libpng12.so*,
# libpng12/png.h and libpng12/pngconf.h
# Prefix must be a full pathname.
prefix=/home/xgy/toolchain/arm/4.3.2/arm-none-linux-gnueabi
exec_prefix=$(prefix)
# Where the zlib library and include filesare located.
#ZLIBLIB=/usr/local/lib
#ZLIBINC=/usr/local/include
ZLIBLIB=/home/xgy/toolchain/arm/4.3.2/arm/arm-none-linux-gnueabi/lib //修改这里
ZLIBINC=/home/xgy/toolchain/arm/4.3.2/arm/arm-none-linux-gnueabi/include//修改这里
保存退出后执行如下命令:
xgy@ubuntu:~/tmp/libpng-1.2.18$ make
xgy@ubuntu:~/tmp/libpng-1.2.18$ makeinstall
然后可以去~/toolchain/arm/4.3.2/arm-none-linux-gnueabi/{include,lib}目录下是否多了一些文件(可以另外再开一个终端查看,这样方便点),如下图:
如果有错,检查下前面的步聚,特别是看zlib有安装有没有出错。
接下来安装jpeg库
xgy@ubuntu:~/tmp/libpng-1.2.18$ cd ..
xgy@ubuntu:~/tmp$tar zxvf jpegsrc.v6b.tar.gz
xgy@ubuntu:~/tmp/jpeg-6b$
xgy@ubuntu:~/tmp/jpeg-6b$ ./configure --prefix=/home/xgy/toolchain/arm/4.3.2/arm-none-linux-gnueabi/--host=arm-linux --enable-shared
按此命令进行,然后修 改makefile文件将CC的值改为arm-linux-gcc,一定得改!!
xgy@ubuntu:~/tmp/jpeg-6b$make
安装前需要在 arm-linux 下建个目录,不然安装会出错
xgy@ubuntu:~/tmp/jpeg-6b$mkdir -pv /home/xgy/toolchain/arm/4.3.2/arm-none-linux-gnueabi/man/man1
mkdir: created directory `/home/xgy/toolchain/arm/4.3.2/arm-none-linux-gnueabi/man/man1
xgy@ubuntu:~/tmp/jpeg-6b$ make install
然后可以去~/toolchain/arm/4.3.2/arm-none-linux-gnueabi/{include, lib}目录下是否多了一些文件(可以另外再开一个终端查看,这样方便点),如下图:
到此,三个库安装完毕!
⑵ 嵌入式系统原理与应用---简答题
环境搭建
一、认识开发板
1,ARM开发板的硬件配置(以S3C2410为例)
CPU、SDRAM、FLASH、LCD(包括键盘LED驱动器,触摸屏)、以太网、USB、串口、调试接口(JTAG)、AD及扩展。
2,ARM体系结构与编程。
仅仅了解arm开发板的硬件构成显然是不够的,还需要由表及里,了解ARM体系结构与编程。这部分内容有相应文档,中文版有杜春雷编写的《ARM体系结构与编程》。
注:SDRAM = Synchronous DRAM,同步动态随机存取存储器
这是一种与CPU实现外频Clock同步的内存模式,一般都采用168Pin的内存模组,工作电压为3.3V。所谓clock同步是将CPU与RAM通过一个相同的时钟锁在一起,使RAM和CPU能够共享一个时钟周期,以相同的速度同步工作,这样可以取消等待周期,减少数据传输的延迟,因此可提升计算机的性能和效率。
二、开发板与宿主机直接通信
开发板与主机之间的通信有4种方式:
1.JTAG。
2.COM。传输协议通常是xmodem/ymodem/zmodem.
3.网口。TFTP协议。
4.SD卡口
三、宿主机之windows平台
开发环境:ADS1.2+超级终端
ADS1.2:学会使用ADS平台软件,会用AXD进行调试。
超级终端:一般设置波特率115200,数据位8位,停止位1,无奇偶校验,软件硬件流控制设为无。
配置网络:主要是配置NFS,需关闭防火墙,简化嵌入式网络调试环境设置过程。
四、宿主机之Linux平台
开发环境:Linux+minicom
Linux:定制或全部安装。下载安装交叉编译器
minicom:初始化,配置,同windows下超级终端。
配置网络:主要是配置NFS,需关闭iptables。
五、文件烧写
包括烧写内核,根文件系统,应用程序等。
内核映像的烧写有两种方式:
1.vivi,xmodem协议下载,然后烧写
2.linux系统启动后,使用imagewrite工具烧写imagewrite /dev/mtd/0 zImage:192k
⑶ 如何制定android交叉编译工具链
经常搞嵌入式开发的朋友对于交叉编译环境应该并不陌生,说白了,就是一组运行在x86 PC机的编译工具,可以让你在PC机上编译出目标平台(例如ARM)可识别的二进制文件。Android平台也提供了这样的交叉编译工具链,就放在Android的NDK开发包的toolchains目录下,因此,我们的Makefile文件中,只需给出相应的编译工具即可。
废话就先说到这,直接上例子,我们目标是把下面这个math.c文件编译成一个静态库文件:
#include <stdio.h>
int add( int a , int b ) {
return a+b;
}
你需要编写一个Makefile文件,这里假设你的Android ndk被安装在 /opt/android/ndk 目录下,当然,你可以根据自己的实际情况修改Makefile中相关路径的定义,Makefile文件示例如下:
# Makefile Written by ticktick
# Show how to cross-compile c/c++ code for android platform
.PHONY: clean
NDKROOT=/opt/android/ndk
PLATFORM=$(NDKROOT)/platforms/android-14/arch-arm
CROSS_COMPILE=$(NDKROOT)/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/arm-linux-androideabi-
CC=$(CROSS_COMPILE)gcc
AR=$(CROSS_COMPILE)ar
LD=$(CROSS_COMPILE)ld
CFLAGS = -I$(PWD) -I$(PLATFORM)/usr/include -Wall -O2 -fPIC -DANDROID -DHAVE_PTHREAD -mfpu=neon -mfloat-abi=softfp
LDFLAGS =
TARGET = libmath.a
SRCS = $(wildcard *.c)
OBJS = $(SRCS:.c=.o)
all: $(OBJS)
$(AR) -rc $(TARGET) $(OBJS)
clean:
rm -f *.o *.a *.so
这里不讲Makefile文件的基本原理,只说明一下针对Android环境的Makefile文件编写的注意事项。
(1) CROSS_COMPILE
必须正确给出Android NDK编译工具链的路径,当在目录中执行make命令的时候,编译系统会根据 CROSS_COMPILE 前缀寻找对应的编译命令。
(2) -I$(PLATFORM)/usr/include
由于Android平台没有使用传统的c语言库libc,而是自己编写了一套更加高效更适合嵌入式平台的c语言库,所以系统头文件目录不能再使用默认的路径,必须直到Android平台的头文件目录
(3) -Wall -O2 -fPIC -DANDROID -DHAVE_PTHREAD -mfpu=neon -mfloat-abi=softfp
这些参数的意义网上基本上都有介绍,我就不一一解释了,并不都是必须添加的,但比较常用。
编译方法:
写好makefile文件,并且保存之后,就可以直接在当前目录下执行make命令,编译完成后,当前目录下会生成 libmath.a ,即可直接拿到Android的jni工程中和使用了。
⑷ 如何使用android的ndk编译器 编译c++的库
1. 概述 首先回顾一下 Android NDK 开发中,Android.mk 和 Application.mk 各自的职责。 Android.mk,负责配置如下内容: (1) 模块名(LOCAL_MODULE) (2) 需要编译的源文件(LOCAL_SRC_FILES) (3) 依赖的第三方库(LOCAL_STATIC_LIBRARIES,LOCAL_SHARED_LIBRARIES) (4) 编译/链接选项(LOCAL_LDLIBS、LOCAL_CFLAGS) Application.mk,负责配置如下内容: (1) 目标平台的ABI类型(默认值:armeabi)(APP_ABI) (2) Toolchains(默认值:GCC 4.8) (3) C++标准库类型(默认值:system)(APP_STL) (4) release/debug模式(默认值:release) 由此我们可以看到,本文所涉及的编译选项在Android.mk和Application.mk中均有出现,下面我们将一个个详细介绍。 2. APP_ABI ABI全称是:Application binary interface,即:应用程序二进制接口,它定义了一套规则,允许编译好的二进制目标代码在所有兼容该ABI的操作系统和硬件平台中无需改动就能运行。(具体的定义请参考 网络 或者 维基网络 ) 由上述定义可以判断,ABI定义了规则,而具体的实现则是由编译器、CPU、操作系统共同来完成的。不同的CPU芯片(如:ARM、Intel x86、MIPS)支持不同的ABI架构,常见的ABI类型包括:armeabi,armeabi-v7a,x86,x86_64,mips,mips64,arm64-v8a等。 这就是为什么我们编译出来的可以运行于Windows的二进制程序不能运行于Mac OS/Linux/Android平台了,因为CPU芯片和操作系统均不相同,支持的ABI类型也不一样,因此无法识别对方的二进制程序。 而我们所说的“交叉编译”的核心原理也跟这些密切相关,交叉编译,就是使用交叉编译工具,在一个平台上编译生成另一个平台上的二进制可执行程序,为什么可以做到?因为交叉编译工具实现了另一个平台所定义的ABI规则。我们在Windows/Linux平台使用Android NDK交叉编译工具来编译出Android平台的库也是这个道理。 这里给出最新 Android NDK 所支持的ABI类型及区别: 那么,如何指定ABI类型呢?在 Application.mk 文件中添加一行即可: APP_ABI := armeabi-v7a //只编译armeabi-v7a版本 APP_ABI := armeabi armeabi-v7a //同时编译armeabi,armeabi-v7a版本 APP_ABI := all //编译所有版本 3. LOCAL_LDLIBS Android NDK 除了提供了Bionic libc库,还提供了一些其他的库,可以在 Android.mk 文件中通过如下方式添加依赖: LOCAL_LDLIBS := -lfoo 其中,如下几个库在 Android NDK 编译时就默认链接了,不需要额外添加在 LOCAL_LDLIBS 中: (1) Bionic libc库 (2) pthread库(-lpthread) (3) math(-lmath) (4) C++ support library (-lstdc++) 下面我列了一个表,给出了可以添加到“LOCAL_LDLIBS”中的不同版本的Android NDK所支持的库: 下面是我总结的一些常用的CFLAGS编译选项: (1)通用的编译选项 -O2 编译优化选项,一般选择O2,兼顾了优化程度与目标大小 -Wall 打开所有编译过程中的Warning -fPIC 编译位置无关的代码,一般用于编译动态库 -shared 编译动态库 -fopenmp 打开多核并行计算, -Idir 配置头文件搜索路径,如果有多个-I选项,则路径的搜索先后顺序是从左到右的,即在前面的路径会被选搜索 -nostdinc 该选项指示不要标准路径下的搜索头文件,而只搜索-I选项指定的路径和当前路径。 --sysroot=dir 用dir作为头文件和库文件的逻辑根目录,例如,正常情况下,如果编译器在/usr/include搜索头文件,在/usr/lib下搜索库文件,它将用dir/usr/include和dir/usr/lib替代原来的相应路径。 -llibrary 查找名为library的库进行链接 -Ldir 增加-l选项指定的库文件的搜索路径,即编译器会到dir路径下搜索-l指定的库文件。 -nostdlib 该选项指示链接的时候不要使用标准路径下的库文件 (2) ARM平台相关的编译选项 -marm -mthumb 二选一,指定编译thumb指令集还是arm指令集 -march=name 指定特定的ARM架构,常用的包括:-march=armv6, -march=armv7-a -mfpu=name 给出目标平台的浮点运算处理器类型,常用的包括:-mfpu=neon,-mfpu=vfpv3-d16 -mfloat-abi=name 给出目标平台的浮点预算ABI,支持的参数包括:“soft”, “softfp” and “hard”
⑸ linux嵌入式中的静态交叉编译是什么意思
应该说是分为静态和动态的
静态就是把需要的库文件也直接编译进去
动态则是在需要的时候才去调用,本身不编译进去
⑹ 编译器的发展史
编译器
编译器,是将便于人编写,阅读,维护的高级计算机语言翻译为计算机能识别,运行的低级机器语言的程序。编译器将源程序(Source program)作为输入,翻译产生使用目标语言(Target language)的等价程序。源程序一般为高级语言(High-level language),如Pascal,C++等,而目标语言则是汇编语言或目标机器的目标代码(Object code),有时也称作机器代码(Machine code)。
一个现代编译器的主要工作流程如下:
源程序(source code)→预处理器(preprocessor)→编译器(compiler)→汇编程序(assembler)→目标程序(object code)→连接器(链接器,Linker)→可执行程序(executables)
目录 [隐藏]
1 工作原理
2 编译器种类
3 预处理器(preprocessor)
4 编译器前端(frontend)
5 编译器后端(backend)
6 编译语言与解释语言对比
7 历史
8 参见
工作原理
翻译是从源代码(通常为高级语言)到能直接被计算机或虚拟机执行的目标代码(通常为低级语言或机器言)。然而,也存在从低级语言到高级语言的编译器,这类编译器中用来从由高级语言生成的低级语言代码重新生成高级语言代码的又被叫做反编译器。也有从一种高级语言生成另一种高级语言的编译器,或者生成一种需要进一步处理的的中间代码的编译器(又叫级联)。
典型的编译器输出是由包含入口点的名字和地址以及外部调用(到不在这个目标文件中的函数调用)的机器代码所组成的目标文件。一组目标文件,不必是同一编译器产生,但使用的编译器必需采用同样的输出格式,可以链接在一起并生成可以由用户直接执行的可执行程序。
编译器种类
编译器可以生成用来在与编译器本身所在的计算机和操作系统(平台)相同的环境下运行的目标代码,这种编译器又叫做“本地”编译器。另外,编译器也可以生成用来在其它平台上运行的目标代码,这种编译器又叫做交叉编译器。交叉编译器在生成新的硬件平台时非常有用。“源码到源码编译器”是指用一种高级语言作为输入,输出也是高级语言的编译器。例如: 自动并行化编译器经常采用一种高级语言作为输入,转换其中的代码,并用并行代码注释对它进行注释(如OpenMP)或者用语言构造进行注释(如FORTRAN的DOALL指令)。
预处理器(preprocessor)
作用是通过代入预定义等程序段将源程序补充完整。
编译器前端(frontend)
前端主要负责解析(parse)输入的源程序,由词法分析器和语法分析器协同工作。词法分析器负责把源程序中的‘单词’(Token)找出来,语法分析器把这些分散的单词按预先定义好的语法组装成有意义的表达式,语句 ,函数等等。 例如“a = b + c;”前端词法分析器看到的是“a, =, b , +, c;”,语法分析器按定义的语法,先把他们组装成表达式“b + c”,再组装成“a = b + c”的语句。 前端还负责语义(semantic checking)的检查,例如检测参与运算的变量是否是同一类型的,简单的错误处理。最终的结果常常是一个抽象的语法树(abstract syntax tree,或 AST),这样后端可以在此基础上进一步优化,处理。
编译器后端(backend)
编译器后端主要负责分析,优化中间代码(Intermediate representation)以及生成机器代码(Code Generation)。
一般说来所有的编译器分析,优化,变型都可以分成两大类: 函数内(intraproceral)还是函数之间(interproceral)进行。很明显,函数间的分析,优化更准确,但需要更长的时间来完成。
编译器分析(compiler analysis)的对象是前端生成并传递过来的中间代码,现代的优化型编译器(optimizing compiler)常常用好几种层次的中间代码来表示程序,高层的中间代码(high level IR)接近输入的源程序的格式,与输入语言相关(language dependent),包含更多的全局性的信息,和源程序的结构;中层的中间代码(middle level IR)与输入语言无关,低层的中间代码(Low level IR)与机器语言类似。 不同的分析,优化发生在最适合的那一层中间代码上。
常见的编译分析有函数调用树(call tree),控制流程图(Control flow graph),以及在此基础上的 变量定义-使用,使用-定义链(define-use/use-define or u-d/d-u chain),变量别名分析(alias analysis),指针分析(pointer analysis),数据依赖分析(data dependence analysis)等等。
上述的程序分析结果是编译器优化(compiler optimization)和程序变形(compiler transformation)的前提条件。常见的优化和变新有:函数内嵌(inlining),无用代码删除(Dead code elimination),标准化循环结构(loop normalization),循环体展开(loop unrolling),循环体合并,分裂(loop fusion,loop fission),数组填充(array padding),等等。 优化和变形的目的是减少代码的长度,提高内存(memory),缓存(cache)的使用率,减少读写磁盘,访问网络数据的频率。更高级的优化甚至可以把序列化的代码(serial code)变成并行运算,多线程的代码(parallelized,multi-threaded code)。
机器代码的生成是优化变型后的中间代码转换成机器指令的过程。现代编译器主要采用生成汇编代码(assembly code)的策略,而不直接生成二进制的目标代码(binary object code)。即使在代码生成阶段,高级编译器仍然要做很多分析,优化,变形的工作。例如如何分配寄存器(register allocatioin),如何选择合适的机器指令(instruction selection),如何合并几句代码成一句等等。
编译语言与解释语言对比
许多人将高级程序语言分为两类: 编译型语言 和 解释型语言 。然而,实际上,这些语言中的大多数既可用编译型实现也可用解释型实现,分类实际上反映的是那种语言常见的实现方式。(但是,某些解释型语言,很难用编译型实现。比如那些允许 在线代码更改 的解释型语言。)
历史
上世纪50年代,IBM的John Backus带领一个研究小组对FORTRAN语言及其编译器进行开发。但由于当时人们对编译理论了解不多,开发工作变得既复杂又艰苦。与此同时,Noam Chomsky开始了他对自然语言结构的研究。他的发现最终使得编译器的结构异常简单,甚至还带有了一些自动化。Chomsky的研究导致了根据语言文法的难易程度以及识别它们所需要的算法来对语言分类。正如现在所称的Chomsky架构(Chomsky Hierarchy),它包括了文法的四个层次:0型文法、1型文法、2型文法和3型文法,且其中的每一个都是其前者的特殊情况。2型文法(或上下文无关文法)被证明是程序设计语言中最有用的,而且今天它已代表着程序设计语言结构的标准方式。分析问题(parsing problem,用于上下文无关文法识别的有效算法)的研究是在60年代和70年代,它相当完善的解决了这个问题。现在它已是编译原理中的一个标准部分。
有限状态自动机(Finite Automaton)和正则表达式(Regular Expression)同上下文无关文法紧密相关,它们与Chomsky的3型文法相对应。对它们的研究与Chomsky的研究几乎同时开始,并且引出了表示程序设计语言的单词的符号方式。
人们接着又深化了生成有效目标代码的方法,这就是最初的编译器,它们被一直使用至今。人们通常将其称为优化技术(Optimization Technique),但因其从未真正地得到过被优化了的目标代码而仅仅改进了它的有效性,因此实际上应称作代码改进技术(Code Improvement Technique)。
当分析问题变得好懂起来时,人们就在开发程序上花费了很大的功夫来研究这一部分的编译器自动构造。这些程序最初被称为编译器的编译器(Compiler-compiler),但更确切地应称为分析程序生成器(Parser Generator),这是因为它们仅仅能够自动处理编译的一部分。这些程序中最着名的是Yacc(Yet Another Compiler-compiler),它是由Steve Johnson在1975年为Unix系统编写的。类似的,有限状态自动机的研究也发展了一种称为扫描程序生成器(Scanner Generator)的工具,Lex(与Yacc同时,由Mike Lesk为Unix系统开发)是这其中的佼佼者。
在70年代后期和80年代早期,大量的项目都贯注于编译器其它部分的生成自动化,这其中就包括了代码生成。这些尝试并未取得多少成功,这大概是因为操作太复杂而人们又对其不甚了解。
编译器设计最近的发展包括:首先,编译器包括了更加复杂算法的应用程序它用于推断或简化程序中的信息;这又与更为复杂的程序设计语言的发展结合在一起。其中典型的有用于函数语言编译的Hindley-Milner类型检查的统一算法。其次,编译器已越来越成为基于窗口的交互开发环境(Interactive Development Environment,IDE)的一部分,它包括了编辑器、连接程序、调试程序以及项目管理程序。这样的IDE标准并没有多少,但是对标准的窗口环境进行开发已成为方向。另一方面,尽管近年来在编译原理领域进行了大量的研究,但是基本的编译器设计原理在近20年中都没有多大的改变,它现在正迅速地成为计算机科学课程中的中心环节。
在九十年代,作为GNU项目或其它开放源代码项目的一部分,许多免费编译器和编译器开发工具被开发出来。这些工具可用来编译所有的计算机程序语言。它们中的一些项目被认为是高质量的,而且对现代编译理论感性趣的人可以很容易的得到它们的免费源代码。
大约在1999年,SGI公布了他们的一个工业化的并行化优化编译器Pro64的源代码,后被全世界多个编译器研究小组用来做研究平台,并命名为Open64。Open64的设计结构好,分析优化全面,是编译器高级研究的理想平台。
编译器是一种特殊的程序,它可以把以特定编程语言写成的程序变为机器可以运行的机器码。我们把一个程序写好,这时我们利用的环境是文本编辑器。这时我程序把程序称为源程序。在此以后程序员可以运行相应的编译器,通过指定需要编译的文件的名称就可以把相应的源文件(通过一个复杂的过程)转化为机器码了。
编译器工作方法
首先编译器进行语法分析,也就是要把那些字符串分离出来。然后进行语义分析,就是把各个由语法分析分析出的语法单元的意义搞清楚。最后生成的是目标文件,我们也称为obj文件。再经过链接器的链接就可以生成最后的可执行代码了。有些时候我们需要把多个文件产生的目标文件进行链接,产生最后的代码。我们把一过程称为交叉链接。
⑺ 什么是嵌入式linux交叉工具链
在编译软件的时候,会用到(链接)一些平台相关的类库,如果是在本地运行的话,一般不用作特殊处理,但由于嵌入式软件的运行平台不是本地,所以要做一些特殊处理,让编译环境信赖的类库脱离本地信赖,使用嵌入式平台的类库来进行链接,处理这一过程就叫作交叉编译工具链。
不只是嵌入式要用到交叉编译工具,跨平台编译也要使用交叉编译工具链,如linux编译win32软件,linu 32位系统编译linux64位软件等等。它们的部署原理都是一样的。
⑻ 如何用gentoo交叉编译一个基本系统
嵌入式系统的编译环境
为某个平台开发软件,首先需要一个编译环境。一般来说,编译环境包括三部分:工具 链/运行环境/编译方法。对于嵌入式系统来说,常见的编译环境有三种:
本地环境。如很流行的Ubuntu for ARM,利用官方制作好的目标机镜像(通常包含了 编译环境),直接在目标机上编译/安装软件,与PC机开发完全一样。这种方法简单省 事。缺点也显而易见,编译速度慢,耗时长,特别是较大的软件包(如xbmc)的时候, 程序员不是停下来喝杯咖啡就可以收摊,恐怕得打场通宵dota后才能看到结果 了…(或许distcc能有所改善)
虚拟环境。在PC上建立目标机的虚拟环境,如QEMU-ARM,然后chroot到虚拟环境 中编译/安装软件。这种方法利用了PC的处理能力,速度比本地环境要快得多,但 QEMU并不能完美的模拟目标机环境,如不支持某些系统调用等,这可能导致它不能 正确的编译某些软件。
交叉编译。为目标机交叉编译软件,这是最常规的办法,也是上面两种方法实现的基 础。说交叉编译是“脏活”,是因为需要手工解决软件包的所有依赖问题,手工编译 每一个软件包,并且解决软件包对目标机兼容问题… 看网上铺天盖地关于求教/指导 某个软件包如何正确交叉编译就知道,有多少程序员在被它虐?
gentoo下的交叉编译
gentoo是一个metadistribution,从源代码构建整个系统,同时支持很多不同的体 系如alpha/arm/hppa/ppc/sh/sparc/s390等,也为交叉编译提供了便利的工具,这是 其它二进制发行版没有办法比拟的(scratchbox也显得弱爆了)。
gentoo下的交叉编译通过crossdev和portage来实现。portage带来的好处是自 动解决依赖和自动升级更新系统,跟本机环境一样。
制作工具链
crossdev用来制作交叉工具链,并且还提供了交叉编译环境下的emerge的辅助脚本。如 下编译arm平台的工具链:
$ sudo crossdev -t arm-supertux-linux-gnueabi
这样,crossdev最终制作了符合“gentoo规范”的arm交叉编译器。
运行环境
crossdev生成/usr/arm-supertux-linux-gnueabi/目录作为目标系统 $buildroot。编译后生成的目标会被emerge到$buildroot,编译时依赖的环境(如 链接库/头文件/pkgconfig等)也都在$buildroot。
交叉编译
有了工具链/运行环境,使用的crossdev封装过的emerge,就可以自由的emerge了。 如交叉编译bash:
$ sudo emerge-arm-supertux-linux-gnueabi -avu bash
porage会自动把bash的依赖如ncurses/readline一起emerge到$buildroot。 交叉编译就是变得如此简单…
碰到的问题
站在巨人的肩膀上可以看的更远,前提是我们先要爬上巨人的肩膀。portage是一个快 速更新迭代的系统,并不完美,维护者没有办法测试每个软件包的所有兼容性。所以, 当你想安装一个图形环境如$emerge -avu enlightenment时,很可能会出现错误。但 portage提供了细粒度的控制帮助解决这样的问题。下面是我碰到过一些情形和解决方 法:
由于软件包的环境变量引起的问题,如链接库指向了/usr/bin,而非 $buildroot。可以配置$buldroot/etc/portage/env/目录下相应的文 件,portage会自动source该文件,从而改变编译时的环境。
portage没有包含该软件或portage自身的bug引起,如默认使能了某个在目标机 平台不能使用的特性。建立一个针对目标机的overlay,自己编写相应软件包的 ebuild文件指导portage进行交叉编译。
当某个软件包分阶段编译时,如perl编译时先生成miniperl,通过miniperl最 后生成perl目标映像。由于miniperl被交叉编译器生成目标机的映像,正常情况 下不能主机环境中继续运行生成最终的目标映像。这就要借助qemu-arm+binfmt模 拟目标机环境,让miniperl在主机环境中也能无缝的运行。
从形式上看,处理上面几种情况,也是“脏活”。不仅需要了解该软件包的编译环境, 还需要了解portage的原理,还要知道ebuild的书写语法。但是,与传统的交叉编译 方式比起来,这是一劳永逸的工作,别人使用我的运行环境和overlay,即不需再做什 么就能生成最终的目标机系统。
⑼ C++编程:什么是CrossGCC
CrossGCC是一个比较通用的编译器,支持几乎所有主流MCU/CPU/DSP 。
它是免费的,借助linux可以大幅提高便捷性。
想了解处理器的秘密执行原理,写出高质量的代码,用它很合适。
补充:C++这个词在中国大陆的程序员圈子中通常被读做“C加加”,而西方的程序员通常读做“C plus plus”,“CPP”。 它是一种使用非常广泛的计算机编程语言。C++是一种静态数据类型检查的、支持多重编程范式的通用程序设计语言。它支持过程化程序设计、数据抽象、面向对象程序设计、泛型程序设计等多种程序设计风格。