303 lines
12 KiB
Plaintext
303 lines
12 KiB
Plaintext
#import "Basic";
|
|
#import "Compiler";
|
|
#import "File";
|
|
#import "File_Utilities";
|
|
#import "String";
|
|
#import "System";
|
|
#import "Process";
|
|
|
|
OUTPUT_EXECUTABLE_NAME_DESKTOP :: "mexplore";
|
|
|
|
SOURCE_ENTRY_POINT :: "src/main.jai";
|
|
|
|
DESKTOP_OS_BUILD_OUTPUT_PATH :: "bin";
|
|
|
|
#run Build_Project();
|
|
|
|
Build_Project :: () {
|
|
// Get start time:
|
|
// Compile prerequisites:
|
|
set_build_options_dc(.{do_output=false});
|
|
args := get_build_options().compile_time_command_line;
|
|
|
|
// Simplify targeting / command line interface?
|
|
// [For now] assume x64 for Windows and Linux
|
|
// Android defaults to ARM64, can be overriden with `x64`. `x64` is ignored on all other OS'
|
|
target_windows = array_find(args, "windows");
|
|
target_linux = array_find(args, "linux");
|
|
target_macos = array_find(args, "macos");
|
|
target_x64 = array_find(args, "x64");
|
|
target_optimize = array_find(args, "release");
|
|
|
|
// NOTE(Charles): Proably makes sense to default os/cpu to OS/CPU then arguments override that.
|
|
if target_windows {
|
|
cpu_target = .X64;
|
|
os_target = .WINDOWS;
|
|
assert(os_target == OS);
|
|
} else if target_linux {
|
|
cpu_target = .X64;
|
|
os_target = .LINUX;
|
|
assert(os_target == OS);
|
|
} else if target_macos {
|
|
cpu_target = .ARM64;
|
|
os_target = .MACOS;
|
|
assert(os_target == OS);
|
|
} else {
|
|
assert(false, "Not a valid build configuration.");
|
|
}
|
|
|
|
set_working_directory(#filepath);
|
|
|
|
compile_native_code(); // Also copies assets and libraries :ThisAintCompilingNativeCode!
|
|
print("\n");
|
|
}
|
|
|
|
compile_native_code :: () {
|
|
VERSION :: "0.1";
|
|
JAI_VERSION := trim(compiler_get_version_info(null));
|
|
current_time := to_calendar(current_time_consensus(), .LOCAL);
|
|
RELEASE_DATE := calendar_to_string(current_time);
|
|
result, branch_name := run_command("git", "branch", "--show-current", capture_and_return_output = true);
|
|
GIT_BRANCH := trim(branch_name);
|
|
result=, revision := run_command("git", "rev-parse", "HEAD", capture_and_return_output = true);
|
|
GIT_REVISION := trim(revision);
|
|
|
|
log("Compiling for % %", os_target, cpu_target);
|
|
|
|
start_time := GetUnixTimestamp();
|
|
defer log("Native code compilation time: %", GetUnixTimestamp()-start_time); // NOTE(Charles): The compiler already outputs this for us?
|
|
build_output_directory: string;
|
|
sdk_lib_path: string;
|
|
android_main_directory: string;
|
|
// #if OS != .MACOS {
|
|
// target_triple, target_triple_with_sdk := get_android_target_triple(cpu_target);
|
|
// if os_target == .ANDROID {
|
|
// ndk := get_ndk_paths();
|
|
// sdk_lib_path = tprint("%/usr/lib/%", ndk.sysroot, target_triple);
|
|
|
|
// // Create the library directory
|
|
// android_main_directory = tprint("%/app/src/main", ANDROID_PROJECT_PATH);
|
|
// assert(file_exists(android_main_directory));
|
|
// build_output_directory = tprint("%/jniLibs/%", android_main_directory, get_android_project_jni_architecture_name(cpu_target));
|
|
// make_directory_if_it_does_not_exist(build_output_directory, recursive = true);
|
|
// }
|
|
// }
|
|
|
|
w := compiler_create_workspace("Target workspace");
|
|
options := get_build_options(w);
|
|
copy_commonly_propagated_fields(get_build_options(), *options);
|
|
options.cpu_target = cpu_target;
|
|
options.os_target = os_target;
|
|
|
|
if os_target == .WINDOWS || os_target == .LINUX || OS == .MACOS {
|
|
if target_optimize {
|
|
set_optimization(*options, .VERY_OPTIMIZED, preserve_debug_info=false);
|
|
options.llvm_options.enable_split_modules = false;
|
|
options.array_bounds_check = .OFF;
|
|
options.null_pointer_check = .OFF;
|
|
options.arithmetic_overflow_check = .OFF;
|
|
options.cast_bounds_check = .OFF;
|
|
options.output_executable_name = OUTPUT_EXECUTABLE_NAME_DESKTOP;
|
|
} else {
|
|
options.output_executable_name = tprint("%-debug", OUTPUT_EXECUTABLE_NAME_DESKTOP);
|
|
}
|
|
options.output_path = DESKTOP_OS_BUILD_OUTPUT_PATH;
|
|
make_directory_if_it_does_not_exist(options.output_path, recursive=true);
|
|
}
|
|
|
|
import_path: [..] string;
|
|
array_add(*import_path, "modules");
|
|
array_add(*import_path, ..options.import_path);
|
|
options.import_path = import_path;
|
|
|
|
if cpu_target == .ARM64 {
|
|
options.backend = .LLVM;
|
|
// Disable +lse for older ARM64 devices.
|
|
// options.llvm_options.target_system_features = "+lse";
|
|
}
|
|
|
|
set_build_options(options, w);
|
|
|
|
compiler_begin_intercept(w);
|
|
|
|
add_build_file(SOURCE_ENTRY_POINT, w);
|
|
|
|
build_constants := tprint(#string STRING
|
|
NAME :: "%";
|
|
VERSION :: "%";
|
|
JAI_VERSION :: "%";
|
|
RELEASE_DATE :: "%";
|
|
GIT_BRANCH :: "%";
|
|
GIT_REVISION :: "%";
|
|
DEBUG :: %;
|
|
STRING,
|
|
OUTPUT_EXECUTABLE_NAME_DESKTOP, VERSION, JAI_VERSION, RELEASE_DATE, GIT_BRANCH, GIT_REVISION,
|
|
ifx target_optimize then "false" else "true",
|
|
);
|
|
|
|
add_build_string(build_constants, w);
|
|
|
|
while true {
|
|
message := compiler_wait_for_message();
|
|
if message.kind == {
|
|
case .PHASE;
|
|
phase_message := cast(*Message_Phase) message;
|
|
if phase_message.phase == .READY_FOR_CUSTOM_LINK_COMMAND {
|
|
// #if OS != .MACOS {
|
|
// run_android_link_command(phase_message, options, extra_args = .[
|
|
// tprint("-L%", sdk_lib_path), "-lc++"] // :AndroidStbImageThreadLocals
|
|
// );
|
|
// }
|
|
}
|
|
|
|
case .ERROR;
|
|
print("\n"); // Seems to be some issue with exit() not flushing output, we miss errors!
|
|
exit(1);
|
|
|
|
case .COMPLETE; break;
|
|
}
|
|
}
|
|
compiler_end_intercept(w);
|
|
|
|
// :ThisAintCompilingNativeCode!
|
|
|
|
ASSETS :: string.[
|
|
// "extras/images/image_test.jpg",
|
|
// "extras/fonts/JetBrainsMono-Regular.ttf",
|
|
// "extras/fonts/RobotoMono-Regular.ttf",
|
|
];
|
|
|
|
if os_target == .WINDOWS {
|
|
WINDOWS_LIBS :: string.[];
|
|
WINDOWS_LIBS_DEBUG :: string.[];
|
|
target_output_directory := tprint("%/bin", #filepath);
|
|
make_directory_if_it_does_not_exist(options.output_path, recursive=true);
|
|
for ASSETS {
|
|
if !copy_file(it, tprint("%/%", target_output_directory, path_filename(it))) {
|
|
compiler_report(tprint("Failed to copy file % to android project assets", it));
|
|
}
|
|
}
|
|
|
|
target_lib_array := ifx target_optimize then WINDOWS_LIBS else WINDOWS_LIBS_DEBUG;
|
|
for target_lib_array {
|
|
if !copy_file(it, tprint("%/%", target_output_directory, path_filename(it))) {
|
|
compiler_report(tprint("Failed to copy file % to android project assets", it));
|
|
}
|
|
}
|
|
}
|
|
|
|
if os_target == .LINUX {
|
|
LINUX_LIBS :: string.[];
|
|
target_output_directory := tprint("%/bin", #filepath);
|
|
make_directory_if_it_does_not_exist(options.output_path, recursive=true);
|
|
for ASSETS {
|
|
if !copy_file(it, tprint("%/%", target_output_directory, path_filename(it))) {
|
|
compiler_report(tprint("Failed to copy file % to android project assets", it));
|
|
}
|
|
}
|
|
for LINUX_LIBS {
|
|
if !copy_file(it, tprint("%/%", target_output_directory, path_filename(it))) {
|
|
compiler_report(tprint("Failed to copy file % to android project assets", it));
|
|
}
|
|
}
|
|
}
|
|
|
|
if os_target == .ANDROID {
|
|
resources_output_directory := tprint("%/assets", android_main_directory);
|
|
make_directory_if_it_does_not_exist(resources_output_directory, recursive = true);
|
|
for ASSETS {
|
|
if !copy_file(it, tprint("%/%", resources_output_directory, path_filename(it))) {
|
|
compiler_report(tprint("Failed to copy file % to android project assets", it));
|
|
}
|
|
}
|
|
|
|
// #if OS != .MACOS {
|
|
// // Package libc++ :AndroidStbImageThreadLocals
|
|
// success := copy_android_libcpp(cpu_target, options.output_path);
|
|
// if !success {
|
|
// compiler_report(tprint("Could not copy Android libc++ to %", options.output_path));
|
|
// }
|
|
// }
|
|
}
|
|
}
|
|
|
|
// #if OS != .MACOS {
|
|
// generate_android_project :: () {
|
|
// GENERATE_ANDROID_FILES :: false;
|
|
// if file_exists(ANDROID_PROJECT_PATH) && !GENERATE_ANDROID_FILES {
|
|
// log("Project folder at %", ANDROID_PROJECT_PATH);
|
|
// return;
|
|
// }
|
|
// log("Generating new project folder at %", ANDROID_PROJECT_PATH);
|
|
// start_time := GetUnixTimestamp();
|
|
// config: Android_Project_Config;
|
|
// config.project_path = ANDROID_PROJECT_PATH;
|
|
// config.app_name = ANDROID_APP_NAME;
|
|
// config.app_id = ANDROID_APP_ID;
|
|
// config.android_gradle_plugin_version = "8.2.2";
|
|
// config.gradle_version = "8.6";
|
|
// config.lib_name = OUTPUT_EXECUTABLE_NAME_ANDROID;
|
|
// // Hmmm. I wanna do portrait for phones and landscape for tablets, or allow the user to choose via device orientation.
|
|
// // For now just roll with this.
|
|
// config.screen_orientation = .PORTRAIT;
|
|
// // config.screen_orientation = .LANDSCAPE;
|
|
// if !generate_android_project(*config) {
|
|
// compiler_report(tprint("Failed to create android project \"%\"", config.project_path));
|
|
// return;
|
|
// }
|
|
// log("Succesfully created or updated android project \"%\".", config.project_path);
|
|
// log("Generate Android project time: %", GetUnixTimestamp()-start_time);
|
|
|
|
// // NOTE(Charles): Android Icons!
|
|
// //
|
|
// // The apps icon is set with the icon attribute of application tag in manifest. This has to be set to a reference
|
|
// // to a "drawable resource". This most direct way to do this is to put a png in the drawable directory, eg
|
|
// // AndroidProject/app/src/main/res/drawable/my_icon.png. The attribute can then be set to
|
|
// // android:icon="@drawable/my_icon".
|
|
// //
|
|
// // However, on my phone at least, this looks total ass. The image gets massively shrunk down and the rest of the
|
|
// // icon is a white circle. Apparently this is because now android expects you to define "adaptive icons". Instead
|
|
// // you now have to provide both a foreground and background image, and define your "image" in xml. So we now have
|
|
// // two images drawable/icon_foreground.png, drawable/icon_background.png and the magic link file mipmap/icon.xml.
|
|
// //
|
|
// // This now looks ok on my phone, but I fully expect on other devices it might look weird and we will have to
|
|
// // figure some more android configuration junk out. If we manage to figure out enough of the junk then I could
|
|
// // maybe write some helper that generates all the required crap given some simpler inputs, for now it's all manually
|
|
// // defined.
|
|
// //
|
|
// // Adaptive icons docs: https://developer.android.com/develop/ui/views/launch/icon_design_adaptive
|
|
// // "Alternative resources" docs: https://developer.android.com/guide/topics/resources/providing-resources#AlternativeResources
|
|
// }
|
|
// }
|
|
|
|
target_windows : bool;
|
|
target_linux : bool;
|
|
target_macos : bool;
|
|
target_android : bool;
|
|
target_optimize : bool;
|
|
target_x64 : bool;
|
|
|
|
cpu_target: CPU_Tag;
|
|
os_target: Operating_System_Tag;
|
|
|
|
android_make_apk := false;
|
|
android_install := false;
|
|
|
|
GetUnixTimestamp :: () -> float64 {
|
|
#if OS == .WINDOWS {
|
|
#import "Windows";
|
|
FILETIME_TO_UNIX :: 116444736000000000;
|
|
ft: FILETIME;
|
|
GetSystemTimePreciseAsFileTime(*ft);
|
|
t: s64 = ((cast(s64)ft.dwHighDateTime) << 32) | (cast(s64)ft.dwLowDateTime);
|
|
return (cast(float64)(t - FILETIME_TO_UNIX)) / (10.0 * 1000.0 * 1000.0);
|
|
}
|
|
#if OS == .LINUX || OS == .MACOS {
|
|
#import "POSIX";
|
|
TIMESPEC_TO_SEC_DIV :: 1000000000.0;
|
|
at := current_time_consensus();
|
|
ts := to_timespec(at);
|
|
return cast(float64)(ts.tv_sec) + cast(float64)(ts.tv_nsec) / TIMESPEC_TO_SEC_DIV;
|
|
}
|
|
}
|