一个应用程序调用动态库, 而这个动态库其中的函数调用某静态库时,如何生成应用程序呢?

看下面的代码就明白了

 

生成动态库: 需要的目标文件得用-fPIC选项生成.

而静态库所需的目标文件可以不用-fPIC选项.

例:

/// static.h
void static_print();
///static.cpp
#include <iostream>
#include "static.h"
void static_print() {
    std::cout<<"This is static_printfunction"<<std::endl;
}
// shared.h
void shared_print();
// shared.cpp
#include <iostream>
#include "shared.h"
#include "static.h"
void shared_print() {
      std::cout<<"This is shared_print function";
        static_print();
}
test.cpp
   #include"share.h"
 
int main()
{
      shared_print();
       return 0;
}

 

 

方法一

 

静态库的.o文件也用-fPIC生成. 生成动态库时把静态库加入.

生成应用程序时只加载动态库

 

 g++ -c -fPICstatic.cpp // 生成static.o

 ar -rlibstatic.a static.o // 生成静态库libstatic.a

 g++ -c -fPICshared.cpp // 生成shared.o

 g++ -sharedshared.o -lstatic-o libshared.so   //生成动态库libshared.so

注: -shared是g++的选项,与shared.o无关. -lstatic选项把libstatic.a的函数加入动态库中.

 g++ test.cpp-lshared -o test.exe // link libshared.so 到test.exe中.

 

 方法二

静态库的.o文件不用-fPIC生成. 生成动态库时不加表态库.

 

生成应用程序时加载动态库和静态库.

 

 g++ -cstatic.cpp // 生成static.o

 ar -rlibstatic.a static.o // 生成静态库libstatic.a

 g++ -c -fPICshared.cpp // 生成shared.o

 g++ -sharedshared.o -o libshared.so // 生成动态库libshared.so

