gcc会用,但只会最简单的命令。最近弄bootloader,发现自己很多基础知识都掌握的极其肤浅。接触都这么久了,仍然停留在这一个地步未能深入,不得不汗顔。
还没有看gnu gcc 的Using the GNU Compiler Collection,一来,这个文档很大,短时间能不可能看完,未来一段时间内都排不到学习计划中;二来自己的很多基础都没有打好,这样硬着去看,效果不会太好。
这里总结一下gcc的使用,不全面,只求能够满足暂时的使用要求。
运行gcc时相关程序和命令:
as 汇编器
ld 链接器
gdb 调试器
nm 列出目标文件中定义的符号
objcopy 将目标文件从一种二进制格式复制和翻译到另一种
objdump 显示一个或多个目标文件中保存的多种不同信息
size 列出目标文件中每个部分的名字和尺寸
strip 去掉目标文件中的符号信息以及调试所用的信息
------------------------------------------------------------------------------------------------------------------------
gcc常用选项:
-E 仅作预处理,不进行编译,汇编和链接
-S 编译到汇编语言,不进行汇编和链接
-c 编译,汇编到目标代码,不进行链接
-o <文件> 输出到<文件>
-x <语言> 指定其后输入文件的语言
-v 显示命令执行的具体步骤
-### 与-v类似,但行期被引号括住,且不执行命令
-Xassembler <参数> 将<参数>传递给汇编器
-Xpreprocessor <参数> 将<参数>传递给预处理器
-Xlinker <参数> 将<参数>传递给链接器
------------------------------------------------------------------------------------------------------------------------
拿hello world 为例:
分步执行gcc
1. 预处理(pre-processing)
gcc -E hello.c -o hello.i
选项 操作 生成文件
-E 预处理,但不编译 对.c文件进行预处理后的结果 .i
-S 编译,但不汇编 .s文件(汇编文件)
-c 汇编,但不链接 .o文件(目标文件)
2. 编译,生成.s的汇编文件
这一阶段根据输入文件产生汇编语言指令.由于通常情况下是立即调用汇编程序as,所以输出一般不保存大文件中,可以使用-c选项完成:
gcc -S hello.i -o hello.s
-x告诉gcc从指定的步骤开始编译.gcc通过依靠文件扩展名来决定如何处理该文件.
3. 汇编,生成目标文件
gcc -c hello.s -o hello.o
(as hello.s -o hello.o)
4. 链接(ld还不太会用,所以直接用gcc替换)
gcc hello.o -o hello
------------------------------------------------------------------------------------------------------------------------
所有的这些,我们只需要一句:
gcc hello.c -o hello
即可完成所有步骤
gcc的执行过程并不是一气呵成的,其中大体经历了以下几个步骤:
1. 调用预处理器程序cpp,对源文件进行预处理
2. 调用as将源代码编译成目标代码
3. 调用链接程序ld把生成的目标代码链接成一个可执行程序
我们来看一下:
--------------------------------------------------------------------------------------------------------------------------
#include <stdio.h>
int
main(void)
{
printf("Hello World!\n");
return 0;
} |
gcc -### hello.c -o hello /* 这个命令可以看到执行的具体步骤,但不进行编译*/
Using built-in specs.
Target: i586-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl= --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --enable-plugin --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --disable-libjava-multilib --with-ppl --with-cloog --with-tune=generic --with-arch=i586 --build=i586-redhat-linux
Thread model: posix
gcc version 4.4.0 20090506 (Red Hat 4.4.0-4) (GCC)
COLLECT_GCC_OPTIONS='-o' 'hello' '-mtune=generic' '-march=i586'
"/usr/libexec/gcc/i586-redhat-linux/4.4.0/cc1" "-quiet" "hello.c""-quiet" "-dumpbase" "hello.c" "-mtune=generic" "-march=i586""-auxbase" "hello" "-o" "/tmp/cchjnnyU.s"
COLLECT_GCC_OPTIONS='-o' 'hello' '-mtune=generic' '-march=i586' /* 上面一句编译到了汇编文件,生成‘.s’汇编文件 */
"as" "-Qy" "-o" "/tmp/ccOF4DiF.o" "/tmp/cchjnnyU.s" /*这一句汇编,生成目标文件*/
COMPILER_PATH=/usr/libexec/gcc/i586-redhat-linux/4.4.0/:/usr/libexec/gcc/i586-redhat-linux/4.4.0/:/usr/libexec/gcc/i586-redhat-linux/:/usr/lib/gcc/i586-redhat-linux/4.4.0/:/usr/lib/gcc/i586-redhat-linux/:/usr/libexec/gcc/i586-redhat-linux/4.4.0/:/usr/libexec/gcc/i586-redhat-linux/:/usr/lib/gcc/i586-redhat-linux/4.4.0/:/usr/lib/gcc/i586-redhat-linux/
LIBRARY_PATH=/usr/lib/gcc/i586-redhat-linux/4.4.0/:/usr/lib/gcc/i586-redhat-linux/4.4.0/:/usr/lib/gcc/i586-redhat-linux/4.4.0/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-o' 'hello' '-mtune=generic' '-march=i586'
"/usr/libexec/gcc/i586-redhat-linux/4.4.0/collect2" "--eh-frame-hdr" "--build-id" "-m" "elf_i386" "--hash-style=gnu""-dynamic-linker" "/lib/ld-linux.so.2" "-o" "hello""/usr/lib/gcc/i586-redhat-linux/4.4.0/../../../crt1.o" "/usr/lib/gcc/i586-redhat-linux/4.4.0/../../../crti.o" "/usr/lib/gcc/i586-redhat-linux/4.4.0/crtbegin.o" "-L/usr/lib/gcc/i586-redhat-linux/4.4.0""-L/usr/lib/gcc/i586-redhat-linux/4.4.0" "-L/usr/lib/gcc/i586-redhat-linux/4.4.0/../../.." "/tmp/ccOF4DiF.o""-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed" "-lc" "-lgcc""--as-needed""-lgcc_s" "--no-as-needed" "/usr/lib/gcc/i586-redhat-linux/4.4.0/crtend.o" "/usr/lib/gcc/i586-redhat-linux/4.4.0/../../../crtn.o"
/* 最后链接,生成目标文件 */
|
上面将关键的地方高亮了红色。中文注释是我加的,并不存在输出中。
--------------------------------------------------------------------------------------------------------------------------
编译的时候,还需要头文件和库,这个是非常重要的。
-I <目录路径> gcc编译时有都几个默认的路径,这里向搜索路径中添加我们指定的目录。
-L <目录路径> 向库文件搜索路径中添加指定的目录
-l(小写的L) <库名> Linux下库文件名都是以lib开头的,用-l选项指定链接的库文件名时,省略lib三个字母。
默认的编译都是使用动态链接的,若要使用静态链接,gcc后面的选项中添加“-static”
--------------------------------------------------------------------------------------------------------------------------
警告提示功能:
大多都以 -W
的形式出现:
-Wcomment
如果 "/*" 出现在注释中,则发出警告
-Wformat
检查对printf和scanf等函数的调用,确认各个参数类型和格式的一致
-Wmain
如果把main函数声明或定义成非法的类型,则发出警告
-Wparentheses
某些情况下,若忽略了括号,则警告
-Wswitch
有switch但没有case语句枚举元素,或case枚举超出了范围,则警告
-Wunused
如果声明某变量,但却没有使用,警告
-Wuninitialized
在初始化之前就使用自动变量,警告。
-Winline
若某函数不能使用内嵌语句(inline),警告
-Wmissing-declarations
没有声明就定义了全局函数,警告
-Wlong-long
使用了long long 类型,则警告。此项为默认项。
-Werror
发生警告时取消编译操作
另:还可使用 -Wall 开启警告,用以捕捉一些错误。这个选项也非常有用。
阅读(1146) | 评论(0) | 转发(0) |