﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-runsisi-文章分类-embeded system</title><link>http://www.cppblog.com/runsisi/category/9693.html</link><description /><language>zh-cn</language><lastBuildDate>Tue, 30 Jun 2009 22:43:30 GMT</lastBuildDate><pubDate>Tue, 30 Jun 2009 22:43:30 GMT</pubDate><ttl>60</ttl><item><title>工具链构造彻底剖析</title><link>http://www.cppblog.com/runsisi/articles/88491.html</link><dc:creator>runsisi</dc:creator><author>runsisi</author><pubDate>Thu, 25 Jun 2009 03:56:00 GMT</pubDate><guid>http://www.cppblog.com/runsisi/articles/88491.html</guid><wfw:comment>http://www.cppblog.com/runsisi/comments/88491.html</wfw:comment><comments>http://www.cppblog.com/runsisi/articles/88491.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/runsisi/comments/commentRss/88491.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/runsisi/services/trackbacks/88491.html</trackback:ping><description><![CDATA[<p><span style="font-size: 10pt;">尽管是老生常谈，但是在比较之前，还是先明确一下什么叫做工具链。</span></p>
<p><span style="font-size: 12pt;">
</span></p>
<p><span style="font-size: 12pt;">
LFS/CLFS工具链是一套用于从C/C++源代码生成可执行文件的软件组件适当地组合在一起形成的系统。它包括4大部分，缺一不可：</span></p>
<p><span style="font-size: 12pt;">
1、一套头文件，包含了这些源代码所需要访问的系统接口。</span></p>
<p><span style="font-size: 12pt;">
2、binutils，包含一些处理二进制可执行文件所需的工具，如汇编器、连接器等等。</span></p>
<p><span style="font-size: 12pt;">
3、gcc，包含了编译C/C++源代码所需的工具，并且还能自动调用相关的binutils工具来完成生成源代码的工具</span></p>
<p><span style="font-size: 12pt;">
4、glibc，包含了系统接口的具体实现。</span></p>
<p><span style="font-size: 12pt;">
</span></p>
<p><span style="font-size: 12pt;">
在上面的定义中，请注意这些软件必须适当地组合，才能形成完整的工具链。那么怎么才算适当组合呢？当然，这个工具链必须能够发挥作用，也就是确实能够编译出目标代码，然后才能算适当组合。</span></p>
<p><span style="font-size: 12pt;">
</span></p>
<p><span style="font-size: 12pt;">
那么，一个适当组合的工具链应当具有什么特点呢？一般我们把工具链运行的机器称为host，所产生的代码称为target。那么对于工具链的要求便是：它必须要能在host上运行，所产生的代码必须能在target上运行。再进一步分析：</span></p>
<p><span style="font-size: 12pt;">
1、头文件：必须是针对target的，因为使用这个工具链编译的源代码需要访问的系统接口是trget上的。</span></p>
<p><span style="font-size: 12pt;">
2、binutils：必须能在host上运行，然而产生target的代码。</span></p>
<p><span style="font-size: 12pt;">
3、gcc：和binutils一样。不过这里要注意的是，gcc自身带有一个库，称为libgcc，它必须是target上的代码。</span></p>
<p><span style="font-size: 12pt;">
4、glibc：必须是target上的代码。</span></p>
<p><span style="font-size: 12pt;">
</span></p>
<p><span style="font-size: 12pt;">
有了这些基本认识，让我们来看一看一些实际的工具链构造过程。</span></p>
<p><span style="font-size: 12pt;">
</span></p>
<p><span style="font-size: 12pt;">
LFS工具链构造顺序：binutils p1-&gt;gcc p1-&gt;头文件-&gt;glibc-&gt;adjust-&gt;gcc p2-&gt;binutils p2</span></p>
<p><span style="font-size: 12pt;">
其中最后两步应该可以互换，但头两步不行。如果你有留意编译过程，会发现，当gcc编译的时候，一旦内部编译第一次gcc完成，产生了xgcc文件，随后的编译就会利用新编译的gcc以及第一遍的binutils，而不是宿主的gcc和binutils。</span></p>
<p><span style="font-size: 12pt;">
正如youbest指出的，第一遍的binutils和gcc存在的意义，仅仅是为了能编译出glibc。而glibc的编译需要工具链所有其它内容，包括binutils,gcc和头文件。</span></p>
<p><span style="font-size: 12pt;">
LFS不使用交叉编译，因此host和target永远是一样的。在编译参数中，我们永远看不到--host和--target的身影。但是，由于工具链的引用路径需要反复变化，因此我们需要通过修改specs来更改。这点是LFS比较容易出错的地方。</span></p>
<p><span style="font-size: 12pt;">
</span></p>
<p><span style="font-size: 12pt;">
CLFS顾名思义，是要采用交叉编译的。其构造顺序如下：</span></p>
<p><span style="font-size: 12pt;">
头文件-&gt;cross binutils-&gt;cross-gcc c-&gt;glibc-&gt;gcc final (c/c++)</span></p>
<p><span style="font-size: 12pt;">
我们首先看到头文件被放在了开头。这不是必须的，它完全可以放在glibc之前。cross-gcc只能编译出C编译器，因为这时候工具链还不全，glibc还不存在，不可能编译出C++编译器。然后构建glibc。之后，我们才能编译出C++编译器，完成我们的工具链。</span></p>
<p><span style="font-size: 12pt;">
</span></p>
<p><span style="font-size: 12pt;">
CLFS-SYSROOT的工具链稍有不同，顺序如下：</span></p>
<p><span style="font-size: 12pt;">
头文件-&gt;cross-binutils-&gt;glibc头文件-&gt;cross-gcc c-&gt;gibc-&gt;gcc-final (c/c++)</span></p>
<p><span style="font-size: 12pt;">
我们看到这里多了一个glibc头文件的安装。事实上，这是由于这里编译的gcc是要用sysroot的缘故。在gcc/configure里面有一段代
码，大家在vi里面输入/inhibit_libc=false就可以发现，在交叉编译，而没有SYSROOT的情况下，inhibit_libc的值会
成为true，而要是sysroot了，就false了。</span></p>
<p><span style="font-size: 12pt;">
这个变量的作用，如同有关的注释所述，是用来关闭gcc对glibc头文件的依赖。因此，在sysroot下我们才会需要这样一个安装glibc头文件的步骤。</span></p>
<p><span style="font-size: 12pt;">
我想在sysroot下消除这个步骤，之前测试过这个补丁可行：</span></p>
<p><span style="font-size: 12pt;">
使用这个sed命令打个补丁即可：</span></p>
<p><span style="font-size: 12pt;">
cp gcc/configure{,.orig}</span></p>
<p><span style="font-size: 12pt;">
sed -e 's/inhibit_libc=false/inhibit_libc=true/g' gcc/configure.orig &gt; gcc/configure</span></p>
<p><span style="font-size: 12pt;">
不过最近发现有更简单的方法：在configure的时候加个参数--with-newlib即可。建议采用这个方法，因为不需要打任何补丁。</span></p>
<p><span style="font-size: 12pt;">
</span></p>
<p><span style="font-size: 12pt;">
在此再说一句，工具链构建过程中，编译脚本对于是否交叉编译的判断非常简单，只要host!=target，就会被认为正在交叉编译。这也就是为什么
CLFS中使用的$CLFS_HOST通常都是i686-cross-linux-gnu这样的形式。原因很简单，因为要确保$CLFS_HOST
与$CLFS_TARGET不同。这样，你完全可以在i686上"交叉编译"i686的代码。</span></p>
<p><span style="font-size: 12pt;">
</span></p>
<p><span style="font-size: 12pt;">
这点非常重要，这意味着我们不需要打任何补丁，即可利用CLFS和CLFS-SYSROOT代替LFS来完成系统。对于想做Multilib的朋友，这也是一个福音。毕竟，CLFS-SYSROOT比起CLFS和LFS来，节省了大量的编译过程。</span></p>
<p><span style="font-size: 12pt;">
</span></p>
<p><span style="font-size: 12pt;">
最后，我们来理解一下如何作CCLFS工具链。这意味着我们要在一个平台上构建在第二个平台上运行、生成第三个平台上代码的工具链。我们用build表示
构建工具链的机器，host表示工具链要运行的机器，target表示工具链生成的代码所在机器。而在工具链组件上，host-target
binutils表示该binutils在host上运行，要生成target的代码。</span></p>
<p><span style="font-size: 12pt;">
</span></p>
<p><span style="font-size: 12pt;">
步骤如下：</span></p>
<p><span style="font-size: 12pt;">
host 头文件-&gt;build-host binutils-&gt;build-host gcc c-&gt;host
glibc-&gt;target 头文件-&gt;build-target binutils-&gt;build-target gcc
c-&gt;target glibc-&gt;host-target binutils-&gt;host-target gcc final
(c/c++)</span></p>
<p><span style="font-size: 12pt;">
</span></p>
<p><span style="font-size: 12pt;">
注意事项如下。首先，头文件必须在相应的glibc之前安装。其次，build-target的binutils和gcc在这里的目的是生成target
glibc。而build-host binutils 还会被构建host-target
binutils和gcc的过程使用到。最后，前两次的gcc都可以只生成c编译器，因为他们的目的都只是生成glibc。只有最后一次gcc需要完整生成。</span></p>
<p><span style="font-size: 12pt;">from: http://www.linuxsir.org/bbs/thread325648.html<br></span></p>
<p><span style="font-size: 12pt;"></span></p>
<p><span style="font-size: 12pt;"></span><span style="font-size: 12pt;"></span><span style="font-size: 12pt;"></span><span style="font-size: 12pt;">
</span><span style="font-size: 12pt;"></span></p>
<br><img src ="http://www.cppblog.com/runsisi/aggbug/88491.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/runsisi/" target="_blank">runsisi</a> 2009-06-25 11:56 <a href="http://www.cppblog.com/runsisi/articles/88491.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>编译工具链</title><link>http://www.cppblog.com/runsisi/articles/76632.html</link><dc:creator>runsisi</dc:creator><author>runsisi</author><pubDate>Sun, 15 Mar 2009 05:04:00 GMT</pubDate><guid>http://www.cppblog.com/runsisi/articles/76632.html</guid><wfw:comment>http://www.cppblog.com/runsisi/comments/76632.html</wfw:comment><comments>http://www.cppblog.com/runsisi/articles/76632.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/runsisi/comments/commentRss/76632.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/runsisi/services/trackbacks/76632.html</trackback:ping><description><![CDATA[<p>编译工具链就是编译出所需要的内核，库函数以及应用程序所使用的工具。编译工具主要由以下3部分组成：<br>binutils:一组开发工具，包括连接器，汇编器和其他用于目标文件和档案的工具<br>gcc:包含GNU编译器的集合，其中有C和C++编译器<br>glibc:提供系统调用和基本函数的C库，比如open,malloc,printf等。所有动态连接的程序都要用到它</p>
<p><br>GNU binutils 是一个二进制工具包，主要包括：</p>
<p>ld-GNU的连接器<br>as-GNU汇编器</p>
<p>除此之外还包括以下工具：</p>
<p>addr2line -将地址转化为文件名和行号<br>ar -创建、修改、解压归档文件<br>c++filt - C++ 关键词过滤器 <br>gprof - 显示总体信息 <br>nlmconv - 将目标代码转换为NLM <br>nm - 列出目标文件的标记<br>objcopy - 复制和翻译（编译器翻译）目标文件 <br>objdump - 显示目标文件信息<br>ranlib - 创建归档文件索引<br>readelf - 显示ELF 格式目标文件的索引<br>size -列出目标文件或者归档文件的段长<br>strings -列出文件中的可打印字符串<br>strip - 删除标记<br>windres - Windows 源文件的编译器</p>
<p>这中间的大部分程序都使用Binary File Descriptor library来进行底层处理。很多程序还要用到 opcodes library 来进行机器指令的汇编<br>和Wintel一样，binutils也被引入到了各种各样的UNIX系统中，它的引入使得GNU系统能够更方便的编译和连接程序。<br></p>
<img src ="http://www.cppblog.com/runsisi/aggbug/76632.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/runsisi/" target="_blank">runsisi</a> 2009-03-15 13:04 <a href="http://www.cppblog.com/runsisi/articles/76632.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>