zoukankan      html  css  js  c++  java
  • Linux学习笔记——如何使用共享库交叉编译

    0.前言
        在较为复杂的项目中会利用到交叉编译得到的共享库(*.so文件)。在这样的情况下便会产生下面疑问,比如:
        【1】交叉编译时的共享库是否须要放置于目标板中,假设须要放置在哪个文件夹中。

        【2】交叉编译时的共享库是否须要放置于宿主机中,假设须要放置于哪个文件夹中。
        【3】交叉编译时怎样指定共享库
        【4】程序执行时怎样查找共享库
        等等问题。

        
        博文总结了使用共享库的一般方法。并通过一个样例说明问题。假设已经有了交叉编译好的共享库,能够从【2】開始,步骤【1】仅仅是为了说明问题。捏造一个简单的共享库试图说明问题。

        【1】交叉编译获得链接库
        【2】交叉编译源文件并增加链接库
        【3】移动动态链接库
        【4】运行

        【必要说明】
        【宿主机】Ubuntu 14.04 AMD64
        【目标板】树莓派
        
        【相关博文】

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

    1.交叉编译获得动态链接库
        本例先制作一个很easy的共享库。共享库包括两个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)
    # 编译规则 $@代表目标文件 $< 代表第一个依赖文件
    %.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 <stdio.h>
    #include <libtest.h>
    int main(void)
    {
        int a = 3;
        int b = 2;
           
        printf("a=%d ", a);
        printf("b=%d ", b);
       
        printf("a+b=%d ", add(a, b));
        printf("a-b=%d ", 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)
    # 编译规则 $@代表目标文件 $< 代表第一个依赖文件
    %.o:%.c
    [tab]$(CC) $(CFLAGS) $(INC) -o $@ -c $<
        【说明】
        【1】交叉工具链为arm-linux-gnueabihf-gcc
        【2】指定了交叉编译之后的共享库和共享库路径,链接共享库使用-ltest,共享库位于lib文件夹下。请注意-ltest相应libtest.so。
        【3】make之后可获得可运行文件,通过file test查看信息。
    test: ELF 32-bit LSB  executable, ARM, EABI5 version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, BuildID[sha1]=88e4142dceabd295369657b29757141f98a03753, not stripped
        从控制台的输出能够看出,该可执行文件执行平台为ARM,而不是AMD64。

    3.移动动态链接库
        【移动共享库至目标板/usr/lib文件夹中】
        通过FTP工具把共享库传输至树莓派中,然后通过cp指令拷贝到/usr/lib中
        sudo cp libtest.so /usr/lib
        linux系统中默认的搜多路径为/lib和/usr/lib,libtest.so能够拷贝到不论什么文件夹中。
        改动libtest.so的运行权限。
        sudo chmod 775 libtest.so

    4.运行
        【FTP上传】
        通过FTP工具把可运行文件test拷贝到树莓派中。然后通过ldd指令查看共享库链接状态。

        【检验】
        ldd test
    /usr/lib/arm-linux-gnueabihf/libcofi_rpi.so (0xb6f7f000)
    libtest.so => /usr/lib/libtest.so (0xb6f6b000)
    libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0xb6e3b000)
    /lib/ld-linux-armhf.so.3 (0xb6f8d000)
        从控制台的输出能够看出,test成功链接了位于/usr/lib中的libtest.so

        【运行】
        ./test
    a=3
    b=2
    a+b=5
    a-b=1
        从运行结果看,前面所做的努力是正确的。


    5.总结
        回答在前言中的问题。
        【1】交叉编译时的共享库是否须要放置于目标板中,假设须要放置在哪个文件夹中。

        交叉编译之后的共享库须要拷贝到目标板中,最好放置于/usr/lib或/lib中。当然也有其它的方法,在这里不具体说明。

        【2】交叉编译时的共享库是否须要放置于宿主机中。假设须要放置于哪个文件夹中。
        交叉编译时确切的说链接过程中须要指定共享库的问题,通过-L指定文件夹,通过-l指定共享库名称。

    可是此时交叉编译的共享库最好不要放置于宿主机的/lib或/usr/lib中。以免产生混淆。

        综合【1】和【2】,libtest.so同一时候存在于目标板和宿主机中。

        【3】交叉编译时怎样指定共享库
        通过-L指定文件夹,通过-l指定共享库名称

        【4】程序执行时怎样查找共享库
        最直观的方法,拷贝到/usr/lib文件夹中。让linux系统自己主动查找。

        最后,发现博文写多了自己感觉好累啊,希望这些总结对大家实用。


    版权声明:本文博客原创文章。博客,未经同意,不得转载。

  • 相关阅读:
    通用工业协议(CIP)形式化的安全分析(前期概念的梳理)
    WEB安全工程师整理资料
    AWVS (Acunetix Web Vulnerability Scanner )
    Java Decompiler反编译Jar文件
    信息安全面试题整理
    工业网络安全 智能电网,SCADA和其他工业控制系统等关键基础设施的网络安全(总结)
    PLC编程的基础知识的总结
    协议安全分析方法的综述
    The Essential Burp Suite
    kali linux 虚拟机克隆之后版本回退问题
  • 原文地址:https://www.cnblogs.com/blfshiye/p/4657419.html
Copyright © 2011-2022 走看看