LFS 学习日记(第5章构建临时系统之5.8. Adjusting the Toolchain )

2010年06月23日 星期三

5.8. Adjusting the Toolchain http://www.linuxfromscratch.org/lfs/view/6.6/chapter05/adjusting.html

SPECS=`dirname $($LFS_TGT-gcc -print-libgcc-file-name)`/specs
(#“$()”的用法: 实际上相当于 ``,上面的命令我试着写成
SPECS=$(dirname `$LFS_TGT-gcc -print-libgcc-file-name`)/specs 或
SPECS=$(dirname $($LFS_TGT-gcc -print-libgcc-file-name))/specs 也能得到正确的结果。但是,写成下面这样不行:
SPECS=`dirname `$LFS_TGT-gcc -print-libgcc-file-name``/specs

参考资料:
 http://tldp.org/LDP/abs/html/varassignment.html
Variable assignment using the $(...)  mechanism (a newer method than backquotes). This is actually a form of command substitution.

# From /etc/rc.d/rc.local
R=$(cat /etc/redhat-release)
arch=$(uname -m)

$LFS_TGT-gcc -dumpspecs | sed \
  -e 's@/lib\(64\)\?/ld@/tools&@g' \
(info sed 菜单:* The "s" Command:: 和 * Regular Expressions::
@ 可用任一单字符代替作分隔符;
若分隔符中间出现了作为字符串的分隔符,用 \ 转义,因为这里的分隔符是 @ ,所以 / 不必转义了;
\(64\) 把64作为整体一组来匹配;
\? 匹配0或1次,与前面 \(64\) 组合形成的 \(64\)\? 表示或者没有 64 这个字符串,或者有一次;
& 代替前面两个分隔符 @ 之间的部分;
g 表示替换所有匹配的字符串,而不只是第一个
整个表达式的意思就是把所有的 /lib/ld 或 /lib64/ld 替换成相应的 /tools/lib/ld 或 /tools/lib64/ld
 )
  -e "/^\*cpp:$/{n;s,$, -isystem /tools/include,}" > $SPECS

(这句语法不懂,零星的看了一下 man sed 和 info sed ,搜索了一下,没得要领,上LFS Support List <lfs-support@linuxfromscratch.org>问了一下,很快有热心的朋友回答了。这句的作用是设定C预处理器的头文件搜索路径:(参见: http://tigcc.ticalc.org/doc/comopts.html 中的 -isystem ) Search dir for header files, after all directories specified by '-I' but before the standard system directories. Mark it as a system directory, so that it gets the same special treatment as is applied to the standard system directories. See System Headers.

参见: 问题: A sed syntax: http://linuxfromscratch.org/pipermail/lfs-support/2010-June/039028.html
特别摘录 Mike McCarty <Mike.McCarty at sbcglobal.net> 的详细解答:http://linuxfromscratch.org/pipermail/lfs-support/2010-June/039030.html

sed    the command

-e    means "execute this little program which follows"

  "    the quotes are necessary to keep the shell from
    trying to do stuff with what's here, and to make
    what follows "all one argument" to the program

/    sed looks at the first character, and takes that
    to be the "delimeter". So, everything from here to
    the next "/" is the "address" sed will use to select
    lines from the file; the program gets executed on lines
    which match this pattern, all other lines pass through
    unchanged

^    this indicates that the pattern must start at
    the beginning of the line

\*    we have to "escape" the "*", or the shell will try to
    put file names in there, hence the "\" to make this
    a literal "*"

cpp:    more string to look for

$    this says that when we've matched what went before,
    we must next find end of line, so, the entire line
    must be "*cpp:", so the command gets executed only
    on lines which contain "*cpp:" and nothing else

/    here's the other delimeter "/" which ends the "address"

{    this tells sed that what is contained is the script to
    execute, when we find a matching line; we do so up to
    the closing "}"

n    Read/append the next line of input into the pattern space
    IOW, print what has been matched so far ("*cpp:") and
    then work on the next line

;    end of "n" command, so all we print is just "*cpp:"
    we use ";" to put multiple commands together, so this
    separates the "n" command from the "s" command

s    now we start a "substitute" command

,    this is taken by sed to be the delimter of the string
    to substitute for; this could be any character, like
    the "/" above; the "s" command wants

    s<delim><string to find><delim><string to sub><delim>

    where <delim> may be any character you like, but all three
    must be the same. In this case, ","

$    the pattern we are going to substitute for is end of line...

,    ... and nothing else, the second "," matches the one above
    and ends the search string

  -isystem /tools/include
    this is the string to substitute at end of line

,    here's the third delimeter

}    this marks end-of-command

"    this is the matching quote for the shell to see

HTH

echo "New specs file is: $SPECS"
unset SPECS #清除变量 SPECS

todo: 据需要掌握 gcc 的 specs 文件的用法和重要部分的修改
todo: 理解 gcc 编译参数 -isystem 和 -I 的区别在实践中的影响(参考资料:GCC Command-Line Options http://tigcc.ticalc.org/doc/comopts.html )

2010年06月24日 星期四

用 diff 比较前面调整了工具链和没有调整工具链的specs文件的区别如下:
18c18
< %{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT} -isystem /tools/include
---
> %{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}
135c135
< %{muclibc:%{mglibc:%e-mglibc and -muclibc used together}/tools/lib/ld-uClibc.so.0;:/tools/lib/ld-linux.so.2}
---
> %{muclibc:%{mglibc:%e-mglibc and -muclibc used together}/lib/ld-uClibc.so.0;:/lib/ld-linux.so.2}

$LFS_TGT-gcc -B/tools/lib dummy.c # -Bprefix 参考资料 man gcc :

       -Bprefix
           This option specifies where to find the executables, libraries,
           include files, and data files of the compiler itself.

           The compiler driver program runs one or more of the subprograms
           cpp, cc1, as and ld.  It tries prefix as a prefix for each program
           it tries to run, both with and without machine/version/.

大体说来指定找到编译器gcc的可执行文件、库文件、头部文件、数据文件的位置,这些位置同样可以传给gcc调用的预处理器cpp、汇编器as、链接器ld等使用。这里是告诉gcc先到/tools/lib下面去找它需要的东西。

这里,如果不指定那个 -B/tools/lib 就会报告:
lfs:~$ $LFS_TGT-gcc dummy.c
/mnt/lfs/tools/bin/../lib/gcc/i686-lfs-linux-gnu/4.4.3/../../../../i686-lfs-linux-gnu/bin/ld: crt1.o: No such file: No such file or directory
collect2: ld returned 1 exit status

question: 在宿主系统中存在有/usr/lib/crt1.o,为什么 ld 不去那里找?

question: cc1 是什么?