一份代码需要编译到几种不同的平台, 依赖一些第三方库,因为没有编译环境,只能采用交叉编译的方式, 有没有方法能解决这种问题?
目前我知道的是通过 dlopen 的方式来处理,但是对代码改动较大,大家有什么其他更好的方法吗?
1
fcten 2020-02-24 11:01:45 +08:00
是动态库就可以,缺少静态库则无法编译成可执行文件
|
2
shylockhg 2020-02-24 11:07:05 +08:00
交叉编译为啥会会没有库文件?
|
3
ai277014717 2020-02-24 11:18:57 +08:00
-undefined dynamic_lookup 可以符号改成动态查找。可以试试
|
4
chinuno 2020-02-24 11:19:39 +08:00 via Android
创建 stub 的 so 文件,编译的时候用 stub 链接
|
5
hitmanx 2020-02-24 11:20:10 +08:00
把 dlopen 这层逻辑封装一下,上层不需要知道调用的库函数是哪里来的。dlopen 这一层可以用代码生成
|
6
chinuno 2020-02-24 11:22:51 +08:00 via Android
第三方库你还是乖乖的交叉编译都编译出来吧
|
7
alphaprogrammer OP @shylockhg 因为本地没有编译平台,只有一个交叉编译器
|
8
alphaprogrammer OP @fcten 但是 gcc/g++ 在链接阶段会查找可执行程序引用到的所有函数,如果找不到会报错的吧
|
9
littlewing 2020-02-24 11:29:15 +08:00
编译不需要库,只需要头文件
链接阶段才需要库 |
10
alphaprogrammer OP @hitmanx 目前是在这方面想,但是我希望是 动态链接的方式和 dlopen 的方式能随意切换
|
11
alphaprogrammer OP @littlewing 这个我知道,现在就是需要编译可执行文件
|
12
alphaprogrammer OP @chinuno 这个思路不错,之前的代码可以原封不动,不用改
|
13
alphaprogrammer OP @ai277014717 gcc/g++ 有这个编译选项吗?
|
14
hitmanx 2020-02-24 11:42:20 +08:00
@alphaprogrammer 控制链接时要不要链接你这个 dlopen 层就可以了,拿个 build flag 控制一下
|
15
ysc3839 2020-02-24 11:47:55 +08:00 via Android
在 Windows 中可以把 DLL 等信息写入导入表中,自己的代码就不需要手动进行 LoadLibrary 等操作了。
我印象中 Linux 也有类似机制的,用这种机制就不需要自己手动 dlopen 了。 |
16
augustheart 2020-02-24 12:01:01 +08:00
要么老老实实 dlopen,要么老老实实把三方库都交叉编译一遍。
|
17
augustheart 2020-02-24 12:02:34 +08:00
你要用别的奇怪方法,就不怕碰到动态库版本不对?
|
18
SPACELAN 2020-02-24 12:15:49 +08:00
既然依赖库都要交叉编译了,不如一起静态链接吧
|
19
alphaprogrammer OP @SPACELAN 依赖库不由我提供, 直接从特定源下载即可
|
20
alphaprogrammer OP @augustheart 版本确实是一个问题,但是动态链接一样会碰到版本问题,这个是 code 应该做兼容处理的
|
21
alphaprogrammer OP @hitmanx 目前在这方面尝试,dlopen 之类的壳代码不知道有没有什么方法能自动生成的
|
22
alphaprogrammer OP @ysc3839 -_-!! 对 window 不了解,没接触过。
|
23
SPACELAN 2020-02-24 12:39:12 +08:00
@alphaprogrammer #19 静态兼容性好很多,也方便别人直接运行
|
24
neighbads 2020-02-24 12:41:12 +08:00
接口不多的话 写个假的 lib,只有导出函数没有功能的。。
|
25
ysc3839 2020-02-24 13:39:50 +08:00 via Android
@alphaprogrammer https://www.cprogramming.com/tutorial/shared-libraries-linux-gcc.html
帮你找到了,Linux 也有这个功能,而且 gcc 可以直接识别 .so 文件,不像 Windows 需要一个 stub lib。 |
26
chinuno 2020-02-24 13:58:40 +08:00 via Android
系统的包管理器不是这样用的。。
那上面的库是为了维护系统内的依赖用的。你要用上面的库应该目标系统上安装 dev 包在目标系统上编译才能用这些库。 另外一种用到包管理器里面库的情况是源维护者自己编译软件包的时候用到,一般也是维护者交叉编译对应库链接过去的。 自己另外编译还强行用这些库很容易依赖被破坏。包管理器安装的软件一般没出问题是因为有维护者一直在更新依赖,就算是这样有时候还是会出现依赖问题。 如果你只是要在对应系统发布可执行程序,最好的做法是每个平台编译对应的静态库,发布的时候发布静态连接的可执行程序。如果需要源码发布就附带每个平台的静态库一起发布。 |
27
augustheart 2020-02-24 15:05:56 +08:00
@alphaprogrammer 甚至平台不同也会碰到问题的。每个平台的实现可能不同。基本上来说就是靠运气编程
|
28
FrankHB 2020-02-25 14:47:55 +08:00
|
29
FrankHB 2020-02-25 14:53:46 +08:00
Ubuntu 用的第三方库,本来就没给你打算交叉编译来用。问题是你自己搞不到源码直接自己编译?
退一步讲,就这些库的节操……真用,跑个虚拟机搞个环境都比你搞交叉编译省事。 |
31
alphaprogrammer OP 说一下情况,就是原本写的代码时基于 x86 的,现在需要在 arm 上跑,依赖于一些第三方库(在目标机上可以直接 apt 安装)。目前由于没有 arm 环境,只能在 x86 上使用交叉编译的方式编译出 arm 可执行程序,第三方库依赖采用 dlopen 的方式去除依赖。(如果能下载 arm 版的第三方库 binary,也可以直接编译的)
目前我的实现方式有点取巧,个人感觉实现方式不太好。 首先,之前实现的代码都定义在一个 namespace A 下, 假定依赖一个 func_b,其类型为 type_func_b, 在 namespace A 下定义一个 type_func_b 的变量 func_b,变量名与函数名相同,通过__attribute__(constructor)初始化 func_b 变量,指向第三方库中的函数符号。 这样以前的代码基本不需要改,只需要根据编译 include 一个头文件即可。 有一个缺点就是必须定义在同一个 namespace 下,否则变量 func_b 会与第三方库中的函数声明冲突 |