// Type-checks src/App.jai for another OS without producing or linking a binary, to catch errors // in code your machine does not build: // // jai check_targets.jai - linux (from any OS) // jai check_targets.jai - macos (from a Mac only: the Objective_C module runs code at compile time) // // The constants below stand in for the ones first.jai generates; keep their names in step. #run,stallable { set_build_options_dc(.{do_output = false}); args := get_build_options().compile_time_command_line; // Linux on the host's CPU: the ARM compiler cannot run x64 code at compile time (String's #asm // in the hotkey checks' #run), so from a Mac it checks Linux on arm64. target := Operating_System_Tag.LINUX; cpu := CPU; if array_find(args, "macos") { target = .MACOS; cpu = .ARM64; } options := get_build_options(); options.os_target = target; options.cpu_target = cpu; options.output_type = .NO_OUTPUT; options.backend = .LLVM; options.output_executable_name = "check"; options.output_path = ".build"; // rpmalloc (modules/Default_Allocator) also runs at compile time, with the target's OS layer, // which crashes on another OS. A check for another OS uses Jai's own allocator instead, through a // module of the same name ahead of modules/ (with the thread_idle the app calls, doing nothing). if target != OS { jai_modules := trim_right(options.import_path[options.import_path.count - 1], "/"); shim := tprint("%/.build/check_modules", get_working_directory()); make_directory_if_it_does_not_exist(tprint("%/Default_Allocator", shim), recursive = true); write_entire_file(tprint("%/Default_Allocator/module.jai", shim), tprint(#string SHIM // Written by check_targets.jai: Jai's own allocator, for type-checking another OS. #load "%/Default_Allocator/module.jai"; thread_idle :: () {} SHIM, jai_modules)); paths: [..] string; array_add(*paths, shim); array_add(*paths, ..options.import_path); options.import_path = paths; } // The macOS check links nothing, but the ScreenCaptureKit shim is built as first.jai builds it. #if OS == .MACOS if target == .MACOS build_macos_shim(); w := compiler_create_workspace("check"); set_build_options(options, w); compiler_begin_intercept(w); add_build_file("src/App.jai", w); add_build_string(#string S APP_NAME :: "mcap"; APP_FOLDER_NAME :: "mcap"; GIT_BRANCH :: "check"; GIT_HASH :: "-"; VERSION :: "0.1.38"; BUILD_DATE :: "-"; DEBUG :: true; COMPILE_TESTS :: true; COMPILE_ARGS :: ""; NO_CRASH_DIALOG :: false; S, w); while true { message := compiler_wait_for_message(); if message.kind == .COMPLETE { m := cast(*Message_Complete) message; log("% check: %", target, m.error_code); break; } } compiler_end_intercept(w); } #if OS == .MACOS { // macOS: modules/Screen_Record/macos/capture.m, mcap's ScreenCaptureKit shim, compiled with clang // into capture.a beside it whenever the source is newer, for the app to link (screen_capture_macos.jai). // check_targets.jai has the same; keep the two in step. build_macos_shim :: () -> bool { FOLDER :: "modules/Screen_Record/macos"; source := tprint("%/capture.m", FOLDER); object := tprint("%/capture.o", FOLDER); library := tprint("%/capture.a", FOLDER); source_time, _, source_ok := file_modtime_and_size(source); header_time := file_modtime_and_size(tprint("%/capture.h", FOLDER)); library_time, _, library_ok := file_modtime_and_size(library); if source_ok && library_ok && library_time >= source_time && library_time >= header_time return true; result := run_command("clang", "-c", "-fobjc-arc", "-O2", "-Wall", "-mmacosx-version-min=14.0", source, "-o", object); if result.exit_code != 0 { log_error("ERROR: clang could not compile %.", source); return false; } file_delete(library); result = run_command("ar", "rcs", library, object); if result.exit_code != 0 { log_error("ERROR: ar could not make %.", library); return false; } log("Built %", library); return true; } #import "Process"; #import "File_Utilities"; } #import "Basic"; #import "Compiler"; #import "File"; #import "String";