Linux学习笔记——如何在交叉编译时使用共享库

  0.前言

  在较为复杂的项目中会利用到交叉编译得到的共享库(*.so文件)。在这种情况下便会产生以下疑问,例如:

  【1】交叉编译时的共享库是否需要放置于目标板中,如果需要放置在哪个目录中。

  【2】交叉编译时的共享库是否需要放置于宿主机中,如果需要放置于哪个目录中。

  【3】交叉编译时如何指定共享库

  【4】程序运行时如何查找共享库

  等等问题。

  博文总结了使用共享库的一般方法,并通过一个例子说明问题。如果已经有了交叉编译好的共享库,可以从【2】开始,步骤【1】只是为了说明问题,捏造一个简单的共享库试图说明问题。

  【1】交叉编译获得链接库

  【2】交叉编译源文件并加入链接库

  【3】移动动态链接库

  【4】执行

  【必要说明】

  【宿主机】Ubuntu 14.04 AMD64

  【目标板】树莓派

  【相关博文】

  【例说makefile索引博文】

  【树莓派学习笔记——交叉编译工具链】

  【代码仓库】——makefile-example

  代码仓库位于bitbucket,可借助TortoiseHg(GUI工具)克隆代码或者在网页中直接下载zip包。

  1.交叉编译获得动态链接库

  本例先制作一个非常简单的共享库,共享库包含两个API——add和sub。

  【libtest.h】

  指定接口,给出相应声明

  #ifndef __LIBTEST_H

  #define __LIBTEST_H

  int sub(int a, int b);

  int add(int a, int b);

  #endif

  【test-add.c】

  int add(int a, int b)

  {

  return a+b;

  }

  【test-sub.c】

  int sub(int a, int b)

  {

  return a-b;

  }

  【makefile】

  在同目录下包含makefile文件,请替换其中的[tab],并以代码仓库中的makefile文件为主。编译完成之后,把libtest.so移动到上级lib目录中。请注意此时的交叉工具链为arm-linux-gnueabihf-gcc

  ,目标b

  # 指令编译器和选项

  CC = arm-linux-gnueabihf-gcc

  CFLAGS = -Wall -std=gnu99

  # 目标文件

  TARGET = libtest.so

  # C文件

  SRCS = test-add.c test-sub.c

  # 目标文件

  OBJS = $(SRCS:.c=.o)

  # 链接为可执行文件

  $(TARGET):$(OBJS)

  [tab]$(CC) -shared -o $@ $^

  [tab]mv $(TARGET) ../lib

  clean:

  [tab]rm -rf $(TARGET) $(OBJS)

  # 编译规则 [email protected] $< 代表第一个依赖文件

  %.o:%.c

  [tab]$(CC) $(CFLAGS) -o $@ -fPIC -c $<

  【必要的验证】

  使用file指令查看libtest.so信息。

  file libtest.so

  libtest.so: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, BuildID[sha1]=e22558b8cf089b92e5534b636c6d501f1cc54581, not stripped

  从控制台的输出信息可以看出,libtest.so运行于ARM平台,而不是宿主机的AMD64平台。

  2.交叉编译源文件并加入动态链接库

  【源文件】

  #include

  #include

  int main(void)

  {

  int a = 3;

  int b = 2;

  printf("a=%d\n", a);

  printf("b=%d\n", b);

  printf("a+b=%d\n", add(a, b));

  printf("a-b=%d\n", sub(a, b));

  return 0;

  }

  【makefile文件】

  # 指定编译器和选项

  # 指定树莓派交叉编译器

  CC = arm-linux-gnueabihf-gcc

  CFLAGS = -Wall -std=gnu99

  # 目标文件

  TARGET = test

  # C文件

  SRCS = test.c

  # 头文件查找路径

  INC = -I.

  # 库文件和库查找路径

  DLIBS = -ltest

  LDFLAGS = -L./lib

  # 目标文件

  OBJS = $(SRCS:.c=.o)

  # 链接为可执行文件

  $(TARGET):$(OBJS)

  [tab]$(CC) -o $@ $^ $(LDFLAGS) $(DLIBS)

  clean:

  [tab]rm -rf $(TARGET) $(OBJS)

  # 编译规则 [email protected] $< 代表第一个依赖文件

  %.o:%.c

  [tab]$(CC) $(CFLAGS) $(INC) -o $@ -c $<

  【说明】

  【1】交叉工具链为arm-linux-gnueabihf-gcc

  【2】指定了交叉编译之后的共享库和共享库路径,链接共享库使用-ltest,共享库位于lib目录下。请注意-ltest对应libtest.so。

  【3】make之后可获得可执行文件,通过file test查看信息。