From 9b0aaf6e51a5a07f30e11e5f64fdf9f62b101d3f Mon Sep 17 00:00:00 2001 From: Maxim Samsonov Date: Sun, 2 Mar 2025 23:52:53 +0300 Subject: [PATCH] chore: move a call of finalize script from CMake script to Ruby --- CMakeLists.txt | 2 +- exe/tebako-packager | 15 ---- lib/tebako/cli_helpers.rb | 7 ++ lib/tebako/options_manager.rb | 4 + lib/tebako/scenario_manager.rb | 8 ++ spec/cli_helpers_spec.rb | 146 +++++++++++++++++++++++++++++++++ spec/options_manager_spec.rb | 35 +++++++- spec/scenario_manager_spec.rb | 64 +++++++++++++++ 8 files changed, 262 insertions(+), 19 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f3110efd..0ba10046 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -436,7 +436,7 @@ if (${SETUP_MODE}) add_dependencies(tebako-fs packaged_filesystem) - add_custom_target(tebako COMMAND ruby ${EXE}/tebako-packager finalize ${RUBY_SOURCE_DIR} ${APP_NAME} ${RUBY_VER} ${DEPS_BIN_DIR}/patchelf ${WITH_PATCHELF}) + add_custom_target(tebako COMMAND ${CMAKE_COMMAND} -E true) add_dependencies(tebako setup tebako-fs) endif(${SETUP_MODE}) diff --git a/exe/tebako-packager b/exe/tebako-packager index a1ec6cb8..b4fa0572 100755 --- a/exe/tebako-packager +++ b/exe/tebako-packager @@ -67,21 +67,6 @@ begin Tebako::Packager.pass1a(ARGV[2]) Tebako::Packager.stash(ARGV[4], ARGV[5], ARGV[2], ruby_ver) Tebako::Packager.pass2(ARGV[1], ARGV[2], ARGV[3], ruby_ver) - - when "finalize" - # ARGV[0] -- command - # ARGV[1] -- RUBY_SOURCE_DIR - # ARGV[2] -- APP_NAME - # ARGV[3] -- RUBY_VER - # ARGV[4] -- patchelf executable - # ARGV[5] -- WITH_PATHELF - unless ARGV.length == 6 - raise Tebako::Error, - "tebako-packager finalize command expects 6 arguments, #{ARGV.length} has been provided." - end - ruby_ver = Tebako::RubyVersion.new(ARGV[3]) - with_patchelf = ARGV[5].casecmp("ON").zero? || ARGV[5].casecmp("YES").zero? - Tebako::Packager.finalize(ARGV[1], ARGV[2], ruby_ver, with_patchelf ? ARGV[4] : nil) else raise Tebako::Error, "tebako-packager cannot process #{ARGV[0]} command" end diff --git a/lib/tebako/cli_helpers.rb b/lib/tebako/cli_helpers.rb index d01ffcdc..7d72b0ae 100644 --- a/lib/tebako/cli_helpers.rb +++ b/lib/tebako/cli_helpers.rb @@ -103,6 +103,7 @@ def do_press_runtime(options_manager, scenario_manager) merged_env = ENV.to_h.merge(scenario_manager.b_env) Tebako.packaging_error(103) unless system(merged_env, press_cfg_cmd(options_manager)) Tebako.packaging_error(104) unless system(merged_env, press_build_cmd(options_manager)) + finalize(options_manager, scenario_manager) end def do_setup(options_manager) @@ -126,6 +127,12 @@ def generate_files(options_manager, scenario_manager) Tebako::Codegen.generate_stub_rb(options_manager) end + def finalize(options_manager, scenario_manager) + use_patchelf = options_manager.patchelf? && scenario_manager.linux_gnu? + patchelf = use_patchelf ? "#{options_manager.deps_bin_dir}/patchelf" : nil + Tebako::Packager.finalize(options_manager.ruby_src_dir, options_manager.package, options_manager.rv, patchelf) + end + def options_from_tebafile(tebafile) ::YAML.load_file(tebafile)["options"] || {} rescue Psych::SyntaxError => e diff --git a/lib/tebako/options_manager.rb b/lib/tebako/options_manager.rb index a65e1ed8..629abe7d 100644 --- a/lib/tebako/options_manager.rb +++ b/lib/tebako/options_manager.rb @@ -180,6 +180,10 @@ def package_within_root? folder_within_root?(package) end + def patchelf? + @options["patchelf"] + end + def prefix @prefix ||= if @options["prefix"].nil? handle_nil_prefix diff --git a/lib/tebako/scenario_manager.rb b/lib/tebako/scenario_manager.rb index 83117e53..8ba73c27 100644 --- a/lib/tebako/scenario_manager.rb +++ b/lib/tebako/scenario_manager.rb @@ -66,6 +66,14 @@ def linux? @linux end + def linux_gnu? + @linux && !@musl + end + + def linux_musl? + @linux && @musl + end + def m_files # [TODO] # Ninja generates incorrect script for tebako press target -- gets lost in a chain custom targets diff --git a/spec/cli_helpers_spec.rb b/spec/cli_helpers_spec.rb index 619e91ae..2eb78c4a 100644 --- a/spec/cli_helpers_spec.rb +++ b/spec/cli_helpers_spec.rb @@ -78,6 +78,7 @@ allow(self).to receive(:system).and_return(true) allow(Tebako::Codegen).to receive(:generate_tebako_version_h).and_return(true) allow(Tebako::Codegen).to receive(:generate_tebako_fs_cpp).and_return(true) + allow(Tebako::Packager).to receive(:finalize) expect { do_press(options_manager) }.not_to raise_error end @@ -102,6 +103,7 @@ allow(Tebako::Codegen).to receive(:generate_tebako_version_h).and_return(true) allow(Tebako::Codegen).to receive(:generate_tebako_fs_cpp).and_return(true) allow(Tebako::Codegen).to receive(:generate_package_header).and_return(true) + allow(Tebako::Packager).to receive(:finalize) expect { do_press(options_manager) }.not_to raise_error end @@ -127,6 +129,7 @@ allow(Tebako::Codegen).to receive(:generate_tebako_version_h).and_return(true) allow(Tebako::Codegen).to receive(:generate_tebako_fs_cpp).and_return(true) allow(Tebako::Codegen).to receive(:generate_package_header).and_return(true) + allow(Tebako::Packager).to receive(:finalize) allow(self).to receive(:sleep).with(any_args).and_return(nil) expect { do_press(options_manager) }.to output(/WARNING/).to_stdout @@ -211,6 +214,149 @@ end end + describe "#finalize" do + let(:options_manager) { Tebako::OptionsManager.new(options) } + let(:scenario_manager) { Tebako::ScenarioManager.new(options_manager.root, options_manager.fs_entrance) } + let(:patchelf_path) { File.join(options_manager.deps_bin_dir, "patchelf") } + + before do + allow(Tebako::Packager).to receive(:finalize) + end + + context "when patchelf is enabled and running on GNU/Linux" do + before do + options["patchelf"] = true + allow(scenario_manager).to receive(:linux_gnu?).and_return(true) + end + + it "calls Packager.finalize with patchelf path" do + expect(Tebako::Packager).to receive(:finalize).with( + options_manager.ruby_src_dir, + options_manager.package, + options_manager.rv, + patchelf_path + ) + finalize(options_manager, scenario_manager) + end + end + + context "when patchelf is disabled" do + before do + options["patchelf"] = false + allow(scenario_manager).to receive(:linux_gnu?).and_return(true) + end + + it "calls Packager.finalize without patchelf path" do + expect(Tebako::Packager).to receive(:finalize).with( + options_manager.ruby_src_dir, + options_manager.package, + options_manager.rv, + nil + ) + finalize(options_manager, scenario_manager) + end + end + + context "when not running on GNU/Linux" do + before do + options["patchelf"] = true + allow(scenario_manager).to receive(:linux_gnu?).and_return(false) + end + + it "calls Packager.finalize without patchelf path" do + expect(Tebako::Packager).to receive(:finalize).with( + options_manager.ruby_src_dir, + options_manager.package, + options_manager.rv, + nil + ) + finalize(options_manager, scenario_manager) + end + end + end + + describe "#do_press_runtime" do + let(:options_manager) { Tebako::OptionsManager.new(options) } + let(:scenario_manager) { Tebako::ScenarioManager.new(options_manager.root, options_manager.fs_entrance) } + + before do + allow(Tebako::Codegen).to receive(:generate_tebako_version_h) + allow(Tebako::Codegen).to receive(:generate_tebako_fs_cpp) + allow(Tebako::Codegen).to receive(:generate_deploy_rb) + allow(Tebako::Codegen).to receive(:generate_stub_rb) + allow(self).to receive(:system).and_return(true) + allow(self).to receive(:finalize) + end + + context "when mode is 'both'" do + before { options["mode"] = "both" } + + it "generates files and executes commands" do + expect(Tebako::Codegen).to receive(:generate_tebako_version_h) + expect(Tebako::Codegen).to receive(:generate_tebako_fs_cpp) + expect(Tebako::Codegen).to receive(:generate_deploy_rb) + expect(Tebako::Codegen).to receive(:generate_stub_rb) + expect(self).to receive(:system).exactly(2).times.and_return(true) + expect(self).to receive(:finalize) + do_press_runtime(options_manager, scenario_manager) + end + end + + context "when mode is 'runtime'" do + before { options["mode"] = "runtime" } + + it "generates files and executes commands" do + expect(Tebako::Codegen).to receive(:generate_tebako_version_h) + expect(Tebako::Codegen).to receive(:generate_tebako_fs_cpp) + expect(Tebako::Codegen).to receive(:generate_deploy_rb) + expect(Tebako::Codegen).to receive(:generate_stub_rb) + expect(self).to receive(:system).exactly(2).times.and_return(true) + expect(self).to receive(:finalize) + do_press_runtime(options_manager, scenario_manager) + end + end + + context "when mode is 'bundle'" do + before { options["mode"] = "bundle" } + + it "generates files and executes commands" do + expect(Tebako::Codegen).to receive(:generate_tebako_version_h) + expect(Tebako::Codegen).to receive(:generate_tebako_fs_cpp) + expect(Tebako::Codegen).to receive(:generate_deploy_rb) + expect(Tebako::Codegen).not_to receive(:generate_stub_rb) + expect(self).to receive(:system).exactly(2).times.and_return(true) + expect(self).to receive(:finalize) + do_press_runtime(options_manager, scenario_manager) + end + end + + context "when mode is 'application'" do + before { options["mode"] = "application" } + + it "returns early without doing anything" do + expect(Tebako::Codegen).not_to receive(:generate_tebako_version_h) + expect(self).not_to receive(:system) + expect(self).not_to receive(:finalize) + do_press_runtime(options_manager, scenario_manager) + end + end + + context "when system commands fail" do + before { options["mode"] = "bundle" } + + it "raises error when press_cfg_cmd fails" do + allow(self).to receive(:system).and_return(false) + expect { do_press_runtime(options_manager, scenario_manager) }.to raise_error(Tebako::Error) + end + + it "raises error when press_build_cmd fails" do + allow(self).to receive(:system).with(anything, press_cfg_cmd(options_manager)).and_return(true) + allow(self).to receive(:system).with(anything, press_build_cmd(options_manager)).and_return(false) + expect { do_press_runtime(options_manager, scenario_manager) }.to raise_error(Tebako::Error) + end + end + end + describe "#options_from_tebafile" do let(:tebafile) { "spec/fixtures/tebafile.yml" } diff --git a/spec/options_manager_spec.rb b/spec/options_manager_spec.rb index b6bcac2e..d72b6dd2 100644 --- a/spec/options_manager_spec.rb +++ b/spec/options_manager_spec.rb @@ -217,9 +217,9 @@ expect(options_manager.package).to eq(File.expand_path("custom_package")) end - context "with Windows-style paths" do - let(:options) { { "output" => "C:/path/to/package" } } - + # requires platform to have cygpath + context "with Windows-style paths", if: Gem.win_platform? do + let(:options) { { "output" => "C:\\path\\to\\package" } } it "converts backslashes to forward slashes" do expect(options_manager.package).to eq("C:/path/to/package") end @@ -725,6 +725,35 @@ end end + describe "#patchelf?" do + context "when patchelf option is set to true" do + let(:options) { { "patchelf" => true } } + let(:options_manager) { Tebako::OptionsManager.new(options) } + + it "returns true" do + expect(options_manager.patchelf?).to be true + end + end + + context "when patchelf option is set to false" do + let(:options) { { "patchelf" => false } } + let(:options_manager) { Tebako::OptionsManager.new(options) } + + it "returns false" do + expect(options_manager.patchelf?).to be false + end + end + + context "when patchelf option is not set" do + let(:options) { {} } + let(:options_manager) { Tebako::OptionsManager.new(options) } + + it "returns nil" do + expect(options_manager.patchelf?).to be_nil + end + end + end + describe "#stash_dir" do let(:options_manager) { Tebako::OptionsManager.new({}) } let(:fake_deps) { "/fake/deps" } diff --git a/spec/scenario_manager_spec.rb b/spec/scenario_manager_spec.rb index c1d9fb02..7b7b84e6 100644 --- a/spec/scenario_manager_spec.rb +++ b/spec/scenario_manager_spec.rb @@ -254,6 +254,70 @@ end end + describe "#linux_gnu?" do + context "when running on GNU/Linux" do + before do + stub_const("RUBY_PLATFORM", "x86_64-linux-gnu") + end + + it "returns true" do + expect(scenario_manager.linux_gnu?).to be true + end + end + + context "when running on Linux musl" do + before do + stub_const("RUBY_PLATFORM", "x86_64-linux-musl") + end + + it "returns false" do + expect(scenario_manager.linux_gnu?).to be false + end + end + + context "when not running on Linux" do + before do + stub_const("RUBY_PLATFORM", "darwin") + end + + it "returns false" do + expect(scenario_manager.linux_gnu?).to be false + end + end + end + + describe "#linux_musl?" do + context "when running on Linux musl" do + before do + stub_const("RUBY_PLATFORM", "x86_64-linux-musl") + end + + it "returns true" do + expect(scenario_manager.linux_musl?).to be true + end + end + + context "when running on GNU/Linux" do + before do + stub_const("RUBY_PLATFORM", "x86_64-linux-gnu") + end + + it "returns false" do + expect(scenario_manager.linux_musl?).to be false + end + end + + context "when not running on Linux" do + before do + stub_const("RUBY_PLATFORM", "darwin") + end + + it "returns false" do + expect(scenario_manager.linux_musl?).to be false + end + end + end + describe "#macos?" do context "when running on macOS" do before do