From aa9ad0ab1a8fbb0e25644e92ab0e515c37fd5a74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=82=8A=E3=81=99=E3=82=8A=E3=81=99/TwoSquirrels?= <47352965+TwoSquirrels@users.noreply.github.com> Date: Tue, 7 Jul 2026 10:09:43 +0900 Subject: [PATCH 1/2] fix: make -- the argument separator for compiler options MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit trailing_var_arg が 以降を無条件に拾っていたため、clap の last = true に置き換え、-- より後ろだけをコンパイラへ渡す。 の後ろに書いた risundle オプションも解釈されるようになり、 -- 無しのハイフン引数はエラーで弾かれる。 Closes #23 Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01TwiopnwyFnRbSUyNoFLWAZ --- src/cli.rs | 27 ++++++++++++++++++++++++++- tests/cli.rs | 23 +++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/src/cli.rs b/src/cli.rs index 9dda28d..884eded 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -38,7 +38,7 @@ pub struct BundleArgs { pub file: PathBuf, /// Extra options passed through to the compiler - #[arg(trailing_var_arg = true, allow_hyphen_values = true)] + #[arg(last = true)] pub options: Vec, } @@ -90,3 +90,28 @@ pub enum LibraryCommand { verbose: bool, }, } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn options_after_file_are_parsed_as_risundle_flags() { + let args = BundleArgs::try_parse_from(["risundle", "main.cpp", "-e"]).unwrap(); + assert!(args.embed); + assert!(args.options.is_empty()); + } + + #[test] + fn double_dash_separates_compiler_options() { + let args = + BundleArgs::try_parse_from(["risundle", "main.cpp", "--", "-std=gnu++20", "-O2"]) + .unwrap(); + assert_eq!(args.options, ["-std=gnu++20", "-O2"]); + } + + #[test] + fn hyphen_arguments_before_double_dash_are_rejected() { + assert!(BundleArgs::try_parse_from(["risundle", "main.cpp", "-O2"]).is_err()); + } +} diff --git a/tests/cli.rs b/tests/cli.rs index 109df67..6de1769 100644 --- a/tests/cli.rs +++ b/tests/cli.rs @@ -344,6 +344,29 @@ fn bundle_ignores_identifiers_in_comments_and_strings() { assert_eq!(compile_and_run(&sandbox, &bundled).trim(), "5"); } +#[test] +fn bundle_passes_options_after_double_dash_to_compiler() { + let sandbox = Sandbox::new(); + sandbox.write( + "main.cpp", + "#ifdef RISUNDLE_TEST_ANSWER\nint main() { return RISUNDLE_TEST_ANSWER; }\n\ + #else\n#error RISUNDLE_TEST_ANSWER is not defined\n#endif\n", + ); + + // -D が届かなければ #error でプリプロセスごと失敗するので、成功 = 受け渡しの証明。 + let output = sandbox + .risundle() + .args(["-k", STD, "main.cpp", "--", "-DRISUNDLE_TEST_ANSWER=0"]) + .output() + .expect("run bundle"); + assert!(output.status.success(), "bundle failed"); + let bundled = String::from_utf8(output.stdout).expect("utf-8"); + assert!( + bundled.contains("return 0"), + "-D で定義したマクロが展開されるべき" + ); +} + #[test] fn embed_includes_original_source_as_comment() { let sandbox = Sandbox::new(); From 925c8e4f1259fef8865cce02fb8d52f3f47fe888 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=82=8A=E3=81=99=E3=82=8A=E3=81=99/TwoSquirrels?= <47352965+TwoSquirrels@users.noreply.github.com> Date: Tue, 7 Jul 2026 10:17:58 +0900 Subject: [PATCH 2/2] refactor: address Copilot review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - options の help に -- を明記し、value_name を README の 表記に揃える - バンドル失敗時のアサートメッセージに stderr を含める (新テストと run_bundle ヘルパーの両方) Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01TwiopnwyFnRbSUyNoFLWAZ --- src/cli.rs | 4 ++-- tests/cli.rs | 12 ++++++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/cli.rs b/src/cli.rs index 884eded..d00e250 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -37,8 +37,8 @@ pub struct BundleArgs { /// C++ source file to bundle pub file: PathBuf, - /// Extra options passed through to the compiler - #[arg(last = true)] + /// Extra options after `--` passed straight to the compiler + #[arg(last = true, value_name = "COMPILER OPTIONS")] pub options: Vec, } diff --git a/tests/cli.rs b/tests/cli.rs index 6de1769..8316e6b 100644 --- a/tests/cli.rs +++ b/tests/cli.rs @@ -215,7 +215,11 @@ fn run_bundle(sandbox: &Sandbox, args: &[&str]) -> String { .arg("main.cpp") .output() .expect("run bundle"); - assert!(output.status.success(), "bundle failed"); + assert!( + output.status.success(), + "bundle failed: {}", + String::from_utf8_lossy(&output.stderr) + ); String::from_utf8(output.stdout).expect("utf-8") } @@ -359,7 +363,11 @@ fn bundle_passes_options_after_double_dash_to_compiler() { .args(["-k", STD, "main.cpp", "--", "-DRISUNDLE_TEST_ANSWER=0"]) .output() .expect("run bundle"); - assert!(output.status.success(), "bundle failed"); + assert!( + output.status.success(), + "bundle failed: {}", + String::from_utf8_lossy(&output.stderr) + ); let bundled = String::from_utf8(output.stdout).expect("utf-8"); assert!( bundled.contains("return 0"),