注: -shared是g++的选项,与shared.o无关. 这时如果加-lstatic. error:relocationR_X86_64_32 against `a local symbol' can not be used when making a sharedobject; recompile with -fPIC

 g++ test.cpp -lshared -lstatic-o test.exe // link libshared.so 到test.exe中.

 两种方法的不同之处在于static_print的实际代码一个在.so中.一个在最后test.exe文件中. 个人觉得第一种方法更好, 因为动态库应该看成一个可以独立运行的程序.

 

Could not read symbols解决方法 


Could not read symbols

 

陈运文

Could not read symbols:Linux/UNIX系统下编译时,常见的一类报错信息。

  通常情况下,该编译报错信息之前会给出出现错误的静态库(.a结尾文件)、或动态库(.so结尾文件),
  该报错的基本原因是当前编译器无法对库文件进行正确的解析

Could not read symbols报错类型

  具体的报错信息会在Could not read symbols:字段后给出,常见的一些报警信息形如:
  /usr/lib/libdemo.so: could not read symbols: File in wrong format
  /usr/lib/libz.a: Could not read symbols: Bad value
  /usr/lib/libcode.a: Could not read symbols:Invalid operation
  /usr/lib/htmlparse.a: could not read symbols: Archive has no index; run ranlib to add one
  /usr/lib/htmlparse.a: could not read symbols: Malformed archive
  Linux出现Could not read symbols报警主要原因为当前编译环境和库文件生成时对应的环境不同,由于Linux本身编译选项非常复杂,可以从以下几个方面逐步排查:

Could not read symbols原因和解决方案

  1、 gcc/g++版本不正确
  众所周知Linux gcc编译器(GNU Compiler Collection)是功能强大的交叉编译器,但其众多的版本会导致兼容问题。如果联编所使用的 .a/.so文件是由另一个不同版本的gcc编译生成后,当移植到另一个不同版本gcc环境下编译时,(例如:将gcc2.9x老版本下的.so,拷贝入新版gcc环境使用),且编译版本不兼容,会出现Could not read symbols的报错。(可以使用gcc -v 查看一下当前版本)
  如果是这种原因导致的问题,需要在新gcc版本下,删除(或更名)旧的库文件,重新由src编译生成.a/.so文件,保证gcc版本一致

  2、64bit/32bit编译环境不一致
  目前Linux OS系统会推出32位和64位两个不同的版本,此时即使使用命令:
  gcc --version
  查看的gcc三位版本一致,但由于32位程序和64位程序可能不兼容,因此如果在32bit OS环境下编译获得的库文件,移植入64bit环境时会产生Could not read symbols错误

  一个简单的方式查看当前系统位数:
  getconf LONG_BIT
  结果显示:32 or 64

  请确定在操作系统位数相同的环境下进行编译,否则删除原库文件重新生成

  3、Makefile配置问题
  查看编译期参数是否缺少 -fPIC , 不仅是共享库,静态库有时也需要有 -fPIC参数
  或者查看Makefile是否存在前后配置项不一致

  4、修改configure配置
  操作系统位数可能导致的另一个问题是,所使用的底层库不同
  linux系统在 /usr/lib/ 和 /usr/lib64/ 两个目录下,会分别存放不同位数版本的lib,
  可通过修改环境配置来指定所需的库位置:
  # ./configure --enable-lib64 --libdir=/usr/lib64
  解决库版本问题

  已知的一个常见问题是:在64位机器上编译httpd-2.0.x时常会出现该原因导致的Could not read symbols报错,通过该方法可解决
  另外,64位系统编译脚本在定位expat上存在问题(编译apache时常出现),修改configure使用自带的expat来编译可解决,具体修改configure配置的方法是增加:
  --with-expat=builtin

  5、Lib路径错误
  目标路径的库文件不存在或不一致,也会导致Could not read symbols错误,
  可以查看路径和库文件所在位置是否一致,环境变量 LD_LIBRARY_PATH 中指明库的搜索路径是否有误

Could not read symbols扩展
  

      具体的编译环境和选项错综复杂,如果通过上述方法仍存在错误,可以将错误信息,Makefile,configure等贴至一些知名的Linux技术论坛,以寻求更具体的帮助





Could not read symbols

 

陈运文

Could not read symbols:Linux/UNIX系统下编译时,常见的一类报错信息。

  通常情况下,该编译报错信息之前会给出出现错误的静态库(.a结尾文件)、或动态库(.so结尾文件),
  该报错的基本原因是当前编译器无法对库文件进行正确的解析

Could not read symbols报错类型

  具体的报错信息会在Could not read symbols:字段后给出,常见的一些报警信息形如:
  /usr/lib/libdemo.so: could not read symbols: File in wrong format
  /usr/lib/libz.a: Could not read symbols: Bad value
  /usr/lib/libcode.a: Could not read symbols:Invalid operation
  /usr/lib/htmlparse.a: could not read symbols: Archive has no index; run ranlib to add one
  /usr/lib/htmlparse.a: could not read symbols: Malformed archive
  Linux出现Could not read symbols报警主要原因为当前编译环境和库文件生成时对应的环境不同,由于Linux本身编译选项非常复杂,可以从以下几个方面逐步排查:

Could not read symbols原因和解决方案

  1、 gcc/g++版本不正确
  众所周知Linux gcc编译器(GNU Compiler Collection)是功能强大的交叉编译器,但其众多的版本会导致兼容问题。如果联编所使用的 .a/.so文件是由另一个不同版本的gcc编译生成后,当移植到另一个不同版本gcc环境下编译时,(例如:将gcc2.9x老版本下的.so,拷贝入新版gcc环境使用),且编译版本不兼容,会出现Could not read symbols的报错。(可以使用gcc -v 查看一下当前版本)
  如果是这种原因导致的问题,需要在新gcc版本下,删除(或更名)旧的库文件,重新由src编译生成.a/.so文件,保证gcc版本一致

  2、64bit/32bit编译环境不一致
  目前Linux OS系统会推出32位和64位两个不同的版本,此时即使使用命令:
  gcc --version
  查看的gcc三位版本一致,但由于32位程序和64位程序可能不兼容,因此如果在32bit OS环境下编译获得的库文件,移植入64bit环境时会产生Could not read symbols错误

  一个简单的方式查看当前系统位数:
  getconf LONG_BIT
  结果显示:32 or 64

  请确定在操作系统位数相同的环境下进行编译,否则删除原库文件重新生成

  3、Makefile配置问题
  查看编译期参数是否缺少 -fPIC , 不仅是共享库,静态库有时也需要有 -fPIC参数
  或者查看Makefile是否存在前后配置项不一致

  4、修改configure配置
  操作系统位数可能导致的另一个问题是,所使用的底层库不同
  linux系统在 /usr/lib/ 和 /usr/lib64/ 两个目录下,会分别存放不同位数版本的lib,
  可通过修改环境配置来指定所需的库位置:
  # ./configure --enable-lib64 --libdir=/usr/lib64
  解决库版本问题

  已知的一个常见问题是:在64位机器上编译httpd-2.0.x时常会出现该原因导致的Could not read symbols报错,通过该方法可解决
  另外,64位系统编译脚本在定位expat上存在问题(编译apache时常出现),修改configure使用自带的expat来编译可解决,具体修改configure配置的方法是增加:
  --with-expat=builtin

  5、Lib路径错误
  目标路径的库文件不存在或不一致,也会导致Could not read symbols错误,
  可以查看路径和库文件所在位置是否一致,环境变量 LD_LIBRARY_PATH 中指明库的搜索路径是否有误

Could not read symbols扩展
  

      具体的编译环境和选项错综复杂,如果通过上述方法仍存在错误,可以将错误信息,Makefile,configure等贴至一些知名的Linux技术论坛,以寻求更具体的帮助