Skip to content

Instantly share code, notes, and snippets.

@yasinkaraaslan
Last active May 31, 2025 16:14
Show Gist options
  • Save yasinkaraaslan/142e96110b929b96f8401c111889a385 to your computer and use it in GitHub Desktop.
Save yasinkaraaslan/142e96110b929b96f8401c111889a385 to your computer and use it in GitHub Desktop.
Jai Metaprogram for Linking with RAD Linker
LINKER_FILE_NAME :: "radlink.exe";
#run build();
build :: () {
set_build_options_dc(.{do_output=false});
set_working_directory(#filepath);
options := get_build_options();
options.output_type = .EXECUTABLE;
options.output_executable_name = "My Executable";
options.output_path = "./build/";
#if OS == .WINDOWS { // RAD Linker is only available on windows
// RAD Linker gives an error on the x64 backend
if options.backend == .LLVM options.use_custom_link_command = true;
}
w := compiler_create_workspace("My Workspace");
set_build_options(options, w);
compiler_begin_intercept(w);
add_build_file("main.jai", w);
while true {
message := compiler_wait_for_message();
if message.kind == {
case .PHASE;
phase := cast(*Message_Phase)message;
if phase.phase == .READY_FOR_CUSTOM_LINK_COMMAND {
target_filename := tprint("%1%2.exe", options.output_path, options.output_executable_name);
vc_path := find_visual_studio_in_a_ridiculous_garbage_way();
kit_root := find_windows_kit_root();
linker_arguments: [..]string;
array_add(*linker_arguments, LINKER_FILE_NAME);
for phase.compiler_generated_object_files array_add(*linker_arguments, it);
for phase.support_object_files array_add(*linker_arguments, it);
for phase.user_libraries array_add(*linker_arguments, it);
// libcmt seems to cause problems when linking with some libraries
// so we are using msvcrt instead.
// https://learn.microsoft.com/en-us/cpp/c-runtime-library/crt-library-features
for phase.system_libraries if it != "libcmt.lib" array_add(*linker_arguments, it);
array_add(*linker_arguments,
"/MACHINE:AMD64",
"/INCREMENTAL:NO",
"/RAD_DEBUG", // Produce .rdi (for rad debugger)
"/DEBUG", // Produce .pdb
tprint("/IMPLIB:%1/%2.lib", options.intermediate_path, options.output_executable_name),
tprint("/OUT:%", target_filename),
tprint("/libpath:%", vc_path),
tprint("/libpath:%\\um\\x64", kit_root),
tprint("/libpath:%\\ucrt\\x64", kit_root),
"msvcrt.lib", // instead of libcmt.lib
"-nodefaultlib"
);
print("Link line: %\n", get_quoted_command_string(linker_arguments));
result := run_command(..linker_arguments);
if result.exit_code != 0 compiler_report(tprint("Linker failed, error code: %\n", result.exit_code));
compiler_custom_link_command_is_complete(w);
}
case .ERROR;
exit(1);
case .COMPLETE;
break;
}
}
}
#import "Compiler";
#if OS == .WINDOWS {
#import "Windows_Resources";
}
#import "Basic";
#import "Process";
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment