Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Makefile.posix
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ config.jou: Makefile.posix
echo 'link "$(shell $(LLVM_CONFIG) --ldflags --libs)"' >> config.jou
echo '@public' >> config.jou
echo 'const JOU_CLANG_PATH: byte* = "$(shell which `$(LLVM_CONFIG) --bindir`/clang || which clang)"' >> config.jou
echo '@public' >> config.jou
echo 'const JOU_AR_PATH: byte* = "$(shell which `$(LLVM_CONFIG) --bindir`/llvm-ar || which ar)"' >> config.jou

jou_bootstrap: bootstrap.sh
env LLVM_CONFIG=$(LLVM_CONFIG) ./bootstrap.sh
Expand Down
15 changes: 12 additions & 3 deletions compiler/main.jou
Original file line number Diff line number Diff line change
Expand Up @@ -492,10 +492,19 @@ def main(argc: int, argv: byte**) -> int:
compst.free()
free(stdlib)

exepath = decide_exe_path()
run_linker(objpaths, exepath, linker_flags)
free(linker_flags)
exepath: byte* = NULL
if (
command_line_args.outfile != NULL
and strlen(command_line_args.outfile) > 2
and ends_with(command_line_args.outfile, ".a")
):
# Output .a file instead of executable
run_ar(objpaths, command_line_args.outfile)
else:
exepath = decide_exe_path()
run_linker(objpaths, exepath, linker_flags)

free(linker_flags)
for p = objpaths.ptr; p < objpaths.end(); p++:
free(*p)
free(objpaths.ptr)
Expand Down
58 changes: 47 additions & 11 deletions compiler/run.jou
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,10 @@ def quote_paths(paths: List[byte*]) -> byte*:
return result


@public
def run_linker(objpaths: List[byte*], exepath: byte*, linker_flags: byte*) -> None:
quoted_object_files = quote_paths(objpaths)

command: byte*
if WINDOWS:
# On Linux, we prefer LLVM tools (clang and llvm-ar) of the same LLVM version.
# On Windows, the tools are in mingw64/bin folder.
if WINDOWS:
def get_mingw_command(exe_filename: byte*, args: byte*) -> byte*:
# Assume mingw with clang has been downloaded with windows_setup.sh.
#
# During the bootstrapping, the location of mingw is something
Expand All @@ -49,16 +47,30 @@ def run_linker(objpaths: List[byte*], exepath: byte*, linker_flags: byte*) -> No
asprintf(&mingw_dir, "%s\\mingw64", dirname(jou_exe))
free(jou_exe)

# Could also use clang, but gcc has less dependencies so we can make the Windows zips smaller.
# Windows quoting is weird. The outermost quotes get stripped here.
asprintf(&command, "\"\"%s\\bin\\gcc.exe\" %s -o \"%s\" %s\"", mingw_dir, quoted_object_files, exepath, linker_flags)
result: byte*
asprintf(&result, "\"\"%s\\bin\\%s\" %s\"", mingw_dir, exe_filename, args)

free(mingw_dir)
else:
# Assume clang is installed and use it to link. Could use lld, but clang is needed anyway.
asprintf(&command, "'%s' %s -o '%s' %s", JOU_CLANG_PATH, quoted_object_files, exepath, linker_flags)
return result


@public
def run_linker(objpaths: List[byte*], exepath: byte*, linker_flags: byte*) -> None:
quoted_object_files = quote_paths(objpaths)

args: byte*
asprintf(&args, "%s -o \"%s\" %s", quoted_object_files, exepath, linker_flags)
free(quoted_object_files)

command: byte*
if WINDOWS:
# Could also use clang, but gcc has less dependencies so we can make the Windows zips smaller.
command = get_mingw_command("gcc.exe", args)
else:
asprintf(&command, "'%s' %s", JOU_CLANG_PATH, args)
free(args)

if command_line_args.verbosity >= 1:
printf("Running linker: %s\n", command)

Expand All @@ -67,6 +79,30 @@ def run_linker(objpaths: List[byte*], exepath: byte*, linker_flags: byte*) -> No
free(command)


@public
def run_ar(objpaths: List[byte*], a_path: byte*) -> None:
assert ends_with(a_path, ".a")
quoted_object_files = quote_paths(objpaths)

args: byte*
asprintf(&args, "rcs \"%s\" %s", a_path, quoted_object_files)
free(quoted_object_files)

command: byte*
if WINDOWS:
command = get_mingw_command("ar.exe", args)
else:
asprintf(&command, "'%s' %s", JOU_AR_PATH, args)
free(args)

if command_line_args.verbosity >= 1:
printf("Running ar: %s\n", command)

if system(command) != 0:
exit(1)
free(command)


@public
def run_exe(exepath: byte*, valgrind: bool) -> int:
command: byte*
Expand Down