zoukankan      html  css  js  c++  java
  • GCC the GNU

        

    GCC简单使用

    -v/-v/--version 查看gcc版本号

    python@ubuntu:~$ gcc -v

    -I 指定头文件目录,注意-I和之间没有空格

    1 #include<stdio.h> //表示从系统路径下查找

    2 #include"include/test.h" //表示从当前系统路径下查找include路径在的tesst.h

    3 void main()

    4 {

    5 printf("ok");

    6 }

    python@ubuntu:~$ gcc -I .include/test.h 1.c -o app

    -c 只编译,生产.o文件,不进行连接

    -g 包含调试信息

    python@ubuntu:~$ gcc 1.c -g -o app1

    python@ubuntu:~$ gcc 1.c -o app2

    python@ubuntu:~$ ls -l

    总用量 3628

    -rw-rw-r-- 1 python python 85 1月 17 13:31 1.c

    -rwxrwxr-x 1 python python 8600 1月 15 09:36 app

    -rwxrwxr-x 1 python python 9592 1月 17 13:32 app1

    -rwxrwxr-x 1 python python 8600 1月 17 13:32 app2

    //可以看出app1比app2大

    python@ubuntu:~$ gdb app1

    (gdb) list

    1    #include<stdio.h> //表示从系统路径下查找

    2    void main()

    3    {

    4     printf("ok");

    5    }

    (gdb)

    //因为没有调试信息所以不能调试

    python@ubuntu:~$ gdb app2

    (gdb) list

    没有符号表被读取。请使用 "file" 命令。

     

    -On n=0-3 编译优化,n越大优化的越多

    //编译器优化自动把不必要的指令优化掉,比如优化有100行,优化后70行

     

     

     

     

     

    -Wall 提示更多警告信息

    python@ubuntu:~$ gcc 1.c -Wall -o app3

    1.c:2:6: warning: return type of 'main' is not 'int' [-Wmain]

    void main()
    //严格编译,不能有一点问题

    -D 编译时定义宏,注意-D和之间没有空格

    1.c文件测试

    1 #include<stdio.h>

    2

    3 int main()

    4 {

    5 #ifdef DEBUG

    6 printf("debug test ");

    7 #endif

    8 printf("helloworld ");

    9 return 0;

    10 }

    python@ubuntu:~$ gcc 1.c -o app

    python@ubuntu:~$ ./app

    helloworld

    python@ubuntu:~$ gcc 1.c -D DEBUG -o app

    python@ubuntu:~$ ./app

    debug test

    helloworld

    ~

    -E 编译生产预处理文件

    python@ubuntu:~$ gcc 1.c -E -o app

    python@ubuntu:~$ vim app

    extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));

    # 942 "/usr/include/stdio.h" 3 4

    # 2 "1.c" 2

     

     

    # 3 "1.c"

    int main()

    {

     

     

     

    printf("helloworld ");

    return 0;

    }

    -M 生产.c文件与头文件依赖关系用于makefile,包括系统的头文件

     

    -MM 生产.c文件与头文件依赖关系用于MakeFile,不包括系统库的文件

     

    Binutils

    一组用于编译、连接、汇编、和其他调试目的的程序,包括ar、as、nm、object等

    gcc编译器

    glibc,该库实现linux系统函数,例如open、read等,也实现标准c语言库,如printf

     

    ar打包生产静态库

    as汇编器

    ld链接器

    nm查看目标文件中的符号

    objcopy将原目标文件中的内容复制到新的目标文件中

    objdump用于生成反汇编文件,主要依赖objcopy实现,a.out编译需要-g

    python@ubuntu:~$ gcc 1.c -D DEBUG -g -o app

    python@ubuntu:~$ objdump -dSsx app >file

    windows下obj,lib,dll,exe的关系

    lib是和dll对应的。lib是静态链接库的库文件,dll是动态链接库的库文件。 
       
    所谓静态就是link的时候把里面需要的东西抽取出来安排到你的exe文件中,以后运行你的exe的时候不再需要lib
       
    所谓动态就是exe运行的时候依赖于dll里面提供的功能,没有这个dll,你的exe无法运行。 
        
        lib,dll,exe
    都算是最终的目标文件,是最终产物。而c/c++属于源代码。源代码和最终目标文件中过渡的就是中间代码obj,实际上之所以需要中间代码,是你不可能一次得到目标文件。比如说一个exe需要很多的cpp文件生成。而编译器一次只能编译一个cpp文件。这样编译器编译好一个cpp以后会将其编译成obj,当所有必须要的cpp都编译成obj以后,再统一link成所需要的exe,应该说缺少任意一个obj都会导致exe的链接失败。
        
        1.obj
    里存的是编译后的代码跟数据,并且有名称,所以在连接时有时会出现未解决的外部符号的问题。当连成exe后便不存在名称的概念了,只有地址。lib就是一堆obj的组合。
        2.
    理论上可以连接obj文件来引用其他工程(可以认为一个obj文件等价于编译生成它的cpp文件,可以引用obj来替换cpp,也可以添加cpp来替换obj ),但实际中通常用lib来实现工程间相互引用。
        3.
    编译器会默认链接一些常用的库,其它的需要你自己指定。

    linux .o,.a,.so

           .o,是目标文件,相当于windows中的.obj文件 

      .so 为共享库,shared object,用于动态连接的,相当于windows下的dll 

      .a为静态库,是好多个.o合在一起,用于静态连接 

     

     

     

     

    静态库和共享库

    程序库,简单说,就是包含了数据和执行码的文件,其不能单独执行可作为其他执行程序一部分完成某些功能,可以使的程序模块化,可以加快程序的在编译,可以实现代码重用,使得程序升级,程序库可为静态库(static library)和共享库(share object)

     

    静态库可以在程序运行前就已经加入到执行码中,成为执行程序的一部分;

    共享库是在执行程序启动后加载到执行文件中,可以被多个执行程序共享使用;

     

    静态库

    在应用程序生成时,可以不在编译,节约再编译时间,但在编译器越来越快的今天,这一点似乎已不重要了,如何其他开发任意要使用你的程序,而你有不想给源码,提供静态库是一个种选择,从理论上讲,应用程序使用了静态库,要比加载动态库速度快1-5%但实际上可能被非如此,由此看来,除了使用方便外,静态库可能备份一种好的选择

     

    要创建一个静态库,或要将目标代码加入到已经存在的静态库中,可以使用一下命令:

    ar rcs libmylib.a file1.o

     

    表示将file1.o加入到 libmulib.a库中

    静态库创建成功后,需要链接到引用程序中使用,使用gcc的-l选项来指定静态库,使用-L参数来指定库文件的搜索路径。

     

     

     

    共享库

    共享库创建比较简单,基本有两步。首先使用-FPIC或-Fpic创建目标文件,或者PIC或

    Pic表示位置无关代码,然后可以使用一下格式创建共享库了:gcc -share -Wl,-soname.your_soname -o library_name file_list library_list

    [root@Zh gccTestLib]# gcc -I/root/gccTestLib/ -c -fpic h.c

    [root@Zh gccTestLib]# cat h.h h.c

    int add(int a,int b)

    {

    return a+b;

    }

    #include "h.h"

    #include <stdio.h>

     

    void main()

    {

    printf("%d",add(10,20));

    }

    //-I 指定头文件的目录

    [root@Zh gccTestLib]# gcc -I/root/gccTestLib/ -c -fpic h.c//编译成.o文件

    [root@Zh gccTestLib]# gcc -c -fpic *.c

    [root@Zh gccTestLib]# ls

    h.c h.o w.c w.o

    [root@Zh gccTestLib]# ls

    h.c h.h h.o

    [root@Zh gccTestLib]# gcc -shared -Wl,-soname,libtest.so.1 -o libtest.so.1.10 h.o

    -soname主版本好

    Libtest.so.1.1o此版本号

    [root@Zh gccTestLib]# ls

    h.c h.h h.o libtest.so.1.10 //编译的库

    [root@Zh gccTestLib]# ldd libtest.so.1.10 //查看库的依赖

        linux-vdso.so.1 => (0x00007ffd0adf1000)

        libc.so.6 => /lib64/libc.so.6 (0x00007ff8e2d82000)

        /lib64/ld-linux-x86-64.so.2 (0x00005558c022f000)

    [root@Zh gccTestLib]# pwd //记作当前的路径,放在系统库的配置文件中,让系统加载

    /root/gccTestLib

    [root@Zh gccTestLib]# vim /etc/ld.so.conf

    [root@Zh gccTestLib]# ldconfig

    [root@Zh gccTestLib]# cat /etc/ld.so.conf

    include ld.so.conf.d/*.conf

    /root/gccTestLib

    [root@Zh gccTestLib]# tree

    .

    ├── h.c

    ├── h.h

    ├── h.o

    ├── libtest.so.1 -> libtest.so.1.10 //自动创建主版本号

    └── libtest.so.1.10

     

    0 directories, 5 files

     

     

    python@ubuntu:~$ gcc 1.c -fpic -shared -o libtest.so.1 一条命令编译

  • 相关阅读:
    消息队列介绍
    SpringBoot随笔-SpringBoot集成Druid
    Redis-Redis基本类型及使用Java操作
    信息安全
    计算机网络基础
    多媒体技术
    数据库基础
    程序设计基础
    计算机软件体系
    计算机硬件体系
  • 原文地址:https://www.cnblogs.com/XiaoGuanYu/p/8328238.html
Copyright © 2011-2022 走看看