Change how tomo command line behavior works and how shared libraries are
built/installed.
This commit is contained in:
parent
7c255c517e
commit
77aa022df0
254
tomo.c
254
tomo.c
@ -18,24 +18,25 @@
|
||||
#include "typecheck.h"
|
||||
#include "types.h"
|
||||
|
||||
#define ENV_CORD(name) CORD_from_char_star(getenv(name) ? getenv(name) : "")
|
||||
#define CORD_RUN(...) ({ CORD _cmd = CORD_all(__VA_ARGS__); if (verbose) CORD_printf("\x1b[33m%r\x1b[m\n", _cmd); popen(CORD_to_const_char_star(_cmd), "w"); })
|
||||
|
||||
typedef enum { MODE_TRANSPILE = 0, MODE_COMPILE_OBJ = 1, MODE_COMPILE_SHARED_OBJ = 2, MODE_COMPILE_EXE = 3, MODE_RUN = 4 } mode_e;
|
||||
|
||||
static bool verbose = false;
|
||||
static bool show_codegen = false;
|
||||
static bool cleanup_files = false;
|
||||
static const char *autofmt, *cconfig, *cflags, *objfiles, *ldlibs, *ldflags, *cc;
|
||||
static CORD autofmt, cconfig, cflags, ldlibs, ldflags, cc;
|
||||
|
||||
static array_t get_file_dependencies(const char *filename, array_t *object_files);
|
||||
static int transpile_header(env_t *base_env, const char *filename, bool force_retranspile);
|
||||
static int transpile_code(env_t *base_env, const char *filename, bool force_retranspile);
|
||||
static int compile_object_file(const char *filename, bool force_recompile);
|
||||
static int compile_executable(env_t *base_env, const char *filename, array_t object_files);
|
||||
static int compile_executable(env_t *base_env, const char *filename, CORD object_files);
|
||||
static void build_file_dependency_graph(const char *filename, table_t *to_compile, table_t *to_link);
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
mode_e mode = MODE_RUN;
|
||||
const char *filename = NULL;
|
||||
int program_arg_index = argc + 1;
|
||||
int after_flags = 1;
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (streq(argv[i], "-t")) {
|
||||
mode = MODE_TRANSPILE;
|
||||
@ -47,10 +48,8 @@ int main(int argc, char *argv[])
|
||||
mode = MODE_RUN;
|
||||
} else if (streq(argv[i], "-e")) {
|
||||
mode = MODE_COMPILE_EXE;
|
||||
} else if (streq(argv[i], "-C")) {
|
||||
cleanup_files = true;
|
||||
} else if (streq(argv[i], "-h") || streq(argv[i], "--help")) {
|
||||
printf("Usage: %s [[-t|-c|-e|-r] [-C] [option=value]* file.tm [args...]]\n", argv[0]);
|
||||
printf("Usage: %s | %s [-r] file.tm args... | %s (-t|-c|-s) file1.tm file2.tm...\n", argv[0], argv[0], argv[0]);
|
||||
return 0;
|
||||
} else if (strchr(argv[i], '=')) {
|
||||
while (argv[i][0] == '-')
|
||||
@ -61,165 +60,176 @@ int main(int argc, char *argv[])
|
||||
*p = toupper(*p);
|
||||
setenv(argv[i], eq + 1, 1);
|
||||
} else {
|
||||
filename = argv[i];
|
||||
program_arg_index = i + 1;
|
||||
after_flags = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// register_printf_modifier(L"p");
|
||||
if (register_printf_specifier('T', printf_type, printf_pointer_size))
|
||||
errx(1, "Couldn't set printf specifier");
|
||||
if (register_printf_specifier('W', printf_ast, printf_pointer_size))
|
||||
errx(1, "Couldn't set printf specifier");
|
||||
|
||||
setenv("TOMO_IMPORT_PATH", "~/.local/tomo/src:.", 0);
|
||||
setenv("TOMO_IMPORT_PATH", "~/.local/src/tomo:.", 0);
|
||||
|
||||
autofmt = getenv("AUTOFMT");
|
||||
CORD home = ENV_CORD("HOME");
|
||||
autofmt = ENV_CORD("AUTOFMT");
|
||||
if (!autofmt) autofmt = "indent -kr -l100 -nbbo -nut -sob";
|
||||
if (!autofmt[0]) autofmt = "cat";
|
||||
|
||||
verbose = (getenv("VERBOSE") && (streq(getenv("VERBOSE"), "1") || streq(getenv("VERBOSE"), "2")));
|
||||
show_codegen = (getenv("VERBOSE") && streq(getenv("VERBOSE"), "2"));
|
||||
|
||||
if (filename == NULL) {
|
||||
if (after_flags >= argc) {
|
||||
repl();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strlen(filename) < strlen(".tm") + 1 || strncmp(filename + strlen(filename) - strlen(".tm"), ".tm", strlen(".tm")) != 0)
|
||||
errx(1, "Not a valid .tm file: %s", filename);
|
||||
|
||||
cconfig = getenv("CCONFIG");
|
||||
cconfig = ENV_CORD("CCONFIG");
|
||||
if (!cconfig)
|
||||
cconfig = "-std=c11 -fdollars-in-identifiers -fsanitize=signed-integer-overflow -fno-sanitize-recover"
|
||||
" -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -D_DEFAULT_SOURCE";
|
||||
|
||||
const char *optimization = getenv("O");
|
||||
if (!optimization || !optimization[0]) optimization = "-O1";
|
||||
else optimization = heap_strf("-O%s", optimization);
|
||||
CORD optimization = ENV_CORD("O");
|
||||
if (!optimization) optimization = "-O1";
|
||||
else optimization = CORD_all("-O", optimization);
|
||||
|
||||
objfiles = getenv("OBJFILES");
|
||||
if (!objfiles)
|
||||
objfiles = "";
|
||||
|
||||
cflags = getenv("CFLAGS");
|
||||
cflags = ENV_CORD("CFLAGS");
|
||||
if (!cflags)
|
||||
cflags = heap_strf("%s %s -fPIC -ggdb -I./include -I%s/.local/tomo/include -D_DEFAULT_SOURCE", cconfig, optimization, getenv("HOME"));
|
||||
cflags = CORD_all(cconfig, " ", optimization, " -fPIC -ggdb -I./include -I'", home, "/.local/include/tomo' -D_DEFAULT_SOURCE");
|
||||
|
||||
ldflags = heap_strf("-Wl,-rpath,'$ORIGIN',-rpath,'%s/.local/tomo/lib' -L. -L%s/.local/tomo/lib", getenv("HOME"), getenv("HOME"));
|
||||
ldflags = CORD_all("-Wl,-rpath='$ORIGIN',-rpath='", home, "/.local/lib/tomo' -L. -L'", home, "/.local/lib/tomo'");
|
||||
|
||||
ldlibs = "-lgc -lcord -lm -ltomo";
|
||||
if (getenv("LDLIBS"))
|
||||
ldlibs = heap_strf("%s %s", ldlibs, getenv("LDLIBS"));
|
||||
|
||||
cc = getenv("CC");
|
||||
cc = ENV_CORD("CC");
|
||||
if (!cc) cc = "cc";
|
||||
|
||||
array_t object_files = {};
|
||||
const char *my_obj = heap_strf("%s.o", resolve_path(filename, ".", "."));
|
||||
Array$insert(&object_files, &my_obj, 0, $ArrayInfo(&$Text));
|
||||
array_t file_deps = get_file_dependencies(filename, &object_files);
|
||||
|
||||
env_t *env = new_compilation_unit();
|
||||
int status = transpile_header(env, filename, true);
|
||||
if (status != 0) return status;
|
||||
table_t dependency_files = {};
|
||||
table_t to_link = {};
|
||||
|
||||
for (int64_t i = 0; i < file_deps.length; i++) {
|
||||
const char *dep = *(char**)(file_deps.data + i*file_deps.stride);
|
||||
status = transpile_header(env, dep, false);
|
||||
for (int i = after_flags; i < argc; i++) {
|
||||
const char *resolved = resolve_path(argv[i], ".", ".");
|
||||
if (!resolved) errx(1, "Couldn't resolve path: %s", argv[i]);
|
||||
build_file_dependency_graph(resolved, &dependency_files, &to_link);
|
||||
if (mode == MODE_RUN) break;
|
||||
}
|
||||
|
||||
int status;
|
||||
// Non-lazily (re)compile header files for each source file passed to the compiler:
|
||||
for (int i = after_flags; i < argc; i++) {
|
||||
const char *filename = argv[i];
|
||||
status = transpile_header(env, filename, true);
|
||||
if (status != 0) return status;
|
||||
}
|
||||
|
||||
env->imports = new(table_t);
|
||||
// Lazily (re)compile all the header files:
|
||||
for (int64_t i = 0; i < dependency_files.entries.length; i++) {
|
||||
const char *filename = *(char**)(dependency_files.entries.data + i*dependency_files.entries.stride);
|
||||
status = transpile_header(env, filename, false);
|
||||
if (status != 0) return status;
|
||||
}
|
||||
|
||||
status = transpile_code(env, filename, true);
|
||||
if (status != 0) return status;
|
||||
// env->imports = new(table_t);
|
||||
|
||||
status = compile_object_file(filename, true);
|
||||
if (status != 0) return status;
|
||||
// Non-lazily (re)compile object files for each source file passed to the compiler:
|
||||
for (int i = after_flags; i < argc; i++) {
|
||||
const char *filename = argv[i];
|
||||
status = transpile_code(env, filename, true);
|
||||
if (status != 0) return status;
|
||||
status = compile_object_file(filename, true);
|
||||
if (status != 0) return status;
|
||||
if (mode == MODE_RUN) break;
|
||||
}
|
||||
|
||||
if (mode == MODE_COMPILE_OBJ)
|
||||
return 0;
|
||||
|
||||
for (int64_t i = 0; i < file_deps.length; i++) {
|
||||
const char *dep = *(char**)(file_deps.data + i*file_deps.stride);
|
||||
|
||||
status = transpile_code(env, dep, false);
|
||||
// Lazily (re)compile object files for each dependency:
|
||||
for (int64_t i = 0; i < dependency_files.entries.length; i++) {
|
||||
const char *filename = *(char**)(dependency_files.entries.data + i*dependency_files.entries.stride);
|
||||
status = transpile_code(env, filename, false);
|
||||
if (status != 0) return status;
|
||||
|
||||
status = compile_object_file(dep, false);
|
||||
status = compile_object_file(filename, false);
|
||||
if (status != 0) return status;
|
||||
}
|
||||
|
||||
CORD object_files = CORD_EMPTY;
|
||||
for (int64_t i = 0; i < dependency_files.entries.length; i++) {
|
||||
const char *filename = *(char**)(dependency_files.entries.data + i*dependency_files.entries.stride);
|
||||
object_files = CORD_all(object_files, filename, ".o ");
|
||||
}
|
||||
for (int64_t i = 0; i < to_link.entries.length; i++) {
|
||||
const char *lib = *(char**)(to_link.entries.data + i*to_link.entries.stride);
|
||||
ldlibs = CORD_all(ldlibs, " ", lib);
|
||||
}
|
||||
|
||||
// For shared objects, link up all the object files into one .so file:
|
||||
if (mode == MODE_COMPILE_SHARED_OBJ) {
|
||||
const char *base = file_base_name(filename);
|
||||
const char *outfile = heap_strf("lib%s.so", base);
|
||||
const char *cmd = heap_strf("%s %s %s %s %s -Wl,-soname,lib%s.so -shared %s.o -o %s", cc, cflags, ldflags, ldlibs, objfiles, base, filename, outfile);
|
||||
if (verbose)
|
||||
printf("Running: %s\n", cmd);
|
||||
FILE *prog = popen(cmd, "w");
|
||||
const char *first_file = argv[after_flags];
|
||||
const char *libname = file_base_name(first_file);
|
||||
|
||||
const char *h_filename = heap_strf("lib%s.h", libname);
|
||||
FILE *h_file = fopen(h_filename, "w");
|
||||
if (!h_file)
|
||||
errx(1, "Couldn't open file: %s", h_filename);
|
||||
fputs("#pragma once\n", h_file);
|
||||
for (int i = after_flags; i < argc; i++) {
|
||||
const char *filename = argv[i];
|
||||
fprintf(h_file, "#include <%s/%s.h>\n", libname, filename);
|
||||
}
|
||||
if (fclose(h_file))
|
||||
errx(1, "Failed to close file: %s", h_filename);
|
||||
|
||||
CORD outfile = CORD_all("lib", libname, ".so");
|
||||
FILE *prog = CORD_RUN(cc, " ", cflags, " ", ldflags, " ", ldlibs, " -Wl,-soname=", outfile, " -shared ", object_files, " -o ", outfile);
|
||||
status = pclose(prog);
|
||||
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
|
||||
return WEXITSTATUS(status);
|
||||
if (verbose)
|
||||
printf("Compiled to %s\n", outfile);
|
||||
CORD_printf("Compiled to %r\n", outfile);
|
||||
|
||||
printf("Do you want to install your library? [Y/n] ");
|
||||
fflush(stdout);
|
||||
switch (getchar()) {
|
||||
case 'y': case 'Y': case '\n': {
|
||||
const char *name = file_base_name(filename);
|
||||
system(heap_strf("mkdir -p ~/.local/tomo/lib ~/.local/tomo/'%s'", name));
|
||||
system(heap_strf("cp -v 'lib%s.so' ~/.local/tomo/'%s'/", name, name));
|
||||
system(heap_strf("ln -sv '../%s/lib%s.so' ~/.local/tomo/lib/'lib%s.so'", name, name, name));
|
||||
for (int64_t i = 0; i < file_deps.length; i++) {
|
||||
const char *dep = *(char**)(file_deps.data + i*file_deps.stride);
|
||||
system(heap_strf("cp -v %s %s.c %s.h %s.o ~/.local/tomo/%s/", dep, dep, dep, dep, name));
|
||||
}
|
||||
system(heap_strf("mkdir -p ~/.local/lib/tomo ~/.local/include/tomo ~/.local/src/tomo/'%s'", libname));
|
||||
system(heap_strf("cp -rv . ~/.local/src/tomo/'%s'", libname));
|
||||
system(heap_strf("ln -sfv '../../src/tomo/%s/lib%s.so' ~/.local/lib/tomo/'lib%s.so'", libname, libname, libname));
|
||||
system(heap_strf("ln -sfv '../../src/tomo/%s/lib%s.h' ~/.local/include/tomo/'lib%s.h'", libname, libname, libname));
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *filename = argv[after_flags];
|
||||
int executable_status = compile_executable(env, filename, object_files);
|
||||
if (mode == MODE_COMPILE_EXE || executable_status != 0)
|
||||
return executable_status;
|
||||
|
||||
if (cleanup_files) {
|
||||
for (int64_t i = 0; i < file_deps.length; i++) {
|
||||
const char *dep = *(char**)(file_deps.data + i*file_deps.stride);
|
||||
if (verbose)
|
||||
printf("Cleaning up %s files...\n", dep);
|
||||
|
||||
system(heap_strf("rm -f %s.c %s.h %s.o", dep, dep, dep));
|
||||
}
|
||||
}
|
||||
|
||||
char *exe_name = heap_strn(filename, strlen(filename) - strlen(".tm"));
|
||||
int num_args = argc - program_arg_index;
|
||||
int num_args = argc - after_flags - 1;
|
||||
char *prog_args[num_args + 2];
|
||||
prog_args[0] = exe_name;
|
||||
for (int i = 0; i < num_args; i++)
|
||||
prog_args[i+1] = argv[program_arg_index+i];
|
||||
prog_args[i+1] = argv[after_flags+1+i];
|
||||
prog_args[num_args+1] = NULL;
|
||||
execv(exe_name, prog_args);
|
||||
|
||||
errx(1, "Failed to run compiled program");
|
||||
}
|
||||
|
||||
static void build_file_dependency_graph(const char *filename, table_t *dependencies, array_t *object_files)
|
||||
void build_file_dependency_graph(const char *filename, table_t *to_compile, table_t *to_link)
|
||||
{
|
||||
size_t len = strlen(filename);
|
||||
assert(strncmp(filename + len - 3, ".tm", 3) == 0);
|
||||
|
||||
if (Table$str_get(*dependencies, filename))
|
||||
if (Table$str_get(*to_compile, filename))
|
||||
return;
|
||||
|
||||
array_t *deps = new(array_t);
|
||||
Array$insert(deps, &filename, 0, $ArrayInfo(&$Text));
|
||||
Table$str_set(dependencies, filename, deps);
|
||||
Table$str_set(to_compile, filename, filename);
|
||||
|
||||
size_t len = strlen(filename);
|
||||
assert(strncmp(filename + len - 3, ".tm", 3) == 0);
|
||||
|
||||
file_t *f = load_file(filename);
|
||||
if (!f)
|
||||
@ -241,45 +251,24 @@ static void build_file_dependency_graph(const char *filename, table_t *dependenc
|
||||
use_path = Match(decl->value, Use)->raw_path;
|
||||
}
|
||||
if (!use_path) continue;
|
||||
const char *import, *obj_file;
|
||||
const char *import;
|
||||
if (use_path[0] == '/' || strncmp(use_path, "~/", 2) == 0 || strncmp(use_path, "./", 2) == 0 || strncmp(use_path, "../", 3) == 0) {
|
||||
import = resolve_path(use_path, filename, "");
|
||||
if (!import) errx(1, "Couldn't resolve path: %s", use_path);
|
||||
obj_file = heap_strf("%s.o", resolve_path(use_path, filename, ""));
|
||||
const char *path = resolve_path(use_path, filename, "");
|
||||
if (Table$str_get(*to_compile, path))
|
||||
continue;
|
||||
Table$str_set(to_compile, path, path);
|
||||
} else {
|
||||
import = resolve_path(use_path, filename, getenv("TOMO_IMPORT_PATH"));
|
||||
obj_file = heap_strf("-l%.*s", strlen(use_path)-3, use_path);
|
||||
const char *lib = heap_strf("-l%.*s", strlen(use_path)-strlen(".tm"), use_path);
|
||||
Table$str_set(to_link, lib, lib);
|
||||
}
|
||||
Array$insert(deps, &import, 0, $ArrayInfo(&$Text));
|
||||
Array$insert(object_files, &obj_file, 0, $ArrayInfo(&$Text));
|
||||
build_file_dependency_graph(import, dependencies, object_files);
|
||||
build_file_dependency_graph(import, to_compile, to_link);
|
||||
}
|
||||
free(file_dir);
|
||||
}
|
||||
|
||||
array_t get_file_dependencies(const char *filename, array_t *object_files)
|
||||
{
|
||||
const char *resolved = resolve_path(filename, ".", ".");
|
||||
if (!resolved) errx(1, "Couldn't resolve path: %s", filename);
|
||||
|
||||
table_t file_dependencies = {};
|
||||
build_file_dependency_graph(resolved, &file_dependencies, object_files);
|
||||
table_t dependency_set = {};
|
||||
|
||||
const TypeInfo unit = {.size=0, .align=0, .tag=CustomInfo};
|
||||
const TypeInfo info = {.size=sizeof(table_t), .align=__alignof__(table_t),
|
||||
.tag=TableInfo, .TableInfo.key=&$Text, .TableInfo.value=&unit};
|
||||
|
||||
for (int64_t i = 1; i <= Table$length(file_dependencies); i++) {
|
||||
struct { const char *name; array_t *deps; } *entry = Table$entry(file_dependencies, i);
|
||||
for (int64_t j = 0; j < entry->deps->length; j++) {
|
||||
const char *dep = *(char**)(entry->deps->data + j*entry->deps->stride);
|
||||
Table$set(&dependency_set, &dep, &dep, &info);
|
||||
}
|
||||
}
|
||||
return dependency_set.entries;
|
||||
}
|
||||
|
||||
static bool is_stale(const char *filename, const char *relative_to)
|
||||
{
|
||||
struct stat target_stat;
|
||||
@ -310,8 +299,8 @@ int transpile_header(env_t *base_env, const char *filename, bool force_retranspi
|
||||
|
||||
CORD h_code = compile_header(module_env, ast);
|
||||
|
||||
if (autofmt && autofmt[0]) {
|
||||
FILE *prog = popen(heap_strf("%s 2>/dev/null >%s", autofmt, h_filename), "w");
|
||||
if (autofmt) {
|
||||
FILE *prog = CORD_RUN(autofmt, " 2>/dev/null >", h_filename);
|
||||
CORD_put(h_code, prog);
|
||||
if (pclose(prog) == -1)
|
||||
errx(1, "Failed to run autoformat program on header file: %s", autofmt);
|
||||
@ -328,7 +317,7 @@ int transpile_header(env_t *base_env, const char *filename, bool force_retranspi
|
||||
printf("Transpiled to %s\n", h_filename);
|
||||
|
||||
if (show_codegen) {
|
||||
FILE *out = popen(heap_strf("bat -P %s", h_filename), "w");
|
||||
FILE *out = CORD_RUN("bat -P ", h_filename);
|
||||
pclose(out);
|
||||
}
|
||||
|
||||
@ -354,8 +343,8 @@ int transpile_code(env_t *base_env, const char *filename, bool force_retranspile
|
||||
|
||||
CORD c_code = compile_file(module_env, ast);
|
||||
|
||||
if (autofmt && autofmt[0]) {
|
||||
FILE *prog = popen(heap_strf("%s 2>/dev/null >%s", autofmt, c_filename), "w");
|
||||
if (autofmt) {
|
||||
FILE *prog = CORD_RUN(autofmt, " 2>/dev/null >", c_filename);
|
||||
CORD_put(c_code, prog);
|
||||
if (pclose(prog) == -1)
|
||||
errx(1, "Failed to output autoformatted C code to %s: %s", c_filename, autofmt);
|
||||
@ -372,7 +361,7 @@ int transpile_code(env_t *base_env, const char *filename, bool force_retranspile
|
||||
printf("Transpiled to %s\n", c_filename);
|
||||
|
||||
if (show_codegen) {
|
||||
FILE *out = popen(heap_strf("bat -P %s", c_filename), "w");
|
||||
FILE *out = CORD_RUN("bat -P ", c_filename);
|
||||
pclose(out);
|
||||
}
|
||||
|
||||
@ -387,20 +376,17 @@ int compile_object_file(const char *filename, bool force_recompile)
|
||||
&& !is_stale(obj_file, heap_strf("%s.h", filename))) {
|
||||
return 0;
|
||||
}
|
||||
const char *outfile = heap_strf("%s.o", filename);
|
||||
const char *cmd = heap_strf("%s %s -c %s.c -o %s", cc, cflags, filename, outfile);
|
||||
if (verbose)
|
||||
printf("Running: %s\n", cmd);
|
||||
FILE *prog = popen(cmd, "w");
|
||||
CORD outfile = CORD_all(filename, ".o");
|
||||
FILE *prog = CORD_RUN(cc, " ", cflags, " -c ", filename, ".c -o ", outfile);
|
||||
int status = pclose(prog);
|
||||
if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
|
||||
if (verbose)
|
||||
printf("Compiled to %s\n", outfile);
|
||||
CORD_printf("Compiled to %r\n", outfile);
|
||||
}
|
||||
return WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int compile_executable(env_t *base_env, const char *filename, array_t object_files)
|
||||
int compile_executable(env_t *base_env, const char *filename, CORD object_files)
|
||||
{
|
||||
const char *name = file_base_name(filename);
|
||||
env_t *env = Table$str_get(*base_env->imports, name);
|
||||
@ -411,11 +397,7 @@ int compile_executable(env_t *base_env, const char *filename, array_t object_fil
|
||||
}
|
||||
|
||||
const char *bin_name = heap_strn(filename, strlen(filename) - strlen(".tm"));
|
||||
const char *run = heap_strf("%s | %s %s %s %s %s %s -x c - -o %s",
|
||||
autofmt, cc, cflags, ldflags, ldlibs, objfiles, CORD_to_const_char_star(Text$join(" ", object_files)), bin_name);
|
||||
if (verbose)
|
||||
printf("%s\n", run);
|
||||
FILE *runner = popen(run, "w");
|
||||
FILE *runner = CORD_RUN(autofmt, " | ", cc, " ", cflags, " ", ldflags, " ", ldlibs, " ", object_files, " -x c - -o ", bin_name);
|
||||
|
||||
CORD program = CORD_all(
|
||||
"#include <tomo/tomo.h>\n"
|
||||
@ -429,7 +411,7 @@ int compile_executable(env_t *base_env, const char *filename, array_t object_fil
|
||||
);
|
||||
|
||||
if (show_codegen) {
|
||||
FILE *out = popen(heap_strf("%s | bat -P --file-name=run.c", autofmt), "w");
|
||||
FILE *out = CORD_RUN(autofmt, " | bat -P --file-name=run.c");
|
||||
CORD_put(program, out);
|
||||
pclose(out);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user