From 85657c9200942097ed4d9937908d5cc3019403b8 Mon Sep 17 00:00:00 2001 From: Savino Pio Liguori <8lall0@users.noreply.github.com> Date: Sun, 7 Dec 2025 00:07:54 +0100 Subject: [PATCH] Added "implement-libc" feature. (#2564) This feature adds an option from project.json and build options to disable libc unreachable statements in order to be able to implement one for yourself. Useful feature for bare metal developing. --------- Co-authored-by: Christoffer Lerno --- lib/std/core/env.c3 | 3 ++- lib/std/libc/libc.c3 | 2 +- releasenotes.md | 1 + src/build/build.h | 10 ++++++++++ src/build/build_options.c | 7 +++++++ src/build/builder.c | 1 + src/build/project.c | 5 +++++ src/build/project_manipulation.c | 2 ++ src/compiler/compiler.c | 1 + src/compiler/compiler_internal.h | 5 +++++ 10 files changed, 35 insertions(+), 2 deletions(-) diff --git a/lib/std/core/env.c3 b/lib/std/core/env.c3 index acdfc17da..1b609bfda 100644 --- a/lib/std/core/env.c3 +++ b/lib/std/core/env.c3 @@ -124,7 +124,8 @@ const usz MAX_VECTOR_SIZE = $$MAX_VECTOR_SIZE; const bool ARCH_32_BIT = $$REGISTER_SIZE == 32; const bool ARCH_64_BIT = $$REGISTER_SIZE == 64; const bool LIBC = $$COMPILER_LIBC_AVAILABLE; -const bool NO_LIBC = !$$COMPILER_LIBC_AVAILABLE; +const bool NO_LIBC = !LIBC && !CUSTOM_LIBC; +const bool CUSTOM_LIBC = $$CUSTOM_LIBC; const CompilerOptLevel COMPILER_OPT_LEVEL = CompilerOptLevel.from_ordinal($$COMPILER_OPT_LEVEL); const bool BIG_ENDIAN = $$PLATFORM_BIG_ENDIAN; const bool I128_NATIVE_SUPPORT = $$PLATFORM_I128_SUPPORTED; diff --git a/lib/std/libc/libc.c3 b/lib/std/libc/libc.c3 index b879f676b..eb73d570a 100644 --- a/lib/std/libc/libc.c3 +++ b/lib/std/libc/libc.c3 @@ -258,7 +258,7 @@ macro CFile stdin() { return (CFile*)(uptr)STDIN_FD; } macro CFile stdout() { return (CFile*)(uptr)STDOUT_FD; } macro CFile stderr() { return (CFile*)(uptr)STDERR_FD; } -module libc @if(!env::LIBC); +module libc @if(env::NO_LIBC); import std::core::mem; diff --git a/releasenotes.md b/releasenotes.md index 46d72e9bc..4424ff3df 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -4,6 +4,7 @@ ## 0.7.9 Change list ### Changes / improvements +- Add `--custom-libc` option for custom libc implementations. ### Fixes - Regression with npot vector in struct triggering an assert #2219. diff --git a/src/build/build.h b/src/build/build.h index 215ca6627..9dc026f8a 100644 --- a/src/build/build.h +++ b/src/build/build.h @@ -237,6 +237,13 @@ typedef enum USE_STDLIB_ON = 1 } UseStdlib; +typedef enum +{ + CUSTOM_LIBC_NOT_SET = -1, + CUSTOM_LIBC_OFF = 0, + CUSTOM_LIBC_ON = 1 +} CustomLibc; + typedef enum { SHOW_BACKTRACE_NOT_SET = -1, @@ -609,6 +616,7 @@ typedef struct BuildOptions_ FpOpt fp_math; EmitStdlib emit_stdlib; UseStdlib use_stdlib; + CustomLibc custom_libc; LinkLibc link_libc; StripUnused strip_unused; OptimizationLevel optlevel; @@ -750,6 +758,7 @@ typedef struct UseStdlib use_stdlib; EmitStdlib emit_stdlib; LinkLibc link_libc; + CustomLibc custom_libc; ShowBacktrace show_backtrace; StripUnused strip_unused; DebugInfo debug_info; @@ -858,6 +867,7 @@ static BuildTarget default_build_target = { .use_stdlib = USE_STDLIB_NOT_SET, .link_libc = LINK_LIBC_NOT_SET, .emit_stdlib = EMIT_STDLIB_NOT_SET, + .custom_libc = CUSTOM_LIBC_NOT_SET, .linker_type = LINKER_TYPE_NOT_SET, .validation_level = VALIDATION_NOT_SET, .single_module = SINGLE_MODULE_NOT_SET, diff --git a/src/build/build_options.c b/src/build/build_options.c index becb169da..a070f24fb 100644 --- a/src/build/build_options.c +++ b/src/build/build_options.c @@ -167,6 +167,7 @@ static void usage(bool full) PRINTF(""); print_opt("--use-stdlib=", "Include the standard library (default: yes)."); print_opt("--link-libc=", "Link libc other default libraries (default: yes)."); + print_opt("--custom-libc=", "Set to true if a custom libc implementation is provided (default: no)."); print_opt("--emit-stdlib=", "Output files for the standard library. (default: yes)"); print_opt("--emit-only ", "Output only the file matching ."); print_opt("--panicfn ", "Override the panic function name."); @@ -948,6 +949,11 @@ static void parse_option(BuildOptions *options) options->emit_stdlib = parse_opt_select(EmitStdlib, argopt, on_off); return; } + if ((argopt = match_argopt("custom-libc"))) + { + options->custom_libc = parse_opt_select(CustomLibc, argopt, on_off); + return; + } if (match_longopt("emit-only")) { if (at_end() || next_is_opt()) error_exit("error: --emit-only expects an output name, e.g. 'foo', to only output 'foo.o'."); @@ -1489,6 +1495,7 @@ BuildOptions parse_arguments(int argc, const char *argv[]) .win.crt_linking = WIN_CRT_DEFAULT, .emit_stdlib = EMIT_STDLIB_NOT_SET, .link_libc = LINK_LIBC_NOT_SET, + .custom_libc = CUSTOM_LIBC_NOT_SET, .use_stdlib = USE_STDLIB_NOT_SET, .arch_os_target_override = ARCH_OS_TARGET_DEFAULT, .linker_type = LINKER_TYPE_NOT_SET, diff --git a/src/build/builder.c b/src/build/builder.c index b3a71265c..8caa281a1 100644 --- a/src/build/builder.c +++ b/src/build/builder.c @@ -460,6 +460,7 @@ static void update_build_target_from_options(BuildTarget *target, BuildOptions * set_if_updated(target->reloc_model, options->reloc_model); set_if_updated(target->use_stdlib, options->use_stdlib); set_if_updated(target->link_libc, options->link_libc); + set_if_updated(target->custom_libc, options->custom_libc); set_if_updated(target->emit_stdlib, options->emit_stdlib); set_if_updated(target->win.crt_linking, options->win.crt_linking); set_if_updated(target->feature.fp_math, options->fp_math); diff --git a/src/build/project.c b/src/build/project.c index 917a2e361..4422bdbb6 100644 --- a/src/build/project.c +++ b/src/build/project.c @@ -26,6 +26,7 @@ const char *project_default_keys[][2] = { {"langrev", "Version of the C3 language used."}, {"link-args", "Linker arguments for all targets."}, {"link-libc", "Link libc (default: true)."}, + {"custom-libc", "Implement your own libc (default: false)."}, {"linked-libraries", "Libraries linked by the linker for all targets."}, {"linker", "'builtin' for the builtin linker, 'cc' for the system linker or to a custom compiler."}, {"linker-search-paths", "Linker search paths."}, @@ -109,6 +110,7 @@ const char* project_target_keys[][2] = { {"link-args", "Additional linker arguments for the target."}, {"link-args-override", "Linker arguments for this target, overriding global settings."}, {"link-libc", "Link libc (default: true)."}, + {"custom-libc", "Implement your own libc (default: false)."}, {"linked-libraries", "Additional libraries linked by the linker for the target."}, {"linked-libraries-override", "Libraries linked by the linker for this target, overriding global settings."}, {"linker", "'builtin' for the builtin linker, 'cc' for the system linker or to a custom compiler."}, @@ -540,6 +542,9 @@ static void load_into_build_target(BuildParseContext context, JSONObject *json, // emit-stdlib target->emit_stdlib = (EmitStdlib) get_valid_bool(context, json, "emit-stdlib", target->emit_stdlib); + // implement-stdlib + target->custom_libc = (CustomLibc) get_valid_bool(context, json, "custom-libc", target->custom_libc); + // single-module target->single_module = (SingleModule) get_valid_bool(context, json, "single-module", target->single_module); diff --git a/src/build/project_manipulation.c b/src/build/project_manipulation.c index 59e042294..708a93ae4 100644 --- a/src/build/project_manipulation.c +++ b/src/build/project_manipulation.c @@ -234,6 +234,7 @@ static void view_target(BuildParseContext context, JSONObject *target, bool verb TARGET_VIEW_STRING_ARRAY("Additional linker arguments", "link-args", ", "); TARGET_VIEW_STRING_ARRAY("Linker arguments (override)", "link-args-override", ", "); TARGET_VIEW_BOOL("Link libc", "link-libc"); + TARGET_VIEW_BOOL("Custom libc", "custom-libc"); TARGET_VIEW_STRING("MacOS SDK directory", "macossdk"); TARGET_VIEW_SETTING("Memory environment", "memory-env", memory_environment); TARGET_VIEW_BOOL("Don't generate/require main function", "no-entry"); @@ -558,6 +559,7 @@ void view_project(BuildOptions *build_options) VIEW_STRING_ARRAY("Linker search paths", "linker-search-paths", ", "); VIEW_STRING_ARRAY("Linker arguments", "link-args", ", "); VIEW_BOOL("Link libc", "link-libc"); + VIEW_BOOL("Custom libc", "custom-libc"); VIEW_STRING("MacOS SDK directory", "macossdk"); VIEW_SETTING("Memory environment", "memory-env", memory_environment); VIEW_BOOL("Don't generate/require main function", "no-entry"); diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index 335d40f03..d8991ce58 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -1502,6 +1502,7 @@ void compile() setup_int_define("ARCH_TYPE", (uint64_t)compiler.platform.arch, type_int); setup_int_define("MEMORY_ENVIRONMENT", (uint64_t)compiler.build.memory_environment, type_int); setup_bool_define("COMPILER_LIBC_AVAILABLE", link_libc()); + setup_bool_define("CUSTOM_LIBC", custom_libc()); setup_int_define("COMPILER_OPT_LEVEL", (uint64_t)compiler.build.optlevel, type_int); setup_int_define("OS_TYPE", (uint64_t)compiler.platform.os, type_int); setup_int_define("COMPILER_SIZE_OPT_LEVEL", (uint64_t)compiler.build.optsize, type_int); diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 85ac481fe..d75e33324 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -2120,6 +2120,11 @@ INLINE bool link_libc(void) return compiler.build.link_libc != LINK_LIBC_OFF; } +INLINE bool custom_libc(void) +{ + return compiler.build.custom_libc == CUSTOM_LIBC_ON; +} + INLINE bool strip_unused(void) { return compiler.build.strip_unused != STRIP_UNUSED_OFF;