ui/first.jai

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;
}
}