• 第22章 软件安装:源码与Tarball


    开放源码的软件安装与升级简介

    什么是开放源码、编译程序与可执行文件

    开放源码:程序代码,写给人类看的程序语言

    编译程序:将源码编译成机器能看得懂的语言

    可执行文件:经过编译变成二进制程序后机器看得懂可以执行的文件

    什么是函数库

    类似子程序的角色,可以被调用来执行的一段功能函数

    什么是make与configure

    一套软件不仅仅有一个程序,而是一对程序代码文件,所以除了每个主程序和子程序均需要编译过程的命令外,还需要写上最终的链接程序。使用make命令,可以简化编译过程。

    (1)执行make时,会在当前目录查找Makefile文件,该文件记录了如何编译源码

    (2)Makefile由检测程序创建,软件开发商都会写一个检测程序检测用户的当前环境,并创建Makefile文件。这个检测程序一般为configure或config

    什么是tarball

    源码体积较大,一般使用gzip等压缩得到的压缩后的源码包就是tarball。tarball一般包括以下文件:(1)源代码文件。(2)检测程序文件。(3)本软件的安装说明。

    如何安装与升级软件

    (1)直接以源码通过编译来安装升级

    (2)直接以编译好的二进制程序来安装和升级

    使用传统程序语言进行编译的简单房里

    单一程序:打印Hello World

    编辑源码

    #include<stdio.h>
    int main(void)
    {
            printf("Hello World
    ");
    }

    编译与执行

    [root@localhost ~]# gcc hello.c
    [root@localhost ~]# ll hello.c a.out
    -rwxr-xr-x. 1 root root 8503 9月   7 14:11 a.out
    -rw-r--r--. 1 root root   63 9月   7 14:10 hello.c
    [root@localhost ~]# ./a.out
    Hello World

    主程序、子程序链接:子程序的编译

    编写主程序、子程序

    [root@localhost ~]# vim thanks.c
    #include<stdio.h>
    int main(void)
    {
            printf("hello world 
    ");
            thanks_2();
    }
    
    [root@localhost ~]# vim thanks_2.c
    #include<stdio.h>
    void thanks_2(void)
    {
            printf("Thank you 
    ");
    }

    程序编译与链接

    [root@localhost ~]# gcc -c thanks.c thanks_2.c
    [root@localhost ~]# ll thanks*
    -rw-r--r--. 1 root root   67 9月   7 14:26 thanks_2.c
    -rw-r--r--. 1 root root 1496 9月   7 14:27 thanks_2.o
    -rw-r--r--. 1 root root   77 9月   7 14:25 thanks.c
    -rw-r--r--. 1 root root 1560 9月   7 14:27 thanks.o
    [root@localhost ~]# gcc -o thanks thanks.o thanks_2.o
    [root@localhost ~]# ./thanks
    hello world 
    Thank you 

    调用外部函数库:加入链接的函数库

    以下调用sin函数

    [root@localhost ~]# vim sin.c
    #include<stdio.h>
    int main(void)
    {
            float value;
            value = sin(3.14/2);
            printf("%f
    ",value);
    }

    编译时加入额外函数库链接

    [root@localhost ~]# gcc sin.c -lm -L/lib -L/usr/lib

    -l:是加入某个函数库的意思

    m:则是libm.so这个函数库,lib和后缀.so不需要写

    如果需要手动制定头文件(如stdio.h)的位置,可以加入”-I/usr/include“这样的指令,/usr/inlcude便是所制定的头文件存放路径

    注:在我的centos7计算机上,直接使用gcc -sin.c可以编译通过,只是会报出不兼容的警告。在程序内加入#include<math.h>便不再出现警告。反而使用以上代码手动加入额外的函数库,也不能消去警告。如下:

    [root@localhost ~]# gcc sin.c -lm -L/lib -L/usr/lib
    sin.c: 在函数‘main’中:
    sin.c:5:10: 警告:隐式声明与内建函数‘sin’不兼容 [默认启用]
      value = sin(3.14/2);
              ^

    用make进行宏编译

    为什么要用make

    假设有以下四个文件:

    main.c

    #include <stdio.h>
    #define pi 3.14159
    char name[15];
    float angle;
    
    int main(void)
    {
        printf ("
    
    Please input your name: ");
        scanf  ("%s", &name );
        printf ("
    Please enter the degree angle (ex> 90): " );
        scanf  ("%f", &angle );
        haha( name );
        sin_value( angle );
        cos_value( angle );
    }

    haha.c

    #include <stdio.h>
    int haha(char name[15])
    {
        printf ("
    
    Hi, Dear %s, nice to meet you.", name);
    }

    cos_value.c

    #include <stdio.h>
    #include <math.h>
    #define pi 3.14159
    float angle;

    void cos_value(void)
    {
        float value;
        value = cos ( angle / 180. * pi );
        printf ("The Cos is: %5.2f ",value);
    }

    sin_value.c

    #include <stdio.h>
    #include <math.h>
    #define pi 3.14159
    float angle;
    
    void sin_value(void)
    {
        float value;
        value = sin ( angle / 180. * pi );
        printf ("
    The Sin is: %5.2f
    ",value);
    }

    那么整个编译执行过程如下:

    [root@localhost c]# gcc -c main.c
    [root@localhost c]# gcc -c haha.c
    [root@localhost c]# gcc -c sin_value.c
    [root@localhost c]# gcc -c cos_value.c
    [root@localhost c]# gcc -o main main.o haha.o sin_value.o cos_value.o -lm
    [root@localhost c]# ./main
    
    
    Please input your name: wuchao
    
    Please enter the degree angle (ex> 90): 30
    
    
    Hi, Dear wuchao, nice to meet you.
    The Sin is:  0.50
    The Cos is:  0.87
    [root@localhost c]# 

      以上编译过程相当麻烦

    以下使用make的方式编译

    使用make指令编译前,需要创建一个Makefile文件

    Makefile文件内容如下:
    main:main.o haha.o sin_value.o cos_value.o gcc -o main main.o haha.o sin_value.o cos_value.o -lm
    [root@localhost c]# vim Makefile
    main:main.o haha.o sin_value.o cos_value.o
            gcc -o main main.o haha.o sin_value.o cos_value.o -lm
    #注意,gcc前面是tab键
    [root@localhost c]# rm -f main*.o
    [root@localhost c]# make
    cc    -c -o main.o main.c
    gcc -o main main.o haha.o sin_value.o cos_value.o -lm
    [root@localhost c]# ./main
    
    
    Please input your name: wuchao
    
    Please enter the degree angle (ex> 90): 45
    
    
    Hi, Dear wuchao, nice to meet you.
    The Sin is:  0.71
    The Cos is:  0.71

    当我们修改过源码以后,再执行make时,只会编译那些修改过的源码文件

    [root@localhost c]# make
    make: “main”是最新的。

    makefile的基本语法与变量

    makefile文件格式如下:

    目标:目标文件1 目标文件2

    <tab> gcc -o 欲新建的可执行文件  目标文件1 目标文件2

    目标就是我们想要建立的信息,而目标文件就是具有相关性的object files,建立可执行的文件的语法就是<tab>按键开头的那一行。

    如果想要在makefile内执行多个操作,比如执行一个命令后立即清除目标文件和可执行文件,则如下:

    main:main.o haha.o sin_value.o cos_value.o
            gcc -o main main.o haha.o sin_value.o cos_value.o -lm
    clean:
            rm -f main main.o haha.o sin_value.o cos_value.o

    以上代码包含两个目标main和clean,如果想要清除目标文件,可以执行”make clean“。如果想先清除再编译可执行”make clean main“。

    [root@localhost c]# make clean main
    rm -f main main.o haha.o sin_value.o cos_value.o
    cc    -c -o main.o main.c
    cc    -c -o haha.o haha.c
    cc    -c -o sin_value.o sin_value.c
    cc    -c -o cos_value.o cos_value.c
    gcc -o main main.o haha.o sin_value.o cos_value.o -lm
    [root@localhost c]# 

    使用变量来简化makefile

    LIBS = -lm
    OBJS = main.o haha.o sin_value.o cos_value.o
    main:${OBJS}
            gcc -o main ${OBJS} ${LIBS}
    clean:
            rm -f main ${OBJS}

    变量的基本语法:

    1. 变量与变量内容以”:“隔开,两边可以有空格

    2. 变量左边不可以有<tab>键

    3. 变量与变量内容两边不能有”:“

    4. 变量名最好使用大写

    5. 运用变量时用${}或$()

    6. 在该shell的环境变量是可以被套用的

    7. 在命令行模式也可以定义变量

     

    gcc在编译时会主动去读取CFLAGS这个环境变量,因此可以在命令行定义这个变量

    [root@localhost c]# CFLAGS="-Wall" make clean main

    也可以如下:

    CFLAGS = -Wall
    LIBS = -lm
    OBJS = main.o haha.o sin_value.o cos_value.o
    main:${OBJS}
            gcc -o main ${OBJS} ${LIBS}
    clean:
            rm -f main ${OBJS}

    由于环境变量既可以在命令行输入,也可以在Makefile文件内指定,所以需要确定使用规则:

    1. make命令行后面加的环境变量第一优先

    2. makefile里面指定的环境变量第二优先

    3. shell原本具有的环境变量第三优先

    $@:代表当前的目标

    每个makefile里面都有一个或多个目标名(如上面的main,clean),在每个目标下的指令中使用$@表示获取当前的目标名

    CFLAGS = -Wall
    LIBS = -lm
    OBJS = main.o haha.o sin_value.o cos_value.o
    main:${OBJS}
            gcc -o $@ ${OBJS} ${LIBS}
    clean:
            rm -f main ${OBJS}

    函数库管理

    动态与静态函数库

    静态函数库

    • 扩展名为.a,通常名为libxxx.a
    • 编译时会直接将这个函数整合到执行程序中去,所以利用静态函数库编译的文件会比较大
    • 独立执行,不需要再向外部读取函数库的数据
    • 升级难度大,函数库升级后,原执行程序也必须重新编译

    动态函数库

    • 扩展名为.so,通常名为libxxx.so
    • 编译时,函数库不会整合到执行程序中去
    • 执行时,函数库文件必须存在,目录也必须正确
    • 容易升级函数库,函数库即使升级,原程序也不需要重新编译

     

    ldconfig与/etc/ld.so.conf

    通过文件配置可以将特定的动态函数库加载到内存中,以提高读取性能。

    1. 首先,在/etc/ld.so.conf下写入需要的动态函数库所在的目录

    2. 利用ldconfig将/etc/ld.so.conf的数据读入缓存

    3. 同时也将数据记录一份在/etc/ld.so.cache中

     

    编辑配置文件/etc/ld.so.conf

    [root@localhost c]# vim /etc/ld.so.conf
    
    include ld.so.conf.d/*.conf
    /usr/lib/mysql    #新添加的

    读入缓存

    [root@localhost c]# ldconfig

    程序的动态函数库解析

    查看二进制文件使用了哪些动态函数库

    [root@localhost c]# ldd /usr/bin/passwd
        linux-vdso.so.1 =>  (0x00007ffc3b1b8000)
        libuser.so.1 => /lib64/libuser.so.1 (0x00007f48e7a48000)
        libgobject-2.0.so.0 => /lib64/libgobject-2.0.so.0 (0x00007f48e77f8000)
        libglib-2.0.so.0 => /lib64/libglib-2.0.so.0 (0x00007f48e74c0000)
        libpopt.so.0 => /lib64/libpopt.so.0 (0x00007f48e72b0000)
        libpam.so.0 => /lib64/libpam.so.0 (0x00007f48e70a0000)
        libpam_misc.so.0 => /lib64/libpam_misc.so.0 (0x00007f48e6e98000)
        libaudit.so.1 => /lib64/libaudit.so.1 (0x00007f48e6c70000)
        libselinux.so.1 => /lib64/libselinux.so.1 (0x00007f48e6a48000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f48e6828000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f48e6460000)
        libgmodule-2.0.so.0 => /lib64/libgmodule-2.0.so.0 (0x00007f48e6258000)
        libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007f48e6020000)
        libffi.so.6 => /lib64/libffi.so.6 (0x00007f48e5e18000)
        libdl.so.2 => /lib64/libdl.so.2 (0x00007f48e5c10000)
        libpcre.so.1 => /lib64/libpcre.so.1 (0x00007f48e59a8000)
        liblzma.so.5 => /lib64/liblzma.so.5 (0x00007f48e5780000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f48e7e88000)
        libfreebl3.so => /lib64/libfreebl3.so (0x00007f48e5578000)

    检查软件的正确性

    使用md5sum或sha1sum可以查看软件的MD5或SHA1编码

    [root@localhost c]# md5sum main
    e6adaa0b35ee4daa1cd7e43916e2d693  main
    [root@localhost c]# sha1sum main
    7735cf8f7ed60ccbad3dcf94fb52be0abe26817b  main

     

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    GNU编码标准
    glade2 与 glade 3 (转)
    简单 gcc 参数
    gtk 主循环函数
    指针与数组关联导致的一些现象
    C语言声明数组变量时,在什么情况下,可不指定数组大小
    文件复制函数的效率比较
    关于VMware虚拟机的上网
    errno的基本用法
    查找数组中最大的2个数
  • 原文地址:https://www.cnblogs.com/wuchaodzxx/p/5850031.html
Copyright © 2020-2023  润新知