kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

commit 0f52c64c72c5244f3d33abc9ff3edfb5998d3f89
parent eb9194365b806f918ea225520271669c9137f379
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Thu, 21 May 2026 06:55:45 -0700

Expand driver flag compatibility

Diffstat:
Mdriver/cc.c | 135+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Mdriver/cflags.c | 15+++++++++++++++
Mdriver/driver.h | 4++++
Mdriver/ld.c | 130+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Mdriver/objdump.c | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Mdriver/target.c | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtest/driver/run.sh | 97+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 491 insertions(+), 7 deletions(-)

diff --git a/driver/cc.c b/driver/cc.c @@ -50,6 +50,19 @@ typedef enum CcDepMode { CC_DEP_MMD, } CcDepMode; +typedef enum CcProbeKind { + CC_PROBE_NONE = 0, + CC_PROBE_PRINT_SEARCH_DIRS, + CC_PROBE_PRINT_FILE_NAME, + CC_PROBE_PRINT_PROG_NAME, + CC_PROBE_PRINT_LIBGCC_FILE_NAME, + CC_PROBE_PRINT_MULTI_OS_DIRECTORY, + CC_PROBE_PRINT_RESOURCE_DIR, + CC_PROBE_DUMPMACHINE, + CC_PROBE_DUMPVERSION, + CC_PROBE_DUMPSPECS, +} CcProbeKind; + typedef enum CcLinkItemKind { CC_LINK_SOURCE_FILE, CC_LINK_SOURCE_MEMORY, @@ -113,6 +126,8 @@ typedef struct CcOptions { const char* linker_script; /* -T path */ const char* sysroot; /* --sysroot / -isysroot */ const char* support_dir; /* --support-dir */ + int probe_kind; /* CcProbeKind */ + const char* probe_arg; /* -print-file-name= / -print-prog-name= */ /* -ffile-prefix-map=old=new entries; old is heap-owned (split out), new * aliases argv. */ @@ -637,6 +652,63 @@ static void cc_log_ignored(const char* arg) { driver_errf(CC_TOOL, "ignoring accepted compatibility flag: %s", arg); } +static int cc_set_probe(CcOptions* o, int kind, const char* arg) { + if (o->probe_kind != CC_PROBE_NONE) { + driver_errf(CC_TOOL, "only one compiler-information probe is supported"); + return 1; + } + o->probe_kind = kind; + o->probe_arg = arg; + return 0; +} + +static int cc_run_probe(CcOptions* o) { + char triple[64]; + if (driver_target_to_triple(o->target, triple, sizeof(triple)) != 0) { + driver_errf(CC_TOOL, "failed to render target triple"); + return 1; + } + + switch (o->probe_kind) { + case CC_PROBE_PRINT_SEARCH_DIRS: + driver_printf("install: %s\n", o->support_dir ? o->support_dir : ""); + driver_printf("programs: =\n"); + driver_printf("libraries: ="); + if (o->sysroot) driver_printf("%s/lib", o->sysroot); + driver_printf("\n"); + return 0; + case CC_PROBE_PRINT_FILE_NAME: + driver_printf("%s\n", o->probe_arg ? o->probe_arg : ""); + return 0; + case CC_PROBE_PRINT_PROG_NAME: + driver_printf("%s\n", o->probe_arg ? o->probe_arg : ""); + return 0; + case CC_PROBE_PRINT_LIBGCC_FILE_NAME: + driver_printf("libcfree_rt.a\n"); + return 0; + case CC_PROBE_PRINT_MULTI_OS_DIRECTORY: + driver_printf(".\n"); + return 0; + case CC_PROBE_PRINT_RESOURCE_DIR: + driver_printf("%s\n", o->support_dir ? o->support_dir : ""); + return 0; + case CC_PROBE_DUMPMACHINE: + driver_printf("%s\n", triple); + return 0; + case CC_PROBE_DUMPVERSION: + driver_printf("0\n"); + return 0; + case CC_PROBE_DUMPSPECS: + driver_printf("*cfree:\n"); + driver_printf("%%{!S:%%{!E:%%{!c:%%{!r:link}}}}\n"); + return 0; + default: + break; + } + + return 0; +} + static int cc_record_stdin(CcOptions* o) { CfreeSourceInput* in; if (o->stdin_buf) { @@ -934,8 +1006,45 @@ static int cc_parse(int argc, char** argv, CcOptions* o) { o->support_dir = a + 14; continue; } - if (driver_streq(a, "-include") || driver_streq(a, "-iquote") || - driver_streq(a, "-idirafter")) { + if (driver_streq(a, "-print-search-dirs")) { + if (cc_set_probe(o, CC_PROBE_PRINT_SEARCH_DIRS, NULL) != 0) return 1; + continue; + } + if (driver_strneq(a, "-print-file-name=", 17)) { + if (cc_set_probe(o, CC_PROBE_PRINT_FILE_NAME, a + 17) != 0) return 1; + continue; + } + if (driver_strneq(a, "-print-prog-name=", 17)) { + if (cc_set_probe(o, CC_PROBE_PRINT_PROG_NAME, a + 17) != 0) return 1; + continue; + } + if (driver_streq(a, "-print-libgcc-file-name")) { + if (cc_set_probe(o, CC_PROBE_PRINT_LIBGCC_FILE_NAME, NULL) != 0) + return 1; + continue; + } + if (driver_streq(a, "-print-multi-os-directory")) { + if (cc_set_probe(o, CC_PROBE_PRINT_MULTI_OS_DIRECTORY, NULL) != 0) + return 1; + continue; + } + if (driver_streq(a, "-print-resource-dir")) { + if (cc_set_probe(o, CC_PROBE_PRINT_RESOURCE_DIR, NULL) != 0) return 1; + continue; + } + if (driver_streq(a, "-dumpmachine")) { + if (cc_set_probe(o, CC_PROBE_DUMPMACHINE, NULL) != 0) return 1; + continue; + } + if (driver_streq(a, "-dumpversion")) { + if (cc_set_probe(o, CC_PROBE_DUMPVERSION, NULL) != 0) return 1; + continue; + } + if (driver_streq(a, "-dumpspecs")) { + if (cc_set_probe(o, CC_PROBE_DUMPSPECS, NULL) != 0) return 1; + continue; + } + if (driver_streq(a, "-include")) { if (++i >= argc) { driver_errf(CC_TOOL, "%s requires an argument", a); return 1; @@ -1049,6 +1158,20 @@ static int cc_parse(int argc, char** argv, CcOptions* o) { o->output_path_set = 1; continue; } + if (driver_strneq(a, "--output=", 9)) { + o->output_path = a + 9; + o->output_path_set = 1; + continue; + } + if (driver_streq(a, "--output")) { + if (++i >= argc) { + driver_errf(CC_TOOL, "--output requires an argument"); + return 1; + } + o->output_path = argv[i]; + o->output_path_set = 1; + continue; + } if (driver_streq(a, "-e")) { if (++i >= argc) { driver_errf(CC_TOOL, "-e requires an argument"); @@ -1213,6 +1336,8 @@ static int cc_parse(int argc, char** argv, CcOptions* o) { if (cc_classify_positional(o, a, forced_lang) != 0) return 1; } + if (o->probe_kind != CC_PROBE_NONE) return 0; + if (cc_apply_env(o) != 0) return 1; if (cc_resolve_pending_libs(o) != 0) return 1; @@ -2203,6 +2328,12 @@ int driver_cc(int argc, char** argv) { driver_env_fini(&env); return 2; } + if (co.probe_kind != CC_PROBE_NONE) { + rc = cc_run_probe(&co); + cc_options_release(&co); + driver_env_fini(&env); + return rc; + } link_action = !co.compile_only && !co.preprocess_only && !co.dump_tokens && co.dep_mode != CC_DEP_M && co.dep_mode != CC_DEP_MM; diff --git a/driver/cflags.c b/driver/cflags.c @@ -110,6 +110,21 @@ int driver_cflags_try_consume(DriverCflags* cf, DriverEnv* env, return 1; } + if (driver_strneq(a, "-iquote", 7)) { + const char* dir = cflags_pull_value(tool, argc, argv, i, 7, "-iquote"); + if (!dir) return -1; + cf->include_dirs[cf->ninclude_dirs++] = dir; + return 1; + } + + if (driver_strneq(a, "-idirafter", 10)) { + const char* dir = + cflags_pull_value(tool, argc, argv, i, 10, "-idirafter"); + if (!dir) return -1; + cf->system_include_dirs[cf->nsystem_include_dirs++] = dir; + return 1; + } + if (driver_strneq(a, "-D", 2)) { const char* arg = cflags_pull_value(tool, argc, argv, i, 2, "-D"); if (!arg) return -1; diff --git a/driver/driver.h b/driver/driver.h @@ -142,6 +142,10 @@ CfreeTarget driver_host_target(void); * unrecognized arch or NULL inputs. */ int driver_target_from_triple(const char *triple, CfreeTarget *out); +/* Render a canonical driver target triple into `buf`. Returns 0 on success, + * nonzero when `buf` is too small. */ +int driver_target_to_triple(CfreeTarget target, char *buf, size_t cap); + /* ---------------------------------------------------------------------- * Host-shim helpers * diff --git a/driver/ld.c b/driver/ld.c @@ -107,6 +107,7 @@ typedef struct LdOptions { int new_dtags; /* 1=DT_RUNPATH (default), 0=DT_RPATH */ int export_dynamic; /* -E / --export-dynamic */ int gc_sections; /* --gc-sections / --no-gc-sections */ + int allow_undefined; /* shared output undefined-symbol policy */ /* --build-id state */ uint8_t build_id_mode; /* CfreeBuildIdMode */ @@ -190,6 +191,8 @@ void driver_help_ld(void) { " --no-gc-sections Disable section GC (default)\n" " -E, --export-dynamic Promote defined globals into dynsym\n" " (no-op for -shared; recorded for exe)\n" + " --no-undefined Reject unresolved symbols in -shared output\n" + " -z defs Same as --no-undefined\n" "\n" "BUILD ID\n" " --build-id Same as --build-id=sha256\n" @@ -221,6 +224,7 @@ static int ld_alloc_arrays(LdOptions* o, int argc) { return 1; } o->new_dtags = 1; + o->allow_undefined = 1; return 0; } @@ -382,6 +386,28 @@ static int ld_parse(int argc, char** argv, LdOptions* o) { o->output_seen = 1; continue; } + if ((val = arg_eq_value(a, "--output")) != NULL) { + if (o->output_seen) { + driver_errf(LD_TOOL, "-o specified more than once"); + return 1; + } + o->output_path = val; + o->output_seen = 1; + continue; + } + if (driver_streq(a, "--output")) { + if (++i >= argc) { + driver_errf(LD_TOOL, "--output requires an argument"); + return 1; + } + if (o->output_seen) { + driver_errf(LD_TOOL, "-o specified more than once"); + return 1; + } + o->output_path = argv[i]; + o->output_seen = 1; + continue; + } if (driver_streq(a, "-e")) { if (++i >= argc) { driver_errf(LD_TOOL, "-e requires an argument"); @@ -390,6 +416,18 @@ static int ld_parse(int argc, char** argv, LdOptions* o) { o->entry = argv[i]; continue; } + if ((val = arg_eq_value(a, "--entry")) != NULL) { + o->entry = val; + continue; + } + if (driver_streq(a, "--entry")) { + if (++i >= argc) { + driver_errf(LD_TOOL, "--entry requires an argument"); + return 1; + } + o->entry = argv[i]; + continue; + } if (driver_streq(a, "-T")) { if (++i >= argc) { driver_errf(LD_TOOL, "-T requires an argument"); @@ -398,6 +436,18 @@ static int ld_parse(int argc, char** argv, LdOptions* o) { o->script_path = argv[i]; continue; } + if ((val = arg_eq_value(a, "--script")) != NULL) { + o->script_path = val; + continue; + } + if (driver_streq(a, "--script")) { + if (++i >= argc) { + driver_errf(LD_TOOL, "--script requires an argument"); + return 1; + } + o->script_path = argv[i]; + continue; + } if (driver_strneq(a, "-L", 2)) { const char* dir = a[2] ? a + 2 : (++i < argc ? argv[i] : NULL); @@ -408,6 +458,18 @@ static int ld_parse(int argc, char** argv, LdOptions* o) { o->lib_dirs[o->nlib_dirs++] = dir; continue; } + if ((val = arg_eq_value(a, "--library-path")) != NULL) { + o->lib_dirs[o->nlib_dirs++] = val; + continue; + } + if (driver_streq(a, "--library-path")) { + if (++i >= argc) { + driver_errf(LD_TOOL, "--library-path requires an argument"); + return 1; + } + o->lib_dirs[o->nlib_dirs++] = argv[i]; + continue; + } if (driver_strneq(a, "-l", 2)) { const char* name = a[2] ? a + 2 : (++i < argc ? argv[i] : NULL); @@ -435,6 +497,48 @@ static int ld_parse(int argc, char** argv, LdOptions* o) { } continue; } + if ((val = arg_eq_value(a, "--library")) != NULL) { + char* resolved; + size_t resolved_size; + LibResolveKind kind; + LibResolveMode mode = + (o->cur_link_mode == CFREE_LM_STATIC) ? LIB_RESOLVE_STATIC_ONLY + : LIB_RESOLVE_DYNAMIC_PREFER; + if (driver_lib_resolve(o->env, val, mode, o->lib_dirs, o->nlib_dirs, + &resolved, &resolved_size, &kind) != 0) { + driver_errf(LD_TOOL, "cannot find -l%s", val); + return 1; + } + if (kind == LIB_RESOLVE_KIND_SHARED || kind == LIB_RESOLVE_KIND_TBD) { + ld_push_dso(o, resolved, 1, resolved_size); + } else { + ld_push_archive(o, resolved, 1, resolved_size); + } + continue; + } + if (driver_streq(a, "--library")) { + char* resolved; + size_t resolved_size; + LibResolveKind kind; + LibResolveMode mode; + if (++i >= argc) { + driver_errf(LD_TOOL, "--library requires an argument"); + return 1; + } + mode = (o->cur_link_mode == CFREE_LM_STATIC) ? LIB_RESOLVE_STATIC_ONLY + : LIB_RESOLVE_DYNAMIC_PREFER; + if (driver_lib_resolve(o->env, argv[i], mode, o->lib_dirs, o->nlib_dirs, + &resolved, &resolved_size, &kind) != 0) { + driver_errf(LD_TOOL, "cannot find -l%s", argv[i]); + return 1; + } + if (kind == LIB_RESOLVE_KIND_SHARED || kind == LIB_RESOLVE_KIND_TBD) { + ld_push_dso(o, resolved, 1, resolved_size); + } else { + ld_push_archive(o, resolved, 1, resolved_size); + } + continue; + } if (driver_streq(a, "-static")) { o->target.pic = CFREE_PIC_NONE; @@ -530,6 +634,26 @@ static int ld_parse(int argc, char** argv, LdOptions* o) { o->export_dynamic = 1; continue; } + if (driver_streq(a, "--no-undefined")) { + o->allow_undefined = 0; + continue; + } + if (driver_streq(a, "--allow-shlib-undefined")) { + o->allow_undefined = 1; + continue; + } + if (driver_streq(a, "-z")) { + if (++i >= argc) { + driver_errf(LD_TOOL, "-z requires an argument"); + return 1; + } + if (driver_streq(argv[i], "defs")) { + o->allow_undefined = 0; + continue; + } + driver_errf(LD_TOOL, "unsupported -z option: %s", argv[i]); + return 1; + } if (driver_streq(a, "--whole-archive")) { o->cur_whole_archive = 1; @@ -881,9 +1005,9 @@ static int ld_run_link(LdOptions* o) { shared_opts.rpaths = o->rpaths; shared_opts.nrpaths = o->nrpaths; } - /* allow_undefined defaults to 1 for shared output (the produced - * object resolves against its loader at runtime). */ - shared_opts.allow_undefined = 1; + /* By default shared output may resolve symbols against its loader at + * runtime; --no-undefined / -z defs tightens that policy. */ + shared_opts.allow_undefined = o->allow_undefined ? 1 : 0; shared_opts.gc_sections = o->gc_sections; (void)o->export_dynamic; rc = cfree_link_shared(compiler, &shared_opts, writer) == CFREE_OK ? 0 : 1; diff --git a/driver/objdump.c b/driver/objdump.c @@ -17,6 +17,7 @@ #define MAX_J_FILTERS 16 typedef struct ObjdumpOpts { + int f; /* -f: file header */ int h; /* -h: section headers */ int t; /* -t: symbol table */ int d; /* -d: disasm exec sections */ @@ -52,6 +53,7 @@ void driver_help_objdump(void) { " symbol table), matching GNU objdump's default-ish behaviour.\n" "\n" "OPERATIONS (any combination)\n" + " -f Print the file header\n" " -h Print section headers (idx, name, size, align,\n" " flags). NOTE: this is the GNU objdump meaning of\n" " -h — it does NOT print this help; use --help.\n" @@ -60,6 +62,7 @@ void driver_help_objdump(void) { " -D Disassemble all sections\n" " -r Print relocation records\n" " -s Print section contents as a hex+ASCII dump\n" + " -x Aggregate: -f -h -r -t\n" "\n" "FILTERS\n" " -j NAME Restrict output to the named section. Repeatable;\n" @@ -336,6 +339,11 @@ static void dump_disasm(const CfreeDisasmContext* dctx, CfreeObjFile* f, const ObjdumpOpts* opts) { uint32_t nsec = cfree_obj_nsections(f); uint32_t i; + CfreeDisasmContext file_dctx; + + if (!dctx) return; + file_dctx = *dctx; + file_dctx.target = cfree_obj_target(f); for (i = 0; i < nsec; ++i) { CfreeObjSecInfo sec; @@ -356,7 +364,7 @@ static void dump_disasm(const CfreeDisasmContext* dctx, CfreeObjFile* f, driver_printf("Disassembly of section %s:\n\n", sec.name[0] ? sec.name : "(anon)"); - if (cfree_disasm_iter_new(dctx, data, len, 0, f, &dis) != CFREE_OK) + if (cfree_disasm_iter_new(&file_dctx, data, len, 0, f, &dis) != CFREE_OK) continue; for (;;) { CfreeIterResult r = cfree_disasm_iter_next(dis, &insn); @@ -446,6 +454,9 @@ static int parse_short_flags(const char* arg, ObjdumpOpts* o) { const char* p; for (p = arg + 1; *p; ++p) { switch (*p) { + case 'f': + o->f = 1; + break; case 'h': o->h = 1; break; @@ -464,6 +475,12 @@ static int parse_short_flags(const char* arg, ObjdumpOpts* o) { case 's': o->s = 1; break; + case 'x': + o->f = 1; + o->h = 1; + o->r = 1; + o->t = 1; + break; default: driver_errf(OBJDUMP_TOOL, "unknown flag: -%c", *p); return -1; @@ -472,6 +489,41 @@ static int parse_short_flags(const char* arg, ObjdumpOpts* o) { return 0; } +static int parse_long_flag(const char* arg, ObjdumpOpts* o) { + if (driver_streq(arg, "--file-headers")) { + o->f = 1; + return 1; + } + if (driver_streq(arg, "--section-headers")) { + o->h = 1; + return 1; + } + if (driver_streq(arg, "--syms")) { + o->t = 1; + return 1; + } + if (driver_streq(arg, "--reloc")) { + o->r = 1; + return 1; + } + if (driver_streq(arg, "--full-contents")) { + o->s = 1; + return 1; + } + if (driver_streq(arg, "--disassemble")) { + o->d = 1; + return 1; + } + if (driver_streq(arg, "--all-headers")) { + o->f = 1; + o->h = 1; + o->r = 1; + o->t = 1; + return 1; + } + return 0; +} + int driver_objdump(int argc, char** argv) { DriverEnv env; ObjdumpOpts opts = {0}; @@ -511,6 +563,7 @@ int driver_objdump(int argc, char** argv) { opts.j[opts.nj++] = argv[++i]; continue; } + if (parse_long_flag(a, &opts)) continue; if (parse_short_flags(a, &opts) != 0) { objdump_usage(); rc = 2; @@ -518,7 +571,7 @@ int driver_objdump(int argc, char** argv) { } } - saw_op = opts.h || opts.t || opts.d || opts.D || opts.r || opts.s; + saw_op = opts.f || opts.h || opts.t || opts.d || opts.D || opts.r || opts.s; if (!saw_op) { /* Default = -h -t (matches the prior behavior). */ opts.h = 1; opts.t = 1; diff --git a/driver/target.c b/driver/target.c @@ -1,5 +1,6 @@ #include <stddef.h> #include <stdint.h> +#include <stdio.h> #include <string.h> #include "driver.h" @@ -119,3 +120,62 @@ int driver_target_from_triple(const char* triple, CfreeTarget* out) { *out = t; return 0; } + +int driver_target_to_triple(CfreeTarget target, char* buf, size_t cap) { + const char* arch; + const char* os; + int n; + if (!buf || cap == 0) return 1; + + switch (target.arch) { + case CFREE_ARCH_X86_64: + arch = "x86_64"; + break; + case CFREE_ARCH_X86_32: + arch = "i386"; + break; + case CFREE_ARCH_ARM_64: + arch = "aarch64"; + break; + case CFREE_ARCH_ARM_32: + arch = "arm"; + break; + case CFREE_ARCH_RV64: + arch = "riscv64"; + break; + case CFREE_ARCH_RV32: + arch = "riscv32"; + break; + case CFREE_ARCH_WASM: + arch = target.ptr_size == 8 ? "wasm64" : "wasm32"; + break; + default: + arch = "unknown"; + break; + } + + switch (target.os) { + case CFREE_OS_LINUX: + os = "linux"; + break; + case CFREE_OS_MACOS: + os = "apple-darwin"; + break; + case CFREE_OS_WINDOWS: + os = "windows"; + break; + case CFREE_OS_FREEBSD: + os = "freebsd"; + break; + case CFREE_OS_WASI: + os = "wasi"; + break; + case CFREE_OS_FREESTANDING: + default: + os = "elf"; + break; + } + + n = snprintf(buf, cap, "%s-%s", arch, os); + return n < 0 || (size_t)n >= cap; +} diff --git a/test/driver/run.sh b/test/driver/run.sh @@ -179,6 +179,28 @@ else fail=$((fail + 1)) fi +if "$CFREE" cc -target riscv64-linux -dumpmachine \ + > "$work/cc-dumpmachine.out" 2> "$work/cc-dumpmachine.err" && + [ "$(cat "$work/cc-dumpmachine.out")" = "riscv64-linux" ]; then + printf 'PASS %s\n' "cc-dumpmachine-probe" + pass=$((pass + 1)) +else + printf 'FAIL %s\n' "cc-dumpmachine-probe" + sed 's/^/ | /' "$work/cc-dumpmachine.err" + fail=$((fail + 1)) +fi + +if "$CFREE" cc -print-file-name=crt1.o \ + > "$work/cc-print-file-name.out" 2> "$work/cc-print-file-name.err" && + [ "$(cat "$work/cc-print-file-name.out")" = "crt1.o" ]; then + printf 'PASS %s\n' "cc-print-file-name-probe" + pass=$((pass + 1)) +else + printf 'FAIL %s\n' "cc-print-file-name-probe" + sed 's/^/ | /' "$work/cc-print-file-name.err" + fail=$((fail + 1)) +fi + if "$CFREE" cc -Wall -Wextra -std=c11 -ffreestanding -c "$work/main.c" \ -o "$work/ignored.o" > "$work/cc-ignored.out" 2> "$work/cc-ignored.err"; then if grep -q "ignoring accepted compatibility flag: -Wall" "$work/cc-ignored.err" && @@ -196,6 +218,36 @@ else fail=$((fail + 1)) fi +if "$CFREE" cc -c "$work/main.c" --output="$work/cc-long-output.o" \ + > "$work/cc-long-output.out" 2> "$work/cc-long-output.err" && + [ -f "$work/cc-long-output.o" ]; then + printf 'PASS %s\n' "cc-long-output" + pass=$((pass + 1)) +else + printf 'FAIL %s\n' "cc-long-output" + sed 's/^/ | /' "$work/cc-long-output.err" + fail=$((fail + 1)) +fi + +mkdir -p "$work/quote-inc" +cat > "$work/quote-inc/q.h" <<'SRC' +#define Q_VALUE 7 +SRC +cat > "$work/quote-include.c" <<'SRC' +#include "q.h" +int q(void) { return Q_VALUE; } +SRC +if "$CFREE" cc -c "$work/quote-include.c" -iquote "$work/quote-inc" \ + -o "$work/quote-include.o" \ + > "$work/quote-include.out" 2> "$work/quote-include.err"; then + printf 'PASS %s\n' "cc-iquote-include" + pass=$((pass + 1)) +else + printf 'FAIL %s\n' "cc-iquote-include" + sed 's/^/ | /' "$work/quote-include.err" + fail=$((fail + 1)) +fi + cat > "$work/implicit-header.c" <<'SRC' #include <stddef.h> #include <stdint.h> @@ -237,6 +289,51 @@ else fail=$((fail + 1)) fi +if "$CFREE" ld "$work/main.o" --output="$work/ld-long-output" \ + > "$work/ld-long-output.out" 2> "$work/ld-long-output.err" && + [ -f "$work/ld-long-output" ]; then + printf 'PASS %s\n' "ld-long-output" + pass=$((pass + 1)) +else + printf 'FAIL %s\n' "ld-long-output" + sed 's/^/ | /' "$work/ld-long-output.err" + fail=$((fail + 1)) +fi + +cat > "$work/shared-undef.c" <<'SRC' +int missing(void); +int f(void) { return missing(); } +SRC +if "$CFREE" cc -target x86_64-linux -fPIC -c "$work/shared-undef.c" \ + -o "$work/shared-undef.o" > "$work/shared-undef-cc.out" \ + 2> "$work/shared-undef-cc.err"; then + if ! "$CFREE" ld -shared --no-undefined "$work/shared-undef.o" \ + -o "$work/shared-undef.so" > "$work/shared-undef-ld.out" \ + 2> "$work/shared-undef-ld.err"; then + printf 'PASS %s\n' "ld-no-undefined" + pass=$((pass + 1)) + else + printf 'FAIL %s (link unexpectedly succeeded)\n' "ld-no-undefined" + fail=$((fail + 1)) + fi +else + printf 'FAIL %s (setup compile failed)\n' "ld-no-undefined" + sed 's/^/ | /' "$work/shared-undef-cc.err" + fail=$((fail + 1)) +fi + +if "$CFREE" objdump -x "$work/main.o" \ + > "$work/objdump-x.out" 2> "$work/objdump-x.err" && + grep -q "Sections:" "$work/objdump-x.out" && + grep -q "SYMBOL TABLE:" "$work/objdump-x.out"; then + printf 'PASS %s\n' "objdump-x-aggregate" + pass=$((pass + 1)) +else + printf 'FAIL %s\n' "objdump-x-aggregate" + sed 's/^/ | /' "$work/objdump-x.err" + fail=$((fail + 1)) +fi + cat > "$work/run-main.c" <<'SRC' int add42(int); int main(void) { return add42(0); }