zoukankan      html  css  js  c++  java
  • gcc编译静态库到自己的程序 解决在不同linux下因libc版本问题而不能运行 版本兼容问题

    运行软件的目标机器报错:

    ./qt_cef_poc --no-sandbox --url=http://www.baidu.com
    ./qt_cef_poc: /lib64/libc.so.6: version `GLIBC_2.18' not found (required by ./libstdc++.so.6)
    $ strings /lib64/libc.so.6 | grep LIBCXX
    GLIBCXX_3.4 GLIBCXX_3.4.1 GLIBCXX_3.4.2 …

    在目标机器上看他的libc.so.6支持的版本。或者grep libc。 发现最高支持到GLIBC 2.17

    查看自己机器上的版本库stackoverflow回答

    1 libstdc++.so 版本

    To find which library is being used you could run 
    (1) 方式一 
    $ /sbin/ldconfig -p | grep stdc++ 
    libstdc++.so.6 (libc6) => /usr/lib/libstdc++.so.6

    (2) 方式二 
    $ locate libstdc++.so 
    /usr/lib/gcc/x86_64-redhat-linux/3.4.6/libstdc++.so 
    /usr/lib/gcc/x86_64-redhat-linux/3.4.6/32/libstdc++.so 
    /usr/lib/gcc/x86_64-redhat-linux/4.4.4/libstdc++.so 
    /usr/lib/gcc/x86_64-redhat-linux/4.4.4/32/libstdc++.so 
    /usr/lib64/libstdc++.so.5 
    /usr/lib64/libstdc++.so.5.0.7 
    /usr/lib64/libstdc++.so.6 
    /usr/lib64/libstdc++.so.6.0.13 
    其中,如果用 ll 仔细看,有些是软链接,指向一个具体的版本,如 /usr/libstdc++.so.6 ( libstdc++.so.6 -> libstdc++.so.6.0.13 ),这个软链接搜索过程是:链接程序ld-linux.so 先后搜索elf文件的 DT_RPATH段—环境变量LD_LIBRARY_PATH—/etc/ld.so.cache文件列表—/lib/, /usr/lib, /usr/lib64 …。

    7.12 这个 libstdc++.so 版本所兼容的 GLIBC 版本

    $ strings /usr/lib/libstdc++.so.6 | grep LIBCXX 
    GLIBCXX_3.4 
    GLIBCXX_3.4.1 
    GLIBCXX_3.4.2 

    GLIBCXX_3.4.19

    7.2 版本兼容

    很多时候,我们在自己机器上编译完成了 C/C++ 程序,但是放在其他机器上会出现类似 /usr/lib/libstdc++.so.6: version GLIBCXX_3.4.9' not found 这个错误。 
    [stackoverflow回答](https://stackoverflow.com/questions/4133674/glibcxx-versions) 
    就是说,GLIBCXX_3.4.* 这一系列版本都是想下兼容,高的版本可能做了 一些改动。那么 c 程序 link 的时候,会用到新版本的东西,就出现了这个错误。 

    readelf -a

    对于c++ : readelf -aW <file> | c++filt

    objdump -x

    可以查看 c 程序里哪里用到了哪个版本的库函数。 
    注: objdump命令的使用objdump命令是Linux下的反汇编目标文件或者可执行文件的命令。

     

    在自己的编译机器上查看:

    程序引用的动态库需要的libc版本:
    ldd qt_cef_poc|grep libc.so.6
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb759fcf000)
    程序自身elf文件需要的ligc版本
    readelf -s qt_cef_poc | grep -oP "GLIBC_[d.]*" | sort | uniq GLIBC_ GLIBC_2 GLIBC_2.14 GLIBC_2.2.5 GLIBC_2.4

    自己编译机器上支持的libc到什么版本
    strings /lib/x86_64-linux-gnu/libc.so.6 | grep libc
    libc-2.23.so

    用 readelf -a and objdump -x` 可以查看 c 程序里哪里用到了哪个版本的库函数。 
    注: objdump命令的使用objdump命令是Linux下的反汇编目标文件或者可执行文件的命令。

    解决方法:

    1, 链接静态库解决

    1.在linux中用yum下载安装glibc和libstdc++的静态库
    sudo yum install glibc-static libstdc++-static
    
    2.在编译选项LDFLAGS中添加-static即可正常编译运行。-satic会将所有库都变成静态的。gcc有内置加入libc的。参考:https://www.cnblogs.com/bigben0123/p/3304863.html

    2,指定版本编译: GLIBC GLIBC++库。

    这种情况,只有自己的代码真的没使用这些库(不可能吧,如果没使用,gcc也不会打包到最新版本????   

    有过这种情况,同样的代码,在低版本gcc编译通过。在高版本也编译通过。结果高版本的依赖的库就是高版本。

     3,在高级版本上,指定低级版本编译。降级编译。


    • 查看libc/libc++库的版本

      `strings "/lib/libc.so.6" | grep LIBC`
      `strings "/lib/libstdc++.so.6" | grep LIBC`
      把库的路径换成你机器的路径即可
    • 查看elf文件需要的库的版本

      `readelf -s ltrace  | grep -oP "GLIBC_[d.]*" | sort | uniq`
      把`-s`后面的文件换成你的程序

    我是通过vs2015安装的visualGDB远程连接centos的linux系统作为开发环境的,因为正式服务器中glibc版本为2.12,而开发环境中的glibc版本为2.17,所以当编译好的程序放到正式服中会报版本错误,一种解决方式是把正式服的glibc版本升级到最新版,但因为怕升级会引起其他问题,所以只能通过连接静态库增加程序大小的方式解决。

    1.在linux中用yum下载安装glibc和libstdc++的静态库
    sudo yum install glibc-static libstdc++-static

    2.在编译选项LDFLAGS中添加-static即可正常编译运行

    CMake 指定gcc编译版本

    修改 CMakeLists.txt 文件,添加如下命令

    SET(CMAKE_C_COMPILER “/home/hhb/gcc-5.2.0/bin/gcc”)

    SET(CMAKE_CXX_COMPILER “/home/hhb/gcc-5.2.0/bin/g++”)

    参考: 
    http://blog.csdn.net/amds123/article/details/53812133

    更新:上面那个方法经实践发现不行 
    使用下面的方法搞定了! 
    Do not overwrite CMAKE_C_COMPILER, but export CC (and CXX) before calling cmake:

    export CC=/usr/local/bin/gcc
    export CXX=/usr/local/bin/g++
    cmake /path/to/your/project
    make

    参考: 
    https://stackoverflow.com/questions/17275348/how-to-specify-new-gcc-path-for-cmake

     
     

    glibc、libc、gcc、g++

    1、libc

    C standard library 
    The C standard library or libc is the standard library for the C programming language, as specified in the ANSI C standard.[1] It was developed at the same time as the C library POSIX specification, which is a superset of it.[2][3] Since ANSI C was adopted by the International Organization for Standardization,[4] the C standard library is also called the ISO C library. 
    The C standard library provides macros, type definitions and functions for tasks such as string handling, mathematical computations, input/output processing, memory management, and several other operating system services.

    ANSI 
    ANSI C, ISO C and Standard C refer to the successive standards for the C programming language published by the American National Standards Institute (ANSI) and the International Organization for Standardization (ISO). Historically, the names referred specifically to the original and best-supported version of the standard (known as C89 or C90). Software developers writing in C are encouraged to conform to the standards, as doing so helps portability between compilers.

    2、glibc

    2.1、wiki解释

    GNU C Library 
    “glibc” redirects here. It is not to be confused with GLib or Gnulib. 
    The GNU C Library, commonly known as glibc, is the GNU Project’s implementation of the C standard library. Despite its name, it now also directly supports C++ (and, indirectly, other programming languages). It was started in the early 1990s by the Free Software Foundation (FSF) for their GNU operating system.

    Released under the GNU Lesser General Public License[3], glibc is free software.

    GNU 
    GNU /ɡnuː/ (About this sound listen)[3][4] is an operating system[5][6][7] and an extensive collection of computer software. GNU is composed wholly of free software,[8][9][10] most of which is licensed under the GNU Project’s own GPL. 
    GNU is a recursive acronym for “GNU’s Not Unix!”,[8][11] chosen because GNU’s design is Unix-like, but differs from Unix by being free software and containing no Unix code.[8][12][13] The GNU project includes an operating system kernel, GNU HURD, which was the original focus of the Free Software Foundation (FSF).[8][14][15][16] However, non-GNU kernels, most famously Linux, can also be used with GNU software; as the Hurd kernel is not yet production-ready,[17] this is how the GNU system is usually used.[18][19] The combination of GNU software and the Linux kernel is commonly known as Linux (or less frequently GNU/Linux; see GNU/Linux naming controversy). 
    Richard Stallman, the founder of the project, views GNU as a “technical means to a social end”.[20] Relatedly Lawrence Lessig states in his introduction to the second edition of Stallman’s book Free Software, Free Society that in it Stallman has written about “the social aspects of software and how Free Software can create community and social justice.”[21]

    GNU Project 
    he GNU Project /ɡnuː/ (About this sound listen)[3] is a free-software, mass-collaboration project, first announced on September 27, 1983 by Richard Stallman at MIT. Its aim is to give computer users freedom and control in their use of their computers and computing devices, by collaboratively developing and providing software that is based on the following freedom rights: users are free to run the software, share it (copy, distribute), study it and modify it. GNU software guarantees these freedom-rights legally (via its license), and is therefore free software; the use of the word “free” always being taken to refer to freedom. 
    In order to ensure that the entire software of a computer grants its users all freedom rights (use, share, study, modify), even the most fundamental and important part, the operating system (including all its numerous utility programs), needed to be free software. According to its manifesto, the founding goal of the project was to build a free operating system and, if possible, “everything useful that normally comes with a Unix system so that one could get along without any software that is not free.” Stallman decided to call this operating system GNU (a recursive acronym meaning “GNU’s not Unix”), basing its design on that of Unix, a proprietary operating system.[4] Development was initiated in January 1984. In 1991, the kernel Linux appeared, developed outside the GNU project by Linus Torvalds,[5] and in December 1992 it was made available under version 2 of the GNU General Public License.[6] Combined with the operating system utilities already developed by the GNU project, it allowed for the first operating system that was free software, known as Linux or GNU/Linux.[7][8] 
    The project’s current work includes software development, awareness building, political campaigning and sharing of the new material.

    2.2、gnu.org解释

    链接戳我 
    What is glibc?

    The GNU C Library project provides the core libraries for the GNU system and GNU/Linux systems, as well as many other systems that use Linux as the kernel. These libraries provide critical APIs including ISO C11, POSIX.1-2008, BSD, OS-specific APIs and more. These APIs include such foundational facilities as open, read, write, malloc, printf, getaddrinfo, dlopen, pthread_create, crypt, login, exit and more.

    The GNU C Library is designed to be a backwards compatible, portable, and high performance ISO C library. It aims to follow all relevant standards including ISO C11, POSIX.1-2008, and IEEE 754-2008.

    The project was started circa 1988 and is almost 30 years old. You can see the complete project release history on the wiki.

    Despite the project’s age there is still a lot to do so please Get Started and Get Involved!

    Current Status

    The GNU C Library releases every 6 months. See the NEWS file in the glibc sources for more information.

    The current stable version of glibc is 2.26, released on August 2, 2017. 
    The current development version of glibc 2.27, releasing on or around February 1, 2018.

    3、What’s the difference between glibc and libc6?

    原链接 
    libc is the C library; basically, it contains all of the system functions that most (if not all) programs need to run on Linux. It’s similar to a combination of dos.library and exec.library on Amigas, but it also contains a lot of things that are in the C runtime library (like, for example, ixemul.library or the .lib files included with SAS/C and other compilers for AmigaOS).

    libc6 and glibc are the same version of libc; officially, it’s version 2 of the GNU C Library (but it’s the sixth major version of the Linux C library). You can read more about glibc at the GNU C Library pages.

    The major versions of libc for Linux/m68k are:

    libc4: Version 4 of the C library is based on the a.out binary format; it was the first version to support dynamic linking (shared libraries). However, a.out dynamic linking had a lot of problems (for example, you had to build the library twice, so you could add a jump table to the library on the second pass, and the library was non-relocatable, so every library had to be allocated a block of space to load into), so it was abandoned (at least on m68k; Intel users may still need it for some esoteric applications). You should not be using libc4 for anything any more. If you do use it, we will hunt you down and execute you as an example to others. (Not really, but you get the point…)

    libc5: Version 5 of the C library was a fairly big improvement over version 4. However, it still had some problems (adding new functions or changing structure sizes introduced subtle bugs) so it is no longer being actively developed. It was the first version of the Linux C Library based on ELF, a different file format that made programs loadable in more flexible ways (it uses hunks, similar to the AmigaOS executable file format). libc5 is officially deprecated on m68k; use libc6 for new compilations.

    libc6: Version 6 of the Linux C Library is version 2 of the GNU C Library; the confusion is because Linux has had multiple C library versions. This is the newest technology available, and includes features (like “weak symbols”) that theoretically allow new functions and modified structures in the library without breaking existing code that uses version 6, and avoid kernel version dependency problems. You should be coding and compiling all code against this version.

    4、What the role of libc(glibc) in our linux app?

    原链接 
    libc implements both standard C functions like strcpy() and POSIX functions (which may be system calls) like getpid(). Note that not all standard C functions are in libc - most math functions are in libm.

    You cannot directly make system calls in the same way that you call normal functions because calls to the kernel aren’t normal function calls, so they can’t be resolved by the linker. Instead, architecture-specific assembly language thunks are used to call into the kernel - you can of course write these directly in your own program too, but you don’t need to because libc provides them for you.

    Note that in Linux it is the combination of the kernel and libc that provides the POSIX API. libc adds a decent amount of value - not every POSIX function is necessarily a system call, and for the ones that are, the kernel behaviour isn’t always POSIX conforming.

    libc is a single library file (both .so and .a versions are available) and in most cases resides in /usr/lib. However, the glibc (GNU libc) project provides more than just libc - it also provides the libm mentioned earlier, and other core libraries like libpthread. So libc is just one of the libraries provided by glibc - and there are other alternate implementations of libc other than glibc.

    5、GCC

    5.1、wiki解释

    the GNU Compiler Collection 
    GNU编译器套装(英语:GNU Compiler Collection,缩写为GCC),指一套编程语言编译器,以GPL及LGPL许可证所发行的自由软件,也是GNU项目的关键部分,也是GNU工具链的主要组成部分之一。GCC(特别是其中的C语言编译器)也常被认为是跨平台编译器的事实标准。1985年由理查德·马修·斯托曼开始发展,现在由自由软件基金会负责维护工作。 
    原名为GNU C语言编译器(GNU C Compiler),因为它原本只能处理C语言。GCC在发布后很快地得到扩展,变得可处理C++。之后也变得可处理Fortran、Pascal、Objective-C、Java、Ada,Go与其他语言。 
    许多操作系统,包括许多类Unix系统,如Linux及BSD家族都采用GCC作为标准编译器。苹果电脑预装的Mac OS X操作系统也采用这个编译器。 
    GCC原本用C开发,后来因为LLVM、Clang的崛起,它更快地将开发语言转换为C++。许多C的爱好者在对C++一知半解的情况下主观认定C++的性能一定会输给C,但是Taylor给出了不同的意见,并表明C++不但性能不输给C,而且能设计出更好,更容易维护的程序(GCC’s move to C++)

    5.2、gnu解释

    链接戳我 
    The GNU Compiler Collection includes front ends for C, C++, Objective-C, Fortran, Ada, and Go, as well as libraries for these languages (libstdc++,…). GCC was originally written as the compiler for the GNU operating system. The GNU system was developed to be 100% free software, free in the sense that it respects the user’s freedom.

    We strive to provide regular, high quality releases, which we want to work well on a variety of native and cross targets (including GNU/Linux), and encourage everyone to contribute changes or help testing GCC. Our sources are readily and freely available via SVN and weekly snapshots.

    Major decisions about GCC are made by the steering committee, guided by the mission statement.

    6、gcc and g++

    6.1stackoverflow回答

    6.1.1 回答1

    gcc and g++ are compiler-drivers of the ‘Gnu Compiler Collection’ (which was once upon a time just the ‘Gnu C Compiler’).

    Even though they automatically determine which backends (cc1 cc1plus …) to call depending on the file-type, unless overridden with -x language, they have some differences.

    The probably most important difference in their defaults is which libraries they link against automatically.

    According to 1 and 2, g++ is equivalent to gcc -xc++ -lstdc++ -shared-libgcc (the 1st is a compiler option, the 2nd two are linker options). This can be checked by running both with the -v option (it displays the backend toolchain commands being run).

    6.1.2 回答2

    6.2 知乎回答

    6.2.1 回答1

    gcc 最开始的时候是 GNU C Compiler, 如你所知,就是一个c编译器。但是后来因为这个项目里边集成了更多其他不同语言的编译器,GCC就代表 the GNU Compiler Collection,所以表示一堆编译器的合集。 g++则是GCC的c++编译器。现在你在编译代码时调用的gcc,已经不是当初那个c语言编译器了,更确切的说他是一个驱动程序,根据代码的后缀名来判断调用c编译器还是c++编译器 (g++)。比如你的代码后缀是*.c,他会调用c编译器还有linker去链接c的library。如果你的代码后缀是cpp, 他会调用g++编译器,当然library call也是c++版本的。当然我说了这么多你可能感到有些混乱,没关系,你就把gcc当成c语言编译器,g++当成c++语言编译器用就是了。

    作者:李锋 
    链接:https://www.zhihu.com/question/20940822/answer/16667772 
    来源:知乎 
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    6.2.2 回答2

    一:gcc与g++比较 
    编译c/c++代码的时候,有人用gcc,有人用g++,于是各种说法都来了,譬如c代码用gcc,而 c++代码用g++,或者说编译用gcc,链接用g++,一时也不知哪个说法正确,如果再遇上个extern “C”,分歧就更多了,这里我想作个了结,毕竟知识的目的是令人更清醒,而不是更糊涂。 
    误区一:gcc只能编译c代码,g++只能编译c++代码两者都可以,但是请注意: 
    1.后缀为.c的,gcc把它当作是C程序,而g++当作是c++程序;后缀为.cpp的,两者都会认为是c++程序,注意,虽然c++是c的超集,但是两者对语法的要求是有区别的,例如

    <C++>
    #include<stdio.h>
    int main(int argc, char* argv[]) {
        if(argv == 0) return;
            printString(argv);
        return 0;
    }
    int printString(char* string) {
        sprintf(string, "This is a test.
    ")
    }
    </C++>
    

    如果按照C的语法规则,OK,没问题,但是,一旦把后缀改为cpp,立刻报三个错: 
    “printString未定义”; 
    “cannot convert char**' tochar*”; 
    ”return-statement with no value“; 
    分别对应前面红色标注的部分。可见C++的语法规则更加严谨一些。 
    2.编译阶段,g++会调用gcc,对于c++代码,两者是等价的,但是因为gcc命令不能自动和C++程序使用的库联接,所以通常用g++来完成链接,为了统一起见,干脆编译/链接统统用g++了,这就给人一种错觉,好像cpp程序只能用g++似的。 
    误区二:gcc不会定义__cplusplus宏,而g++会 
    实际上,这个宏只是标志着编译器将会把代码按C还是C++语法来解释,如上所述,如果后缀为.c,并且采用gcc编译器,则该宏就是未定义的,否则,就是已定义。 
    误区三:编译只能用gcc,链接只能用g++ 
    严格来说,这句话不算错误,但是它混淆了概念,应该这样说:编译可以用gcc/g++,而链接可以用g++或者gcc -lstdc++。因为gcc命令不能自动和C++程序使用的库联接,所以通常使用g++来完成联接。但在编译阶段,g++会自动调用gcc,二者等价。 
    误区四:extern “C”与gcc/g++有关系 
    实际上并无关系,无论是gcc还是g++,用extern “c”时,都是以C的命名方式来为symbol命名,否则,都以c++方式命名。

    二:gcc和g++的包含头文件库文件方法 
    -l参数就是用来指定程序要链接的库,-l参数紧接着就是库名,那么库名跟真正的库文件名有什么关系呢?就拿数学库来说,他的库名是m,他的库文件名是libm.so,很容易看出,把库文件名的头lib和尾.so去掉就是库名了。 
    好了现在我们知道怎么得到库名,当我们自已要用到一个第三方提供的库名字libtest.so,那么我们只要把 libtest.so拷贝到/usr/lib里,编译时加上-ltest参数,我们就能用上libtest.so库了(当然要用libtest.so库里 的函数,我们还需要与libtest.so配套的头文件) 
    放在/lib和/usr/lib和/usr/local/lib里的库直接用-l参数就能链接了,但如果库文件没放 在这三个目录里,而是放在其他目录里,这时我们只用-l参数的话,链接还是会出错,出错信息大概是:“/usr/bin/ld: cannot find -lxxx”,也就是链接程序ld在那3个目录里找不到libxxx.so,这时另外一个参数-L就派上用场了,比如常用的X11的库,它在/usr /X11R6/lib目录下,我们编译时就要用-L/usr/X11R6/lib -lX11参数,-L参数跟着的是库文件所在的目录名。再比如我们把libtest.so放在/aaa/bbb/ccc目录下, 
    那链接参数就是-L /aaa/bbb/ccc -ltest另外,大部分libxxxx.so只是一个链接,以RH9为例,比如libm.so它链接到/lib/libm.so.x,/lib/libm.so.6又链接到/lib/libm-2.3.2.so,如果没有这样的链接,还是会出错,因为ld只会找libxxxx.so,所以如果你要用到xxxx库,而只有libxxxx.so.x或者libxxxx-x.x.x.so,做一个链接就可以了ln -s libxxxx-x.x.x.so libxxxx.so 
    手工来写链接参数总是很麻烦的,还好很多库开发包提供了生成链接参数的程序,名字一般叫xxxx-config,一般放在/usr/bin目录下,比如gtk1.2的链接参数生成程序是gtk-config,执行gtk-config –libs就能得到以下输出”-L/usr/lib -L/usr/X11R6/lib -lgtk -lgdk -rdynamic-lgmodule -lglib -ldl -lXi -lXext -lX11 -lm”,这就是编译一个gtk1.2程序所需的gtk链接参数,xxx-config除了–libs参数外还有一个参数是–cflags用来生成头 文件包含目录的,也就是-I参数,在下面我们将会讲到。 
    你可以试试执行gtk-config –libs –cflags,看看输出结果现在的问题就是怎样用这些输出结果了,最笨的方法就是复制粘贴或者照抄,聪明的办法是在编译命令行里加入这个 xxxx-config --libs --cflags,比如编译一个gtk程序:gcc gtktest.c gtk-config --libs --cflags这样就差不多了。注意`不是单引号,而是1键左边那个键。 
    5、-include和-I参数 
    -include用来包含头文件,但一般情况下包含头文件都在源码里用#include xxxxxx实现,-include参数很少用。-I参数是用来指定头文件目录,/usr/include目录一般是不用指定的,gcc知道去那里找,但 是如果头文件不在/usr/include里我们就要用-I参数指定了,比如头文件放在/myinclude目录里,那编译命令行就要加上-I /myinclude参数了,如果不加你会得到一个”xxxx.h: No such file or directory”的错误。-I参数可以用相对路径,比如头文件在当前目录,可以用-I.来指定。

    结论例子: 
    g++ curltest.cpp -o curltest -L/mnt/hgfs/windows/curl-7.19.5/lib/.libs -lcurl -I/mnt/hgfs/windows/curl-7.19.5/include

    7、 版本兼容问题

     

    Linux编译不同版本glibc

    方法步骤

    1. 在http://ftp.gnu.org/gnu/glibc/网站下载你需要的glibc版本
    2. 解压下载的文件,同时在本目录下创建一个bulid文件夹,在其他目录下建立一个glibc-x.xx目录:
    tar -zxvf glibc-2.23.tar.gz
    cd glibc-2.23
    mkdir build
    
    1. 进入build目录,然后输入下面的命令,文件的路径自己确定:
    cd build
    CFLAGS="-g -g3 -ggdb -gdwarf-4 -Og -Wno-error=maybe-uninitialized" 
    CXXFLAGS="-g -g3 -ggdb -gdwarf-4 -Og -Wno-error=maybe-uninitialized" 
    ../configure --prefix=/home/sir/cc-sir/glibc/glibc-2.23/
    make
    make install
    
    1. 最后进行软链接就可以:
    sudo ln -s /home/sir/cc-sir/glibc-2.23/lib/ld-2.23.so 23-linux-x86-64.so.2
    

    然后检查/lib64目录可以看到新增加的libc:

    sir@sir-PC:~/desktop$ ls -l /lib64
    总用量 0
    lrwxrwxrwx 1 root root 42 4月  14 12:54 23-linux-x86-64.so.2 -> /home/sir/cc-sir/glibc-2.23/lib/ld-2.23.so
    lrwxrwxrwx 1 root root 42 4月  14 10:12 26-linux-x86-64.so.2 -> /home/sir/cc-sir/glibc-2.26/lib/ld-2.26.so
    lrwxrwxrwx 1 root root 32 11月  3 19:49 ld-linux-x86-64.so.2 -> /lib/x86_64-linux-gnu/ld-2.27.so
    

    如果编译的glibc版本太低,在make的时候可能会出现一些问题,可能需要自己根据报错的信息,修改源代码;

    报错例子

    nis_call.c: In function ‘nis_server_cache_add’:
    nis_call.c:682:6: error: suggest explicit braces to avoid ambiguous ‘else’ [-Werror=dangling-else]
       if (*loc != NULL)
          ^
    cc1: all warnings being treated as errors
    make[2]: *** [../o-iterator.mk:9:/home/sir/cc-sir/glibc-2.23/nis/nis_call.o] 错误 1
    make[2]: 离开目录“/home/sir/tools/glibc-2.23/nis”
    make[1]: *** [Makefile:214:nis/others] 错误 2
    make[1]: 离开目录“/home/sir/tools/glibc-2.23”
    make: *** [Makefile:9:all] 错误 2
    

    nis_call.cer文件中第682行的if语句没有加‘{ }’,导致语义不明报错,自行补上{ }就可以;

     -o /home/sir/cc-sir/glibc-2.23/misc/regexp.os -MD -MP -MF /home/sir/cc-sir/glibc-2.23/misc/regexp.os.dt -MT /home/sir/cc-sir/glibc-2.23/misc/regexp.os
    /tmp/cc2dus00.s: Assembler messages:
    /tmp/cc2dus00.s: 错误:`loc1@GLIBC_2.2.5' can't be versioned to common symbol 'loc1'
    /tmp/cc2dus00.s: 错误:`loc2@GLIBC_2.2.5' can't be versioned to common symbol 'loc2'
    /tmp/cc2dus00.s: 错误:`locs@GLIBC_2.2.5' can't be versioned to common symbol 'locs'
    make[2]: *** [../o-iterator.mk:9:/home/sir/cc-sir/glibc-2.23/misc/regexp.os] 错误 1
    make[2]: 离开目录“/home/sir/tools/glibc-2.23/misc”
    make[1]: *** [Makefile:214:misc/subdir_lib] 错误 2
    make[1]: 离开目录“/home/sir/tools/glibc-2.23”
    make: *** [Makefile:9:all] 错误 2
    

    将regexp.c源文件中的:

    char *loc1
    char *loc2
    char *locs
    

    修改为:

    char *loc1 __attribute__ ((nocommon));
    char *loc2 __attribute__ ((nocommon));
    char *locs __attribute__ ((nocommon));
    

    还有其他的报错都大同小异,修改一下源代码基本都可以解决…

    我有已经修改好了的libc, 需要的可以私信…

    有时候我们需要测试不同的glibc的性能,此时可以使用如下命令来指定动态库加载器和glibc,

     g++ test_log.c -Wl,--rpath=/usr/local/lib -Wl,--dynamic-linker=/usr/local/lib/ld-linux-x86-64.so.2 

    其中/usr/local/lib为glibc动态库的路径,linker为动态装载器 
    以下test_log.c代码为例

    /*
     *  learn for syslog/openlog 
     *
     *
     * */
    #include <syslog.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    
    int main(int argc,char **argv)
    {
        //check the argc,usage e.g. ./a.out filename 
        if(argc != 2){
            perror("argc != 2");
            exit(1);    
        }
        openlog(argv[0],LOG_PID | LOG_NOWAIT | LOG_NDELAY,LOG_USER);
    
        syslog(LOG_INFO,"%s","hello,world");
        closelog();
    }

    使用上述命令编译后,可以用/usr/bin/ldd查看a.out依赖的动态库

    [jefby@localhost work]$ /usr/bin/ldd a.out 
        linux-vdso.so.1 =>  (0x00007fff3d9ff000)
        libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x0000003c67400000)
        libm.so.6 => /usr/local/lib/libm.so.6 (0x00007fdf9bc5c000)
        libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x0000003c67000000)
        libc.so.6 => /usr/local/lib/libc.so.6 (0x00007fdf9b8b8000)
        /usr/local/lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x0000003c5a000000)

    说明已经替换成功,运行

    ./a.out jefby

    然后使用tail来查看是否成功写入系统日志中

    sudo tail /var/log/messages

    如下所示,可以看到已经成功写入:

    [jefby@localhost work]$ ./a.out jefby
    [jefby@localhost work]$ sudo tail /var/log/messages -n 1
    Aug 22 14:30:02 localhost ./a.out[12965]: hello,world
  • 相关阅读:
    [转]Sublime Text 3安装Json格式化插件
    Golang 新手可能会踩的 50 个坑【转】
    [golang]svg图片默认按照左上角旋转,改为按中心旋转,重新计算中心偏移量
    序列化是干什么的,有什么作用,什么情况下会用到?
    Hbase设置多个hmaster
    基于JMX动态配置Log4J日志级别
    面向过程与面向对象编程的区别和优缺点
    log4j自带的两个类MDC和NDC作用以及用途
    【架构师之路】集群/分布式环境下5种session处理策略
    Java Web项目如何做到升级不断掉服务,同时涉及到的相关问题
  • 原文地址:https://www.cnblogs.com/bigben0123/p/12594972.html
Copyright © 2011-2022 走看看