From 4aa3aec4ff5a79d898a51b229f2a633ea96a4474 Mon Sep 17 00:00:00 2001 From: Volkan Date: Fri, 9 Feb 2024 07:58:23 +0100 Subject: [PATCH] fix(linker): Avoid filename clashes when linking (#1086) Append .o extension to end of file name instead of replacing previous extension --- compiler/plc_driver/src/pipelines.rs | 10 +++++----- tests/integration/data/linking/consts.dt | 0 tests/integration/data/linking/consts.st | 3 +++ tests/integration/linking.rs | 12 ++++++++++++ 4 files changed, 20 insertions(+), 5 deletions(-) create mode 100644 tests/integration/data/linking/consts.dt diff --git a/compiler/plc_driver/src/pipelines.rs b/compiler/plc_driver/src/pipelines.rs index fb4414192f..c1e9b40489 100644 --- a/compiler/plc_driver/src/pipelines.rs +++ b/compiler/plc_driver/src/pipelines.rs @@ -312,7 +312,7 @@ impl AnnotatedProject { let current_dir = env::current_dir()?; let current_dir = compile_options.root.as_deref().unwrap_or(¤t_dir); let unit_location = PathBuf::from(&unit.file_name); - let unit_location = std::fs::canonicalize(unit_location)?; + let unit_location = fs::canonicalize(unit_location)?; let output_name = if unit_location.starts_with(current_dir) { unit_location.strip_prefix(current_dir).map_err(|it| { Diagnostic::error(format!( @@ -329,9 +329,9 @@ impl AnnotatedProject { }; let output_name = match compile_options.output_format { - FormatOption::IR => output_name.with_extension("ll"), - FormatOption::Bitcode => output_name.with_extension("bc"), - _ => output_name.with_extension("o"), + FormatOption::IR => format!("{}.ll", output_name.to_string_lossy()), + FormatOption::Bitcode => format!("{}.bc", output_name.to_string_lossy()), + _ => format!("{}.o", output_name.to_string_lossy()), }; let context = CodegenContext::create(); //Create a build location for the generated object files @@ -340,7 +340,7 @@ impl AnnotatedProject { module .persist( Some(&compile_directory), - &output_name.to_string_lossy(), + &output_name, compile_options.output_format, target, compile_options.optimization, diff --git a/tests/integration/data/linking/consts.dt b/tests/integration/data/linking/consts.dt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/integration/data/linking/consts.st b/tests/integration/data/linking/consts.st index 17e9c05522..d0e500449e 100644 --- a/tests/integration/data/linking/consts.st +++ b/tests/integration/data/linking/consts.st @@ -1,3 +1,6 @@ VAR_GLOBAL CONSTANT myValue : BOOL := TRUE; END_VAR + +FUNCTION main : DINT +END_FUNCTION diff --git a/tests/integration/linking.rs b/tests/integration/linking.rs index bd0d42fe6b..fd8e5cd3e4 100644 --- a/tests/integration/linking.rs +++ b/tests/integration/linking.rs @@ -225,3 +225,15 @@ fn link_files_with_same_name() { //Delete it fs::remove_file(&out1).unwrap(); } + +#[test] +fn link_files_with_same_name_but_different_extension() { + let file1 = get_test_file("linking/consts.st"); + let file2 = get_test_file("linking/consts.dt"); + + // We want to make sure that generating object files for two or more files with the same name but different + // extensions works. Previously this would fail because both `const.st` and `const.dt` would persist to a + // `const.o` file, which causes linking issues and more specifically "duplicate symbol" errors. Hence we only + // check whether the compilation resulted in some Ok value here. + assert!(compile(&["plc", file1.as_str(), file2.as_str(), "--target", TARGET.unwrap()]).is_ok()); +}