如何生成没有依赖项的 Crystal 可执行文件?
How can I produce a Crystal executable with no dependencies?
我正在 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。
在 Linux 中,您可以使用 ldd
命令列出可执行文件所需的共享库。在 OSX 中,otool -L
可以用于相同的目的。
通常情况下,链接器会在构建可执行文件时使用共享库(如果可以找到的话)。因此,您需要做的是强制链接器改用静态库。 (将来我们可能会向编译器添加一个标志以强制执行此选择)
您应该在 /opt/crystal/embedded/lib 中找到其中一些静态库。我们使用这些来生成可移植的 Crystal 编译器。
要使用这些库,您可以 运行:
$ LIBRARY_PATH=/opt/crystal/embedded/lib crystal build my_app.cr
在考虑安装在标准位置的其他库之前,应该优先选择该目录中可用的库。
遗憾的是,OpenSSL 未随 Crystal 分发,因此您必须复制或构建 libssl
和 libcrypto
的静态版本。无论如何,它是一个通用库,在任何 Linux 发行版中都可用。
关于libc
,这更棘手。我们为使用旧 CentOS 和 Debian 发行版的版本编译 Crystal 二进制文件,以使其与更多的 libc 版本兼容。
Crystal docs 提到 --static
编译器标志当前仅适用于 Alpine Linux(并建议使用 Alpine Linux Docker容器)。
如果您不喜欢 Docker 但碰巧在您的机器上安装了 Vagrant,您可以使用我的 Alpine 盒子 (relativkreativ/alpine),而不是经历构建自己的麻烦。
无论哪种情况,静态链接都适用于 Alpine。
只需运行以下步骤:
- 在
/etc/apk/repositories
中启用社区存储库
- 运行
apk update
获取最新的包列表
- 安装 Crystal 和
apk add crystal shards
- 使用
apk add libc-dev
引入正确的 libc(一个元包就是这样做的)
完成后,您可以使用 crystal build src/FILE.cr -o bin/FILE --release --static
编译您的 Crystal 项目。
现在拥有一个没有依赖项的 Crystal 二进制文件可以让您轻松地将您的项目分发为 RPM,例如(这就是我最初发现这个问题的方式)。
我也在我的网站 an article 中总结了这一点。
我正在 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。
在 Linux 中,您可以使用 ldd
命令列出可执行文件所需的共享库。在 OSX 中,otool -L
可以用于相同的目的。
通常情况下,链接器会在构建可执行文件时使用共享库(如果可以找到的话)。因此,您需要做的是强制链接器改用静态库。 (将来我们可能会向编译器添加一个标志以强制执行此选择)
您应该在 /opt/crystal/embedded/lib 中找到其中一些静态库。我们使用这些来生成可移植的 Crystal 编译器。
要使用这些库,您可以 运行:
$ LIBRARY_PATH=/opt/crystal/embedded/lib crystal build my_app.cr
在考虑安装在标准位置的其他库之前,应该优先选择该目录中可用的库。
遗憾的是,OpenSSL 未随 Crystal 分发,因此您必须复制或构建 libssl
和 libcrypto
的静态版本。无论如何,它是一个通用库,在任何 Linux 发行版中都可用。
关于libc
,这更棘手。我们为使用旧 CentOS 和 Debian 发行版的版本编译 Crystal 二进制文件,以使其与更多的 libc 版本兼容。
Crystal docs 提到 --static
编译器标志当前仅适用于 Alpine Linux(并建议使用 Alpine Linux Docker容器)。
如果您不喜欢 Docker 但碰巧在您的机器上安装了 Vagrant,您可以使用我的 Alpine 盒子 (relativkreativ/alpine),而不是经历构建自己的麻烦。
无论哪种情况,静态链接都适用于 Alpine。
只需运行以下步骤:
- 在
/etc/apk/repositories
中启用社区存储库
- 运行
apk update
获取最新的包列表 - 安装 Crystal 和
apk add crystal shards
- 使用
apk add libc-dev
引入正确的 libc(一个元包就是这样做的)
完成后,您可以使用 crystal build src/FILE.cr -o bin/FILE --release --static
编译您的 Crystal 项目。
现在拥有一个没有依赖项的 Crystal 二进制文件可以让您轻松地将您的项目分发为 RPM,例如(这就是我最初发现这个问题的方式)。
我也在我的网站 an article 中总结了这一点。