您的位置:首页 > 运维架构 > Linux

【Linux C/C++】 第02讲 HelloWorld程序编译流程详解

2016-05-25 10:04 507 查看
    也许你习惯了VC的编译方式,只需要点击一下编译按钮即可,至于VC的编译流程已经被VS封装好了,看到本文之前你可能对详细流程还是一头雾水,通过GCC的编译流程的学习,你可以很好的理解编译过程的各个阶段,下面详细分解一下HelloWorld程序的编译流程细节。

     一 HelloWorld.c程序编译流程

#include <stdio.h>

int main()
{
printf("Hello World\n");
return 0;
}


          1.0 gcc 命令参数

               -o  指定输出文件名

               -O  -O0 -O1 -O2 -O3  编译优化

               -g  -g0 -g1 -g2 -g3      产生调试信息

               -W  all error 

                    -Wall 显示所有警告

                    -Werror 把警告当错误

               -w  关闭警告

               -c   只编译不链接

               -E   预编译

               -S   汇编

          1.1 预编译 生成.i文件

                  预编译就是处理头文件包含,将宏替换掉等等预编译指令

                  


                  HelloWorld.i的内容如下:

                  


          1.2 编译 生成.o目标文件

                 


          1.3 汇编 生成.s汇编文件

                 


                 HelloWorld.s内容如下:

                 


          1.4  链接 ld

                 链接器 ld 和 gcc是两个相对的独立的工具(两个exe文件)

                 gcc负责编译,ld负责将gcc编译生成的.o文件链接

                 ld的执行和参数指定是自动完成的

    二 静态库的编译过程

         2.1 编译成目标文件(*.a a是archive的缩写,意为归档)

                -static 可选

                gcc -c -static  源文件.c

//lib1.c
int add(int a,int b)
{
return a+b;
}

//lib2.c
int sub(int a,int b)
{
return a-b;
}
//main.c
int main()
{
int r = add(1,2);
int s = sub(2,1);
}
               先生成*.o文件,再归档

                


         2.2 归档成静态库

                ar工具

                      -r  归档文件  被归档的文件

                          ar -r 静态库文件.a 被归档文件1.o  被归档文件2.o ...

                          


                      -t  查看静态库里的目标文件列表

                          


                nm工具 -查看函数符号表

                      nm    动态库/静态库/可执行文件/目标文件

                          


         2.3 库的使用

               直接指定库名 gcc main.c 静态库.a

               -l 指定库名 注意此时的库名必须以lib开头,如libmath.a

               -L 指定目录

                    


    三 动态库的编译过程

        3.1 工具

              ldd 查看程序依赖的动态库列表

                  


              readelf -h ./a.out 查看可执行文件的头信息,elf是可执行文件格式

                  


        3.2 动态库的编译

            3.2.1 编译

                -c    -fpic(可选) 

                    -fpic 是-f(format格式缩写) + pic(position independent code)

                     


            3.2.2 链接

                -shared

                      


        3.3 使用动态库

              gcc   代码  动态库名

              gcc   代码 -l  -L

              命名规则

                 lib库名.so

             动态库的加载过程

                    3.3.1 找到动态库

                    3.3.2 加载动态库到内存

                    3.3.3 映射到用户的内存空间

                


            系统对动态库的查找规则

                   /lib

                  /usr/lib

                  export LD_LIBRARY_PATH (是动态库的目录,类似windows下的path)

                          LD_LIBRARY_PATH 只对当前终端有效

                   


             缓冲机制:

                 linux启动时会把:/lib:/usr/lib:LD_LIBRARY_PATH加载到缓冲

                 /sbin/ldconfig -v  刷新缓冲中的.so

    四 使用libdl.so库

        动态库加载的原理

        动态库中函数的查找已经封装成函数libdl.so

             dlopen    打开一个动态库

             dlsym     在打开的动态库查找一个函数

             dlclose    关闭动态库

#include <dlfcn.h>

int main()
{
void* handle = dlopen("./libmath.so",LD_LAZY);
int(* func)(int,int) = dlsym(handle,"add");
int ret = func(1,2);
dlclose(handle);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  编译 linux gcc