Fix #1718: Add --header-output option to specify header file directory (#2161)

* Fix #1718: Add --header-output option to specify header file directory

- Add header_out field to BuildOptions struct
- Add header_file_dir field to BuildTarget struct
- Add --header-output command line option parsing with help text
- Modify header_gen() to use configured output directory instead of hardcoded root
- Add default behavior to use build directory when no custom path specified
- Add directory creation for header output paths
- Resolves issue where generated C headers were always output to root directory

* Fix directory creation timing for header output

- Move header output directory creation before header_gen() call
- Ensures custom header output directories are created before files are written
- Fixes issue where --header-output would fail if directory doesn't exist

* Fix style

* Fix Style

* Add to releasenotes.

---------

Co-authored-by: Christoffer Lerno <christoffer@aegik.com>
This commit is contained in:
Christian Brendlin
2025-05-30 10:19:46 +02:00
committed by GitHub
parent ae5a74bc41
commit e685414829
6 changed files with 28 additions and 2 deletions

View File

@@ -24,6 +24,7 @@
- Deprecate `f32`, `f64` and `f128` suffixes.
- Allow recursive generic modules.
- Add deprecation for `@param foo "abc"`.
- Add `--header-output` and `header-output` options for controlling header output folder.
### Fixes
- Assert triggered when casting from `int[2]` to `uint[2]` #2115

View File

@@ -562,6 +562,7 @@ typedef struct BuildOptions_
const char *output_dir;
const char *llvm_out;
const char *asm_out;
const char *header_out;
const char *obj_out;
const char *script_dir;
RelocModel reloc_model;
@@ -651,6 +652,7 @@ typedef struct
const char *output_dir;
const char *ir_file_dir;
const char *asm_file_dir;
const char *header_file_dir;
const char *script_dir;
const char *run_dir;
bool is_non_project;

View File

@@ -113,6 +113,7 @@ static void usage(bool full)
print_opt("--script-dir <dir>", "Override the base directory for $exec.");
print_opt("--llvm-out <dir>", "Override llvm output directory for '--emit-llvm'.");
print_opt("--asm-out <dir> ", "Override asm output directory for '--emit-asm'.");
print_opt("--header-output <dir>", "Override header file output directory when building libraries.");
print_opt("--emit-llvm", "Emit LLVM IR as a .ll file per module.");
print_opt("--emit-asm", "Emit asm as a .s file per module.");
print_opt("--obj", "Emit object files. (Enabled by default)");
@@ -1172,6 +1173,12 @@ static void parse_option(BuildOptions *options)
options->asm_out = next_arg();
return;
}
if (match_longopt("header-output"))
{
if (at_end() || next_is_opt()) error_exit("error: --header-output needs a directory.");
options->header_out = next_arg();
return;
}
if (match_longopt("lib"))
{
if (at_end() || next_is_opt()) error_exit("error: --lib needs a name.");

View File

@@ -494,6 +494,7 @@ static void update_build_target_from_options(BuildTarget *target, BuildOptions *
}
target->ir_file_dir = options->llvm_out;
target->asm_file_dir = options->asm_out;
target->header_file_dir = options->header_out;
target->object_file_dir = options->obj_out;
if (!target->ir_file_dir)
{
@@ -511,6 +512,10 @@ static void update_build_target_from_options(BuildTarget *target, BuildOptions *
{
target->object_file_dir = file_append_path(file_append_path(target->build_dir, "obj"), target_name);
}
if (!target->header_file_dir)
{
target->header_file_dir = target->output_dir ? target->output_dir : target->build_dir;
}
switch (options->compile_option)
{

View File

@@ -438,9 +438,12 @@ void compiler_compile(void)
{
error_exit("No module to compile.");
}
if (compiler.build.output_headers)
{
if (compiler.build.header_file_dir)
{
create_output_dir(compiler.build.header_file_dir);
}
header_gen(modules, module_count);
}

View File

@@ -765,7 +765,15 @@ void header_gen(Module **modules, unsigned module_count)
htable_init(&table1, 1024);
htable_init(&table2, 1024);
const char *name = build_base_name();
const char *filename = str_printf("%s.h", name);
const char *filename;
if (compiler.build.header_file_dir)
{
filename = file_append_path(compiler.build.header_file_dir, str_printf("%s.h", name));
}
else
{
filename = str_printf("%s.h", name);
}
FILE *file = fopen(filename, "w");
HeaderContext context = { .file = file, .gen_def = &table1, .gen_decl = &table2 };
HeaderContext *c = &context;