Skip to content

Commit 912b156

Browse files
Fix command-line argument handling for static library builds
Use argc/argv directly instead of std::env::args() because when built as a static library, the Rust runtime isn't properly initialized and std::env::args() returns an empty list. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent c1d5baf commit 912b156

File tree

1 file changed

+23
-13
lines changed

1 file changed

+23
-13
lines changed

src/lib.rs

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -957,30 +957,40 @@ static HOSTED_FNS: [HostedFn; 27] = [
957957
];
958958

959959
/// Build a RocList<RocStr> from command-line arguments.
960-
fn build_args_list(roc_ops: &RocOps) -> RocList<RocStr> {
961-
let args: Vec<String> = std::env::args().collect();
962-
963-
if args.is_empty() {
960+
///
961+
/// Uses argc/argv directly instead of std::env::args() because when built
962+
/// as a static library, the Rust runtime isn't properly initialized.
963+
fn build_args_list(argc: i32, argv: *const *const i8, roc_ops: &RocOps) -> RocList<RocStr> {
964+
if argc <= 0 || argv.is_null() {
964965
return RocList::empty();
965966
}
966967

967-
let mut list = RocList::with_capacity(args.len(), roc_ops);
968-
for arg in args {
969-
let roc_str = RocStr::from_str(&arg, roc_ops);
970-
list.push(roc_str, roc_ops);
968+
let mut list = RocList::with_capacity(argc as usize, roc_ops);
969+
970+
for i in 0..argc as isize {
971+
unsafe {
972+
let arg_ptr = *argv.offset(i);
973+
if arg_ptr.is_null() {
974+
break;
975+
}
976+
let c_str = std::ffi::CStr::from_ptr(arg_ptr);
977+
let arg = c_str.to_string_lossy();
978+
let roc_str = RocStr::from_str(&arg, roc_ops);
979+
list.push(roc_str, roc_ops);
980+
}
971981
}
972982
list
973983
}
974984

975985
/// C-compatible main entry point for the Roc program.
976986
/// This is exported so the linker can find it.
977987
#[no_mangle]
978-
pub extern "C" fn main(_argc: i32, _argv: *const *const i8) -> i32 {
979-
rust_main()
988+
pub extern "C" fn main(argc: i32, argv: *const *const i8) -> i32 {
989+
rust_main(argc, argv)
980990
}
981991

982992
/// Main entry point for the Roc program.
983-
pub fn rust_main() -> i32 {
993+
pub fn rust_main(argc: i32, argv: *const *const i8) -> i32 {
984994
// Create the RocOps struct with all callbacks
985995
// We Box it to ensure stable memory address
986996
let roc_ops = Box::new(RocOps {
@@ -997,8 +1007,8 @@ pub fn rust_main() -> i32 {
9971007
},
9981008
});
9991009

1000-
// Build List(Str) from command-line arguments
1001-
let args_list = build_args_list(&roc_ops);
1010+
// Build List(Str) from command-line arguments (using argc/argv directly)
1011+
let args_list = build_args_list(argc, argv, &roc_ops);
10021012

10031013
// Call the Roc main function
10041014
let mut exit_code: i32 = -99;

0 commit comments

Comments
 (0)