12

我正在用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 系统上运行。那么,如何生成没有依赖关系的 Crystal 可执行文件?除了libc,我想。

4

2 回答 2

12

ldd在 Linux 中,您可以使用该命令列出可执行文件所需的共享库。在 OSX 中,otool -L可以用于相同的目的。

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

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

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

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

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

不幸的是,OpenSSL 没有与 Crystal 一起分发,因此您必须复制或构建libssland的静态版本libcrypto。无论如何,它是一个通用库,可在任何 Linux 发行版中使用。

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

于 2016-02-03T01:59:04.287 回答
5

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

如果你不喜欢 Docker,但碰巧在你的机器上安装了 Vagrant,你可以使用我的 Alpine 盒子(relativkreativ/alpine),而不用费力地构建你自己的盒子。

无论哪种情况,静态链接都适用于 Alpine。

只需运行以下步骤:

  • 启用社区存储库/etc/apk/repositories
  • 运行apk update获取最新的包列表
  • 安装水晶apk add crystal shards
  • 拉入正确的libc apk add libc-dev(一个这样做的元包)

完成后,您可以使用crystal build src/FILE.cr -o bin/FILE --release --static.

例如,现在拥有一个没有依赖项的 Crystal 二进制文件可以让您轻松地将项目分发为 RPM(这就是我最初发现这个问题的方式)。

我还在我网站上的一篇文章中总结了这一点。

于 2019-02-03T10:27:46.840 回答