// Copyright (c) 2019-2025 Christoffer Lerno. All rights reserved. // Use of this source code is governed by the GNU LGPLv3.0 license // a copy of which can be found in the LICENSE file. #include "../utils/whereami.h" #include "build.h" #include "build_internal.h" #include "git_hash.h" extern int llvm_version_major; bool silence_deprecation; static int arg_index; static int arg_count; static const char **args; static const char *current_arg; extern const char *llvm_version; extern const char *llvm_target; static const char *unchecked_dir(BuildOptions *options, const char *path); static inline bool at_end(); static inline const char *next_arg(); static inline bool next_is_opt(); INLINE bool match_longopt(const char *name); static inline const char *match_argopt(const char *name); static inline bool match_shortopt(const char *name); void append_file(BuildOptions *build_options); static inline const char *match_argopt(const char *name); void append_arg(BuildOptions *build_options); static bool arg_match(const char *candidate); static void parse_optional_target(BuildOptions *options); static void add_linker_arg(BuildOptions *options, const char *arg); static void update_feature_flags(const char ***flags, const char ***removed_flags, const char *arg, bool add); static void print_all_targets(void); static int parse_option_select(const char *start, unsigned count, const char **elements); static void print_cmd(const char *command, const char *desc); static void print_opt(const char *option, const char *desc); #define parse_opt_select(type_, start_, elements_) (type_)parse_option_select(start_, ELEMENTLEN(elements_), elements_) const char *arch_os_target[ARCH_OS_TARGET_LAST + 1]; #define EOUTPUT(string, ...) fprintf(stderr, string "\n", ##__VA_ARGS__) // NOLINT #define PRINTF(string, ...) fprintf(stdout, string "\n", ##__VA_ARGS__) // NOLINT #define FAIL_WITH_ERR(string, ...) do { fprintf(stderr, "Error: " string "\n\n", ##__VA_ARGS__); usage(false); exit_compiler(EXIT_FAILURE); } while (0) /* NOLINT */ #define FAIL_WITH_ERR_LONG(string, ...) do { fprintf(stderr, "Error: " string "\n\n", ##__VA_ARGS__); usage(true); exit_compiler(EXIT_FAILURE); } while (0) /* NOLINT */ #define PROJECT_FAIL_WITH_ERR(string, ...) do { fprintf(stderr, "Error: " string "\n\n", ##__VA_ARGS__); project_usage(); exit_compiler(EXIT_FAILURE); } while (0) /* NOLINT */ #define FETCH_MSVC_FAIL_WITH_ERR(string, ...) do { fprintf(stderr, "Error: " string "\n\n", ##__VA_ARGS__); fetch_msvc_usage(); exit_compiler(EXIT_FAILURE); } while (0) /* NOLINT */ static void usage(bool full) { PRINTF("Usage: %s [] []", args[0]); PRINTF(""); PRINTF("Commands:"); PRINTF(""); print_cmd("compile [ ...]", "Compile files without a project into an executable."); print_cmd("init ", "Initialize a new project structure."); print_cmd("init-lib ", "Initialize a new library structure."); print_cmd("build []", "Build the target in the current project."); print_cmd("benchmark []", "Run the benchmarks for the target in the current project."); print_cmd("test []", "Run the unit tests for the target in the current project."); print_cmd("clean", "Clean all build files."); print_cmd("run [] [-- [ ...]] ", "Run (and build if needed) the target in the current project."); print_cmd("dist []", "Clean and build a target for distribution."); print_cmd("clean-run [] [-- [ ...]]", "Clean, then run the target."); print_cmd("compile-run [ ...] [-- [ ...]]", "Compile files then immediately run the result."); print_cmd("compile-only [ ...]", "Compile files but do not perform linking."); print_cmd("compile-benchmark [ ...]", "Compile files into a test-executable and run benchmarks."); print_cmd("compile-test [ ...]", "Compile files into a benchmark-executable and run unit tests."); print_cmd("static-lib [ ...]", "Compile files without a project into a static library."); print_cmd("dynamic-lib [ ...]", "Compile files without a project into a dynamic library."); print_cmd("vendor-fetch ...", "Fetches one or more libraries from the vendor collection."); print_cmd("project ...", "Manipulate or view project files."); print_cmd("fetch-msvc []", "Fetches the MSVC SDK required for cross-compiling."); PRINTF(""); full ? PRINTF("Options:") : PRINTF("Common options:"); print_opt("-h -hh --help", "Print the help, -h for the normal options, -hh for the full help."); print_opt("-V --version", "Print version information."); print_opt("-q --quiet", "Silence unnecessary output."); print_opt("-v -vv -vvv", "Verbose output, -v for default, -vv and -vvv gives more information."); print_opt("-E", "Lex only."); print_opt("-P", "Only parse and output the AST as JSON."); print_opt("-C", "Only lex, parse and check."); print_opt("-", "Read code from standard in."); print_opt("-o ", "Write output to ."); print_opt("-O0", "Safe, no optimizations, emit debug info."); print_opt("-O1", "Safe, high optimization, emit debug info."); print_opt("-O2", "Unsafe, high optimization, emit debug info."); print_opt("-O3", "Unsafe, high optimization, single module, emit debug info."); print_opt("-O4", "Unsafe, highest optimization, relaxed maths, single module, emit debug info, no panic messages."); print_opt("-O5", "Unsafe, highest optimization, fast maths, single module, emit debug info, no panic messages, no backtrace."); print_opt("-Os", "Unsafe, high optimization, small code, single module, no debug info, no panic messages."); print_opt("-Oz", "Unsafe, high optimization, tiny code, single module, no debug info, no panic messages, no backtrace."); print_opt("-D ", "Add feature flag ."); print_opt("-U ", "Remove feature flag ."); PRINTF(""); print_opt("--about", "Prints a short description of C3."); print_opt("--build-env", "Prints build environment information (only valid with in combination with a command such as 'compile')."); print_opt("--run-dir ", "Set the directory from where to run the binary (only for run and compile-run)."); print_opt("--libdir ", "Add this directory to the c3l library search paths."); print_opt("--lib ", "Add this c3l library to the compilation."); print_opt("--sources [ ...]", "Add these additional sources to the compilation."); if (full) { print_opt("--validation=