V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
yuzenan888
V2EX  ›  Linux

有没有什么方法可以强制编译出静态的二进制文件?

  •  
  •   yuzenan888 · 2018-02-22 16:11:56 +08:00 · 6289 次点击
    这是一个创建于 2500 天前的主题,其中的信息可能已经有所发展或是发生改变。

    今天打算在树莓派上编译一个 hostapd 给安卓机用,结果发现里面没有 /configure 脚本,只有 Makefile。

    我编译一下,然后用 file 命令看了一下,是动态的二进制文件。

    	linux-vdso.so.1 =>  (0x00007ffec77ce000)
    	librt.so.1 => /lib64/librt.so.1 (0x00007f782ab23000)
    	libssl.so.10 => /lib64/libssl.so.10 (0x00007f782a8b1000)
    	libcrypto.so.10 => /lib64/libcrypto.so.10 (0x00007f782a450000)
    	libc.so.6 => /lib64/libc.so.6 (0x00007f782a08d000)
    	libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f7829e71000)
    	libgssapi_krb5.so.2 => /lib64/libgssapi_krb5.so.2 (0x00007f7829c24000)
    	libkrb5.so.3 => /lib64/libkrb5.so.3 (0x00007f782993c000)
    	libcom_err.so.2 => /lib64/libcom_err.so.2 (0x00007f7829738000)
    	libk5crypto.so.3 => /lib64/libk5crypto.so.3 (0x00007f7829505000)
    	libdl.so.2 => /lib64/libdl.so.2 (0x00007f7829301000)
    	libz.so.1 => /lib64/libz.so.1 (0x00007f78290eb000)
    	/lib64/ld-linux-x86-64.so.2 (0x00007f782ad2b000)
    	libkrb5support.so.0 => /lib64/libkrb5support.so.0 (0x00007f7828edd000)
    	libkeyutils.so.1 => /lib64/libkeyutils.so.1 (0x00007f7828cd9000)
    	libresolv.so.2 => /lib64/libresolv.so.2 (0x00007f7828abf000)
    	libselinux.so.1 => /lib64/libselinux.so.1 (0x00007f7828898000)
    	libpcre.so.1 => /lib64/libpcre.so.1 (0x00007f7828636000)
    

    由于安卓机没有这些库文件,所以不能使用动态库。有什么方法可以强制将它编译成静态二进制文件吗?

    我对 Linux 开发完全不懂,谢谢了!

    第 1 条附言  ·  2018-02-23 11:50:55 +08:00
    谢谢大家的回复。虽然没能静态编译,但是我放在安卓机上编译成功了。
    21 条回复    2018-02-23 13:06:59 +08:00
    Nitroethane
        2
    Nitroethane  
       2018-02-22 16:27:00 +08:00 via Android   ❤️ 1
    先添加 -static 参数使 GCC 强制静态链接,然后 -l 参数指定要静态链接的库。没记错的话应该是这样
    Nitroethane
        3
    Nitroethane  
       2018-02-22 16:28:43 +08:00 via Android
    上面说的有些问题,LZ 可以看看这个 https://www.zhihu.com/question/22940048
    smallzhan
        4
    smallzhan  
       2018-02-22 16:51:41 +08:00   ❤️ 1
    这个程序用到了 libdl, 估计没办法编译成纯静态的。
    0ZXYDDu796nVCFxq
        5
    0ZXYDDu796nVCFxq  
       2018-02-22 17:27:07 +08:00 via iPhone
    建议用 -Wl,-rpath 指定库路径,这里可以用相对路径
    然后把这些库一起打包

    好处就是可以单独更新一些库
    一般建议用相同版本的 gcc 编译
    we000
        6
    we000  
       2018-02-22 17:30:30 +08:00
    比较复杂, 出状况的可能性也很大, 完全不懂的话可能没法一节课说明白或者期待别人免费帮你搞定, 建议 workaround 或者找人.

    另外编译出来也不一定能用, 安卓机网卡一般不支持 AP 模式, 一般也不是兼容的通用接口.
    linyinma
        7
    linyinma  
       2018-02-22 17:33:28 +08:00
    这应该不是编译静态库的问题,目的是移植到安卓机,故要找到对应处理器(是 ARM ?)的交叉编译工具链,如果这些概念不熟悉,这个就是白谈了~
    xupefei
        8
    xupefei  
       2018-02-22 17:34:21 +08:00
    前四楼真的知道 LZ 在干啥吗? LZ 想要在树莓派的 Linux 上本地编译一个 elf 去安卓上运行。

    正确答案是用 PC 开个虚拟机交叉编译才对。不过就算编译成了也不一定能用。
    yuzenan888
        9
    yuzenan888  
    OP
       2018-02-22 17:41:06 +08:00
    @Nitroethane 谢谢回复,刚试了,不行。

    @linyinma @xupefei 之前在 x86 上交叉编译过,可以运行。这次由于换电脑了,交叉编译的环境没保存丢了,所以我为了省点事想在树莓派上弄,看来省不了了。我想问下就是为什么静态库一定要交叉编译,同架构本地编译不行吗?
    linyinma
        10
    linyinma  
       2018-02-22 17:47:52 +08:00
    @yuzenan888 不是静态库一定要交叉编译,是必须编译在对应处理器能识别的 CPU 指令~~
    choury
        11
    choury  
       2018-02-22 17:52:08 +08:00
    首先你需要把这些动态库对应的静态库找到,就是.a 文件
    zhaoxiting1997
        12
    zhaoxiting1997  
       2018-02-22 17:54:49 +08:00
    或许考虑 android 上装个 termux,直接在 android 删编译?
    updateing
        13
    updateing  
       2018-02-22 20:52:28 +08:00 via Android
    hostapd 里面已经有 Android.mk 了,应该是可以直接在 NDK 中编译。可以试试在这个文件里引用静态库……

    此外,Android 不是自带 hostapd 么?
    vuuv
        14
    vuuv  
       2018-02-22 22:31:20 +08:00 via Android
    pi 是 arm v5 ?现在安卓一般都是 v7a 或者 v8 了,应该可以向前兼容。
    但是即便能运行 elf 不代表能正常使用,毕竟 api 不一样。
    icedx
        15
    icedx  
       2018-02-22 22:39:26 +08:00 via Android
    CMake 是在库名后加.a
    yuzenan888
        16
    yuzenan888  
    OP
       2018-02-22 23:09:36 +08:00
    @zhaoxiting1997 如果能这样那就好了,关键是……很多库都没有。

    @updateing Android.mk 是啥啊?我根本没接触过,可以编译出 ELF 吗?我想编译一个带 Radius 服务器功能的,想开 EAP-TLS 的 Wi-Fi。

    @vuuv 我用的是 pi3,貌似是 armv7。
    updateing
        17
    updateing  
       2018-02-23 00:40:48 +08:00 via Android
    @yuzenan888 看到 Android.mk 思路就给带偏了,抱歉 😂 这个文件是配合 Android NDK 给 Android 编译 C/C++ 代码用的。但是 NDK 一般是运行在 x86 平台交叉编译用的……

    可以试试看 Android 自带的 hostapd 能不能用 EAP-TLS 的配置文件。不能的话,就只能像楼上各位说的一样找齐所有的 .a 再加 -static 了。
    yuzenan888
        18
    yuzenan888  
    OP
       2018-02-23 09:17:59 +08:00
    @zhaoxiting1997 @updateing 我试着在安卓机上编译,卡在这了……
    ```
    /data/data/com.termux/files/usr/include/syslog.h:119: undefined reference to `__android_log_print'
    /data/data/com.termux/files/usr/include/syslog.h:116: undefined reference to `__android_log_vprint'
    ```
    fgodt
        19
    fgodt  
       2018-02-23 09:50:22 +08:00
    @yuzenan888 没有找到 log 库 你编译选项添加-llog
    yuzenan888
        20
    yuzenan888  
    OP
       2018-02-23 11:48:55 +08:00
    @fgodt 编译好了。删掉这两个函数调用就好了,谢谢。

    ```
    //__android_log_vprint(a, "syslog", format, ap);
    //__android_log_print(a, "syslog", "%s - %s", __progname, syslog_text);
    ```
    Osk
        21
    Osk  
       2018-02-23 13:06:59 +08:00 via Android
    可以直接把对应架构的 so 库和可执行文件拷贝过去,然后

    export LD_LIBRARY_PATH=`pwd`/usr/lib
    ./usr/lib/ld-linux-aarch64.so.1 ./usr/bin/XXX

    这样运行,反正我一直这么使用一些 linux 下面的命令,直接从 archlinuxarm 里面拷贝过来的,不需要自己编译
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4653 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 33ms · UTC 09:54 · PVG 17:54 · LAX 01:54 · JFK 04:54
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.