zoukankan      html  css  js  c++  java
  • gcc总结【基本用法】【选项】【动静态库】(转)

    1.////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    linuxc编程起步一:掌握gcc基本用法

     初学时最好从命令行入手,这样可以熟悉从编写程序、编译、调试和执行的整个过程。编写程序可以用vi或其它编辑器编写。

    编译则使用gcc命令。要往下学习首先就得熟悉gcc命令的用法。

    gcc命令提供了非常多的命令选项,但并不是所有都要熟悉,初学时掌握几个常用的就可以了,到后面再慢慢学习其它选项,免得因选项太多而打击了学习的信心。

     

    .常用编译命令选项

    假设源程序文件名为test.c

     

    1.无选项编译链接

    用法:#gcc test.c

    作用:将test.c预处理、汇编、编译并链接形成可执行文件。这里未指定输出文件,默认输出为a.out

     

    2.选项-o

    用法:#gcc test.c -o test

    作用:将test.c预处理、汇编、编译并链接形成可执行文件test-o选项用来指定输出文件的文件名

     

    3.选项-E

    用法:#gcc -E test.c -o test.i

    作用:将test.c预处理输出test.i文件。

     

    4.选项-S

    用法:#gcc -S test.i

    作用:将预处理输出文件test.i汇编成test.s文件。

     

    5.选项-c

    用法:#gcc -c test.s

    作用:将汇编输出文件test.s编译输出test.o文件。

     

    6.无选项链接

    用法:#gcc test.o -o test

    作用:将编译输出文件test.o链接成最终可执行文件test

     

    7.选项-O

    用法:#gcc -O1 test.c -o test

    作用:使用编译优化级别1编译程序。级别为1~3,级别越大优化效果越好,但编译时间越长

     

    .多源文件的编译方法

     

    如果有多个源文件,基本上有两种编译方法:

    [假设有两个源文件为test.ctestfun.c]

     

    1.多个文件一起编译

    用法:#gcc testfun.c test.c -o test

    作用:将testfun.ctest.c分别编译后链接成test可执行文件。

     

    2.分别编译各个源文件,之后对编译后输出的目标文件链接。

    用法:

    #gcc -c testfun.c //testfun.c编译成testfun.o

    #gcc -c test.c //test.c编译成test.o

    #gcc -o testfun.o test.o -o test //testfun.otest.o链接成test

     

    以上两种方法相比较,第一种方法编译时需要所有文件重新编译,而第二种方法可以只重新编译修改的文件,未修改的文件不用重新编译。

     

    gcc编程环境基础5--编译时头文件和库文件路径指定


    预处理(preprocessing),编译(compilation),汇编(assembly)和连接(linking)
    include
    header文件,连结数据库,系统定义,总共有下列来源指定gcc去那找.
    当初在编译时指定的(~gcc/gcc/collect2.c:locatelib()
    写在specs内的
    后来用-D-I -L指定的
    gcc
    环境变量设定(编译的时候)
    ld.so
    的环境变量(这是runtime的时候)
    =======================================
      1
    =======================================
    1.
    头文件
    gcc
    在编译时怎么去寻找所需要的头文件
    所以headerfile的搜寻会从-I开始
    然后找gcc的环境变量C_INCLUDE_PATH,CPLUS_INCLUDE_PATH,OBJC_INCLUDE_PATH
    再找内定目录
    /usr/include
    /usr/local/include
    /usr/lib/gcc-lib/i386-linux/2.95.2/include
    /usr/lib/gcc-lib/i386-linux/2.95.2/../../../../include/g++-3
    /usr/lib/gcc-lib/i386-linux/2.95.2/../../../../i386-linux/include
    库文件不过如果装gcc的时候,是有给定的prefix的话,那么就是
    /usr/include
    prefix/include
    prefix/xxx-xxx-xxx-gnulibc/include
    prefix/lib/gcc-lib/xxxx-xxx-xxx-gnulibc/2.8.1/include

    2.库文件
    cos()
    等函式库的选项要多加-lm
    编译的时候:
    gcc
    会去找-L
    再找gcc的环境变量LIBRARY_PATH
    再找内定目录/lib/usr/lib /usr/local/lib这是当初compilegcc时写在程式内的
    =======================================
        2
    =======================================

    2.利用Linux系统上已有的研发库
    (1).
    查看库文件提供了哪些调用
    能用nm命令自己查看库文件提供了哪些调用
    (2).
    通过头文件查看函数的定义
    =======================================
        3
    =======================================
    3.gcc
    选项
    总体选项(OverallOption)         :(-c(生成目标但不连接)-S(汇编)-E(预处理)  -ofile(生成指定的文件)-pipe-v(显示过程)    -xlanguage(设定文件所使用的语言,使后缀名无效`c’,可用参数`objective-c’,`c-header’, `c++’, `cpp-output’, `assembler’, and`assembler-with-cpp’))
    语言选项(LANGUAGEOPTIONS) :(-ansi只支持ANSI标准的C语法.这一选项将禁止GNU C的某些特色)
    预处理器选项(PreprocessorOption):(-Aassertion-C -dD -dM -dN -Dmacro[=defn] -E -H -idirafter dir -include file-imacros file -iprefix file -iwithprefix dir -M -MD -MM -MMD-nostdinc -P -Umacro相当于C语言中的#undefmacro -undef -DMACRO以字符串1”定义MACRO, -DMACRO=DEFN以字符串DEFN”定义MACRO宏)
    汇编器选项(ASSEMBLEROPTION)     :(-Wa,option
    连接器选项(LINKEROPTION)        :(-llibrary-nostartfiles -nostdlib -static -shared -symbolic -Xlinker option-Wl,option -u symbol 
    目录选项(DIRECTORYOPTION)       :(-Bprefix-Idir -I- -Ldir) 
    警告选项(WARNINGOPTION)  :(-w不生成所有警告信息,-Wall生成所有警告信息)
    调试选项(DEBUGGINGOPTION)       :(-a-dletters -fpretend-float -g -glevel -gcoff -gxcoff -gxcoff+ -gdwarf-gdwarf+ -gstabs -gstabs+ -ggdb  -p -pg -save-temps-print-file-name=library -print-libgcc-file-name-print-prog-name=program 
    优化选项(OPTIMIZATIONOPTION)    :(-O0不进行优化处理,-O-O1优化生成代码-O2进一步优化 -O3-O2更进一步优化,包括inline函数)
    目标机选项(TARGETOPTION)  :(-bmachine -V version
    机器相关选项(MACHINEDEPENDENT OPTION):(-m486针对486进行代码优化)
    代码生成选项(CODEGENERATION OPTION)  (-fpic-fPIC)

     

     

     

     

    2.//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////GCC选项
    GCC
    有超过100个的编译选项可用.这些选项中的许多你可能永远都不会用到,但一些主要的选项将会频繁用到.很多的GCC选项包括一个以上的字符.因此你必须为每个选项指定各自的连字符,并且就象大多数Linux命令一样你不能在一个单独的连字符后跟一组选项.例如,下面的两个命令是不同的:
    gcc -p -g test.c 

    gcc -pg test.c 
    第一条命令告诉GCC编译test.c时为prof命令建立剖析(profile)信息并且把调试信息加入到可执行的文件里.第二条命令只告诉GCCgprof命令建立剖析信息.

    当你不用任何选项编译一个程序时,GCC将会建立(假定编译成功)一个名为a.out的可执行文件.例如,下面的命令将在当前目录下产生一个叫a.out的文件:
    gcc test.c 
    你能用-o编译选项来为将产生的可执行文件指定一个文件名来代替a.out.例如,将一个叫count.cC程序编译为名叫count的可执行文件,你将输入下面的命令:
    gcc -o count count.c 

    注意:当你使用-o选项时,-o后面必须跟一个文件名.

    -c只编译并生成目标文件。

    --------------------------------------------------------------------------------
    gcc and g++
    分别是gnuc& c++编译器gcc/g++在执行编译工作的时候,总共需要4

    1.
    预处理,生成.i的文件[预处理器cpp]
    2.
    将预处理后的文件不转换成汇编语言,生成文件.s[编译器egcs]
    3.
    有汇编变为目标代码(机器代码)生成.o的文件[汇编器as]
    4.
    连接目标代码,生成可执行程序[链接器ld]
    [
    参数详解]
    -x language filename 
     设定文件所使用的语言,使后缀名无效,对以后的多个有效.也就是根据约定C语言的后
    缀名称是.c的,而C++的后缀名是.C或者.cpp,如果你很个性,决定你的C代码文件的后缀
    名是.pig哈哈,那你就要用这个参数,这个参数对他后面的文件名都起作用,除非到了
    下一个参数的使用。
      可以使用的参数吗有下面的这些
      `c',`objective-c', `c-header', `c++', `cpp-output', `assembler', and `a
    ssembler-with-cpp'. 
      看到英文,应该可以理解的。
      例子用法:
      gcc-x c hello.pig
      
    -xnone filename 
      关掉上一个选项,也就是让gcc根据文件名后缀,自动识别文件类型
      例子用法:
      gcc-x c hello.pig -x none hello2.c
      
    -c
      只激活预处理,编译,和汇编,也就是他只把程序做成obj文件
      例子用法:
      gcc-c hello.c
      他将生成.oobj文件
    -S
      只激活预处理和编译,就是指把文件编译成为汇编代码。
      例子用法
      gcc-S hello.c
      他将生成.s的汇编代码,你可以用文本编辑器察看
    -E
      只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里面.
      例子用法:
      gcc-E hello.c > pianoapan.txt
      gcc-E hello.c | more
      慢慢看吧,一个helloword也要与处理成800行的代码
    -o
      制定目标名称,缺省的时候,gcc编译出来的文件是a.out,很难听,如果你和我有同感
    ,改掉它,哈哈
      例子用法
      gcc-o hello.exe hello.c (,windows用习惯了)
      gcc-o hello.asm -S hello.c
    -pipe
      使用管道代替编译中临时文件,在使用非gnu汇编工具的时候,可能有些问题
      gcc-pipe -o hello.exe hello.c
    -ansi 
      关闭gnuc中与ansic不兼容的特性,激活ansic的专有特性(包括禁止一些asminl
    ine typeof
    关键字,以及UNIX,vax等预处理宏,
    -fno-asm 
      此选项实现ansi选项的功能的一部分,它禁止将asm,inlinetypeof用作关键字。
        
    -fno-strict-prototype
      只对g++起作用,使用这个选项,g++将对不带参数的函数,都认为是没有显式的对参数
    的个数和类型说明,而不是没有参数.
      而gcc无论是否使用这个参数,都将对没有带参数的函数,认为城没有显式说明的类型

      
    -fthis-is-varialble
      就是向传统c++看齐,可以使用this当一般变量使用.
      
    -fcond-mismatch
      允许条件表达式的第二和第三参数类型不匹配,表达式的值将为void类型
      
    -funsigned-char
    -fno-signed-char 
    -fsigned-char 
    -fno-unsigned-char
      这四个参数是对char类型进行设置,决定将char类型设置成unsignedchar(前两个参
    )或者signedchar(后两个参数)
      
    -includefile 
      包含某个代码,简单来说,就是便以某个文件,需要另一个文件的时候,就可以用它设
    ,功能就相当于在代码中使用#include<filename>
      例子用法:
      gcchello.c -include /root/pianopan.h
      
    -imacrosfile 
      将file文件的宏,扩展到gcc/g++的输入文件,宏定义本身并不出现在输入文件中
      
    -Dmacro
      相当于C语言中的#definemacro
      
    -Dmacro=defn
      相当于C语言中的#definemacro=defn
      
    -Umacro
      相当于C语言中的#undefmacro
    -undef 
      取消对任何非标准宏的定义
      
    -Idir
      在你是用#include"file"的时候,gcc/g++会先在当前目录查找你所制定的头文件,
    果没有找到,他回到缺省的头文件目录找,如果使用-I制定了目录,
      回先在你所制定的目录查找,然后再按常规的顺序去找.
      对于#include<file>,gcc/g++会到-I制定的目录查找,查找不到,然后将到系统的缺
    省的头文件目录查找
      
    -I-
      就是取消前一个参数的功能,所以一般在-Idir之后使用
      
    -idirafterdir 
      在-I的目录里面查找失败,讲到这个目录里面查找.
      
    -iprefixprefix 
    -iwithprefix dir 
      一般一起使用,-I的目录查找失败,会到prefix+dir下查找
      
    -nostdinc
      使编译器不再系统缺省的头文件目录里面找头文件,一般和-I联合使用,明确限定头
    文件的位置
      
    -nostdinC++ 
      规定不在g++指定的标准路经中搜索,但仍在其他路径中搜索,.此选项在创libg++
    使用
      
    -C
      在预处理的时候,不删除注释信息,一般和-E使用,有时候分析程序,用这个很方便的

      
    -M
      生成文件关联的信息。包含目标文件所依赖的所有源代码你可以用gcc-M hello.c
    来测试一下,很简单。
      
    -MM
      和上面的那个一样,但是它将忽略由#include<file>造成的依赖关系。
      
    -MD
      和-M相同,但是输出将导入到.d的文件里面
      
    -MMD
      和-MM相同,但是输出将导入到.d的文件里面
      
    -Wa,option
      此选项传递option给汇编程序;如果option中间有逗号,就将option分成多个选项,
    后传递给会汇编程序
      
    -Wl.option
      此选项传递option给连接程序;如果option中间有逗号,就将option分成多个选项,
    后传递给会连接程序.
      
    -llibrary
      制定编译的时候使用的库
      例子用法
      gcc-lcurses hello.c
      使用ncurses库编译程序
      
    -Ldir
      制定编译的时候,搜索库的路径。比如你自己的库,可以用它制定目录,不然
      编译器将只在标准库的目录找。这个dir就是目录的名称。
      
    -O0
    -O1 
    -O2 
    -O3 
      编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高 
       
    -g
      只是编译器,在编译的时候,产生调试信息。
      
    -gstabs
      此选项以stabs格式声称调试信息,但是不包括gdb调试信息.
      
    -gstabs+
      此选项以stabs格式声称调试信息,并且包含仅供gdb使用的额外调试信息.
      
    -ggdb
      此选项将尽可能的生成gdb的可以使用的调试信息.
    -static 
      此选项将禁止使用动态库,所以,编译出来的东西,一般都很大,也不需要什么
    动态连接库,就可以运行.
    -share 
      此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库.
    -traditional 
      试图让编译器支持传统的C语言特性
    [
    参考资料]
    -Linux/UNIX
    高级编程
      中科红旗软件技术有限公司编著.清华大学出版社出版
    -Gccman page 
      
    [ChangeLog]
    -2002-08-10 
      ver0.1发布最初的文档
    -2002-08-11
      ver0.11修改文档格式
    -2002-08-12
      ver0.12加入了对静态库,动态库的参数
    -2002-08-16
      ver0.16增加了gcc编译的4个阶段的命令
    运行gcc/egcs
    **********
    运行gcc/egcs***********************
      GCCGNUCC++编译器。实际上,GCC能够编译三种语言:CC++O
    bject C
    C语言的一种面向对象扩展)。利用gcc命令可同时编译并连接CC++
    源程序。
      如果你有两个或少数几个C源文件,也可以方便地利用GCC编译、连接并生成可
    执行文件。例如,假设你有两个源文件main.cfactorial.c两个源文件,现在要编
    译生成一个计算阶乘的程序。
    代码:

    ----------------------- 
    清单factorial.c
    ----------------------- 
    int factorial (int n) 
    { 
      if(n <= 1)
       return1;
      else
       returnfactorial (n - 1) * n;
    } 
    ----------------------- 
    清单main.c
    ----------------------- 
    #include <stdio.h>
    #include <unistd.h>
    int factorial (int n); 
    int main (int argc, char **argv) 
    {
      intn;
      if(argc < 2)
      {
        printf("Usage: %s n
    ", argv [0]);
        return-1;
      }
      else
      {
       n= atoi (argv[1]);
       printf("Factorial of %d is %d.
    ", n, factorial (n));
      }
      return0;
    } 


    ----------------------- 
    利用如下的命令可编译生成可执行文件,并执行程序:
    $gcc -o factorial main.c factorial.c 
    $ ./factorial 5 
    Factorialof 5 is 120. 
      GCC可同时用来编译C程序和C++程序。一般来说,C编译器通过源文件的后缀
    名来判断是C程序还是C++程序。在Linux中,C源文件的后缀名为.c,而C++
    文件的后缀名为.C.cpp。但是,gcc命令只能编译C++源文件,而不能自动和C
    ++ 
    程序使用的库连接。因此,通常使用g++命令来完成C++程序的编译和连接,该程
    序会自动调用gcc实现编译。假设我们有一个如下的C++源文件(hello.C):
    #include<iostream> 
    void main (void) 

      cout<< "Hello, world!" << endl;

    则可以如下调用g++命令编译、连接并生成可执行文件:
    $g++ -o hello hello.C 
    $ ./hello 
    Hello, world!
    **********************gcc/egcs 
    的主要选项*********
    gcc 
    命令的常用选项
    选项解释
    -ansi
    只支持ANSI标准的C语法。这一选项将禁止GNUC的某些特色,
    例如asmtypeof关键词。
    -c
    只编译并生成目标文件。
    -DMACRO
    以字符串1”定义MACRO宏。
    -DMACRO=DEFN
    以字符串DEFN”定义MACRO宏。
    -E
    只运行C预编译器。
    -g
    生成调试信息。GNU调试器可利用该信息。
    -IDIRECTORY
    指定额外的头文件搜索路径DIRECTORY
    -LDIRECTORY
    指定额外的函数库搜索路径DIRECTORY
    -lLIBRARY
    连接时搜索指定的函数库LIBRARY
    -m486
    针对486进行代码优化。
    -oFILE 
    生成指定的输出文件。用在生成可执行文件时。
    -O0
    不进行优化处理。
    -O
    -O1优化生成代码。
    -O2
    进一步优化。
    -O3
    -O2更进一步优化,包括inline函数。
    -shared
    生成共享目标文件。通常用在建立共享库时。
    -static
    禁止使用共享连接。
    -UMACRO
    取消对MACRO宏的定义。
    -w
    不生成任何警告信息。
    -Wall
    生成所有警告信息。

    3./////////////////////////////////////////////////动态静态库制作////////////////////////////////////////////////////////////////

    我们通常把一些公用函数制作成函数库,供其它程序使用。函数库分为静态库和动态库两种。静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。本文主要通过举例来说明在Linux中如何创建静态库和动态库,以及使用它们。

           在创建函数库前,我们先来准备举例用的源程序,并将函数库的源程序编译成.o文件。

           第1步:编辑得到举例的程序--hello.hhello.cmain.c

           hello.c(见程序2)是函数库的源程序,其中包含公用函数hello,该函数将在屏幕上输出"HelloXXX!"hello.h(见程序1)为该函数库的头文件。main.c(见程序3)为测试库文件的主程序,在主程序中调用了公用函数hello

             #ifndefHELLO_H
             #defineHELLO_H

             voidhello(const char *name);

             #endif//HELLO_H
             
    程序1:hello.h

             #include

             voidhello(const char *name)
            {
             printf("Hello %s! ", name);
            }
             
    程序2:hello.c

             #include"hello.h"

             intmain()
            {
             hello("everyone");
             return 0;
            }
             
    程序3:main.c

            第2步:将hello.c编译成.o文件;

           无论静态库,还是动态库,都是由.o文件创建的。因此,我们必须将源程序hello.c通过gcc先编译成.o文件。

            在系统提示符下键入以下命令得到hello.o文件。

            #gcc -c hello.c

            #

           (1:本文不介绍各命令使用和其参数功能,若希望详细了解它们,请参考其他文档。)

           (2:首字符"#"是系统提示符,不需要键入,下文相同。)

            我们运行ls命令看看是否生存了hello.o文件。

            #ls

            hello.chello.h hello.o main.c

            #

            (3:首字符不是"#"为系统运行结果,下文相同。)

           在ls命令结果中,我们看到了hello.o文件,本步操作完成。

            下面我们先来看看如何创建静态库,以及使用它。

            第3步:由.o文件创建静态库;

           静态库文件名的命名规范是以lib为前缀,紧接着跟静态库名,扩展名为.a。例如:我们将创建的静态库名为myhello,则静态库文件名就是libmyhello.a。在创建和使用静态库时,需要注意这点。创建静态库用ar命令。

           在系统提示符下键入以下命令将创建静态库文件libmyhello.a

            #ar cr libmyhello.a hello.o

            #

            我们同样运行ls命令查看结果:

            #ls

            hello.chello.h hello.o libmyhello.a main.c

     

           #

            ls命令结果中有libmyhello.a

            4步:在程序中使用静态库;

           静态库制作完了,如何使用它内部的函数呢?只需要在使用到这些公用函数的源程序中包含这些公用函数的原型声明,然后在用gcc命令生成目标文件时指明静态库名,gcc将会从静态库中将公用函数连接到目标文件中。注意,gcc会在静态库名前加上前缀lib,然后追加扩展名.a得到的静态库文件名来查找静态库文件。

    在程序3:main.c中,我们包含了静态库的头文件hello.h,然后在主程序main中直接调用公用函数hello。下面先生成目标程序hello,然后运行hello程序看看结果如何。

            #gcc -o hello main.c -L. -lmyhello

            #./hello

            Helloeveryone!

            #

           我们删除静态库文件试试公用函数hello是否真的连接到目标文件hello中了。

            #rm libmyhello.a

            rm:remove regular file `libmyhello.a'? y

            #./hello

            Helloeveryone!

            #

           程序照常运行,静态库中的公用函数已经连接到目标文件中了。

           我们继续看看如何在Linux中创建动态库。我们还是从.o文件开始。

            5步:由.o文件创建动态库文件;

           动态库文件名命名规范和静态库文件名命名规范类似,也是在动态库名增加前缀lib,但其文件扩展名为.so。例如:我们将创建的动态库名为myhello,则动态库文件名就是libmyhello.so。用gcc来创建动态库。

           在系统提示符下键入以下命令得到动态库文件libmyhello.so

            #gcc -shared -fPCI -o libmyhello.so hello.o

            #

            我们照样使用ls命令看看动态库文件是否生成。

            #ls

            hello.chello.h hello.o libmyhello.so main.c

            #

            6步:在程序中使用动态库;

           在程序中使用动态库和使用静态库完全一样,也是在使用到这些公用函数的源程序中包含这些公用函数的原型声明,然后在用gcc命令生成目标文件时指明动态库名进行编译。我们先运行gcc命令生成目标文件,再运行它看看结果。

            #gcc -o hello main.c -L. -lmyhello

            #./hello

            ./hello:error while loading shared libraries: libmyhello.so: cannot openshared object file: No such file or directory

            #

           哦!出错了。快看看错误提示,原来是找不到动态库文件libmyhello.so。程序在运行时,会在/usr/lib/lib等目录中查找需要的动态库文件。若找到,则载入动态库,否则将提示类似上述错误而终止程序运行。我们将文件libmyhello.so复制到目录/usr/lib中,再试试。或者设置环境变量LD_LIBRARY_PATH到动态库所在目录

            #mv libmyhello.so /usr/lib

            #./hello

            Helloeveryone!

            #

           成功了。这也进一步说明了动态库在程序运行时是需要的。

           我们回过头看看,发现使用静态库和使用动态库编译成目标程序使用的gcc命令完全一样,那当静态库和动态库同名时,gcc命令会使用哪个库文件呢?抱着对问题必究到底的心情,来试试看。

           先删除除.c.h外的所有文件,恢复成我们刚刚编辑完举例程序状态。

            #rm -f hello hello.o /usr/lib/libmyhello.so

            #ls

            hello.chello.h main.c

            #

           在来创建静态库文件libmyhello.a和动态库文件libmyhello.so

            #gcc -c hello.c

            #ar cr libmyhello.a hello.o

            #gcc -shared -fPCI -o libmyhello.so hello.o

            #ls

           hello.chello.h hello.o libmyhello.a libmyhello.so main.c

           #

           通过上述最后一条ls命令,可以发现静态库文件libmyhello.a和动态库文件libmyhello.so都已经生成,并都在当前目录中。然后,我们运行gcc命令来使用函数库myhello生成目标文件hello,并运行程序hello

            #gcc -o hello main.c -L. -lmyhello

            #./hello

            ./hello:error while loading shared libraries: libmyhello.so: cannot openshared object file: No such file or directory

            #

           从程序hello运行的结果中很容易知道,当静态库和动态库同名时,gcc命令将优先使用动态库。

     

    4.///////////////////////////////////////////////////////////////////////动态库编写

    C语言中有一些函数不需要进行编译,有一些函数也可以在多个文件中使用。一般来说,这些函数都会执行一些标准任务,如数据库输入/输出操作或屏幕控制等。可以事先对这些函数进行编译,然后将它们放置在一些特殊的目标代码文件中,这些目标代码文件就称为库。库文件中的函数可以通过连接程序与应用程序进行连接。这样就不必在每次开发程序时都对这些通用的函数进行编译了。

      不同类型的应用程序将会使用不同的函数库。例如:libdbm库中组包含了对数据库文件进行访问的dbm函数,需要对数据库进行操作的程序就会与该库进行连接。数学应用程序将使用数学库libmX-Windows应用程序将使用Xlib库,libX11。另外,所有的程序都将使用标准的C函数库。libc,该库中包含了诸好内存管理或输入输出操作的基本函数,这些库都存放在/usr/lib这些系统公用的目录中,系统中的任何用户都可以利用这些库。当然用户也可以建立自己专用的库函数,供自己或其它指定的人员使用。

      库可以有三种使用的形式:静态、共享和动态。静态库的代码在编译时就已连接到开发人员开发的应用程序中,而共享库只是在程序开始运行时才载入,在编译时,只是简单地指定需要使用的库函数。动态库则是共享库的另一种变化形式。动态库也是在程序运行时载入,但与共享库不同的是,使用的库函数不是在程序运行开始,而是在程序中的语句需要使用该函数时才载入。动态库可以在程序运行期间释放动态库所占用的内存,腾出空间供其它程序使用。由于共享库和动态库并没有在程序中包括库函数的内容,只是包含了对库函数的引用,因此代码的规模比较小。

      已经开发的大多数库都采取共享库的方式。ELF格式的可执行文件使得共享库能够比较容易地实现,当然使用旧的a.out模式也可以实现库的共享。Linux系统中目前可执行文件的标准格式为ELF格式。

      GNU库的使用必须遵守LibraryGNU PublicLicense(LGPL许可协议)。该协议与GNU许可协议略有不同,开发人员可以免费使用GNU库进行软件开发,但必须保证向用户提供所用的库函数的源代码。

      系统中可用的库都存放在/usr/lib/lib目录中。库文件名由前缀lib和库名以及后缀组成。根据库的类型不同,后缀名也不一样。共享库的后缀名由.so和版本号组成,静态库的后缀名为.a。采用旧的a.out格式的共享库的后缀名为.sa
      libname.so.major.minor
      libname.a

      这里的name可以是任何字符串,用来唯一标识某个库。该字符串可以是一个单字、几个字符、甚至一个字母。数学共享库的库名为libm.so.5,这里的标识字符为m,版本号为5libm.a则是静态数学库。X-Windows库名为libX11.so.6,这里使用X11作为库的标识,版本号为6

      使用gcc编译器就可以将库与自己开发的程序连接起来,例如:libc.so.5中包含了标准的输入输出函数,当连接程序进行目标代码连接时会自动搜索该程序并将其连接到生成的可执行文件中。标准的输入输出库中包含了许多基本的输入输出函数,如printf函数等。也可以连接其它的一些系统函数库,如数学库等,但与libc.so.5不同,大部分其它的系统库需要在命令行中显式指定所用的库名。

      在/usr/lib/lib目录中可以找到绝大多数的共享库。连接时将首先搜索这两个目录。有一些库也可能存放在特定的目录中,在/etc/ld.conf配置文件中给出了这些目录的列表。连接程序也会对列出的这些目录进行搜索。在默认情况下,Linux将首先搜索指定库的共享版本,如果找不到,才会去搜索静态版本。在对共享库进行更新或安装新库后,必须运行ldconfig命令更新/etc/ld.conf文件中相应的项(如果使用RPM进行安装,一般会自动进行更新,不过也不能保证这一点)

      在gcc编译器中引用可搜索到的目录中的库文件时,需要使用-l选项和库名。在gcc命令行上输入-lm可以在程序中连接标准算术库,-l将首先使用libname.so进行搜索,这里是libm.so。下面的例子将使用算术库创建bookrecs程序,请注意这里的-lm选项。
      $gccmain.c io.c -o bookrecs -lm

      系统中还有一些其它可用的库,常用的是libncurses.a库,包含了一些简单的鼠标移动例程。在命令行中使用-lncurses选项引用libncurses.so库。下面的例子同时调用了数学和光标库。
      $gccmian.c io.c -o bookrecs -lm -lncurses

      在引用其它目录中的库时,需要使用-ldir选项指定该目录。该选项指定了搜索库函数时其它路径。在下面的例子中,用户在连接时使用了mydir目录中的myio.so库文件。
      $gccmain.c -o bookrecs -lmydir -lmyio 

      .a的是为了支持较老的a.out格式的可执行文件的
      .so的是支持elf格式的可执行文件的库。

      静态库是指编译连接时,把库文件的代码全部加入到可执行文件中,所以生成的文件较大,但运行时,就不再需要库文件了。动态库正好相反,在编译连接时,没有把库文件的代码加入到可执行文件中,所以生成的文件较小,但运行时,仍需要加载库文件

      .a是静态库文件,可以用ar命令生成。
      .so是动态库文件,编译时加上指定的选项即可生成,具体选项看相应的系统文档了。。。。

      IBMAIX下如下:
      $(CC)(SHOPT)(SHLIBS)a.o b.o -o lib@(DBBUILDTAIL)

      假设你有test1.ctest2.c test3.c ,编写成动态链接库
      1.先编译成test1.otest2.o test3.o 
      2.gcc -shared -W1, -soname,libvTest.so.1 -o libvTest.so.1.0*.o





    二、正确编译与命名动态链接库:  g++   -shared   -fPIC   -Wall  -o   libMy.so   getdate.cc  gettime.cc  


        ###########    Makefile   ############  
       obj   =   libmy.so  
       CC   =   g++  
       all   :   
    (obj)  
       SRC   =   getdate.cc   gettime.cc  
       TGT   =   
    (SRC:.cc=.o)  
       
    (SRC)  :   adatetime.h  
                       @touch   
    @  
       %.o   :   %.c  
                       
    (CC)  -c  ?  
       
    (obj)  :  (TGT)  
                       
    (CC)  -shared   -fPIC   -Wall   -o  @  (TGT)  

    gcc  -shared   -fPIC   -o   libjcmpp.so  JCMPP.c   libtssx_cmpp.a   -I.  -I/opt/jdk142/include/   -I/opt/jdk142/include/linux
      

  • 相关阅读:
    统计SQL
    记一次惨痛教训
    window ssh 连接 本地虚拟机ubuntu 16
    js undefined 笔记
    java new java.text.SimpleDateFormat("yyyyMM01").format(date)
    java 反射
    mapinfo使用
    EnableAutoConfiguration注解说明
    Eureka Server 代码分析01
    BigDecimal 学习比较
  • 原文地址:https://www.cnblogs.com/wiessharling/p/3708604.html
Copyright © 2011-2022 走看看