mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
New linker build option. "system-linker" deprecated and removed from project settings.
This commit is contained in:
@@ -5,6 +5,8 @@
|
||||
### Changes / improvements
|
||||
- Disallow multiple `_` in a row in digits, e.g. `1__000`.
|
||||
- Added `@link` attribute.
|
||||
- New 'linker' build option.
|
||||
- "linker" project setting updated, "system-linker" removed.
|
||||
|
||||
### Fixes
|
||||
- Struct/union members now correctly rejects members without storage size #1147.
|
||||
|
||||
@@ -83,6 +83,14 @@ typedef enum
|
||||
SAFETY_ON = 1,
|
||||
} SafetyLevel;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LINKER_TYPE_NOT_SET = -1,
|
||||
LINKER_TYPE_BUILTIN = 0,
|
||||
LINKER_TYPE_CC = 1,
|
||||
LINKER_TYPE_CUSTOM = 2,
|
||||
} LinkerType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TRUST_NONE,
|
||||
@@ -330,7 +338,8 @@ typedef struct BuildOptions_
|
||||
const char *target_select;
|
||||
const char *path;
|
||||
const char *template;
|
||||
const char *linker;
|
||||
LinkerType linker_type;
|
||||
const char *custom_linker_path;
|
||||
uint32_t symtab_size;
|
||||
unsigned version;
|
||||
CompilerBackend backend;
|
||||
@@ -367,7 +376,6 @@ typedef struct BuildOptions_
|
||||
EmitStdlib emit_stdlib;
|
||||
UseStdlib use_stdlib;
|
||||
LinkLibc link_libc;
|
||||
SystemLinker system_linker;
|
||||
StripUnused strip_unused;
|
||||
OptimizationLevel optlevel;
|
||||
SizeOptimizationLevel optsize;
|
||||
@@ -471,7 +479,7 @@ typedef struct
|
||||
RelocModel reloc_model;
|
||||
ArchOsTarget arch_os_target;
|
||||
CompilerBackend backend;
|
||||
SystemLinker system_linker;
|
||||
LinkerType linker_type;
|
||||
uint32_t symtab_size;
|
||||
uint32_t switchrange_max_size;
|
||||
const char *panicfn;
|
||||
@@ -483,7 +491,7 @@ typedef struct
|
||||
const char **csource_dirs;
|
||||
const char **csources;
|
||||
const char **feature_list;
|
||||
const char *linker;
|
||||
const char *custom_linker_path;
|
||||
struct
|
||||
{
|
||||
SoftFloat soft_float : 3;
|
||||
@@ -537,7 +545,7 @@ static BuildTarget default_build_target = {
|
||||
.use_stdlib = USE_STDLIB_NOT_SET,
|
||||
.link_libc = LINK_LIBC_NOT_SET,
|
||||
.emit_stdlib = EMIT_STDLIB_NOT_SET,
|
||||
.system_linker = SYSTEM_LINKER_NOT_SET,
|
||||
.linker_type = LINKER_TYPE_NOT_SET,
|
||||
.single_module = SINGLE_MODULE_NOT_SET,
|
||||
.strip_unused = STRIP_UNUSED_NOT_SET,
|
||||
.symtab_size = DEFAULT_SYMTAB_SIZE,
|
||||
|
||||
@@ -25,18 +25,17 @@ static const char *wincrt_linking[3] = {
|
||||
[WIN_CRT_STATIC] = "static",
|
||||
};
|
||||
|
||||
static const char *trust_level[3] = {
|
||||
[TRUST_NONE] = "none",
|
||||
[TRUST_INCLUDE] = "include",
|
||||
[TRUST_FULL] = "full",
|
||||
};
|
||||
|
||||
static const char *optsizes[3] = {
|
||||
[SIZE_OPTIMIZATION_NONE] = "none",
|
||||
[SIZE_OPTIMIZATION_SMALL] = "small",
|
||||
[SIZE_OPTIMIZATION_TINY] = "tiny",
|
||||
};
|
||||
|
||||
static const char *linker[3] = {
|
||||
[LINKER_TYPE_BUILTIN] = "builtin",
|
||||
[LINKER_TYPE_CC] = "cc",
|
||||
[LINKER_TYPE_CUSTOM] = "custom"
|
||||
};
|
||||
static const char *on_off[2] = {
|
||||
[SAFETY_OFF] = "no",
|
||||
[SAFETY_ON] = "yes",
|
||||
|
||||
@@ -41,6 +41,12 @@ char *arch_os_target[ARCH_OS_TARGET_LAST + 1] = {
|
||||
[WINDOWS_X64] = "windows-x64",
|
||||
};
|
||||
|
||||
const char *trust_level[3] = {
|
||||
[TRUST_NONE] = "none",
|
||||
[TRUST_INCLUDE] = "include",
|
||||
[TRUST_FULL] = "full",
|
||||
};
|
||||
|
||||
#define EOUTPUT(string, ...) fprintf(stderr, string "\n", ##__VA_ARGS__)
|
||||
#define OUTPUT(string, ...) fprintf(stdout, string "\n", ##__VA_ARGS__)
|
||||
#define FAIL_WITH_ERR(string, ...) do { fprintf(stderr, "Error: " string "\n\n", ##__VA_ARGS__); usage(); exit_compiler(EXIT_FAILURE); } while (0)
|
||||
@@ -73,104 +79,105 @@ static void usage(void)
|
||||
OUTPUT(" vendor-fetch <library> ... Fetches one or more libraries from the vendor collection.");
|
||||
OUTPUT("");
|
||||
OUTPUT("Options:");
|
||||
OUTPUT(" --tb - Use Tilde Backend for compilation.");
|
||||
OUTPUT(" --stdlib <dir> - Use this directory as the C3 standard library path.");
|
||||
OUTPUT(" --no-entry - Do not generate (or require) a main function.");
|
||||
OUTPUT(" --libdir <dir> - Add this directory to the C3 library search paths.");
|
||||
OUTPUT(" --lib <name> - Add this library to the compilation.");
|
||||
OUTPUT(" --path <dir> - Use this as the base directory for the current command.");
|
||||
OUTPUT(" --template <template> - Select template for 'init': \"exe\", \"static-lib\", \"dynamic-lib\" or a path.");
|
||||
OUTPUT(" --about - Prints a short description of C3.");
|
||||
OUTPUT(" --symtab <value> - Sets the preferred symtab size.");
|
||||
OUTPUT(" -V --version - Print version information.");
|
||||
OUTPUT(" -E - Lex only.");
|
||||
OUTPUT(" -P - Only parse and output the AST as JSON.");
|
||||
OUTPUT(" -C - Only lex, parse and check.");
|
||||
OUTPUT(" - - Read code from standard in.");
|
||||
OUTPUT(" -o <file> - Write output to <file>.");
|
||||
OUTPUT(" -O0 - Safe, no optimizations, emit debug info.");
|
||||
OUTPUT(" -O1 - Safe, high optimization, emit debug info.");
|
||||
OUTPUT(" -O2 - Unsafe, high optimization, emit debug info.");
|
||||
OUTPUT(" -O3 - Unsafe, high optimization, single module, emit debug info.");
|
||||
OUTPUT(" -O4 - Unsafe, highest optimization, relaxed maths, single module, emit debug info.");
|
||||
OUTPUT(" -O5 - Unsafe, highest optimization, fast maths, single module, emit debug info.");
|
||||
OUTPUT(" -Os - Unsafe, high optimization, small code, single module, no debug info.");
|
||||
OUTPUT(" -Oz - Unsafe, high optimization, tiny code, single module, no debug info.");
|
||||
OUTPUT(" -D <name> - Add feature flag <name>.");
|
||||
OUTPUT(" -U <name> - Remove feature flag <name>.");
|
||||
OUTPUT(" --trust=<option> - Trust level: none (default), include ($include allowed), full ($exec / exec allowed).");
|
||||
OUTPUT(" --build-dir <dir> - Override build output directory.");
|
||||
OUTPUT(" --obj-out <dir> - Override object file output directory.");
|
||||
OUTPUT(" --script-dir <dir> - Override the base directory for $exec.");
|
||||
OUTPUT(" --llvm-out <dir> - Override llvm output directory for '--emit-llvm'.");
|
||||
OUTPUT(" --emit-llvm - Emit LLVM IR as a .ll file per module.");
|
||||
OUTPUT(" --asm-out <dir> - Override asm output directory for '--emit-asm'.");
|
||||
OUTPUT(" --emit-asm - Emit asm as a .s file per module.");
|
||||
OUTPUT(" --obj - Emit object files. (Enabled by default)");
|
||||
OUTPUT(" --no-obj - Do not output object files, this is only valid for `compile-only`.");
|
||||
OUTPUT(" --target <target> - Compile for a particular architecture + OS target.");
|
||||
OUTPUT(" --threads <number> - Set the number of threads to use for compilation.");
|
||||
OUTPUT(" --safe=<yes|no> - Turn safety (contracts, runtime bounds checking, null pointer checks etc) on or off.");
|
||||
OUTPUT(" --optlevel=<option> - Code optimization level: none, less, more, max.");
|
||||
OUTPUT(" --optsize=<option> - Code size optimization: none, small, tiny.");
|
||||
OUTPUT(" --single-module=<yes|no> - Compile all modules together, enables more inlining.");
|
||||
OUTPUT(" --tb - Use Tilde Backend for compilation.");
|
||||
OUTPUT(" --stdlib <dir> - Use this directory as the C3 standard library path.");
|
||||
OUTPUT(" --no-entry - Do not generate (or require) a main function.");
|
||||
OUTPUT(" --libdir <dir> - Add this directory to the C3 library search paths.");
|
||||
OUTPUT(" --lib <name> - Add this library to the compilation.");
|
||||
OUTPUT(" --path <dir> - Use this as the base directory for the current command.");
|
||||
OUTPUT(" --template <template> - Select template for 'init': \"exe\", \"static-lib\", \"dynamic-lib\" or a path.");
|
||||
OUTPUT(" --about - Prints a short description of C3.");
|
||||
OUTPUT(" --symtab <value> - Sets the preferred symtab size.");
|
||||
OUTPUT(" -V --version - Print version information.");
|
||||
OUTPUT(" -E - Lex only.");
|
||||
OUTPUT(" -P - Only parse and output the AST as JSON.");
|
||||
OUTPUT(" -C - Only lex, parse and check.");
|
||||
OUTPUT(" - - Read code from standard in.");
|
||||
OUTPUT(" -o <file> - Write output to <file>.");
|
||||
OUTPUT(" -O0 - Safe, no optimizations, emit debug info.");
|
||||
OUTPUT(" -O1 - Safe, high optimization, emit debug info.");
|
||||
OUTPUT(" -O2 - Unsafe, high optimization, emit debug info.");
|
||||
OUTPUT(" -O3 - Unsafe, high optimization, single module, emit debug info.");
|
||||
OUTPUT(" -O4 - Unsafe, highest optimization, relaxed maths, single module, emit debug info.");
|
||||
OUTPUT(" -O5 - Unsafe, highest optimization, fast maths, single module, emit debug info.");
|
||||
OUTPUT(" -Os - Unsafe, high optimization, small code, single module, no debug info.");
|
||||
OUTPUT(" -Oz - Unsafe, high optimization, tiny code, single module, no debug info.");
|
||||
OUTPUT(" -D <name> - Add feature flag <name>.");
|
||||
OUTPUT(" -U <name> - Remove feature flag <name>.");
|
||||
OUTPUT(" --trust=<option> - Trust level: none (default), include ($include allowed), full ($exec / exec allowed).");
|
||||
OUTPUT(" --build-dir <dir> - Override build output directory.");
|
||||
OUTPUT(" --obj-out <dir> - Override object file output directory.");
|
||||
OUTPUT(" --script-dir <dir> - Override the base directory for $exec.");
|
||||
OUTPUT(" --llvm-out <dir> - Override llvm output directory for '--emit-llvm'.");
|
||||
OUTPUT(" --emit-llvm - Emit LLVM IR as a .ll file per module.");
|
||||
OUTPUT(" --asm-out <dir> - Override asm output directory for '--emit-asm'.");
|
||||
OUTPUT(" --emit-asm - Emit asm as a .s file per module.");
|
||||
OUTPUT(" --obj - Emit object files. (Enabled by default)");
|
||||
OUTPUT(" --no-obj - Do not output object files, this is only valid for `compile-only`.");
|
||||
OUTPUT(" --target <target> - Compile for a particular architecture + OS target.");
|
||||
OUTPUT(" --threads <number> - Set the number of threads to use for compilation.");
|
||||
OUTPUT(" --safe=<yes|no> - Turn safety (contracts, runtime bounds checking, null pointer checks etc) on or off.");
|
||||
OUTPUT(" --optlevel=<option> - Code optimization level: none, less, more, max.");
|
||||
OUTPUT(" --optsize=<option> - Code size optimization: none, small, tiny.");
|
||||
OUTPUT(" --single-module=<yes|no> - Compile all modules together, enables more inlining.");
|
||||
OUTPUT("");
|
||||
OUTPUT(" -g - Emit debug info.");
|
||||
OUTPUT(" -g0 - Emit no debug info.");
|
||||
OUTPUT(" -g - Emit debug info.");
|
||||
OUTPUT(" -g0 - Emit no debug info.");
|
||||
OUTPUT("");
|
||||
OUTPUT("");
|
||||
OUTPUT(" -l <library> - Link with the library provided.");
|
||||
OUTPUT(" -L <library dir> - Append the directory to the linker search paths.");
|
||||
OUTPUT(" -z <argument> - Send the <argument> as a parameter to the linker.");
|
||||
OUTPUT(" --system-linker=<yes|no> - Use the system linker (default: no for cross compilation, yes otherwise).");
|
||||
OUTPUT(" --cc <path> - Set C compiler (for C files in projects and use as system linker).");
|
||||
OUTPUT(" --linker <path> - Use the linker in the given path.");
|
||||
OUTPUT(" -l <library> - Link with the library provided.");
|
||||
OUTPUT(" -L <library dir> - Append the directory to the linker search paths.");
|
||||
OUTPUT(" -z <argument> - Send the <argument> as a parameter to the linker.");
|
||||
OUTPUT(" --system-linker=<yes|no> - Use the system linker (default: no for cross compilation, yes otherwise). [deprecated]");
|
||||
OUTPUT(" --cc <path> - Set C compiler (for C files in projects and use as system linker).");
|
||||
OUTPUT(" --linker <path> - Use the linker in the given path. [deprecated]");
|
||||
OUTPUT(" --linker=<option> [<path>] - Linker: builtin, cc, custom (default is 'cc'), 'custom' requires a path.");
|
||||
OUTPUT("");
|
||||
OUTPUT(" --use-stdlib=<yes|no> - Include the standard library (default: yes).");
|
||||
OUTPUT(" --link-libc=<yes|no> - Link libc other default libraries (default: yes).");
|
||||
OUTPUT(" --emit-stdlib=<yes|no> - Output files for the standard library. (default: yes)");
|
||||
OUTPUT(" --panicfn <name> - Override the panic function name.");
|
||||
OUTPUT(" --testfn <name> - Override the test runner function name.");
|
||||
OUTPUT(" --benchfn <name> - Override the benchmark runner function name.");
|
||||
OUTPUT(" --use-stdlib=<yes|no> - Include the standard library (default: yes).");
|
||||
OUTPUT(" --link-libc=<yes|no> - Link libc other default libraries (default: yes).");
|
||||
OUTPUT(" --emit-stdlib=<yes|no> - Output files for the standard library. (default: yes)");
|
||||
OUTPUT(" --panicfn <name> - Override the panic function name.");
|
||||
OUTPUT(" --testfn <name> - Override the test runner function name.");
|
||||
OUTPUT(" --benchfn <name> - Override the benchmark runner function name.");
|
||||
OUTPUT("");
|
||||
OUTPUT(" --reloc=<option> - Relocation model: none, pic, PIC, pie, PIE.");
|
||||
OUTPUT(" --x86cpu=<option> - Set general level of x64 cpu: baseline, ssse3, sse4, avx1, avx2-v1, avx2-v2 (Skylake/Zen1+), avx512 (Icelake/Zen4+), native.");
|
||||
OUTPUT(" --x86vec=<option> - Set max type of vector use: none, mmx, sse, avx, avx512, native.");
|
||||
OUTPUT(" --riscvfloat=<option> - Set type of RISC-V float support: none, float, double");
|
||||
OUTPUT(" --memory-env=<option> - Set the memory environment: normal, small, tiny, none.");
|
||||
OUTPUT(" --strip-unused=<yes|no> - Strip unused code and globals from the output. (default: yes)");
|
||||
OUTPUT(" --fp-math=<option> - FP math behaviour: strict, relaxed, fast.");
|
||||
OUTPUT(" --reloc=<option> - Relocation model: none, pic, PIC, pie, PIE.");
|
||||
OUTPUT(" --x86cpu=<option> - Set general level of x64 cpu: baseline, ssse3, sse4, avx1, avx2-v1, avx2-v2 (Skylake/Zen1+), avx512 (Icelake/Zen4+), native.");
|
||||
OUTPUT(" --x86vec=<option> - Set max type of vector use: none, mmx, sse, avx, avx512, native.");
|
||||
OUTPUT(" --riscvfloat=<option> - Set type of RISC-V float support: none, float, double");
|
||||
OUTPUT(" --memory-env=<option> - Set the memory environment: normal, small, tiny, none.");
|
||||
OUTPUT(" --strip-unused=<yes|no> - Strip unused code and globals from the output. (default: yes)");
|
||||
OUTPUT(" --fp-math=<option> - FP math behaviour: strict, relaxed, fast.");
|
||||
OUTPUT("");
|
||||
OUTPUT(" --debug-stats - Print debug statistics.");
|
||||
OUTPUT(" --print-linking - Print linker arguments.");
|
||||
OUTPUT(" --debug-stats - Print debug statistics.");
|
||||
OUTPUT(" --print-linking - Print linker arguments.");
|
||||
#ifndef NDEBUG
|
||||
OUTPUT(" --debug-log - Print debug logging to stdout.");
|
||||
OUTPUT(" --debug-log - Print debug logging to stdout.");
|
||||
#endif
|
||||
OUTPUT("");
|
||||
OUTPUT(" --benchmarking - Run built-in benchmarks.");
|
||||
OUTPUT(" --testing - Run built-in tests.");
|
||||
OUTPUT(" --benchmarking - Run built-in benchmarks.");
|
||||
OUTPUT(" --testing - Run built-in tests.");
|
||||
OUTPUT("");
|
||||
OUTPUT(" --list-attributes - List all attributes.");
|
||||
OUTPUT(" --list-builtins - List all builtins.");
|
||||
OUTPUT(" --list-keywords - List all keywords.");
|
||||
OUTPUT(" --list-operators - List all operators.");
|
||||
OUTPUT(" --list-precedence - List operator precedence order.");
|
||||
OUTPUT(" --list-project-properties - List all available keys used in project.json files.");
|
||||
OUTPUT(" --list-targets - List all architectures the compiler supports.");
|
||||
OUTPUT(" --list-type-properties - List all type properties.");
|
||||
OUTPUT(" --list-attributes - List all attributes.");
|
||||
OUTPUT(" --list-builtins - List all builtins.");
|
||||
OUTPUT(" --list-keywords - List all keywords.");
|
||||
OUTPUT(" --list-operators - List all operators.");
|
||||
OUTPUT(" --list-precedence - List operator precedence order.");
|
||||
OUTPUT(" --list-project-properties - List all available keys used in project.json files.");
|
||||
OUTPUT(" --list-targets - List all architectures the compiler supports.");
|
||||
OUTPUT(" --list-type-properties - List all type properties.");
|
||||
OUTPUT("");
|
||||
OUTPUT(" --print-output - Print the object files created to stdout.");
|
||||
OUTPUT(" --print-output - Print the object files created to stdout.");
|
||||
OUTPUT("");
|
||||
OUTPUT(" --winsdk <dir> - Set the directory for Windows system library files for cross compilation.");
|
||||
OUTPUT(" --wincrt=<option> - Windows CRT linking: none, static, dynamic (default).");
|
||||
OUTPUT(" --windef <file> - Use Windows 'def' file for function exports instead of 'dllexport'.");
|
||||
OUTPUT(" --winsdk <dir> - Set the directory for Windows system library files for cross compilation.");
|
||||
OUTPUT(" --wincrt=<option> - Windows CRT linking: none, static, dynamic (default).");
|
||||
OUTPUT(" --windef <file> - Use Windows 'def' file for function exports instead of 'dllexport'.");
|
||||
OUTPUT("");
|
||||
OUTPUT(" --macossdk <dir> - Set the directory for the MacOS SDK for cross compilation.");
|
||||
OUTPUT(" --macos-min-version <ver> - Set the minimum MacOS version to compile for.");
|
||||
OUTPUT(" --macos-sdk-version <ver> - Set the MacOS SDK compiled for.");
|
||||
OUTPUT(" --macossdk <dir> - Set the directory for the MacOS SDK for cross compilation.");
|
||||
OUTPUT(" --macos-min-version <ver> - Set the minimum MacOS version to compile for.");
|
||||
OUTPUT(" --macos-sdk-version <ver> - Set the MacOS SDK compiled for.");
|
||||
OUTPUT("");
|
||||
OUTPUT(" --linux-crt <dir> - Set the directory to use for finding crt1.o and related files.");
|
||||
OUTPUT(" --linux-crtbegin <dir> - Set the directory to use for finding crtbegin.o and related files.");
|
||||
OUTPUT(" --linux-crt <dir> - Set the directory to use for finding crt1.o and related files.");
|
||||
OUTPUT(" --linux-crtbegin <dir> - Set the directory to use for finding crtbegin.o and related files.");
|
||||
}
|
||||
|
||||
|
||||
@@ -674,17 +681,40 @@ static void parse_option(BuildOptions *options)
|
||||
options->single_module = (SingleModule)parse_multi_option(argopt, 2, on_off);
|
||||
return;
|
||||
}
|
||||
if ((argopt = match_argopt("linker")))
|
||||
{
|
||||
options->custom_linker_path = NULL;
|
||||
options->linker_type = (LinkerType) parse_multi_option(argopt, 3, linker);
|
||||
if (options->linker_type == LINKER_TYPE_CUSTOM)
|
||||
{
|
||||
if (at_end() || next_is_opt()) error_exit("error: --linker=custom expects a valid linker name.");
|
||||
options->custom_linker_path = next_arg();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if ((argopt = match_argopt("system-linker")))
|
||||
{
|
||||
options->system_linker = (SystemLinker)parse_multi_option(argopt, 2, on_off);
|
||||
options->linker = NULL;
|
||||
puts("NOTE: 'system-linker' is deprecated, please use --linker instead.");
|
||||
options->custom_linker_path = NULL;
|
||||
switch ((SystemLinker)parse_multi_option(argopt, 2, on_off))
|
||||
{
|
||||
case SYSTEM_LINKER_ON:
|
||||
options->linker_type = LINKER_TYPE_CC;
|
||||
break;
|
||||
case SYSTEM_LINKER_OFF:
|
||||
options->linker_type = LINKER_TYPE_BUILTIN;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (match_longopt("linker"))
|
||||
{
|
||||
if (at_end() || next_is_opt()) error_exit("error: --linker expects a valid linker name.");
|
||||
options->system_linker = SYSTEM_LINKER_NOT_SET;
|
||||
options->linker = next_arg();
|
||||
options->linker_type = LINKER_TYPE_CUSTOM;
|
||||
options->custom_linker_path = next_arg();
|
||||
puts("NOTE: 'linker' is deprecated, please use --linker=custom <path> instead.");
|
||||
return;
|
||||
}
|
||||
if ((argopt = match_argopt("link-libc")))
|
||||
@@ -1091,7 +1121,7 @@ BuildOptions parse_arguments(int argc, const char *argv[])
|
||||
.emit_stdlib = EMIT_STDLIB_NOT_SET,
|
||||
.link_libc = LINK_LIBC_NOT_SET,
|
||||
.use_stdlib = USE_STDLIB_NOT_SET,
|
||||
.system_linker = SYSTEM_LINKER_NOT_SET,
|
||||
.linker_type = LINKER_TYPE_NOT_SET,
|
||||
.strip_unused = STRIP_UNUSED_NOT_SET,
|
||||
.single_module = SINGLE_MODULE_NOT_SET,
|
||||
.files = NULL,
|
||||
|
||||
@@ -277,15 +277,10 @@ static void update_build_target_from_options(BuildTarget *target, BuildOptions *
|
||||
if (options->win.def) target->win.def = options->win.def;
|
||||
if (options->use_stdlib != USE_STDLIB_NOT_SET) target->use_stdlib = options->use_stdlib;
|
||||
if (options->link_libc != LINK_LIBC_NOT_SET) target->link_libc = options->link_libc;
|
||||
if (options->system_linker != SYSTEM_LINKER_NOT_SET)
|
||||
if (options->linker_type != LINKER_TYPE_NOT_SET)
|
||||
{
|
||||
target->system_linker = options->system_linker;
|
||||
target->linker = NULL;
|
||||
}
|
||||
if (options->linker)
|
||||
{
|
||||
target->linker = options->linker;
|
||||
target->system_linker = SYSTEM_LINKER_NOT_SET;
|
||||
target->custom_linker_path = options->custom_linker_path;
|
||||
target->linker_type = options->linker_type;
|
||||
}
|
||||
if (options->emit_stdlib != EMIT_STDLIB_NOT_SET) target->emit_stdlib = options->emit_stdlib;
|
||||
if (options->no_entry) target->no_entry = true;
|
||||
|
||||
@@ -21,6 +21,7 @@ const char *project_default_keys[][2] = {
|
||||
{"fp-math", "Set math behaviour: `strict`, `relaxed` or `fast`."},
|
||||
{"langrev", "Version of the C3 language used."},
|
||||
{"linked-libraries", "Libraries linked by the linker for all targets."},
|
||||
{"linker", "'builtin' for the builtin linker, 'cc' for the system linker or <path> to a custom compiler."},
|
||||
{"linker-search-paths", "Linker search paths."},
|
||||
{"link-args", "Linker arguments for all targets."},
|
||||
{"link-libc", "Link libc (default: true)."},
|
||||
@@ -40,7 +41,6 @@ const char *project_default_keys[][2] = {
|
||||
{"sources", "Paths to project sources for all targets."},
|
||||
{"strip-unused", "Strip unused code and globals from the output. (default: true)"},
|
||||
{"symtab", "Sets the preferred symtab size."},
|
||||
{"system-linker", "Use the system linker (default: no for cross compilation, yes otherwise)."},
|
||||
{"target", "Compile for a particular architecture + OS target."},
|
||||
{"targets", "Set of targets for the project."},
|
||||
{"testfn", "Override the test function."},
|
||||
@@ -78,6 +78,7 @@ const char* project_target_keys[][2] = {
|
||||
{"langrev", "Version of the C3 language used."},
|
||||
{"linked-libraries-add", "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 <path> to a custom compiler."},
|
||||
{"linker-search-paths-add", "Additional linker search paths for the target."},
|
||||
{"linker-search-paths-override", "Linker search paths for this target, overriding global settings."},
|
||||
{"link-args-add", "Additional linker arguments for the target."},
|
||||
@@ -100,7 +101,6 @@ const char* project_target_keys[][2] = {
|
||||
{"sources-override", "Paths to project sources for this target, overriding global settings."},
|
||||
{"strip-unused", "Strip unused code and globals from the output. (default: true)"},
|
||||
{"symtab", "Sets the preferred symtab size."},
|
||||
{"system-linker", "Use the system linker (default: no for cross compilation, yes otherwise)."},
|
||||
{"target", "Compile for a particular architecture + OS target."},
|
||||
{"testfn", "Override the test function."},
|
||||
{"trap-on-wrap", "Make signed and unsigned integer overflow generate a panic rather than wrapping."},
|
||||
@@ -488,16 +488,27 @@ static void load_into_build_target(JSONObject *json, const char *type, BuildTarg
|
||||
// strip-unused
|
||||
target->strip_unused = (StripUnused)get_valid_bool(json, "strip-unused", type, target->strip_unused);
|
||||
|
||||
// system-linker
|
||||
target->system_linker = (SystemLinker)get_valid_bool(json, "system-linker", type, target->system_linker);
|
||||
|
||||
// linker
|
||||
target->linker = get_string(json, "linker", type, target->linker);
|
||||
|
||||
if (target->system_linker != SYSTEM_LINKER_NOT_SET && target->linker)
|
||||
const char *linker_selection = get_string(json, "linker", type, NULL);
|
||||
if (linker_selection)
|
||||
{
|
||||
error_exit("%s has both 'linker' and 'system-linker' set. They cannot be combined, so please remove one of them.", type);
|
||||
if (str_eq("cc", linker_selection))
|
||||
{
|
||||
target->linker_type = LINKER_TYPE_CC;
|
||||
target->custom_linker_path = NULL;
|
||||
}
|
||||
else if (str_eq("builtin", linker_selection))
|
||||
{
|
||||
target->linker_type = LINKER_TYPE_BUILTIN;
|
||||
target->custom_linker_path = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
target->linker_type = LINKER_TYPE_CUSTOM;
|
||||
target->custom_linker_path = linker_selection;
|
||||
}
|
||||
}
|
||||
|
||||
// no-entry
|
||||
target->no_entry = get_valid_bool(json, "no-entry", type, target->no_entry);
|
||||
|
||||
|
||||
@@ -493,9 +493,9 @@ void compiler_compile(void)
|
||||
}
|
||||
bool system_linker_available = link_libc() && platform_target.os != OS_TYPE_WIN32;
|
||||
bool use_system_linker = system_linker_available && active_target.arch_os_target == default_target;
|
||||
switch (active_target.system_linker)
|
||||
switch (active_target.linker_type)
|
||||
{
|
||||
case SYSTEM_LINKER_ON:
|
||||
case LINKER_TYPE_CC:
|
||||
if (!system_linker_available)
|
||||
{
|
||||
eprintf("System linker is not supported, defaulting to built-in linker\n");
|
||||
@@ -503,13 +503,13 @@ void compiler_compile(void)
|
||||
}
|
||||
use_system_linker = true;
|
||||
break;
|
||||
case SYSTEM_LINKER_OFF:
|
||||
case LINKER_TYPE_BUILTIN:
|
||||
use_system_linker = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (use_system_linker || active_target.linker)
|
||||
if (use_system_linker || active_target.linker_type == LINKER_TYPE_BUILTIN)
|
||||
{
|
||||
platform_linker(output_exe, obj_files, output_file_count);
|
||||
compiler_link_time = bench_mark();
|
||||
|
||||
@@ -49,6 +49,7 @@ extern const char *project_default_keys[][2];
|
||||
extern const int project_default_keys_count;
|
||||
extern const char* project_target_keys[][2];
|
||||
extern const int project_target_keys_count;
|
||||
extern const char *trust_level[3];
|
||||
|
||||
typedef struct Ast_ Ast;
|
||||
typedef struct Decl_ Decl;
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
#define MANIFEST_FILE "manifest.json"
|
||||
|
||||
static inline void parse_library_target(Library *library, LibraryTarget *target, JSONObject *object);
|
||||
|
||||
static inline JSONObject *get_mandatory(Library *library, JSONObject *object, const char *key)
|
||||
{
|
||||
JSONObject *value = json_obj_get(object, key);
|
||||
@@ -43,37 +45,6 @@ static inline const char **get_optional_string_array_as_array(Library *library,
|
||||
}
|
||||
|
||||
|
||||
static inline void parse_provides(Library *library, JSONObject *object)
|
||||
{
|
||||
const char *provides = get_mandatory_string(library, object, "provides");
|
||||
if (!str_is_valid_lowercase_name(provides))
|
||||
{
|
||||
char *res = strdup(provides);
|
||||
str_ellide_in_place(res, 32);
|
||||
error_exit("Invalid 'provides' module name in %s, was '%s'.", library->dir, json_obj_get(object, "provides")->str);
|
||||
}
|
||||
library->provides = provides;
|
||||
}
|
||||
|
||||
static inline void parse_execs(Library *library, JSONObject *object)
|
||||
{
|
||||
library->execs = get_optional_string_array_as_array(library, object, "execs");
|
||||
}
|
||||
static inline void parse_depends(Library *library, JSONObject *object)
|
||||
{
|
||||
library->depends = get_optional_string_array_as_array(library, object, "depends");
|
||||
}
|
||||
|
||||
static inline void parse_library_run(Library *library, LibraryTarget *target, JSONObject *object)
|
||||
{
|
||||
target->execs = get_optional_string_array_as_array(library, object, "execs");
|
||||
}
|
||||
static inline void parse_library_target(Library *library, LibraryTarget *target, JSONObject *object)
|
||||
{
|
||||
target->link_flags = get_optional_string_array_as_array(library, object, "linkflags");
|
||||
target->linked_libs = get_optional_string_array_as_array(library, object, "linked-libs");
|
||||
target->depends = get_optional_string_array_as_array(library, object, "depends");
|
||||
}
|
||||
static inline void parse_library_type(Library *library, LibraryTarget ***target_group, JSONObject *object)
|
||||
{
|
||||
if (!object) return;
|
||||
@@ -95,16 +66,35 @@ static inline void parse_library_type(Library *library, LibraryTarget ***target_
|
||||
}
|
||||
}
|
||||
|
||||
static inline void parse_library_target(Library *library, LibraryTarget *target, JSONObject *object)
|
||||
{
|
||||
target->link_flags = get_optional_string_array_as_array(library, object, "linkflags");
|
||||
target->linked_libs = get_optional_string_array_as_array(library, object, "linked-libs");
|
||||
target->depends = get_optional_string_array_as_array(library, object, "depends");
|
||||
target->execs = get_optional_string_array_as_array(library, object, "execs");
|
||||
}
|
||||
|
||||
static Library *add_library(JSONObject *object, const char *dir)
|
||||
{
|
||||
Library *library = CALLOCS(Library);
|
||||
library->dir = dir;
|
||||
parse_provides(library, object);
|
||||
parse_depends(library, object);
|
||||
const char *provides = get_mandatory_string(library, object, "provides");
|
||||
if (!str_is_valid_lowercase_name(provides))
|
||||
{
|
||||
char *res = strdup(provides);
|
||||
str_ellide_in_place(res, 32);
|
||||
error_exit("Invalid 'provides' module name in %s, was '%s'.", library->dir,
|
||||
json_obj_get(object, "provides")->str);
|
||||
}
|
||||
library->provides = provides;
|
||||
library->execs = get_optional_string_array_as_array(library, object, "execs");
|
||||
library->depends = get_optional_string_array_as_array(library, object, "depends");
|
||||
parse_library_type(library, &library->targets, json_obj_get(object, "targets"));
|
||||
return library;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static Library *find_library(Library **libs, size_t lib_count, const char *name)
|
||||
{
|
||||
for (size_t i = 0; i < lib_count; i++)
|
||||
@@ -260,9 +250,9 @@ void resolve_libraries(void)
|
||||
if (file_is_dir(libdir)) vec_add(active_target.linker_libdirs, libdir);
|
||||
if ((vec_size(library->execs) || vec_size(target->execs)) && active_target.trust_level < TRUST_FULL)
|
||||
{
|
||||
error_exit("Could not use library '%s' as it requires the 'exec' trust level (it "
|
||||
"is currently %d). Use the '-t' option to enable it.",
|
||||
library->provides, active_target.trust_level + 1);
|
||||
error_exit("Could not use library '%s' as it requires 'exec' trust level to execute (it "
|
||||
"is currently '%s'). Use the '--trust=full' option to enable it.",
|
||||
library->provides, trust_level[active_target.trust_level]);
|
||||
}
|
||||
FOREACH_BEGIN(const char *exec, library->execs)
|
||||
printf("] Execute '%s' for library '%s':", exec, library->provides);
|
||||
|
||||
@@ -32,7 +32,7 @@ typedef enum
|
||||
LINKER_WASM,
|
||||
LINKER_CC,
|
||||
LINKER_UNKNOWN
|
||||
} LinkerType;
|
||||
} Linker;
|
||||
|
||||
#define add_arg(arg_) vec_add(*args_ref, (arg_))
|
||||
#define add_arg2(arg_, arg_2) vec_add(*args_ref, str_cat((arg_), (arg_2)))
|
||||
@@ -77,7 +77,7 @@ static const char *string_esc(const char *str)
|
||||
return strdup(scratch_buffer_to_string());
|
||||
}
|
||||
|
||||
static void linker_setup_windows(const char ***args_ref, LinkerType linker_type)
|
||||
static void linker_setup_windows(const char ***args_ref, Linker linker_type)
|
||||
{
|
||||
add_arg(active_target.win.use_win_subsystem ? "/SUBSYSTEM:WINDOWS" : "/SUBSYSTEM:CONSOLE");
|
||||
global_context_add_link("dbghelp");
|
||||
@@ -206,7 +206,7 @@ static void linker_setup_windows(const char ***args_ref, LinkerType linker_type)
|
||||
add_arg("/NOLOGO");
|
||||
}
|
||||
|
||||
static void linker_setup_macos(const char ***args_ref, LinkerType linker_type)
|
||||
static void linker_setup_macos(const char ***args_ref, Linker linker_type)
|
||||
{
|
||||
if (linker_type == LINKER_CC)
|
||||
{
|
||||
@@ -311,7 +311,7 @@ static const char *find_linux_crt_begin(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void linker_setup_linux(const char ***args_ref, LinkerType linker_type)
|
||||
static void linker_setup_linux(const char ***args_ref, Linker linker_type)
|
||||
{
|
||||
global_context_add_link("dl");
|
||||
if (linker_type == LINKER_CC)
|
||||
@@ -377,7 +377,7 @@ static void linker_setup_linux(const char ***args_ref, LinkerType linker_type)
|
||||
add_arg(ld_target(platform_target.arch));
|
||||
}
|
||||
|
||||
static void linker_setup_freebsd(const char ***args_ref, LinkerType linker_type)
|
||||
static void linker_setup_freebsd(const char ***args_ref, Linker linker_type)
|
||||
{
|
||||
if (linker_type == LINKER_CC) return;
|
||||
if (is_no_pie(platform_target.reloc_model)) add_arg("-no-pie");
|
||||
@@ -453,7 +453,7 @@ static void add_linked_libs(const char ***args_ref, const char **libs, bool is_w
|
||||
}
|
||||
|
||||
static bool linker_setup(const char ***args_ref, const char **files_to_link, unsigned file_count,
|
||||
const char *output_file, LinkerType linker_type)
|
||||
const char *output_file, Linker linker_type)
|
||||
{
|
||||
bool is_dylib = active_target.type == TARGET_TYPE_DYNAMIC_LIB;
|
||||
bool use_win = linker_type == LINKER_LINK_EXE;
|
||||
@@ -524,6 +524,10 @@ static bool linker_setup(const char ***args_ref, const char **files_to_link, uns
|
||||
case OS_TYPE_NONE:
|
||||
break;
|
||||
}
|
||||
if (link_libc())
|
||||
{
|
||||
global_context_add_link("m");
|
||||
}
|
||||
for (unsigned i = 0; i < file_count; i++)
|
||||
{
|
||||
add_arg(files_to_link[i]);
|
||||
@@ -583,7 +587,7 @@ static void append_fpie_pic_options(RelocModel reloc, const char ***args_ref)
|
||||
}
|
||||
}
|
||||
|
||||
LinkerType linker_find_linker_type(void)
|
||||
Linker linker_find_linker_type(void)
|
||||
{
|
||||
if (arch_is_wasm(platform_target.arch)) return LINKER_WASM;
|
||||
switch (platform_target.os)
|
||||
@@ -613,7 +617,7 @@ static bool link_exe(const char *output_file, const char **files_to_link, unsign
|
||||
{
|
||||
INFO_LOG("Using linker directly.");
|
||||
const char **args = NULL;
|
||||
LinkerType linker_type = linker_find_linker_type();
|
||||
Linker linker_type = linker_find_linker_type();
|
||||
linker_setup(&args, files_to_link, file_count, output_file, linker_type);
|
||||
|
||||
const char *error = NULL;
|
||||
@@ -697,11 +701,11 @@ const char *concat_string_parts(const char **args)
|
||||
void platform_linker(const char *output_file, const char **files, unsigned file_count)
|
||||
{
|
||||
const char **parts = NULL;
|
||||
LinkerType linker_type = LINKER_CC;
|
||||
if (active_target.linker)
|
||||
Linker linker_type = LINKER_CC;
|
||||
if (active_target.linker_type == LINKER_TYPE_CUSTOM)
|
||||
{
|
||||
INFO_LOG("Using linker %s.", active_target.linker);
|
||||
vec_add(parts, active_target.linker);
|
||||
INFO_LOG("Using linker %s.", active_target.custom_linker_path);
|
||||
vec_add(parts, active_target.custom_linker_path);
|
||||
switch (platform_target.object_format)
|
||||
{
|
||||
case OBJ_FORMAT_UNSUPPORTED:
|
||||
@@ -732,10 +736,6 @@ void platform_linker(const char *output_file, const char **files, unsigned file_
|
||||
}
|
||||
|
||||
linker_setup(&parts, files, file_count, output_file, linker_type);
|
||||
if (link_libc())
|
||||
{
|
||||
vec_add(parts, "-lm");
|
||||
}
|
||||
const char *output = concat_string_parts(parts);
|
||||
if (active_target.print_linking) puts(output);
|
||||
if (system(output) != 0)
|
||||
@@ -812,14 +812,14 @@ bool dynamic_lib_linker(const char *output_file, const char **files, unsigned fi
|
||||
{
|
||||
INFO_LOG("Using linker directly.");
|
||||
const char **args = NULL;
|
||||
if (active_target.linker) vec_add(args, active_target.linker);
|
||||
LinkerType linker_type = linker_find_linker_type();
|
||||
if (active_target.linker_type == LINKER_TYPE_CUSTOM) vec_add(args, active_target.custom_linker_path);
|
||||
Linker linker_type = linker_find_linker_type();
|
||||
linker_setup(&args, files, file_count, output_file, linker_type);
|
||||
|
||||
const char *command = concat_string_parts(args);
|
||||
if (active_target.print_linking) puts(command);
|
||||
DEBUG_LOG("Linker arguments: %s to %d", command, platform_target.object_format);
|
||||
if (active_target.linker)
|
||||
if (active_target.linker_type == LINKER_TYPE_CUSTOM)
|
||||
{
|
||||
if (system(command) != 0)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user