mirror of
https://git.sr.ht/~lattis/muon
synced 2026-01-30 11:25:37 +00:00
1875 lines
46 KiB
C
1875 lines
46 KiB
C
/*
|
|
* SPDX-FileCopyrightText: Stone Tickle <lattis@mochiro.moe>
|
|
* SPDX-FileCopyrightText: illiliti <illiliti@dimension.sh>
|
|
* SPDX-FileCopyrightText: Owen Rafferty <owen@owenrafferty.com>
|
|
* SPDX-FileCopyrightText: illiliti <illiliti@thunix.net>
|
|
* SPDX-FileCopyrightText: Vincent Torri <vincent.torri@gmail.com>
|
|
* SPDX-License-Identifier: GPL-3.0-only
|
|
*/
|
|
|
|
#include "compat.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "args.h"
|
|
#include "buf_size.h"
|
|
#include "compilers.h"
|
|
#include "error.h"
|
|
#include "guess.h"
|
|
#include "lang/object_iterators.h"
|
|
#include "lang/typecheck.h"
|
|
#include "lang/workspace.h"
|
|
#include "log.h"
|
|
#include "machines.h"
|
|
#include "options.h"
|
|
#include "platform/path.h"
|
|
#include "platform/run_cmd.h"
|
|
|
|
struct toolchain_id {
|
|
const char *public_id;
|
|
const char *id;
|
|
};
|
|
#define TOOLCHAIN_NAME(_, public_id, id) { public_id, id },
|
|
static const struct toolchain_id compiler_type_name[] = { FOREACH_TOOLCHAIN_COMPILER_TYPE(TOOLCHAIN_NAME) };
|
|
static const struct toolchain_id linker_type_name[] = { FOREACH_TOOLCHAIN_LINKER_TYPE(TOOLCHAIN_NAME) };
|
|
static const struct toolchain_id static_linker_type_name[] = { FOREACH_TOOLCHAIN_STATIC_LINKER_TYPE(TOOLCHAIN_NAME) };
|
|
#undef TOOLCHAIN_CASE
|
|
|
|
static bool
|
|
toolchain_id_lookup(const char *name, const struct toolchain_id names[], uint32_t len, uint32_t *res)
|
|
{
|
|
uint32_t i;
|
|
for (i = 0; i < len; ++i) {
|
|
if (strcmp(name, names[i].id) == 0) {
|
|
*res = i;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
const char *
|
|
compiler_type_to_s(enum compiler_type t)
|
|
{
|
|
return compiler_type_name[t].public_id;
|
|
}
|
|
|
|
bool
|
|
compiler_type_from_s(const char *name, uint32_t *res)
|
|
{
|
|
return toolchain_id_lookup(name, compiler_type_name, ARRAY_LEN(compiler_type_name), res);
|
|
}
|
|
|
|
const char *
|
|
linker_type_to_s(enum linker_type t)
|
|
{
|
|
return linker_type_name[t].public_id;
|
|
}
|
|
|
|
bool
|
|
linker_type_from_s(const char *name, uint32_t *res)
|
|
{
|
|
return toolchain_id_lookup(name, linker_type_name, ARRAY_LEN(linker_type_name), res);
|
|
}
|
|
|
|
static const char *
|
|
static_linker_type_to_s(enum static_linker_type t)
|
|
{
|
|
return static_linker_type_name[t].public_id;
|
|
}
|
|
|
|
bool
|
|
static_linker_type_from_s(const char *name, uint32_t *res)
|
|
{
|
|
return toolchain_id_lookup(name, static_linker_type_name, ARRAY_LEN(static_linker_type_name), res);
|
|
}
|
|
|
|
static const char *compiler_language_names[compiler_language_count] = {
|
|
[compiler_language_null] = "null",
|
|
[compiler_language_c] = "c",
|
|
[compiler_language_c_hdr] = "c_hdr",
|
|
[compiler_language_cpp] = "cpp",
|
|
[compiler_language_cpp_hdr] = "cpp_hdr",
|
|
[compiler_language_c_obj] = "c_obj",
|
|
[compiler_language_objc] = "objc",
|
|
[compiler_language_objcpp] = "objcpp",
|
|
[compiler_language_assembly] = "assembly",
|
|
[compiler_language_llvm_ir] = "llvm_ir",
|
|
[compiler_language_nasm] = "nasm",
|
|
};
|
|
|
|
const char *
|
|
compiler_language_to_s(enum compiler_language l)
|
|
{
|
|
assert(l < compiler_language_count);
|
|
return compiler_language_names[l];
|
|
}
|
|
|
|
bool
|
|
s_to_compiler_language(const char *_s, enum compiler_language *l)
|
|
{
|
|
const struct str s = WKSTR(_s);
|
|
uint32_t i;
|
|
for (i = 0; i < compiler_language_count; ++i) {
|
|
if (str_eqli(&s, &WKSTR(compiler_language_names[i]))) {
|
|
*l = i;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
static const char *compiler_language_exts[compiler_language_count][10] = {
|
|
[compiler_language_c] = { "c" },
|
|
[compiler_language_c_hdr] = { "h" },
|
|
[compiler_language_cpp] = { "cc", "cpp", "cxx", "C" },
|
|
[compiler_language_cpp_hdr] = { "hh", "hpp", "hxx" },
|
|
[compiler_language_c_obj] = { "o", "obj" },
|
|
[compiler_language_objc] = { "m", "M" },
|
|
[compiler_language_objcpp] = { "mm" },
|
|
[compiler_language_assembly] = { "S", "s" },
|
|
[compiler_language_llvm_ir] = { "ll" },
|
|
[compiler_language_nasm] = { "asm" },
|
|
};
|
|
|
|
bool
|
|
filename_to_compiler_language(const char *str, enum compiler_language *l)
|
|
{
|
|
uint32_t i, j;
|
|
const char *ext;
|
|
|
|
if (!(ext = strrchr(str, '.'))) {
|
|
return false;
|
|
}
|
|
++ext;
|
|
|
|
for (i = 0; i < compiler_language_count; ++i) {
|
|
for (j = 0; compiler_language_exts[i][j]; ++j) {
|
|
if (strcmp(ext, compiler_language_exts[i][j]) == 0) {
|
|
*l = i;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
const char *
|
|
compiler_language_extension(enum compiler_language l)
|
|
{
|
|
return compiler_language_exts[l][0];
|
|
}
|
|
|
|
enum compiler_language
|
|
coalesce_link_languages(enum compiler_language cur, enum compiler_language new)
|
|
{
|
|
switch (new) {
|
|
case compiler_language_null:
|
|
case compiler_language_c_hdr:
|
|
case compiler_language_cpp_hdr:
|
|
case compiler_language_llvm_ir: break;
|
|
case compiler_language_assembly:
|
|
if (!cur) {
|
|
return compiler_language_assembly;
|
|
}
|
|
break;
|
|
case compiler_language_nasm:
|
|
case compiler_language_c:
|
|
case compiler_language_c_obj:
|
|
case compiler_language_objc:
|
|
if (!cur) {
|
|
return compiler_language_c;
|
|
}
|
|
break;
|
|
case compiler_language_cpp:
|
|
case compiler_language_objcpp:
|
|
if (!cur || cur == compiler_language_c || cur == compiler_language_assembly) {
|
|
return compiler_language_cpp;
|
|
}
|
|
break;
|
|
case compiler_language_count: UNREACHABLE;
|
|
}
|
|
|
|
return cur;
|
|
}
|
|
|
|
static bool
|
|
run_cmd_arr(struct workspace *wk, struct run_cmd_ctx *cmd_ctx, obj cmd_arr, const char *arg)
|
|
{
|
|
obj args;
|
|
obj_array_dup(wk, cmd_arr, &args);
|
|
obj_array_push(wk, args, make_str(wk, arg));
|
|
|
|
const char *argstr;
|
|
uint32_t argc;
|
|
join_args_argstr(wk, &argstr, &argc, args);
|
|
|
|
if (!run_cmd(cmd_ctx, argstr, argc, NULL, 0)) {
|
|
run_cmd_ctx_destroy(cmd_ctx);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
static const char *
|
|
guess_version_arg(struct workspace *wk, bool msvc_like)
|
|
{
|
|
if (msvc_like) {
|
|
return "/?";
|
|
} else {
|
|
return "--version";
|
|
}
|
|
}
|
|
|
|
static bool
|
|
compiler_detect_c_or_cpp(struct workspace *wk, obj cmd_arr, obj comp_id)
|
|
{
|
|
bool msvc_like = obj_array_in(wk, cmd_arr, make_str(wk, "cl"));
|
|
|
|
// helpful: mesonbuild/compilers/detect.py:350
|
|
struct run_cmd_ctx cmd_ctx = { 0 };
|
|
if (!run_cmd_arr(wk, &cmd_ctx, cmd_arr, guess_version_arg(wk, msvc_like))) {
|
|
run_cmd_ctx_destroy(&cmd_ctx);
|
|
return false;
|
|
}
|
|
|
|
enum compiler_type type;
|
|
bool unknown = true;
|
|
obj ver;
|
|
|
|
if (cmd_ctx.status != 0) {
|
|
goto detection_over;
|
|
}
|
|
|
|
if (strstr(cmd_ctx.out.buf, "clang") || strstr(cmd_ctx.out.buf, "Clang")) {
|
|
if (strstr(cmd_ctx.out.buf, "Apple") && strstr(cmd_ctx.out.buf, "clang")) {
|
|
type = compiler_apple_clang;
|
|
} else if (strstr(cmd_ctx.out.buf, "CL.EXE COMPATIBILITY")) {
|
|
type = compiler_clang_cl;
|
|
} else {
|
|
type = compiler_clang;
|
|
}
|
|
} else if (strstr(cmd_ctx.out.buf, "Free Software Foundation")) {
|
|
type = compiler_gcc;
|
|
} else if (strstr(cmd_ctx.out.buf, "Microsoft") || strstr(cmd_ctx.err.buf, "Microsoft")) {
|
|
type = compiler_msvc;
|
|
} else {
|
|
goto detection_over;
|
|
}
|
|
|
|
if (!guess_version(wk, (type == compiler_msvc) ? cmd_ctx.err.buf : cmd_ctx.out.buf, &ver)) {
|
|
ver = make_str(wk, "unknown");
|
|
}
|
|
|
|
unknown = false;
|
|
|
|
detection_over:
|
|
if (unknown) {
|
|
LOG_W("unable to detect compiler type, falling back on posix compiler");
|
|
type = compiler_posix;
|
|
ver = make_str(wk, "unknown");
|
|
}
|
|
|
|
struct obj_compiler *comp = get_obj_compiler(wk, comp_id);
|
|
comp->cmd_arr = cmd_arr;
|
|
comp->type[toolchain_component_compiler] = type;
|
|
comp->ver = ver;
|
|
|
|
run_cmd_ctx_destroy(&cmd_ctx);
|
|
return true;
|
|
}
|
|
|
|
static bool
|
|
compiler_detect_nasm(struct workspace *wk, obj cmd_arr, obj comp_id)
|
|
{
|
|
struct run_cmd_ctx cmd_ctx = { 0 };
|
|
if (!run_cmd_arr(wk, &cmd_ctx, cmd_arr, "--version")
|
|
|| strstr(cmd_ctx.err.buf, "nasm: error: unable to find utility")) {
|
|
run_cmd_ctx_destroy(&cmd_ctx);
|
|
return false;
|
|
}
|
|
|
|
enum compiler_type type;
|
|
obj ver;
|
|
|
|
if (strstr(cmd_ctx.out.buf, "NASM")) {
|
|
type = compiler_nasm;
|
|
} else if (strstr(cmd_ctx.out.buf, "yasm")) {
|
|
type = compiler_yasm;
|
|
} else {
|
|
// Just assume it is nasm
|
|
type = compiler_nasm;
|
|
}
|
|
|
|
if (!guess_version(wk, cmd_ctx.out.buf, &ver)) {
|
|
ver = make_str(wk, "unknown");
|
|
}
|
|
|
|
obj new_cmd;
|
|
obj_array_dup(wk, cmd_arr, &new_cmd);
|
|
|
|
{
|
|
uint32_t addr_bits = host_machine.address_bits;
|
|
|
|
const char *plat;
|
|
SBUF(define);
|
|
|
|
if (host_machine.is_windows) {
|
|
plat = "win";
|
|
sbuf_pushf(wk, &define, "WIN%d", addr_bits);
|
|
} else if (host_machine.sys == machine_system_darwin) {
|
|
plat = "macho";
|
|
sbuf_pushs(wk, &define, "MACHO");
|
|
} else {
|
|
plat = "elf";
|
|
sbuf_pushs(wk, &define, "ELF");
|
|
}
|
|
|
|
obj_array_push(wk, new_cmd, make_strf(wk, "-f%s%d", plat, addr_bits));
|
|
obj_array_push(wk, new_cmd, make_strf(wk, "-D%s", define.buf));
|
|
if (addr_bits == 64) {
|
|
obj_array_push(wk, new_cmd, make_str(wk, "-D__x86_64__"));
|
|
}
|
|
}
|
|
|
|
struct obj_compiler *comp = get_obj_compiler(wk, comp_id);
|
|
comp->cmd_arr = new_cmd;
|
|
comp->type[toolchain_component_compiler] = type;
|
|
comp->ver = ver;
|
|
comp->lang = compiler_language_nasm;
|
|
|
|
run_cmd_ctx_destroy(&cmd_ctx);
|
|
return true;
|
|
}
|
|
|
|
static bool
|
|
compiler_get_libdirs(struct workspace *wk, struct obj_compiler *comp)
|
|
{
|
|
struct run_cmd_ctx cmd_ctx = { 0 };
|
|
if (!run_cmd_arr(wk, &cmd_ctx, comp->cmd_arr, "-print-search-dirs") || cmd_ctx.status) {
|
|
goto done;
|
|
}
|
|
|
|
const char *key = "libraries: ";
|
|
char *s, *e;
|
|
bool beginning_of_line = true;
|
|
for (s = cmd_ctx.out.buf; *s; ++s) {
|
|
if (beginning_of_line && strncmp(s, key, strlen(key)) == 0) {
|
|
s += strlen(key);
|
|
if (*s == '=') {
|
|
++s;
|
|
}
|
|
|
|
e = strchr(s, '\n');
|
|
|
|
struct str str = {
|
|
.s = s,
|
|
.len = e ? (uint32_t)(e - s) : strlen(s),
|
|
};
|
|
|
|
comp->libdirs = str_split(wk, &str, &WKSTR(ENV_PATH_SEP_STR));
|
|
goto done;
|
|
}
|
|
|
|
beginning_of_line = *s == '\n';
|
|
}
|
|
|
|
done:
|
|
run_cmd_ctx_destroy(&cmd_ctx);
|
|
|
|
if (!comp->libdirs) {
|
|
const char *libdirs[] = { "/usr/lib", "/usr/local/lib", "/lib", NULL };
|
|
|
|
make_obj(wk, &comp->libdirs, obj_array);
|
|
|
|
uint32_t i;
|
|
for (i = 0; libdirs[i]; ++i) {
|
|
obj_array_push(wk, comp->libdirs, make_str(wk, libdirs[i]));
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
static void
|
|
compiler_refine_host_machine(struct workspace *wk, struct obj_compiler *comp)
|
|
{
|
|
struct run_cmd_ctx cmd_ctx = { 0 };
|
|
if (run_cmd_arr(wk, &cmd_ctx, comp->cmd_arr, "-dumpmachine") && cmd_ctx.status == 0) {
|
|
machine_parse_and_apply_triplet(&host_machine, cmd_ctx.out.buf);
|
|
}
|
|
run_cmd_ctx_destroy(&cmd_ctx);
|
|
|
|
// TODO: check for macros like ILP32 and x86_64
|
|
}
|
|
|
|
static bool
|
|
compiler_detect_cmd_arr(struct workspace *wk, obj comp, enum compiler_language lang, obj cmd_arr)
|
|
{
|
|
if (log_should_print(log_debug)) {
|
|
obj_fprintf(wk, log_file(), "checking compiler %o\n", cmd_arr);
|
|
}
|
|
|
|
switch (lang) {
|
|
case compiler_language_c:
|
|
case compiler_language_cpp:
|
|
case compiler_language_objc:
|
|
case compiler_language_objcpp:
|
|
if (!compiler_detect_c_or_cpp(wk, cmd_arr, comp)) {
|
|
return false;
|
|
}
|
|
|
|
struct obj_compiler *compiler = get_obj_compiler(wk, comp);
|
|
compiler_get_libdirs(wk, compiler);
|
|
|
|
compiler_refine_host_machine(wk, compiler);
|
|
|
|
compiler->lang = lang;
|
|
|
|
compiler->linker_passthrough = compiler->type[toolchain_component_compiler] != compiler_msvc;
|
|
return true;
|
|
case compiler_language_nasm:
|
|
if (!compiler_detect_nasm(wk, cmd_arr, comp)) {
|
|
return false;
|
|
}
|
|
return true;
|
|
default:
|
|
LOG_E("tried to get a compiler for unsupported language '%s'", compiler_language_to_s(lang));
|
|
return false;
|
|
}
|
|
}
|
|
|
|
static bool
|
|
static_linker_detect(struct workspace *wk, obj comp, enum compiler_language lang, obj cmd_arr)
|
|
{
|
|
struct obj_compiler *compiler = get_obj_compiler(wk, comp);
|
|
|
|
struct run_cmd_ctx cmd_ctx = { 0 };
|
|
if (!run_cmd_arr(wk,
|
|
&cmd_ctx,
|
|
cmd_arr,
|
|
guess_version_arg(wk, compiler->type[toolchain_component_compiler] == compiler_msvc))) {
|
|
run_cmd_ctx_destroy(&cmd_ctx);
|
|
return false;
|
|
}
|
|
|
|
enum static_linker_type type = compiler->type[toolchain_component_compiler] == compiler_msvc ?
|
|
static_linker_msvc :
|
|
static_linker_ar_posix;
|
|
|
|
if (cmd_ctx.status == 0 && strstr(cmd_ctx.out.buf, "Free Software Foundation")) {
|
|
type = static_linker_ar_gcc;
|
|
}
|
|
|
|
run_cmd_ctx_destroy(&cmd_ctx);
|
|
|
|
get_obj_compiler(wk, comp)->static_linker_cmd_arr = cmd_arr;
|
|
get_obj_compiler(wk, comp)->type[toolchain_component_static_linker] = type;
|
|
return true;
|
|
}
|
|
|
|
static bool
|
|
linker_detect(struct workspace *wk, obj comp, enum compiler_language lang, obj cmd_arr)
|
|
{
|
|
struct obj_compiler *compiler = get_obj_compiler(wk, comp);
|
|
|
|
bool msvc_like = compiler->type[toolchain_component_compiler] == compiler_msvc;
|
|
|
|
enum linker_type type = compilers[compiler->type[toolchain_component_compiler]].default_linker;
|
|
if (host_machine.sys == machine_system_windows) {
|
|
if (compiler->type[toolchain_component_compiler] == compiler_clang) {
|
|
type = linker_lld_link;
|
|
msvc_like = true;
|
|
}
|
|
}
|
|
|
|
struct run_cmd_ctx cmd_ctx = { 0 };
|
|
if (!run_cmd_arr(wk, &cmd_ctx, cmd_arr, guess_version_arg(wk, msvc_like))) {
|
|
run_cmd_ctx_destroy(&cmd_ctx);
|
|
return false;
|
|
}
|
|
|
|
// TODO: do something with command output?
|
|
|
|
run_cmd_ctx_destroy(&cmd_ctx);
|
|
|
|
get_obj_compiler(wk, comp)->linker_cmd_arr = cmd_arr;
|
|
get_obj_compiler(wk, comp)->type[toolchain_component_linker] = type;
|
|
return true;
|
|
}
|
|
|
|
typedef bool((*toolchain_detect_cmd_arr_cb)(struct workspace *wk, obj comp, enum compiler_language lang, obj cmd_arr));
|
|
|
|
bool
|
|
toolchain_exe_detect(struct workspace *wk,
|
|
const char *toolchain_exe_option_name,
|
|
const char *exe_list[],
|
|
obj comp,
|
|
enum compiler_language lang,
|
|
toolchain_detect_cmd_arr_cb cb)
|
|
{
|
|
if (!toolchain_exe_option_name) {
|
|
return false;
|
|
}
|
|
|
|
obj cmd_arr_opt;
|
|
get_option(wk, NULL, &WKSTR(toolchain_exe_option_name), &cmd_arr_opt);
|
|
struct obj_option *cmd_arr = get_obj_option(wk, cmd_arr_opt);
|
|
|
|
if (cmd_arr->source > option_value_source_default) {
|
|
return cb(wk, comp, lang, cmd_arr->val);
|
|
}
|
|
|
|
uint32_t i;
|
|
for (i = 0; exe_list[i]; ++i) {
|
|
obj cmd_arr;
|
|
make_obj(wk, &cmd_arr, obj_array);
|
|
obj_array_push(wk, cmd_arr, make_str(wk, exe_list[i]));
|
|
|
|
if (cb(wk, comp, lang, cmd_arr)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
static bool
|
|
toolchain_linker_detect(struct workspace *wk, obj comp, enum compiler_language lang)
|
|
{
|
|
struct obj_compiler *compiler = get_obj_compiler(wk, comp);
|
|
|
|
enum linker_type t = compilers[compiler->type[toolchain_component_compiler]].default_linker;
|
|
if (host_machine.sys == machine_system_windows) {
|
|
if (compiler->type[toolchain_component_compiler] == compiler_clang) {
|
|
t = linker_lld_link;
|
|
}
|
|
}
|
|
|
|
const char *exe_list[] = { linker_type_to_s(t), "ld", NULL };
|
|
|
|
return toolchain_exe_detect(wk, "env.LD", exe_list, comp, lang, linker_detect);
|
|
}
|
|
|
|
static bool
|
|
toolchain_static_linker_detect(struct workspace *wk, obj comp, enum compiler_language lang)
|
|
{
|
|
const char **exe_list = NULL;
|
|
|
|
struct obj_compiler *compiler = get_obj_compiler(wk, comp);
|
|
|
|
if (compiler->type[toolchain_component_compiler] == compiler_msvc) {
|
|
static const char *msvc_list[] = { "lib", NULL };
|
|
exe_list = msvc_list;
|
|
} else {
|
|
static const char *default_list[] = { "ar", "llvm-ar", NULL };
|
|
exe_list = default_list;
|
|
}
|
|
|
|
return toolchain_exe_detect(wk, "env.AR", exe_list, comp, lang, static_linker_detect);
|
|
}
|
|
|
|
static bool
|
|
toolchain_compiler_detect(struct workspace *wk, obj comp, enum compiler_language lang)
|
|
{
|
|
static const char *compiler_option[compiler_language_count] = {
|
|
[compiler_language_c] = "env.CC",
|
|
[compiler_language_cpp] = "env.CXX",
|
|
[compiler_language_objc] = "env.OBJC",
|
|
[compiler_language_objcpp] = "env.OBJCPP",
|
|
[compiler_language_nasm] = "env.NASM",
|
|
};
|
|
|
|
const char **exe_list = NULL;
|
|
|
|
if (host_machine.sys == machine_system_windows) {
|
|
static const char *default_executables[][compiler_language_count] = {
|
|
[compiler_language_c] = { "cl", "cc", "gcc", "clang", "clang-cl", NULL },
|
|
[compiler_language_cpp] = { "cl", "c++", "g++", "clang++", "clang-cl", NULL },
|
|
[compiler_language_objc] = { "cc", "gcc", NULL },
|
|
[compiler_language_objcpp] = { "c++", "g++", "clang++", "clang-cl", NULL },
|
|
[compiler_language_nasm] = { "nasm", "yasm", NULL },
|
|
};
|
|
|
|
exe_list = default_executables[lang];
|
|
} else {
|
|
static const char *default_executables[][compiler_language_count] = {
|
|
[compiler_language_c] = { "cc", "gcc", "clang", NULL },
|
|
[compiler_language_cpp] = { "c++", "g++", "clang++", NULL },
|
|
[compiler_language_objc] = { "cc", "gcc", "clang", NULL },
|
|
[compiler_language_objcpp] = { "c++", "g++", "clang++", NULL },
|
|
[compiler_language_nasm] = { "nasm", "yasm", NULL },
|
|
};
|
|
|
|
exe_list = default_executables[lang];
|
|
}
|
|
|
|
return toolchain_exe_detect(wk, compiler_option[lang], exe_list, comp, lang, compiler_detect_cmd_arr);
|
|
}
|
|
|
|
bool
|
|
toolchain_detect(struct workspace *wk, obj *comp, enum compiler_language lang)
|
|
{
|
|
make_obj(wk, comp, obj_compiler);
|
|
|
|
if (!toolchain_compiler_detect(wk, *comp, lang)) {
|
|
LOG_E("failed to detect compiler");
|
|
return false;
|
|
}
|
|
|
|
if (!toolchain_linker_detect(wk, *comp, lang)) {
|
|
LOG_E("failed to detect linker");
|
|
return false;
|
|
}
|
|
|
|
if (!toolchain_static_linker_detect(wk, *comp, lang)) {
|
|
LOG_E("failed to detect static linker");
|
|
return false;
|
|
}
|
|
|
|
struct obj_compiler *compiler = get_obj_compiler(wk, *comp);
|
|
|
|
LLOG_I("detected compiler %s ", compiler_type_to_s(compiler->type[toolchain_component_compiler]));
|
|
obj_fprintf(wk,
|
|
log_file(),
|
|
"%o (%o), linker: %s (%o), static_linker: %s (%o)\n",
|
|
compiler->ver,
|
|
compiler->cmd_arr,
|
|
linker_type_to_s(compiler->type[toolchain_component_linker]),
|
|
compiler->linker_cmd_arr,
|
|
static_linker_type_to_s(compiler->type[toolchain_component_static_linker]),
|
|
compiler->static_linker_cmd_arr);
|
|
|
|
return true;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* Toolchain args
|
|
******************************************************************************/
|
|
|
|
#define TOOLCHAIN_ARGS(...) \
|
|
static const char *argv[] = __VA_ARGS__; \
|
|
static struct args args = { .args = argv, .len = ARRAY_LEN(argv) };
|
|
|
|
#define TOOLCHAIN_ARGS_RETURN static const struct args *
|
|
#define TOOLCHAIN_PROTO_0(name) TOOLCHAIN_ARGS_RETURN name(TOOLCHAIN_SIG_0)
|
|
#define TOOLCHAIN_PROTO_1i(name) TOOLCHAIN_ARGS_RETURN name(TOOLCHAIN_SIG_1i)
|
|
#define TOOLCHAIN_PROTO_1s(name) TOOLCHAIN_ARGS_RETURN name(TOOLCHAIN_SIG_1s)
|
|
#define TOOLCHAIN_PROTO_2s(name) TOOLCHAIN_ARGS_RETURN name(TOOLCHAIN_SIG_2s)
|
|
#define TOOLCHAIN_PROTO_1s1b(name) TOOLCHAIN_ARGS_RETURN name(TOOLCHAIN_SIG_1s1b)
|
|
#define TOOLCHAIN_PROTO_ns(name) TOOLCHAIN_ARGS_RETURN name(TOOLCHAIN_SIG_ns)
|
|
|
|
/* empty functions */
|
|
|
|
TOOLCHAIN_PROTO_0(toolchain_arg_empty_0)
|
|
{
|
|
TOOLCHAIN_ARGS({ NULL });
|
|
args.len = 0;
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_1i(toolchain_arg_empty_1i)
|
|
{
|
|
TOOLCHAIN_ARGS({ NULL });
|
|
args.len = 0;
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_1s(toolchain_arg_empty_1s)
|
|
{
|
|
TOOLCHAIN_ARGS({ NULL });
|
|
args.len = 0;
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_2s(toolchain_arg_empty_2s)
|
|
{
|
|
TOOLCHAIN_ARGS({ NULL });
|
|
args.len = 0;
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_1s1b(toolchain_arg_empty_1s1b)
|
|
{
|
|
TOOLCHAIN_ARGS({ NULL });
|
|
args.len = 0;
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_ns(toolchain_arg_empty_ns)
|
|
{
|
|
return a;
|
|
}
|
|
|
|
/* posix compilers */
|
|
|
|
TOOLCHAIN_PROTO_0(compiler_posix_args_object_extension)
|
|
{
|
|
TOOLCHAIN_ARGS({ ".o" });
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_0(compiler_posix_args_compile_only)
|
|
{
|
|
TOOLCHAIN_ARGS({ "-c" });
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_0(compiler_posix_args_preprocess_only)
|
|
{
|
|
TOOLCHAIN_ARGS({ "-E" });
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_1s(compiler_posix_args_output)
|
|
{
|
|
TOOLCHAIN_ARGS({ "-o", NULL });
|
|
|
|
argv[1] = a;
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_1i(compiler_posix_args_optimization)
|
|
{
|
|
TOOLCHAIN_ARGS({ NULL });
|
|
|
|
switch ((enum compiler_optimization_lvl)a) {
|
|
case compiler_optimization_lvl_0: argv[0] = "-O0"; break;
|
|
case compiler_optimization_lvl_1:
|
|
case compiler_optimization_lvl_2:
|
|
case compiler_optimization_lvl_3: argv[0] = "-O1"; break;
|
|
case compiler_optimization_lvl_none:
|
|
case compiler_optimization_lvl_g:
|
|
case compiler_optimization_lvl_s: args.len = 0; break;
|
|
}
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_0(compiler_posix_args_debug)
|
|
{
|
|
TOOLCHAIN_ARGS({ "-g" });
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_1s(compiler_posix_args_include)
|
|
{
|
|
TOOLCHAIN_ARGS({ "-I", NULL });
|
|
|
|
argv[1] = a;
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_1s(compiler_posix_args_define)
|
|
{
|
|
TOOLCHAIN_ARGS({ "-D", NULL });
|
|
|
|
argv[1] = a;
|
|
|
|
return &args;
|
|
}
|
|
|
|
/* gcc compilers */
|
|
|
|
TOOLCHAIN_PROTO_ns(linker_args_passthrough)
|
|
{
|
|
static char buf[BUF_SIZE_S], buf2[BUF_SIZE_S];
|
|
TOOLCHAIN_ARGS({ buf, NULL, buf2 });
|
|
|
|
if (a->len == 0) {
|
|
return a;
|
|
} else if (a->len == 1) {
|
|
const char *passthrough_blacklist[] = {
|
|
"-shared",
|
|
"-bundle",
|
|
"-dynamiclib",
|
|
};
|
|
|
|
uint32_t i;
|
|
for (i = 0; i < ARRAY_LEN(passthrough_blacklist); ++i) {
|
|
if (strcmp(passthrough_blacklist[i], a->args[0]) == 0) {
|
|
return a;
|
|
}
|
|
}
|
|
|
|
snprintf(buf, BUF_SIZE_S, "-Wl,%s", a->args[0]);
|
|
args.len = 1;
|
|
} else if (a->len == 2) {
|
|
snprintf(buf, BUF_SIZE_S, "-Wl,%s,%s", a->args[0], a->args[1]);
|
|
args.len = 1;
|
|
} else if (a->len == 3) {
|
|
snprintf(buf, BUF_SIZE_S, "-Wl,%s", a->args[0]);
|
|
argv[1] = a->args[1];
|
|
snprintf(buf2, BUF_SIZE_S, "-Wl,%s", a->args[2]);
|
|
args.len = 3;
|
|
} else {
|
|
UNREACHABLE;
|
|
}
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_0(compiler_gcc_args_preprocess_only)
|
|
{
|
|
TOOLCHAIN_ARGS({ "-E", "-P" });
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_1s(compiler_gcc_args_include_system)
|
|
{
|
|
TOOLCHAIN_ARGS({ "-isystem", NULL });
|
|
|
|
argv[1] = a;
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_2s(compiler_gcc_args_deps)
|
|
{
|
|
TOOLCHAIN_ARGS({ "-MD", "-MQ", NULL, "-MF", NULL });
|
|
|
|
argv[2] = a;
|
|
argv[4] = b;
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_1i(compiler_gcc_args_optimization)
|
|
{
|
|
TOOLCHAIN_ARGS({ NULL });
|
|
|
|
switch ((enum compiler_optimization_lvl)a) {
|
|
case compiler_optimization_lvl_none: args.len = 0; break;
|
|
case compiler_optimization_lvl_0: argv[0] = "-O0"; break;
|
|
case compiler_optimization_lvl_1: argv[0] = "-O1"; break;
|
|
case compiler_optimization_lvl_2: argv[0] = "-O2"; break;
|
|
case compiler_optimization_lvl_3: argv[0] = "-O3"; break;
|
|
case compiler_optimization_lvl_g: argv[0] = "-Og"; break;
|
|
case compiler_optimization_lvl_s: argv[0] = "-Os"; break;
|
|
}
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_1i(compiler_gcc_args_warning_lvl)
|
|
{
|
|
TOOLCHAIN_ARGS({ NULL, NULL, NULL });
|
|
|
|
args.len = 0;
|
|
|
|
switch ((enum compiler_warning_lvl)a) {
|
|
case compiler_warning_lvl_everything: UNREACHABLE; break;
|
|
case compiler_warning_lvl_3: argv[args.len] = "-Wpedantic"; ++args.len;
|
|
/* fallthrough */
|
|
case compiler_warning_lvl_2: argv[args.len] = "-Wextra"; ++args.len;
|
|
/* fallthrough */
|
|
case compiler_warning_lvl_1: argv[args.len] = "-Wall"; ++args.len;
|
|
/* fallthrough */
|
|
case compiler_warning_lvl_0: break;
|
|
}
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_0(compiler_gcc_args_werror)
|
|
{
|
|
TOOLCHAIN_ARGS({ "-Werror" });
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_0(compiler_gcc_args_warn_everything)
|
|
{
|
|
TOOLCHAIN_ARGS({ "-Wall",
|
|
"-Winvalid-pch",
|
|
"-Wextra",
|
|
"-Wpedantic",
|
|
"-Wcast-qual",
|
|
"-Wconversion",
|
|
"-Wfloat-equal",
|
|
"-Wformat=2",
|
|
"-Winline",
|
|
"-Wmissing-declarations",
|
|
"-Wredundant-decls",
|
|
"-Wshadow",
|
|
"-Wundef",
|
|
"-Wuninitialized",
|
|
"-Wwrite-strings",
|
|
"-Wdisabled-optimization",
|
|
"-Wpacked",
|
|
"-Wpadded",
|
|
"-Wmultichar",
|
|
"-Wswitch-default",
|
|
"-Wswitch-enum",
|
|
"-Wunused-macros",
|
|
"-Wmissing-include-dirs",
|
|
"-Wunsafe-loop-optimizations",
|
|
"-Wstack-protector",
|
|
"-Wstrict-overflow=5",
|
|
"-Warray-bounds=2",
|
|
"-Wlogical-op",
|
|
"-Wstrict-aliasing=3",
|
|
"-Wvla",
|
|
"-Wdouble-promotion",
|
|
"-Wsuggest-attribute=const",
|
|
"-Wsuggest-attribute=noreturn",
|
|
"-Wsuggest-attribute=pure",
|
|
"-Wtrampolines",
|
|
"-Wvector-operation-performance",
|
|
"-Wsuggest-attribute=format",
|
|
"-Wdate-time",
|
|
"-Wformat-signedness",
|
|
"-Wnormalized=nfc",
|
|
"-Wduplicated-cond",
|
|
"-Wnull-dereference",
|
|
"-Wshift-negative-value",
|
|
"-Wshift-overflow=2",
|
|
"-Wunused-const-variable=2",
|
|
"-Walloca",
|
|
"-Walloc-zero",
|
|
"-Wformat-overflow=2",
|
|
"-Wformat-truncation=2",
|
|
"-Wstringop-overflow=3",
|
|
"-Wduplicated-branches",
|
|
"-Wattribute-alias=2",
|
|
"-Wcast-align=strict",
|
|
"-Wsuggest-attribute=cold",
|
|
"-Wsuggest-attribute=malloc",
|
|
"-Wanalyzer-too-complex",
|
|
"-Warith-conversion",
|
|
"-Wbidi-chars=ucn",
|
|
"-Wopenacc-parallelism",
|
|
"-Wtrivial-auto-var-init",
|
|
"-Wbad-function-cast",
|
|
"-Wmissing-prototypes",
|
|
"-Wnested-externs",
|
|
"-Wstrict-prototypes",
|
|
"-Wold-style-definition",
|
|
"-Winit-self",
|
|
"-Wc++-compat",
|
|
"-Wunsuffixed-float-constants" });
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_0(compiler_clang_args_warn_everything)
|
|
{
|
|
TOOLCHAIN_ARGS({ "-Weverything" });
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_1s(compiler_gcc_args_set_std)
|
|
{
|
|
static char buf[BUF_SIZE_S];
|
|
TOOLCHAIN_ARGS({ buf });
|
|
|
|
snprintf(buf, BUF_SIZE_S, "-std=%s", a);
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_1i(compiler_gcc_args_pgo)
|
|
{
|
|
TOOLCHAIN_ARGS({ NULL, NULL });
|
|
|
|
args.len = 1;
|
|
|
|
switch ((enum compiler_pgo_stage)a) {
|
|
case compiler_pgo_generate: argv[0] = "-fprofile-generate"; break;
|
|
case compiler_pgo_use:
|
|
argv[1] = "-fprofile-correction";
|
|
++args.len;
|
|
argv[0] = "-fprofile-use";
|
|
break;
|
|
}
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_0(compiler_gcc_args_pic)
|
|
{
|
|
TOOLCHAIN_ARGS({ "-fpic" });
|
|
|
|
if (host_machine.is_windows) {
|
|
args.len = 0;
|
|
} else {
|
|
args.len = 1;
|
|
}
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_0(compiler_gcc_args_pie)
|
|
{
|
|
TOOLCHAIN_ARGS({ "-fpie" });
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_1s(compiler_gcc_args_sanitize)
|
|
{
|
|
static char buf[BUF_SIZE_S];
|
|
TOOLCHAIN_ARGS({ buf });
|
|
|
|
snprintf(buf, BUF_SIZE_S, "-fsanitize=%s", a);
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_1i(compiler_gcc_args_visibility)
|
|
{
|
|
TOOLCHAIN_ARGS({ NULL, NULL });
|
|
|
|
args.len = 1;
|
|
|
|
switch ((enum compiler_visibility_type)a) {
|
|
case compiler_visibility_default: argv[0] = "-fvisibility=default"; break;
|
|
case compiler_visibility_internal: argv[0] = "-fvisibility=internal"; break;
|
|
case compiler_visibility_protected: argv[0] = "-fvisibility=protected"; break;
|
|
case compiler_visibility_inlineshidden: argv[1] = "-fvisibility-inlines-hidden"; ++args.len;
|
|
// fallthrough
|
|
case compiler_visibility_hidden: argv[0] = "-fvisibility=hidden"; break;
|
|
default: assert(false && "unreachable");
|
|
}
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_1s(compiler_gcc_args_specify_lang)
|
|
{
|
|
TOOLCHAIN_ARGS({
|
|
"-x",
|
|
NULL,
|
|
});
|
|
|
|
argv[1] = a;
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_1s(compiler_gcc_args_color_output)
|
|
{
|
|
static char buf[BUF_SIZE_S];
|
|
TOOLCHAIN_ARGS({ buf });
|
|
|
|
snprintf(buf, BUF_SIZE_S, "-fdiagnostics-color=%s", a);
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_0(compiler_gcc_args_lto)
|
|
{
|
|
TOOLCHAIN_ARGS({ "-flto" });
|
|
|
|
return &args;
|
|
}
|
|
|
|
/* cl compilers
|
|
* see mesonbuild/compilers/mixins/visualstudio.py for reference
|
|
*/
|
|
|
|
TOOLCHAIN_PROTO_0(compiler_cl_args_always)
|
|
{
|
|
TOOLCHAIN_ARGS({ "/nologo" });
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_1s1b(compiler_cl_args_crt)
|
|
{
|
|
TOOLCHAIN_ARGS({ NULL });
|
|
|
|
if (strcmp(a, "from_buildtype") == 0) {
|
|
argv[0] = b ? "/MDd" : "/MD";
|
|
} else if (strcmp(a, "static_from_buildtype") == 0) {
|
|
argv[0] = b ? "/MTd" : "/MT";
|
|
} else {
|
|
argv[0] = a;
|
|
}
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_1s(compiler_cl_args_debugfile)
|
|
{
|
|
static char buf[BUF_SIZE_S];
|
|
TOOLCHAIN_ARGS({ buf });
|
|
|
|
snprintf(buf, BUF_SIZE_S, "/Fd%s.pdb", a);
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_2s(compiler_cl_args_deps)
|
|
{
|
|
TOOLCHAIN_ARGS({ "/showIncludes" });
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_0(compiler_cl_args_compile_only)
|
|
{
|
|
TOOLCHAIN_ARGS({ "/c" });
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_0(compiler_cl_args_preprocess_only)
|
|
{
|
|
TOOLCHAIN_ARGS({ "/EP" });
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_1s(compiler_cl_args_output)
|
|
{
|
|
static char buf[BUF_SIZE_S];
|
|
TOOLCHAIN_ARGS({ buf });
|
|
|
|
if (str_endswithi(&WKSTR(a), &WKSTR(".exe"))) {
|
|
snprintf(buf, BUF_SIZE_S, "/Fe%s", a);
|
|
} else {
|
|
snprintf(buf, BUF_SIZE_S, "/Fo%s", a);
|
|
}
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_1i(compiler_cl_args_optimization)
|
|
{
|
|
TOOLCHAIN_ARGS({ NULL, NULL });
|
|
switch ((enum compiler_optimization_lvl)a) {
|
|
case compiler_optimization_lvl_none:
|
|
case compiler_optimization_lvl_g: args.len = 0; break;
|
|
case compiler_optimization_lvl_0:
|
|
args.len = 1;
|
|
argv[0] = "/Od";
|
|
break;
|
|
case compiler_optimization_lvl_1:
|
|
args.len = 1;
|
|
argv[0] = "/O1";
|
|
break;
|
|
case compiler_optimization_lvl_2:
|
|
args.len = 1;
|
|
argv[0] = "/O2";
|
|
break;
|
|
case compiler_optimization_lvl_3:
|
|
args.len = 2;
|
|
argv[0] = "/O2";
|
|
argv[1] = "/Gw";
|
|
break;
|
|
case compiler_optimization_lvl_s:
|
|
args.len = 2;
|
|
argv[0] = "/O1";
|
|
argv[1] = "/Gw";
|
|
break;
|
|
}
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_0(compiler_cl_args_debug)
|
|
{
|
|
TOOLCHAIN_ARGS({ "/Zi" });
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_1i(compiler_cl_args_warning_lvl)
|
|
{
|
|
/* meson uses nothing instead of /W0, but it's the same warning level
|
|
* see: https://mesonbuild.com/Builtin-options.html#details-for-warning_level
|
|
*/
|
|
|
|
TOOLCHAIN_ARGS({ NULL });
|
|
|
|
switch ((enum compiler_warning_lvl)a) {
|
|
case compiler_warning_lvl_0: args.len = 0; break;
|
|
case compiler_warning_lvl_1: argv[0] = "/W2"; break;
|
|
case compiler_warning_lvl_2: argv[0] = "/W3"; break;
|
|
case compiler_warning_lvl_everything:
|
|
case compiler_warning_lvl_3: argv[0] = "/W4"; break;
|
|
}
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_0(compiler_cl_args_warn_everything)
|
|
{
|
|
TOOLCHAIN_ARGS({ "/Wall" });
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_0(compiler_cl_args_werror)
|
|
{
|
|
TOOLCHAIN_ARGS({ "/WX" });
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_1s(compiler_cl_args_set_std)
|
|
{
|
|
static char buf[BUF_SIZE_S];
|
|
TOOLCHAIN_ARGS({ buf });
|
|
snprintf(buf, BUF_SIZE_S, "/std:%s", a);
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_1s(compiler_cl_args_include)
|
|
{
|
|
TOOLCHAIN_ARGS({ "/I", NULL });
|
|
|
|
argv[1] = a;
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_1s(compiler_cl_args_sanitize)
|
|
{
|
|
static char buf[BUF_SIZE_S];
|
|
TOOLCHAIN_ARGS({ buf });
|
|
snprintf(buf, BUF_SIZE_S, "-fsanitize=%s", a);
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_1s(compiler_cl_args_define)
|
|
{
|
|
TOOLCHAIN_ARGS({ "/D", NULL });
|
|
|
|
argv[1] = a;
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_0(compiler_cl_args_object_extension)
|
|
{
|
|
TOOLCHAIN_ARGS({ ".obj" });
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_1s(compiler_clang_cl_args_color_output)
|
|
{
|
|
TOOLCHAIN_ARGS({ "-fcolor-diagnostics" });
|
|
|
|
return &args;
|
|
(void)a;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_0(compiler_clang_cl_args_lto)
|
|
{
|
|
TOOLCHAIN_ARGS({ "-flto" });
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_0(compiler_deps_gcc)
|
|
{
|
|
TOOLCHAIN_ARGS({ "gcc" });
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_0(compiler_deps_msvc)
|
|
{
|
|
TOOLCHAIN_ARGS({ "msvc" });
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_1s(linker_posix_args_lib)
|
|
{
|
|
TOOLCHAIN_ARGS({ "-l", NULL });
|
|
argv[1] = a;
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_2s(linker_posix_args_input_output)
|
|
{
|
|
TOOLCHAIN_ARGS({ NULL, NULL });
|
|
argv[0] = b;
|
|
argv[1] = a;
|
|
return &args;
|
|
}
|
|
|
|
/* technically not a posix linker argument, but include it here since it is so
|
|
* common
|
|
*/
|
|
|
|
TOOLCHAIN_PROTO_0(linker_posix_args_shared)
|
|
{
|
|
TOOLCHAIN_ARGS({ "-shared" });
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_0(linker_ld_args_as_needed)
|
|
{
|
|
TOOLCHAIN_ARGS({ "--as-needed" });
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_0(linker_ld_args_no_undefined)
|
|
{
|
|
TOOLCHAIN_ARGS({ "--no-undefined" });
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_0(linker_ld_args_start_group)
|
|
{
|
|
TOOLCHAIN_ARGS({ "--start-group" });
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_0(linker_ld_args_end_group)
|
|
{
|
|
TOOLCHAIN_ARGS({ "--end-group" });
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_1s(linker_ld_args_soname)
|
|
{
|
|
TOOLCHAIN_ARGS({ "-soname", NULL });
|
|
argv[1] = a;
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_1s(linker_ld_args_rpath)
|
|
{
|
|
static char buf[BUF_SIZE_S];
|
|
TOOLCHAIN_ARGS({ buf });
|
|
|
|
snprintf(buf, BUF_SIZE_S, "-rpath,%s", a);
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_0(linker_ld_args_allow_shlib_undefined)
|
|
{
|
|
TOOLCHAIN_ARGS({ "--allow-shlib-undefined" });
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_0(linker_ld_args_export_dynamic)
|
|
{
|
|
TOOLCHAIN_ARGS({ "-export-dynamic" });
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_0(linker_ld_args_fatal_warnings)
|
|
{
|
|
TOOLCHAIN_ARGS({ "--fatal-warnings" });
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_1s(linker_ld_args_whole_archive)
|
|
{
|
|
TOOLCHAIN_ARGS({ "--whole-archive", NULL, "--no-whole-archive" });
|
|
argv[1] = a;
|
|
return &args;
|
|
}
|
|
|
|
/* cl linkers */
|
|
|
|
TOOLCHAIN_PROTO_1s(linker_link_args_lib)
|
|
{
|
|
TOOLCHAIN_ARGS({ NULL });
|
|
argv[0] = a;
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_0(linker_link_args_debug)
|
|
{
|
|
TOOLCHAIN_ARGS({ "/DEBUG" });
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_0(linker_link_args_shared)
|
|
{
|
|
TOOLCHAIN_ARGS({ "/DLL" });
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_1s(linker_link_args_soname)
|
|
{
|
|
static char buf[BUF_SIZE_S];
|
|
TOOLCHAIN_ARGS({ buf });
|
|
|
|
snprintf(buf, BUF_SIZE_S, "/OUT:%s", a);
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_2s(linker_link_args_input_output)
|
|
{
|
|
static char buf[BUF_SIZE_S];
|
|
TOOLCHAIN_ARGS({ buf, NULL });
|
|
|
|
snprintf(buf, BUF_SIZE_S, "/out:%s", b);
|
|
|
|
argv[1] = a;
|
|
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_1s(linker_lld_link_args_whole_archive)
|
|
{
|
|
TOOLCHAIN_ARGS({ "/whole-archive", NULL });
|
|
argv[1] = a;
|
|
return &args;
|
|
}
|
|
|
|
/* apple linker */
|
|
|
|
TOOLCHAIN_PROTO_1s(linker_apple_args_whole_archive)
|
|
{
|
|
TOOLCHAIN_ARGS({ "-force_load", NULL });
|
|
argv[1] = a;
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_0(linker_apple_args_allow_shlib_undefined)
|
|
{
|
|
TOOLCHAIN_ARGS({ "-undefined", "dynamic_lookup" });
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_0(linker_apple_args_shared_module)
|
|
{
|
|
TOOLCHAIN_ARGS({ "-bundle" });
|
|
return &args;
|
|
}
|
|
|
|
/* static linkers */
|
|
|
|
TOOLCHAIN_PROTO_0(static_linker_ar_posix_args_base)
|
|
{
|
|
TOOLCHAIN_ARGS({ "csr" });
|
|
return &args;
|
|
}
|
|
|
|
TOOLCHAIN_PROTO_0(static_linker_ar_gcc_args_base)
|
|
{
|
|
TOOLCHAIN_ARGS({ "csrD" });
|
|
return &args;
|
|
}
|
|
|
|
struct compiler compilers[compiler_type_count];
|
|
struct linker linkers[linker_type_count];
|
|
struct static_linker static_linkers[static_linker_type_count];
|
|
|
|
const struct language languages[compiler_language_count] = {
|
|
[compiler_language_null] = { 0 },
|
|
[compiler_language_c] = { .is_header = false },
|
|
[compiler_language_c_hdr] = { .is_header = true },
|
|
[compiler_language_cpp] = { .is_header = false },
|
|
[compiler_language_cpp_hdr] = { .is_header = true },
|
|
[compiler_language_c_obj] = { .is_linkable = true },
|
|
[compiler_language_assembly] = { 0 },
|
|
[compiler_language_llvm_ir] = { 0 },
|
|
};
|
|
|
|
#define TOOLCHAIN_ARG_MEMBER_(name, __type, params, names) .name = toolchain_arg_empty_##__type,
|
|
#define TOOLCHAIN_ARG_MEMBER(name, comp, type) TOOLCHAIN_ARG_MEMBER_(name, type)
|
|
|
|
static void
|
|
build_compilers(void)
|
|
{
|
|
struct compiler empty = {
|
|
.args = { FOREACH_COMPILER_ARG(TOOLCHAIN_ARG_MEMBER) },
|
|
};
|
|
|
|
empty.args.object_ext = compiler_posix_args_object_extension;
|
|
|
|
struct compiler clang_llvm_ir = empty;
|
|
clang_llvm_ir.args.compile_only = compiler_posix_args_compile_only;
|
|
clang_llvm_ir.args.output = compiler_posix_args_output;
|
|
|
|
struct compiler posix = empty;
|
|
posix.args.compile_only = compiler_posix_args_compile_only;
|
|
posix.args.preprocess_only = compiler_posix_args_preprocess_only;
|
|
posix.args.output = compiler_posix_args_output;
|
|
posix.args.optimization = compiler_posix_args_optimization;
|
|
posix.args.debug = compiler_posix_args_debug;
|
|
posix.args.include = compiler_posix_args_include;
|
|
posix.args.include_system = compiler_posix_args_include;
|
|
posix.args.define = compiler_posix_args_define;
|
|
posix.default_linker = linker_posix;
|
|
posix.default_static_linker = static_linker_ar_posix;
|
|
|
|
struct compiler gcc = posix;
|
|
gcc.args.linker_passthrough = linker_args_passthrough;
|
|
gcc.args.preprocess_only = compiler_gcc_args_preprocess_only;
|
|
gcc.args.deps = compiler_gcc_args_deps;
|
|
gcc.args.optimization = compiler_gcc_args_optimization;
|
|
gcc.args.warning_lvl = compiler_gcc_args_warning_lvl;
|
|
gcc.args.warn_everything = compiler_gcc_args_warn_everything;
|
|
gcc.args.werror = compiler_gcc_args_werror;
|
|
gcc.args.set_std = compiler_gcc_args_set_std;
|
|
gcc.args.include_system = compiler_gcc_args_include_system;
|
|
gcc.args.pgo = compiler_gcc_args_pgo;
|
|
gcc.args.pic = compiler_gcc_args_pic;
|
|
gcc.args.pie = compiler_gcc_args_pie;
|
|
gcc.args.sanitize = compiler_gcc_args_sanitize;
|
|
gcc.args.visibility = compiler_gcc_args_visibility;
|
|
gcc.args.specify_lang = compiler_gcc_args_specify_lang;
|
|
gcc.args.color_output = compiler_gcc_args_color_output;
|
|
gcc.args.enable_lto = compiler_gcc_args_lto;
|
|
gcc.args.deps_type = compiler_deps_gcc;
|
|
gcc.default_linker = linker_ld;
|
|
gcc.default_static_linker = static_linker_ar_gcc;
|
|
|
|
struct compiler clang = gcc;
|
|
clang.args.warn_everything = compiler_clang_args_warn_everything;
|
|
clang.default_linker = linker_clang;
|
|
|
|
struct compiler apple_clang = clang;
|
|
apple_clang.default_linker = linker_apple;
|
|
apple_clang.default_static_linker = static_linker_ar_posix;
|
|
|
|
struct compiler msvc = empty;
|
|
msvc.args.deps = compiler_cl_args_deps;
|
|
msvc.args.compile_only = compiler_cl_args_compile_only;
|
|
msvc.args.preprocess_only = compiler_cl_args_preprocess_only;
|
|
msvc.args.output = compiler_cl_args_output;
|
|
msvc.args.optimization = compiler_cl_args_optimization;
|
|
msvc.args.debug = compiler_cl_args_debug;
|
|
msvc.args.warning_lvl = compiler_cl_args_warning_lvl;
|
|
msvc.args.warn_everything = compiler_cl_args_warn_everything;
|
|
msvc.args.werror = compiler_cl_args_werror;
|
|
msvc.args.set_std = compiler_cl_args_set_std;
|
|
msvc.args.include = compiler_cl_args_include;
|
|
msvc.args.sanitize = compiler_cl_args_sanitize;
|
|
msvc.args.define = compiler_cl_args_define;
|
|
msvc.args.always = compiler_cl_args_always;
|
|
msvc.args.crt = compiler_cl_args_crt;
|
|
msvc.args.debugfile = compiler_cl_args_debugfile;
|
|
msvc.default_linker = linker_msvc;
|
|
msvc.default_static_linker = static_linker_msvc;
|
|
msvc.args.object_ext = compiler_cl_args_object_extension;
|
|
msvc.args.deps_type = compiler_deps_msvc;
|
|
|
|
struct compiler clang_cl = msvc;
|
|
clang_cl.args.color_output = compiler_clang_cl_args_color_output;
|
|
clang_cl.args.enable_lto = compiler_clang_cl_args_lto;
|
|
clang_cl.default_linker = linker_lld_link;
|
|
|
|
compilers[compiler_posix] = posix;
|
|
compilers[compiler_gcc] = gcc;
|
|
compilers[compiler_clang] = clang;
|
|
compilers[compiler_apple_clang] = apple_clang;
|
|
compilers[compiler_clang_llvm_ir] = clang_llvm_ir;
|
|
compilers[compiler_clang_cl] = clang_cl;
|
|
compilers[compiler_msvc] = msvc;
|
|
|
|
struct compiler nasm = empty;
|
|
nasm.args.output = compiler_posix_args_output;
|
|
nasm.args.optimization = compiler_posix_args_optimization;
|
|
nasm.args.debug = compiler_posix_args_debug;
|
|
nasm.args.include = compiler_posix_args_include;
|
|
nasm.args.include_system = compiler_posix_args_include;
|
|
nasm.args.define = compiler_posix_args_define;
|
|
nasm.default_linker = linker_posix;
|
|
nasm.default_static_linker = static_linker_ar_posix;
|
|
|
|
compilers[compiler_nasm] = nasm;
|
|
compilers[compiler_yasm] = nasm;
|
|
}
|
|
|
|
static void
|
|
build_linkers(void)
|
|
{
|
|
/* linkers */
|
|
struct linker empty = { .args = { FOREACH_LINKER_ARG(TOOLCHAIN_ARG_MEMBER) } };
|
|
|
|
struct linker posix = empty;
|
|
posix.args.lib = linker_posix_args_lib;
|
|
posix.args.shared = linker_posix_args_shared;
|
|
posix.args.input_output = linker_posix_args_input_output;
|
|
|
|
struct linker ld = posix;
|
|
ld.args.as_needed = linker_ld_args_as_needed;
|
|
ld.args.no_undefined = linker_ld_args_no_undefined;
|
|
ld.args.start_group = linker_ld_args_start_group;
|
|
ld.args.end_group = linker_ld_args_end_group;
|
|
ld.args.soname = linker_ld_args_soname;
|
|
ld.args.rpath = linker_ld_args_rpath;
|
|
ld.args.pgo = compiler_gcc_args_pgo;
|
|
ld.args.sanitize = compiler_gcc_args_sanitize;
|
|
ld.args.allow_shlib_undefined = linker_ld_args_allow_shlib_undefined;
|
|
ld.args.shared_module = linker_posix_args_shared;
|
|
ld.args.export_dynamic = linker_ld_args_export_dynamic;
|
|
ld.args.fatal_warnings = linker_ld_args_fatal_warnings;
|
|
ld.args.whole_archive = linker_ld_args_whole_archive;
|
|
ld.args.enable_lto = compiler_gcc_args_lto;
|
|
|
|
struct linker lld = ld;
|
|
|
|
struct linker apple = posix;
|
|
posix.args.shared = linker_posix_args_shared;
|
|
apple.args.sanitize = compiler_gcc_args_sanitize;
|
|
apple.args.enable_lto = compiler_gcc_args_lto;
|
|
apple.args.allow_shlib_undefined = linker_apple_args_allow_shlib_undefined;
|
|
apple.args.shared_module = linker_apple_args_shared_module;
|
|
apple.args.whole_archive = linker_apple_args_whole_archive;
|
|
|
|
struct linker link = empty;
|
|
link.args.lib = linker_link_args_lib;
|
|
link.args.debug = linker_link_args_debug;
|
|
link.args.shared = linker_link_args_shared;
|
|
link.args.soname = linker_link_args_soname;
|
|
link.args.input_output = linker_link_args_input_output;
|
|
link.args.always = compiler_cl_args_always;
|
|
|
|
struct linker lld_link = link;
|
|
lld_link.args.whole_archive = linker_lld_link_args_whole_archive;
|
|
lld_link.args.always = toolchain_arg_empty_0;
|
|
|
|
linkers[linker_posix] = posix;
|
|
linkers[linker_ld] = ld;
|
|
linkers[linker_clang] = lld;
|
|
linkers[linker_apple] = apple;
|
|
linkers[linker_lld_link] = lld_link;
|
|
linkers[linker_msvc] = link;
|
|
}
|
|
|
|
static void
|
|
build_static_linkers(void)
|
|
{
|
|
struct static_linker empty = { .args = { FOREACH_STATIC_LINKER_ARG(TOOLCHAIN_ARG_MEMBER) } };
|
|
|
|
struct static_linker posix = empty;
|
|
posix.args.base = static_linker_ar_posix_args_base;
|
|
posix.args.input_output = linker_posix_args_input_output;
|
|
|
|
struct static_linker gcc = posix;
|
|
gcc.args.base = static_linker_ar_gcc_args_base;
|
|
|
|
struct static_linker msvc = empty;
|
|
msvc.args.input_output = linker_link_args_input_output;
|
|
msvc.args.always = compiler_cl_args_always;
|
|
|
|
static_linkers[static_linker_ar_posix] = posix;
|
|
static_linkers[static_linker_ar_gcc] = gcc;
|
|
static_linkers[static_linker_msvc] = msvc;
|
|
}
|
|
|
|
#undef TOOLCHAIN_ARG_MEMBER
|
|
#undef TOOLCHAIN_ARG_MEMBER_
|
|
|
|
void
|
|
compilers_init(void)
|
|
{
|
|
build_compilers();
|
|
build_linkers();
|
|
build_static_linkers();
|
|
}
|
|
|
|
#define TOOLCHAIN_ARG_MEMBER_(name, comp, __type, params, names) { #name, toolchain_arg_arity_##__type },
|
|
#define TOOLCHAIN_ARG_MEMBER(name, comp, type) TOOLCHAIN_ARG_MEMBER_(name, comp, type)
|
|
static struct toolchain_arg_handler toolchain_compiler_arg_handlers[] = { FOREACH_COMPILER_ARG(TOOLCHAIN_ARG_MEMBER) };
|
|
static struct toolchain_arg_handler toolchain_linker_arg_handlers[] = { FOREACH_LINKER_ARG(TOOLCHAIN_ARG_MEMBER) };
|
|
static struct toolchain_arg_handler toolchain_static_linker_arg_handlers[]
|
|
= { FOREACH_STATIC_LINKER_ARG(TOOLCHAIN_ARG_MEMBER) };
|
|
#undef TOOLCHAIN_ARG_MEMBER
|
|
#undef TOOLCHAIN_ARG_MEMBER_
|
|
|
|
static struct {
|
|
struct toolchain_arg_handler *handlers;
|
|
uint32_t len;
|
|
} toolchain_arg_handlers[] = {
|
|
[toolchain_component_compiler]
|
|
= { toolchain_compiler_arg_handlers, ARRAY_LEN(toolchain_compiler_arg_handlers) },
|
|
[toolchain_component_linker] = { toolchain_linker_arg_handlers, ARRAY_LEN(toolchain_linker_arg_handlers) },
|
|
[toolchain_component_static_linker]
|
|
= { toolchain_static_linker_arg_handlers, ARRAY_LEN(toolchain_static_linker_arg_handlers) },
|
|
};
|
|
|
|
const struct toolchain_arg_handler *
|
|
get_toolchain_arg_handler_info(enum toolchain_component component, const char *name)
|
|
{
|
|
uint32_t i;
|
|
for (i = 0; i < toolchain_arg_handlers[component].len; ++i) {
|
|
if (strcmp(toolchain_arg_handlers[component].handlers[i].name, name) == 0) {
|
|
return &toolchain_arg_handlers[component].handlers[i];
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
toolchain_arg_arity_to_sig(enum toolchain_arg_arity arity, type_tag signature[2], uint32_t *len)
|
|
{
|
|
switch (arity) {
|
|
case toolchain_arg_arity_0: {
|
|
*len = 0;
|
|
break;
|
|
}
|
|
case toolchain_arg_arity_1i: {
|
|
signature[0] = tc_number;
|
|
*len = 1;
|
|
break;
|
|
}
|
|
case toolchain_arg_arity_1s: {
|
|
signature[0] = tc_string;
|
|
*len = 1;
|
|
break;
|
|
}
|
|
case toolchain_arg_arity_2s: {
|
|
signature[0] = tc_string;
|
|
signature[1] = tc_string;
|
|
*len = 2;
|
|
break;
|
|
}
|
|
case toolchain_arg_arity_1s1b: {
|
|
signature[0] = tc_string;
|
|
signature[1] = tc_bool;
|
|
*len = 2;
|
|
break;
|
|
}
|
|
case toolchain_arg_arity_ns: {
|
|
signature[0] = TYPE_TAG_GLOB | tc_string;
|
|
*len = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static obj
|
|
lookup_toolchain_arg_override(struct workspace *wk,
|
|
struct obj_compiler *c,
|
|
enum toolchain_component component,
|
|
uint32_t arg)
|
|
{
|
|
obj overrides = c->overrides[component], override;
|
|
if (overrides
|
|
&& obj_dict_index_str(wk, overrides, toolchain_arg_handlers[component].handlers[arg].name, &override)) {
|
|
return override;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
enum toolchain_arg_by_component {
|
|
#define TOOLCHAIN_ARG_MEMBER_(comp, _name) toolchain_arg_by_component_##comp##_name,
|
|
#define TOOLCHAIN_ARG_MEMBER(name, comp, type) TOOLCHAIN_ARG_MEMBER_(comp, _##name)
|
|
FOREACH_COMPILER_ARG(TOOLCHAIN_ARG_MEMBER) toolchain_arg_by_component_reset_0 = -1,
|
|
FOREACH_LINKER_ARG(TOOLCHAIN_ARG_MEMBER) toolchain_arg_by_component_reset_1 = -1,
|
|
FOREACH_STATIC_LINKER_ARG(TOOLCHAIN_ARG_MEMBER)
|
|
#undef TOOLCHAIN_ARG_MEMBER
|
|
#undef TOOLCHAIN_ARG_MEMBER_
|
|
};
|
|
|
|
static obj handle_toolchain_arg_override;
|
|
|
|
static const struct args *
|
|
handle_toolchain_arg_override_convert_to_args(struct workspace *wk, obj list)
|
|
{
|
|
static const char *argv[32];
|
|
static struct args args = { .args = argv, .len = 0 };
|
|
|
|
obj v;
|
|
obj_array_for(wk, list, v) {
|
|
assert(args.len < ARRAY_LEN(argv) && "increase size of argv");
|
|
|
|
++args.len;
|
|
argv[args.len] = get_cstr(wk, v);
|
|
}
|
|
|
|
return &args;
|
|
}
|
|
|
|
static const struct args *
|
|
handle_toolchain_arg_override_check_const(struct workspace *wk)
|
|
{
|
|
if (get_obj_type(wk, handle_toolchain_arg_override) == obj_array) {
|
|
return handle_toolchain_arg_override_convert_to_args(wk, handle_toolchain_arg_override);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#define constant_override_check() \
|
|
{ \
|
|
const struct args *args = handle_toolchain_arg_override_check_const(wk); \
|
|
if (args) { \
|
|
return args; \
|
|
} \
|
|
}
|
|
|
|
static const struct args *
|
|
handle_toolchain_arg_override_0(TOOLCHAIN_SIG_0)
|
|
{
|
|
constant_override_check();
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct args *
|
|
handle_toolchain_arg_override_1i(TOOLCHAIN_SIG_1i)
|
|
{
|
|
constant_override_check();
|
|
return 0;
|
|
}
|
|
|
|
static const struct args *
|
|
handle_toolchain_arg_override_1s(TOOLCHAIN_SIG_1s)
|
|
{
|
|
constant_override_check();
|
|
return 0;
|
|
}
|
|
|
|
static const struct args *
|
|
handle_toolchain_arg_override_2s(TOOLCHAIN_SIG_2s)
|
|
{
|
|
constant_override_check();
|
|
return 0;
|
|
}
|
|
|
|
static const struct args *
|
|
handle_toolchain_arg_override_1s1b(TOOLCHAIN_SIG_1s1b)
|
|
{
|
|
constant_override_check();
|
|
return 0;
|
|
}
|
|
|
|
static const struct args *
|
|
handle_toolchain_arg_override_ns(TOOLCHAIN_SIG_ns)
|
|
{
|
|
constant_override_check();
|
|
return 0;
|
|
}
|
|
|
|
#define TOOLCHAIN_ARG_MEMBER_(name, _name, component, _type, params, names) \
|
|
const struct args *toolchain_##component##_name params \
|
|
{ \
|
|
handle_toolchain_arg_override = lookup_toolchain_arg_override( \
|
|
wk, comp, toolchain_component_##component, toolchain_arg_by_component_##component##_name); \
|
|
if (handle_toolchain_arg_override) { \
|
|
return handle_toolchain_arg_override_##_type names; \
|
|
} \
|
|
\
|
|
return component##s[comp->type[toolchain_component_##component]].args.name names; \
|
|
}
|
|
|
|
#define TOOLCHAIN_ARG_MEMBER(name, comp, type) TOOLCHAIN_ARG_MEMBER_(name, _##name, comp, type)
|
|
|
|
FOREACH_COMPILER_ARG(TOOLCHAIN_ARG_MEMBER)
|
|
FOREACH_LINKER_ARG(TOOLCHAIN_ARG_MEMBER)
|
|
FOREACH_STATIC_LINKER_ARG(TOOLCHAIN_ARG_MEMBER)
|
|
|
|
#undef TOOLCHAIN_ARG_MEMBER
|
|
#undef TOOLCHAIN_ARG_MEMBER_
|