From 31096531e19534a551235e0c17d71d75ebc6b6eb Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Tue, 25 Feb 2025 14:05:00 +0100 Subject: [PATCH] Several fixes for .o files and -o output, improving handling and naming, checking for existence of sub-folders before output. Warning on using .o and -o output when not single module etc. Fix to static lib regression. Info about asm / llvm / obj output. --- lib7/std/io/path.c3 | 2 +- releasenotes.md | 1 + src/build/builder.c | 12 ++++++++---- src/compiler/codegen_general.c | 32 ++++++++++++++++++++++++++++++-- src/compiler/compiler.c | 20 ++++++++++++++++++-- src/compiler/compiler_internal.h | 1 + src/compiler/llvm_codegen.c | 2 +- 7 files changed, 60 insertions(+), 10 deletions(-) diff --git a/lib7/std/io/path.c3 b/lib7/std/io/path.c3 index 15ca8e34f..6e6547df0 100644 --- a/lib7/std/io/path.c3 +++ b/lib7/std/io/path.c3 @@ -201,7 +201,7 @@ fn Path! Path.tappend(self, String filename) => self.append(tmem(), filename); fn usz! start_of_base_name(String str, PathEnv path_env) @local { - if (!str.len) return PathResult.INVALID_PATH?; + if (!str.len) return 0; usz! start_slash = str.rindex_of_char('/'); if (path_env != PathEnv.WIN32) return start_slash + 1 ?? 0; if (try index = str.rindex_of_char('\\')) diff --git a/releasenotes.md b/releasenotes.md index 853509b15..02668a84a 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -24,6 +24,7 @@ - Correctly handle in/out when interacting with inout. - Don't delete .o files not produced by the compiler. - Fix optional jumps in expression lists, #1942. +- Several fixes for .o files and -o output, improving handling and naming. ### Stdlib changes diff --git a/src/build/builder.c b/src/build/builder.c index 1c6fb7e08..77b7b2e0f 100644 --- a/src/build/builder.c +++ b/src/build/builder.c @@ -314,7 +314,7 @@ static void update_build_target_from_options(BuildTarget *target, BuildOptions * break; case COMMAND_STATIC_LIB: target->type = TARGET_TYPE_STATIC_LIB; - target->single_module = true; + target->single_module = SINGLE_MODULE_ON; break; default: target->run_after_compile = false; @@ -504,9 +504,7 @@ static void update_build_target_from_options(BuildTarget *target, BuildOptions * } if (!target->object_file_dir) { - target->object_file_dir = options->build_dir - ? file_append_path(file_append_path(options->build_dir, "obj"), target_name) - : file_append_path("obj", target_name); + target->object_file_dir = file_append_path(file_append_path(target->build_dir, "obj"), target_name); } switch (options->compile_option) @@ -558,6 +556,11 @@ static void update_build_target_from_options(BuildTarget *target, BuildOptions * { target->emit_object_files = false; } + if (options->output_name && target->emit_object_files + && target->single_module != SINGLE_MODULE_ON && target->type == TARGET_TYPE_OBJECT_FILES) + { + error_exit("'-o' cannot be used when generating multiple output files, try using '--single-module=yes' to compile into a single object file."); + } for (int i = 0; i < options->lib_dir_count; i++) { vec_add(target->libdirs, options->lib_dir[i]); @@ -572,6 +575,7 @@ static void update_build_target_from_options(BuildTarget *target, BuildOptions * { target->link_libc = libc_from_arch_os(target->arch_os_target); } + } void init_default_build_target(BuildTarget *target, BuildOptions *options) diff --git a/src/compiler/codegen_general.c b/src/compiler/codegen_general.c index 06e0cc5cf..1dcf13141 100644 --- a/src/compiler/codegen_general.c +++ b/src/compiler/codegen_general.c @@ -288,16 +288,44 @@ AlignSize type_alloca_alignment(Type *type) return align; } +bool codegen_single_obj_output() +{ + if (!compiler.build.output_name) return false; + if (compiler.build.type != TARGET_TYPE_OBJECT_FILES) return false; + return compiler.build.single_module == SINGLE_MODULE_ON; +} + void codegen_setup_object_names(Module *module, const char **ir_filename, const char **asm_filename, const char **object_filename) { const char *result = module_create_object_file_name(module); + assert(compiler.build.object_file_dir); + if (codegen_single_obj_output()) + { + const char *ext = get_object_extension(); + if (!str_has_suffix(result, ext)) + { + result = str_printf("%s%s", result, ext); + } + compiler.obj_output = *object_filename = file_append_path(compiler.build.output_dir ? compiler.build.output_dir : ".", result); + char *dir_path = NULL; + char *filename = NULL; + file_get_dir_and_filename_from_full(compiler.obj_output, &filename, &dir_path); + if (dir_path && strlen(dir_path) && !file_is_dir(dir_path)) + { + error_exit("Can't output '%s', the directory '%s' could not be found.", compiler.obj_output, dir_path); + } + result = str_remove_suffix(filename, ext); + } + else + { + *object_filename = file_append_path(compiler.build.object_file_dir, str_printf("%s%s", result, get_object_extension())); + } + *ir_filename = str_printf(compiler.build.backend == BACKEND_LLVM ? "%s.ll" : "%s.ir", result); if (compiler.build.ir_file_dir) *ir_filename = file_append_path(compiler.build.ir_file_dir, *ir_filename); - *object_filename = str_printf("%s%s", result, get_object_extension()); if (compiler.build.emit_asm) { *asm_filename = str_printf("%s.s", result); if (compiler.build.asm_file_dir) *asm_filename = file_append_path(compiler.build.asm_file_dir, *asm_filename); } - if (compiler.build.object_file_dir) *object_filename = file_append_path(compiler.build.object_file_dir, *object_filename); } diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index 46d5266aa..07ab8e6c5 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -491,7 +491,6 @@ void compiler_compile(void) UNREACHABLE } compiler_ir_gen_time = bench_mark(); - const char *output_exe = NULL; const char *output_static = NULL; const char *output_dynamic = NULL; @@ -518,6 +517,12 @@ void compiler_compile(void) output_dynamic = dynamic_lib_name(); break; case TARGET_TYPE_OBJECT_FILES: + if (compiler.obj_output) + { + OUTF("Object file %s created.\n", compiler.obj_output); + break; + } + OUTF("Object files written to %s.\n", compiler.build.object_file_dir); break; case TARGET_TYPE_PREPARE: break; @@ -525,7 +530,14 @@ void compiler_compile(void) UNREACHABLE } } - + if (compiler.build.emit_llvm) + { + OUTF("LLVM files written to %s.\n", compiler.build.ir_file_dir); + } + if (compiler.build.emit_asm) + { + OUTF("Asm files written to %s.\n", compiler.build.asm_file_dir); + } free_arenas(); uint32_t output_file_count = vec_size(gen_contexts); @@ -537,6 +549,7 @@ void compiler_compile(void) cfiles_library += vec_size(lib->csources); } unsigned total_output = output_file_count + cfiles + cfiles_library + external_objfile_count; + if (total_output > MAX_OUTPUT_FILES) { error_exit("Too many output files."); @@ -1430,6 +1443,9 @@ const char *get_object_extension(void) { case ANY_WINDOWS_ARCH_OS: return ".obj"; + case WASM32: + case WASM64: + return ".wasm"; default: return ".o"; } diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 938609fca..d6706cd40 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -1876,6 +1876,7 @@ typedef struct PlatformTarget platform; Linking linking; GlobalContext context; + const char *obj_output; } CompilerState; extern CompilerState compiler; diff --git a/src/compiler/llvm_codegen.c b/src/compiler/llvm_codegen.c index a817916c8..621833c87 100644 --- a/src/compiler/llvm_codegen.c +++ b/src/compiler/llvm_codegen.c @@ -717,7 +717,7 @@ void gencontext_print_llvm_ir(GenContext *context) char *err = NULL; if (LLVMPrintModuleToFile(context->module, context->ir_filename, &err)) { - error_exit("Could not emit ir to file: %s", err); + error_exit("Could not emit ir '%s' to file: %s", context->ir_filename, err); } }