使用 Ruby-build 在 MacOS 上 编译 Portable Ruby - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Mark24
V2EX    Ruby

使用 Ruby-build 在 MacOS 上 编译 Portable Ruby

  •  
  •   Mark24 2024-05-27 19:56:40 +08:00 1936 次点击
    这是一个创建于 500 天前的主题,其中的信息可能已经有所发展或是发生改变。

    RubyChina 讨论: ttps://ruby-china.org/topics/43710

    我的 Blog

    大家好,我是 Mark24 。

    分享下我的笔记,使用 Ruby-build 在 MacOS 上 编译 Portable ruby

    设想一下,如果 ruby 可以变成 portable 的,放在 U 盘上就可以带走,传输到任何一台电脑上就可以执行。

    Portable Ruby + 你的 Ruby 代码 的 zip 包,就像一个行走的独立软件。就像 Go 打包的一样。

    你还可以把他们塞入 一些壳软件里。就像 Electron 那样运行(内部是个浏览器)。

    当然 Ruby 社区曾经有很多方案 Traveling Ruby 、Ruby Packer , 都用各自的方式实现类似的效果,不过都不维护了。

    下面用一个简单的方法来制作 Portable Ruby 。


    截止 2024-05-27 最新版本是 3.3.1 。 每个版本因为特性的不同构建是一个动态的过程。就以 3.3.1 为例。

    过程偷懒,建立在 ruby-build( https://github.com/rbenv/ruby-build) 的基础上。

    不论是 asdf 、rvm …… 他们的背后都是 ruby-build 一个方便安装的 standalone 的工具。ruby-build 解决了大部分的问题,我们只需要找到合适的构建参数。

    一、前置依赖

    1.安装 Mac 的基础工具集

    终端输入 xcode-select --install

    2.安装上 homebrew

    https://brew.sh/

    获得 类似于 Linux 上的包管理工具

    3.安装 Ruby 编译需要的前置依赖

    # 安装前置依赖 # ruby-build 是安装工具 # openssl@3 readline libyaml gmp 是必要的依赖 # rust 是 YJIT 必要的依赖,不装就不会构建 YJIT 功能 brew install ruby-build openssl@3 readline libyaml gmp rust 

    二、编译

    0.知识点

    C 语言( CRuby 是 C 语言项目)编译一般分为 3 个基本过程 1 )预处理:处理一些前置的宏替换 2 )编译:把 .c 代码文件翻译成 .o 机器码文件目标文件 3 )链接:把 .o 文件和系统的底层库(比如标准输入输出)正确的关联起来。生成可执行文件 链接这部,有两个基本的实现 1 )静态链接 2 )动态链接 静态链接比较简单,就是把所有用到的代码打包成一个整体。软件就像一个 exe 文件,带到哪儿都可以执行。 优点就是,随处执行。缺点就是体积大,更新困难,比如你依赖的系统部分有安全缺陷。你必须整体替换。 动态链接,就是软件把用到公共部分(系统、上游 lib )的部分,指他们的动态库( linux 是 so 文件,windows 是 dll 文件,mac 里是 dylib 文件)。 优点:体积小, 如果公共部分有安全漏洞,系统更新,只需要更新动态链接库文件,所有引用的软件都会获得更新。 缺点:除了无法 portable ,软件运行的前提是系统拥有相应的 库。 动态链接是常态,不论是 Linux 、MacOS 、Windows 。动态链接的实践这么多年运行的一直很好。通常库都是按照动态链接库方向来设计的。没有提供静态库。 MacOS 还禁止系统动态库进行 静态链接。 
    1. 最简单的编译

    关键参数:

    • $HOME/portable-ruby 是你存放的目录
    • --enable-load-relative 地址是相对目录,这对我们移动很重要
    • --with-static-linked-ext 静态链接
    RUBY_CONFIGURE_OPTS="--enable-load-relative --with-static-linked-ext" ruby-build 3.2.2 $HOME/portable-ruby 

    2.一些优化选项

    可以参考 https://github.com/rbenv/ruby-build

    额外的选项

    • --with-out-ext=win32,win32ole 去掉 MacOS 上不需要的拓展
    • --disable-install-doc 关闭文档,减小体积
    • --disable-install-rdoc
    • --disable-dependency-tracking
    RUBY_CONFIGURE_OPTS="--enable-load-relative --with-static-linked-ext --with-out-ext=win32,win32ole --disable-install-doc --disable-install-rdoc --disable-dependency-tracking " ruby-build 3.2.2 $HOME/portable-ruby 

    ruby-build 能做的更多,比如支持交叉编译

    三、Portable Ruby

    编译正确完成,你应该获得了 portable ruby

    在拥有 依赖库的电脑上(对,我们前面解释了,系统部分是禁止 静态链接的)。

    你的可以把你的 ruby 代码 + portable ruby 放在一个文件夹里。 用 一个 shell 脚本,通过相对路径连接起来执行。

    比如这样

    #!/usr/bin/env bash ./portable-ruby/bin/ruby ./main.rb 

    某种意义上,Portable Ruby + Ruby Script 和 Go 、Crystal 打包的可执行文件,是一样的。就是大了一点 :D

    我的 Blog

    2 条回复    2024-10-29 14:16:49 +08:00
    Kobayashi
        1
    Kobayashi  
       2024-06-26 18:37:08 +08:00
    这依然是动态链接的,只能保证扩展静态编译,libruby dylib 相对路径链接。

    ```
    otool -L /Users/wyh/.local/share/rbenv/versions/3.2.2/bin/ruby
    /Users/abc/.local/share/rbenv/versions/3.2.2/bin/ruby:
    /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1953.255.0)
    @executable_path/../lib/libruby.3.2.dylib (compatibility version 3.2.0, current version 3.2.2)
    /opt/local/lib/libgmp.10.dylib (compatibility version 16.0.0, current version 16.0.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1319.0.0)
    /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
    ```
    set
        2
    set  
       345 天前
    类似的问题,编译后打包发到另一个没装 brew 的机器, 运行时提示找不到文件:
    dyld[11749]: Library not loaded: /opt/homebrew/opt/gmp/lib/libgmp.10.dylib
    Referenced from: <50730BE9-9AC0-373D-ABB4-791010CB96AF> /Users/jqt/portable-ruby/bin/ruby (built for macOS 14.0 which is newer than running OS)
    Reason: tried: '/opt/homebrew/opt/gmp/lib/libgmp.10.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/opt/homebrew/opt/gmp/lib/libgmp.10.dylib' (no such file), '/opt/homebrew/opt/gmp/lib/libgmp.10.dylib' (no such file)
    z
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     873 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 20:28 PVG 04:28 LAX 13:28 JFK 16:28
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86