diff --git a/src/run.rs b/src/run.rs index 6d1b537..5f68e91 100644 --- a/src/run.rs +++ b/src/run.rs @@ -73,16 +73,16 @@ pub fn run(language: Language, program: &str) -> Result> if msvc { command = compiler.to_command(); - command_add_compiler_flags(&mut command, &variables); + command_add_compiler_flags(&mut command, &variables, msvc); command_add_output_file(&mut command, &output_path, msvc, compiler.is_like_clang()); command.arg(input_path.clone()); - command.envs(variables.clone()); + command_add_linker_flags_msvc(&mut command, &variables); } else { command = Command::new(compiler.path()); command.arg(input_path.clone()); // the input must come first command.args(compiler.args()); - command_add_compiler_flags(&mut command, &variables); + command_add_compiler_flags(&mut command, &variables, msvc); command_add_output_file(&mut command, &output_path, msvc, compiler.is_like_clang()); } @@ -159,24 +159,40 @@ fn command_add_output_file(command: &mut Command, output_path: &PathBuf, msvc: b } } -fn command_add_compiler_flags(command: &mut Command, variables: &HashMap) { - let get_env_flags = |env_name: &str| -> Vec { - variables - .get(env_name) - .map(|e| e.to_string()) - .ok_or_else(|| env::var(env_name)) - .unwrap_or_default() - .split_ascii_whitespace() - .map(|slice| slice.to_string()) - .collect() - }; - - command.args(get_env_flags("CFLAGS")); - command.args(get_env_flags("CPPFLAGS")); - command.args(get_env_flags("CXXFLAGS")); - - for linker_argument in get_env_flags("LDFLAGS") { - command.arg(format!("-Wl,{}", linker_argument)); +fn get_env_flags(variables: &HashMap, env_name: &str) -> Vec { + variables + .get(env_name) + .map(|e| e.to_string()) + .ok_or_else(|| env::var(env_name)) + .unwrap_or_default() + .split_ascii_whitespace() + .map(|slice| slice.to_string()) + .collect() +} + +fn command_add_compiler_flags( + command: &mut Command, + variables: &HashMap, + msvc: bool, +) { + command.args(get_env_flags(variables, "CFLAGS")); + command.args(get_env_flags(variables, "CPPFLAGS")); + command.args(get_env_flags(variables, "CXXFLAGS")); + + if !msvc { + for linker_argument in get_env_flags(variables, "LDFLAGS") { + command.arg(format!("-Wl,{}", linker_argument)); + } + } +} + +fn command_add_linker_flags_msvc(command: &mut Command, variables: &HashMap) { + let linker_flags = get_env_flags(variables, "LDFLAGS"); + if !linker_flags.is_empty() { + command.arg("/link"); + for linker_argument in linker_flags { + command.arg(linker_argument); + } } } @@ -184,6 +200,7 @@ fn command_add_compiler_flags(command: &mut Command, variables: &HashMap + + #include + + int main() { + ULONG_PTR stack_low_limit, stack_high_limit; + GetCurrentThreadStackLimits(&stack_low_limit, &stack_high_limit); + printf("%#llx", stack_high_limit-stack_low_limit); + + return 0; + } + "#, + ) + .unwrap() + .success() + .stdout(predicate::eq("0x40000").normalize()); + + remove_var("INLINE_C_RS_LDFLAGS"); + } else { + // Introduces a symbol using linker flags and builds a program that + // ODR uses that symbol. If the linker flags aren't set properly, + // there will be a linker error. + + set_var("INLINE_C_RS_LDFLAGS", "--defsym MY_SYMBOL=0x0"); + run( + Language::C, + r#" + #include + + extern void* MY_SYMBOL; + + int main() { + printf("%p", MY_SYMBOL); + return 0; + } + "#, + ) + .unwrap() + .success(); + + remove_var("INLINE_C_RS_LDFLAGS"); + } + } #[test] fn test_run_cxx() {