ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Spack 中的 Ruby 构建系统(RubyPackage)完全指南:从 gemspec 源码到预打包 gem 的安装

Spack 中的 Ruby 构建系统(RubyPackage)完全指南:从 gemspec 源码到预打包 gem 的安装 Spack 中的 Ruby 构建系统RubyPackage完全指南从 gemspec 源码到预打包 gem 的安装【免费下载链接】spackA flexible package manager that supports multiple versions, configurations, platforms, and compilers.项目地址: https://gitcode.com/GitHub_Trending/sp/spack导读本文深入讲解 Spack 中用于安装 Ruby gem 的构建系统——RubyPackage与RubyBuilder基类。你将掌握 Spack 如何通过build与install两个阶段分别处理*.gemspec源码包、Rakefile工程与预打包*.gem文件三类 Ruby 发行物学会在package.py中正确声明 Ruby 版本约束、显式列出 gem 依赖并理解 Spack 为何不能依赖gem的自动依赖下载行为。读完本文你可以独立完成一个 Ruby gem 包的 Spack 配方编写与构建系统判别。Ruby 构建系统概览Ruby 与 Perl、Python、R 一样拥有自己的包格式——Ruby gem。Spack 为这种生态提供了专门的构建系统支持RubyBuilder构建器类与RubyPackage包基类共同定义了 gem 的构建与安装流程。在 Spack 的配方模板体系中该基类被spack create工具引用为from spack_repo.builtin.build_systems.ruby import RubyPackage参见 lib/spack/spack/cmd/create.py 中RubyPackageTemplate的定义与 Autotools、CMake 等构建系统不同Ruby 包的构建不涉及configure、make这类流程而是完全围绕 RubyGems 的gem命令体系展开——gem build负责把源码打包成.gem文件gem install负责把.gem文件安装进目标环境。因此理解RubyPackage的核心就是理解 Spack 如何把这两个命令编排进自己的阶段phase模型。构建阶段Phasesbuild 与 installRubyBuilder和RubyPackage基类提供了两个可供子类覆盖override的阶段build—— 构建安装所需的一切内容install—— 从构建目录安装全部内容。这两个阶段的具体行为取决于源码包中携带的文件类型分为三种典型场景。场景一携带*.gemspec文件的源码包如果包源码根目录包含*.gemspec文件两个阶段依次执行$ gem build *.gemspec $ gem install *.gemgem build依据 gemspec 元数据名称、版本、文件清单、依赖等把源码编译打包为.gem文件gem install随后将其安装。场景二携带Rakefile的源码包如果包使用 Rake 作为任务执行器这是 Ruby 项目最常见的构建组织方式两个阶段变为$ rake package $ gem install *.gemrake package调用 Rakefile 中定义的打包任务通常是Gem::PackageTask产出.gem文件后再由gem install完成安装。场景三预打包的*.gem文件如果包直接以*.gem文件形式分发无源码则build 阶段被自动跳过只执行 install 阶段$ gem install *.gem上述这些都是标准的gem命令可以通过 RubyGems 自带的命令列表确认$ gem help commands下载预打包 gemexpandFalse对于只分发*.gem文件的包这类文件在version指令中可以使用expandFalse选项下载——即 Spack 下载后不进行解压展开version(1.2.3, sha256..., expandFalse)当使用expandFalse时Spack 不会把下载内容当作源码归档去猜测构建系统且build 阶段会被自动跳过直接进入gem install流程。从实现上印证Spack 的构建系统猜测逻辑会优先检查 URL 后缀凡是以.gem结尾的 URL 都会被直接判定为 ruby 构建系统见 lib/spack/spack/cmd/create.py 中_determine_build_system的.gem分支无需解包检查内容。如何判定一个包是 Ruby 包重要文件构建 Ruby 包前首先要能识别“这是一个 Ruby 包”。当从源码构建时Ruby 包可以通过以下任一文件的存在来识别*.gemspec—— gem 的元数据描述文件Rakefile—— Rake 任务定义文件setup.rb—— 传统 Ruby 安装脚本尚未支持注意此文件目前不会启用 Ruby 构建路径以外的行为实际支持以*.gemspec和Rakefile为准。这套判别规则在源码与测试中都有直接体现归档内容扫描线索create.py的构建系统猜测表按顺序匹配r/.*\.gemspec$、r/Rakefile$、r/setup\.rb$并将包标记为ruby见 lib/spack/spack/cmd/create.py测试用例验证build_system_guess测试逐一断言foo.gemspec、Rakefile、setup.rb均应猜测为 ruby 构建系统见 lib/spack/spack/test/build_system_guess.py。只有.gem发行物时怎么办并非所有 Ruby 包都以源码形式发布部分包只发布*.gem文件。这类文件本质上是一个打包容器内含源码、元数据与可执行文件可以用 RubyGems 自带的命令解包查看内容$ gem unpack *.gemgem unpack会把 gem 内容解压到当前目录方便你检查其中的 gemspec 与源码结构——这也是确认此类包真实依赖的最直接手段。编写 package.pyDescription 与 Homepage为 Ruby 包编写 Spack 配方时包描述description与主页homepage两个元数据字段应直接取自 gemspec 文件。Description描述*.gemspec文件中通常包含类似以下内容summary An implementation of the AsciiDoc text processor and publishing toolchain description A fast, open source text processor and publishing toolchain for converting AsciiDoc content to HTML 5, DocBook 5, and other formats.summary与description任一字段都可以用作 Spack 包的description。推荐优先使用更详尽的description字段它能让spack info输出与文档检索结果更具信息量。Homepage主页*.gemspec文件中的homepage字段应作为 Spack 包的主页homepage https://asciidoctor.org对应在package.py中homepage https://asciidoctor.org构建系统依赖extends(ruby) 与版本约束所有 Ruby 包在构建期和运行期都要求 Ruby 可用。基于这一硬性要求RubyPackage基类内置了extends(ruby)extends是 Spack 的扩展机制声明它表明该包是 Ruby 的一个扩展extension安装后可以“激活”activate到 Ruby 的安装前缀中从而让 gem 对 Ruby 可见。这意味着编写 Ruby 包配方时无需再手动声明通用的depends_on(ruby)——基类已隐式处理。如果 gemspec 对 Ruby 版本有下限要求例如required_ruby_version 2.3.0则应显式添加版本约束的依赖depends_on(ruby2.3.0:, type(build, run))type(build, run)表示该依赖在构建阶段执行gem build/gem install时与运行阶段使用已安装 gem 时都必需。这一约定同样体现在 Spack 的配方生成模板中RubyPackageTemplate生成的dependencies注释明确提示——只有当需要特定 Ruby 版本时才追加depends_on(rubyX.Y.Z:)通用 Ruby 依赖已由RubyPackage类隐式添加见 lib/spack/spack/cmd/create.py 的RubyPackageTemplate.dependencies。Ruby 依赖管理为什么必须显式列出全部依赖使用gem install安装包时gem 会读取*.gemspec来确定包的依赖若依赖尚未安装gem 会自动联网下载并安装它们。这听起来很方便但Spack 不能依赖这种自动行为原因有二原因一支持离线air-gapped网络环境安装Spack 需要能够在完全断网的内网环境中安装包。如果没有互联网连接gem将无法下载缺失的依赖。通过在package.py中显式列出每一个依赖Spack 可以在构建开始前就得知完整依赖集合提前完成源码获取与调度从而保证离线可用。原因二避免同一依赖的重复安装Spack 支持 Ruby 扩展的activation激活机制——将包的安装前缀符号链接到 Ruby 的安装前缀下。若配方遗漏了某个依赖gem 会把这个依赖安装到当前包的安装目录中而非独立目录。之后当你尝试“激活 包 依赖”的组合时如果该依赖此前已被激活过就会引发冲突——同一依赖存在两份、两个来源激活行为互相干扰。在 gemspec 中寻找真实的依赖线索因此编写 Ruby 包配方时必须始终显式列出所有依赖。官方文档或 README 往往只面向使用gem的普通用户开发者常假设用户不必关心依赖细节所以不要只看文档务必检查*.gemspec文件找出真实依赖。重点留意以下三类线索gemspec 方法含义Spack 处理方式add_runtime_dependency安装时必需的运行时依赖必须添加为包的依赖add_dependencyadd_runtime_dependency的别名同样必须添加add_development_dependency仅供开发使用的可选依赖测试、构建工具等不应添加为包的依赖例如 gemspec 中出现spec.add_runtime_dependency nokogiri, 1.10 spec.add_development_dependency rspec, ~ 3.0对应package.py中应声明nokogiri运行时依赖而rspec这类开发依赖应忽略with default_args(type(build, run)): depends_on(ruby-nokogiri)只有逐个核对 gemspec才能保证离线可装、激活无冲突。用spack create快速生成 Ruby 包骨架Spack 提供了交互式配方生成器可直接产出符合规范的 Ruby 包骨架。当 URL 以.gem结尾或解包后的归档中出现*.gemspec、Rakefile、setup.rb时Spack 会自动选择 ruby 构建系统判别顺序与正则见 lib/spack/spack/cmd/create.py 的_determine_build_system。生成后RubyPackageTemplate还会自动为包名加上ruby-前缀除非用户已显式指定符合 Ruby 包的命名惯例参见 lib/spack/spack/cmd/create.py 中RubyPackageTemplate.__init__的改名逻辑。生成的骨架默认包含class RubyFoo(Package): ... extends(ruby) # 由基类隐式提供 # FIXME: 仅在需要特定 Ruby 版本时追加 # depends_on(rubyX.Y.Z:) def build(self, spec, prefix): pass # 不需要时删除小结Spack 的 Ruby 构建系统通过RubyPackage/RubyBuilder把 RubyGems 生态纳入统一的阶段化构建模型*.gemspec源码包走gem build→gem installRakefile工程走rake package→gem install纯*.gem发行物则直接gem install并跳过构建。判定 Ruby 包可依据*.gemspec、Rakefile等标志文件Spack 的构建系统猜测逻辑与测试用例均对此有明确覆盖配方编写时需继承extends(ruby)的隐式 Ruby 依赖、按需添加depends_on(rubyX.Y.Z:)版本约束并坚持逐个核对 gemspec、显式声明全部运行时依赖从而保证离线安装能力与 activation 机制的正确性。更多关于 Ruby 打包的规范细节gemspec 编写、依赖声明语法等可进一步查阅 RubyGems 官方打包指南。【免费下载链接】spackA flexible package manager that supports multiple versions, configurations, platforms, and compilers.项目地址: https://gitcode.com/GitHub_Trending/sp/spack创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表