如何生成没有依赖性的Crystal可执行文件?

13

我正在使用Crystal编写程序,计划将其编译并移植到其他系统以便执行。理想情况下,它不应该有任何依赖关系,因为目标系统将是Linux的新安装。

不幸的是,我无法避开libc的依赖性,所以我可能必须在拥有我希望针对的最低版本libc的系统上编译可执行文件。我认为它应该是向前兼容的。

然而,我在处理libssl时遇到了麻烦。然而,在Debian Wheezy的默认安装中似乎没有libssl,所以当运行我的可执行文件时出现以下错误:

error while loading shared libraries: libssl.so.1.0.0:
cannot open shared object file: No such file or directory

我认为这种依赖关系是因为我在我的源代码中使用了require "http/client"。然而,我没有进行任何与ssl相关的调用,因为我只用它连接到不安全的网站。

显然,我还依赖于libevent-2.0.so.5。据推测,所有的Crystal程序也都会有此类依赖关系。谁知道Crystal还有多少其他依赖关系呢?

我的可执行文件必须在一个全新安装的Linux系统上运行。那么,除了libc之外,我怎样才能生成一个没有任何依赖关系的Crystal可执行文件呢?


我喜欢这个问题;曾经一度所有东西都是静态链接的。时光荏苒,变革无常。 - will
2个回答

12

在Linux中,您可以使用ldd命令列出可执行文件需要的共享库。在OSX中,可以使用otool -L实现同样的目的。

通常情况下,在构建可执行文件时,链接器会使用共享库,如果它们能够找到的话。因此,你需要强制链接器改用静态库。(在未来,我们可能会添加一个标志到编译器,以强制进行这个选择)

您应该可以在/opt/crystal/embedded/lib中找到一些静态库。我们使用它们来生成可移植的Crystal编译器。

为了使用这些库,您可以运行:

$ LIBRARY_PATH=/opt/crystal/embedded/lib crystal build my_app.cr

在考虑其他标准位置中安装的库之前,应该优先考虑该目录中可用的库。

不幸的是,OpenSSL没有与Crystal一起分发,因此您必须复制或构建libssllibcrypto的静态版本。无论如何,这是一个常见的库,在任何Linux发行版中都可以获得。

关于libc,那就更棘手了。我们使用旧的CentOS和Debian发行版为发布编译Crystal二进制文件,以使其与更多的libc版本兼容。


1
太棒了,谢谢。我用 crystal build FILE.cr --cross-compile "Linux x86_64" --target "x86_64-unknown-linux-gnu"cc FILE.o -o FILE -Wl,-Bstatic -levent -lpcre -lssl -lgc -lcrypto -lz -Wl,-Bdynamic -ldl -lrt -lpthread -lc 成功了,但你的方法更简单。我使用 apt-file 定位 .a 文件,然后将它们软链接到 crystal lib 目录中。 - Sod Almighty
一个静态链接的32位编译可执行文件在64位Linux上能正常工作吗? - Sod Almighty
objdump 除了其他用途外,还可以列出动态库的依赖关系。 - Sod Almighty

5

Crystal 文档 中提到,--static 编译器标志目前仅适用于 Alpine Linux(并建议使用 Alpine Linux Docker 容器)。

如果您不了解 Docker 但恰好在您的计算机上有 Vagrant,则可以使用我的 Alpine box(relativkreativ/alpine)而不是自己构建。

无论哪种情况,静态链接都在 Alpine 上工作。

只需执行以下步骤:

  • /etc/apk/repositories 中启用社区存储库
  • 运行 apk update 以获取最新的软件包列表
  • 使用 apk add crystal shards 安装 Crystal
  • 使用 apk add libc-dev 拉取正确的 libc(一个可以完成此操作的元包)

完成这些步骤后,您可以使用 crystal build src/FILE.cr -o bin/FILE --release --static 编译您的 Crystal 项目。

现在有一个没有依赖关系的Crystal二进制文件,可以轻松地将您的项目分发为RPM,例如(这就是我第一次发现这个问题的方式)。
我也在我的网站上一篇文章中总结了这个问题。

2
我收到了 ld: library not found for -lcrt0.o 的错误信息(通常这意味着您需要安装 libcrt0.o 的开发包)。 - HappyFace

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接