726 lines
18 KiB
C
726 lines
18 KiB
C
#include <std/base.h>
|
|
#include <std/os.h>
|
|
#include <std/project.h>
|
|
|
|
#include <std/base.c>
|
|
#include <std/os.c>
|
|
|
|
typedef enum C_Compiler
|
|
{
|
|
C_COMPILER_GCC,
|
|
C_COMPILER_CLANG,
|
|
C_COMPILER_MSVC,
|
|
C_COMPILER_TCC,
|
|
C_COMPILER_COUNT,
|
|
} C_Compiler;
|
|
|
|
global_variable char* c_compiler_names[] = {
|
|
"gcc",
|
|
"clang",
|
|
"cl",
|
|
"tcc",
|
|
};
|
|
|
|
typedef enum CompilerArgumentStyle
|
|
{
|
|
COMPILER_ARGUMENT_STYLE_GNU,
|
|
COMPILER_ARGUMENT_STYLE_MSVC,
|
|
COMPILER_ARGUMENT_STYLE_COUNT,
|
|
} CompilerArgumentStyle;
|
|
|
|
global_variable C_Compiler preferred_c_compiler = C_COMPILER_COUNT;
|
|
global_variable char** environment_pointer;
|
|
|
|
typedef enum BuildType
|
|
{
|
|
BUILD_TYPE_DEBUG,
|
|
BUILD_TYPE_RELEASE_SAFE,
|
|
BUILD_TYPE_RELEASE_FAST,
|
|
BUILD_TYPE_RELEASE_SMALL,
|
|
BUILD_TYPE_COUNT,
|
|
} BuildType;
|
|
|
|
const char* build_type_strings[BUILD_TYPE_COUNT] = {
|
|
"debug",
|
|
"release_safe",
|
|
"release_fast",
|
|
"release_small",
|
|
};
|
|
|
|
char* optimization_switches[COMPILER_ARGUMENT_STYLE_COUNT][BUILD_TYPE_COUNT] = {
|
|
[COMPILER_ARGUMENT_STYLE_GNU] = {
|
|
[BUILD_TYPE_DEBUG] = "-O0",
|
|
[BUILD_TYPE_RELEASE_SAFE] = "-O2",
|
|
[BUILD_TYPE_RELEASE_FAST] = "-O3",
|
|
[BUILD_TYPE_RELEASE_SMALL] = "-Oz",
|
|
},
|
|
[COMPILER_ARGUMENT_STYLE_MSVC] = {
|
|
[BUILD_TYPE_DEBUG] = "/Od",
|
|
[BUILD_TYPE_RELEASE_SAFE] = "/Ox",
|
|
[BUILD_TYPE_RELEASE_FAST] = "/O2",
|
|
[BUILD_TYPE_RELEASE_SMALL] = "/O1",
|
|
},
|
|
};
|
|
|
|
STRUCT(CompileFlags)
|
|
{
|
|
u64 colored_output:1;
|
|
u64 debug:1;
|
|
u64 error_limit:1;
|
|
u64 time_trace:1;
|
|
};
|
|
|
|
STRUCT(CompileOptions)
|
|
{
|
|
String source_path;
|
|
String output_path;
|
|
String compiler_path;
|
|
RenderingBackend rendering_backend;
|
|
WindowingBackend windowing_backend;
|
|
BuildType build_type;
|
|
CompileFlags flags;
|
|
};
|
|
|
|
typedef enum CompilerSwitch
|
|
{
|
|
COMPILER_SWITCH_DEBUG_INFO,
|
|
COMPILER_SWITCH_COUNT,
|
|
} CompilerSwitch;
|
|
|
|
|
|
global_variable char* compiler_switches[COMPILER_ARGUMENT_STYLE_COUNT][COMPILER_SWITCH_COUNT] = {
|
|
[COMPILER_ARGUMENT_STYLE_GNU] = {
|
|
[COMPILER_SWITCH_DEBUG_INFO] = "-g",
|
|
},
|
|
[COMPILER_ARGUMENT_STYLE_MSVC] = {
|
|
[COMPILER_SWITCH_DEBUG_INFO] = "/Zi",
|
|
},
|
|
};
|
|
|
|
fn String file_find_in_path(Arena* arena, String file, String path_env)
|
|
{
|
|
String result = {};
|
|
assert(path_env.pointer);
|
|
|
|
String path_it = path_env;
|
|
u8 buffer[4096];
|
|
|
|
#if _WIN32
|
|
u8 env_path_separator = ';';
|
|
u8 path_separator = '\\';
|
|
#else
|
|
u8 env_path_separator = ':';
|
|
u8 path_separator = '/';
|
|
#endif
|
|
|
|
while (path_it.length)
|
|
{
|
|
let(index, string_first_ch(path_it, env_path_separator));
|
|
index = unlikely(index == STRING_NO_MATCH) ? path_it.length : index;
|
|
let(path_chunk, s_get_slice(u8, path_it, 0, index));
|
|
|
|
u64 i = 0;
|
|
|
|
memcpy(&buffer[i], path_chunk.pointer, path_chunk.length);
|
|
i += path_chunk.length;
|
|
|
|
buffer[i] = path_separator;
|
|
i += 1;
|
|
|
|
memcpy(&buffer[i], file.pointer, file.length);
|
|
i += file.length;
|
|
|
|
#if _WIN32
|
|
String exe_extension = strlit(".exe");
|
|
memcpy(&buffer[i], exe_extension.pointer, exe_extension.length);
|
|
i += exe_extension.length;
|
|
#endif
|
|
|
|
buffer[i] = 0;
|
|
i += 1;
|
|
|
|
let(total_length, i - 1);
|
|
OSFileOpenFlags flags = {
|
|
.read = 1,
|
|
};
|
|
OSFilePermissions permissions = {
|
|
.readable = 1,
|
|
.writable = 1,
|
|
};
|
|
|
|
String path = { .pointer = buffer, .length = total_length };
|
|
|
|
FileDescriptor fd = os_file_open(path, flags, permissions);
|
|
|
|
if (os_file_descriptor_is_valid(fd))
|
|
{
|
|
os_file_close(fd);
|
|
result.pointer = arena_allocate(arena, u8, total_length + 1);
|
|
memcpy(result.pointer, buffer, total_length + 1);
|
|
result.length = total_length;
|
|
break;
|
|
}
|
|
|
|
String new_path = s_get_slice(u8, path_it, index + (index != path_it.length), path_it.length);
|
|
assert(new_path.length < path_env.length);
|
|
path_it = new_path;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
fn C_Compiler c_compiler_from_path(String path)
|
|
{
|
|
C_Compiler result = C_COMPILER_COUNT;
|
|
let(last_ch_slash, string_last_ch(path, '/'));
|
|
let(start, last_ch_slash);
|
|
#if _WIN32
|
|
let(last_ch_backslash, string_last_ch(path, '\\'));
|
|
start = MIN(last_ch_slash, last_ch_backslash);
|
|
#endif
|
|
assert(start != STRING_NO_MATCH); // This ensures us the path is not just the executable name
|
|
let(compiler_name, s_get_slice(u8, path, start + 1, path.length));
|
|
|
|
for (C_Compiler i = 0; i < C_COMPILER_COUNT; i += 1)
|
|
{
|
|
let(candidate_compiler_name, cstr(c_compiler_names[i]));
|
|
if (string_contains(compiler_name, candidate_compiler_name))
|
|
{
|
|
result = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
fn u8 c_compiler_is_supported_by_os(C_Compiler compiler)
|
|
{
|
|
#ifdef __linux__
|
|
switch (compiler)
|
|
{
|
|
case C_COMPILER_TCC: case C_COMPILER_GCC: case C_COMPILER_CLANG: return 1;
|
|
case C_COMPILER_MSVC: return 0;
|
|
case C_COMPILER_COUNT: unreachable();
|
|
}
|
|
#elif __APPLE__
|
|
switch (compiler)
|
|
{
|
|
case C_COMPILER_TCC: case C_COMPILER_CLANG: return 1;
|
|
case C_COMPILER_MSVC: case C_COMPILER_GCC: return 0;
|
|
case C_COMPILER_COUNT: unreachable();
|
|
}
|
|
#elif _WIN32
|
|
switch (compiler)
|
|
{
|
|
case C_COMPILER_MSVC: case C_COMPILER_TCC: case C_COMPILER_CLANG: return 1;
|
|
case C_COMPILER_GCC: return 0;
|
|
}
|
|
#endif
|
|
unreachable();
|
|
}
|
|
|
|
fn String c_compiler_to_string(C_Compiler c_compiler)
|
|
{
|
|
switch (c_compiler)
|
|
{
|
|
case C_COMPILER_GCC: return strlit("gcc");
|
|
case C_COMPILER_MSVC: return strlit("MSVC");
|
|
case C_COMPILER_CLANG: return strlit("clang");
|
|
case C_COMPILER_TCC: return strlit("tcc");
|
|
default: unreachable();
|
|
}
|
|
}
|
|
|
|
// Returns the absolute path of a C compiler
|
|
fn String get_c_compiler_path(Arena* arena)
|
|
{
|
|
String cc_path = {};
|
|
String cc_env = os_get_environment_variable("CC");
|
|
String path_env = os_get_environment_variable("PATH");
|
|
if (cc_env.pointer)
|
|
{
|
|
cc_path = cc_env;
|
|
}
|
|
#ifndef _WIN32
|
|
else
|
|
{
|
|
cc_path = file_find_in_path(arena, strlit("cc"), path_env);
|
|
}
|
|
#endif
|
|
|
|
if (!cc_path.pointer)
|
|
{
|
|
#if _WIN32
|
|
cc_path = strlit("cl.exe");
|
|
#elif defined(__APPLE__)
|
|
cc_path = strlit("clang");
|
|
#elif defined(__linux__)
|
|
cc_path = strlit("clang");
|
|
#else
|
|
#error "Operating system not supported"
|
|
#endif
|
|
}
|
|
|
|
let(no_path_sep, string_first_ch(cc_path, '/') == STRING_NO_MATCH);
|
|
#ifdef _WIN32
|
|
no_path_sep = no_path_sep && string_first_ch(cc_path, '\\') == STRING_NO_MATCH;
|
|
#endif
|
|
if (no_path_sep)
|
|
{
|
|
cc_path = file_find_in_path(arena, cc_path, path_env);
|
|
}
|
|
|
|
#ifndef _WIN32
|
|
if (cc_path.pointer)
|
|
{
|
|
u8 buffer[4096];
|
|
let(realpath, os_realpath(cc_path, (String)array_to_slice(buffer)));
|
|
if (!s_equal(realpath, cc_path))
|
|
{
|
|
cc_path.pointer = arena_allocate(arena, u8, realpath.length + 1);
|
|
cc_path.length = realpath.length;
|
|
memcpy(cc_path.pointer, realpath.pointer, realpath.length);
|
|
cc_path.pointer[cc_path.length] = 0;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if __APPLE__
|
|
if (s_equal(cc_path, strlit("/usr/bin/cc")))
|
|
{
|
|
cc_path = strlit("/usr/bin/clang");
|
|
}
|
|
#endif
|
|
|
|
if (preferred_c_compiler != C_COMPILER_COUNT && c_compiler_is_supported_by_os(preferred_c_compiler))
|
|
{
|
|
String find_result = file_find_in_path(arena, c_compiler_to_string(preferred_c_compiler), path_env);
|
|
if (find_result.pointer)
|
|
{
|
|
cc_path = find_result;
|
|
}
|
|
}
|
|
|
|
return cc_path;
|
|
}
|
|
|
|
fn u8 c_compiler_supports_colored_output(C_Compiler compiler)
|
|
{
|
|
// TODO: fix
|
|
switch (compiler)
|
|
{
|
|
case C_COMPILER_GCC: case C_COMPILER_CLANG: return 1;
|
|
case C_COMPILER_TCC: case C_COMPILER_MSVC: return 0;
|
|
default: unreachable();
|
|
}
|
|
}
|
|
|
|
fn char* c_compiler_get_error_limit_switch(C_Compiler compiler)
|
|
{
|
|
// TODO: fix
|
|
switch (compiler)
|
|
{
|
|
case C_COMPILER_CLANG: return "-ferror-limit=1";
|
|
case C_COMPILER_GCC: return "-fmax-errors=1";
|
|
case C_COMPILER_MSVC: case C_COMPILER_TCC: return 0;
|
|
default: unreachable();
|
|
}
|
|
}
|
|
|
|
fn char* c_compiler_get_highest_c_standard_flag(C_Compiler compiler)
|
|
{
|
|
switch (compiler)
|
|
{
|
|
case C_COMPILER_CLANG: case C_COMPILER_GCC: return "-std=gnu2x";
|
|
case C_COMPILER_MSVC: return "/std:clatest";
|
|
case C_COMPILER_TCC: return "-std=gnu2x"; // TODO: does it do anything in TCC?
|
|
default: unreachable();
|
|
}
|
|
}
|
|
|
|
fn RenderingBackend rendering_backend_parse_env(String env)
|
|
{
|
|
unused(env);
|
|
todo();
|
|
}
|
|
|
|
fn RenderingBackend rendering_backend_pick()
|
|
{
|
|
RenderingBackend rendering_backend = RENDERING_BACKEND_COUNT;
|
|
#if BB_CI
|
|
rendering_backend = RENDERING_BACKEND_NONE;
|
|
#else
|
|
char* env = getenv("BB_RENDERING_BACKEND");
|
|
if (env)
|
|
{
|
|
rendering_backend = rendering_backend_parse_env(cstr(env));
|
|
}
|
|
|
|
if (!rendering_backend_is_valid(rendering_backend))
|
|
{
|
|
#ifdef __linux__
|
|
rendering_backend = RENDERING_BACKEND_VULKAN;
|
|
#elif defined(__APPLE__)
|
|
rendering_backend = RENDERING_BACKEND_METAL;
|
|
#elif _WIN32
|
|
rendering_backend = RENDERING_BACKEND_VULKAN;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
return rendering_backend;
|
|
}
|
|
|
|
fn WindowingBackend windowing_backend_parse_env(String env)
|
|
{
|
|
unused(env);
|
|
todo();
|
|
}
|
|
|
|
fn WindowingBackend windowing_backend_pick()
|
|
{
|
|
WindowingBackend windowing_backend = WINDOWING_BACKEND_COUNT;
|
|
#if BB_CI
|
|
windowing_backend = WINDOWING_BACKEND_NONE;
|
|
#else
|
|
// Only done for Linux because it is the only operating system in which two windowing backends officially coexist
|
|
#ifdef __linux__
|
|
char* env = getenv("BB_WINDOWING_BACKEND");
|
|
if (env)
|
|
{
|
|
windowing_backend = windowing_backend_parse_env(cstr(env));
|
|
}
|
|
#endif
|
|
|
|
if (!windowing_backend_is_valid(windowing_backend))
|
|
{
|
|
#ifdef __linux__
|
|
// Prefer X11 over Wayland because:
|
|
// 1) It works both on Wayland and on X11 desktops
|
|
// 2) It works with debugging tools like RenderDoc
|
|
windowing_backend = WINDOWING_BACKEND_X11;
|
|
#elif _WIN32
|
|
windowing_backend = WINDOWING_BACKEND_WIN32;
|
|
#elif __APPLE__
|
|
windowing_backend = WINDOWING_BACKEND_COCOA;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
return windowing_backend;
|
|
}
|
|
|
|
fn u8 c_compiler_supports_time_trace(C_Compiler compiler)
|
|
{
|
|
switch (compiler)
|
|
{
|
|
case C_COMPILER_CLANG: return 1;
|
|
default: return 0;
|
|
case C_COMPILER_COUNT: unreachable();
|
|
}
|
|
}
|
|
|
|
fn BuildType build_type_pick()
|
|
{
|
|
String build_type_string = strlit(BB_BUILD_TYPE);
|
|
BuildType build_type;
|
|
|
|
for (build_type = 0; build_type < BUILD_TYPE_COUNT; build_type += 1)
|
|
{
|
|
if (s_equal(build_type_string, cstr(build_type_strings[build_type])))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
return build_type;
|
|
}
|
|
|
|
fn void compile_program(Arena* arena, CompileOptions options)
|
|
{
|
|
if (!options.compiler_path.pointer)
|
|
{
|
|
char* cc_env = getenv("CC");
|
|
if (options.flags.debug)
|
|
{
|
|
print("Could not find a valid compiler for CC: \"{cstr}\"\n", cc_env ? cc_env : "");
|
|
print("PATH: {cstr}\n", getenv("PATH"));
|
|
}
|
|
failed_execution();
|
|
}
|
|
|
|
if (options.flags.debug)
|
|
{
|
|
print("C compiler path: {s}\n", options.compiler_path);
|
|
}
|
|
|
|
C_Compiler c_compiler = c_compiler_from_path(options.compiler_path);
|
|
if (c_compiler != C_COMPILER_COUNT)
|
|
{
|
|
String compiler_name = c_compiler_to_string(c_compiler);
|
|
if (options.flags.debug)
|
|
{
|
|
print("Identified compiler as {s}\n", compiler_name);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
print("Unrecognized C compiler: {s}\n", options.compiler_path);
|
|
os_exit(1);
|
|
}
|
|
char* args[4096];
|
|
u64 arg_i = 0;
|
|
#define add_arg(arg) args[arg_i++] = (arg)
|
|
add_arg(string_to_c(options.compiler_path));
|
|
if (c_compiler == C_COMPILER_MSVC)
|
|
{
|
|
add_arg("/nologo");
|
|
}
|
|
|
|
#if __APPLE__
|
|
add_arg("-x");
|
|
add_arg("objective-c");
|
|
#endif
|
|
|
|
add_arg(string_to_c(options.source_path));
|
|
|
|
if (c_compiler == C_COMPILER_MSVC)
|
|
{
|
|
String strings[] = {
|
|
strlit("/Fe"),
|
|
options.output_path,
|
|
};
|
|
String arg = arena_join_string(arena, (Slice(String))array_to_slice(strings));
|
|
add_arg(string_to_c(arg));
|
|
|
|
add_arg("/Fo" BUILD_DIR "\\");
|
|
add_arg("/Fd" BUILD_DIR "\\");
|
|
}
|
|
else
|
|
{
|
|
add_arg("-o");
|
|
add_arg(string_to_c(options.output_path));
|
|
}
|
|
|
|
add_arg("-Ibootstrap");
|
|
add_arg("-Idependencies/stb");
|
|
|
|
char* c_include_path = getenv("C_INCLUDE_PATH");
|
|
if (c_include_path)
|
|
{
|
|
String c_include_path_string = cstr(c_include_path);
|
|
|
|
u64 previous_i = 0;
|
|
for (u64 i = 0; i < c_include_path_string.length; i += 1)
|
|
{
|
|
u8 ch = c_include_path_string.pointer[i];
|
|
if (ch == ':')
|
|
{
|
|
todo();
|
|
}
|
|
}
|
|
|
|
String strings[] = {
|
|
strlit("-I"),
|
|
s_get_slice(u8, c_include_path_string, previous_i, c_include_path_string.length),
|
|
};
|
|
String arg = arena_join_string(arena, (Slice(String))array_to_slice(strings));
|
|
add_arg(string_to_c(arg));
|
|
}
|
|
|
|
let(debug_info, options.build_type != BUILD_TYPE_RELEASE_SMALL);
|
|
if (debug_info)
|
|
{
|
|
add_arg(compiler_switches[c_compiler == C_COMPILER_MSVC][COMPILER_SWITCH_DEBUG_INFO]);
|
|
}
|
|
|
|
if (c_compiler != C_COMPILER_TCC)
|
|
{
|
|
add_arg(optimization_switches[c_compiler == C_COMPILER_MSVC][options.build_type]);
|
|
}
|
|
|
|
if (options.flags.colored_output && c_compiler_supports_colored_output(c_compiler))
|
|
{
|
|
add_arg("-fdiagnostics-color=auto");
|
|
}
|
|
|
|
if (options.flags.error_limit)
|
|
{
|
|
char* error_limit = c_compiler_get_error_limit_switch(c_compiler);
|
|
if (error_limit)
|
|
{
|
|
add_arg(error_limit);
|
|
}
|
|
}
|
|
|
|
if (options.flags.time_trace && c_compiler_supports_time_trace(c_compiler))
|
|
{
|
|
add_arg("-ftime-trace");
|
|
}
|
|
|
|
if (c_compiler == C_COMPILER_MSVC)
|
|
{
|
|
add_arg("/diagnostics:caret");
|
|
}
|
|
else
|
|
{
|
|
add_arg("-fdiagnostics-show-option");
|
|
}
|
|
|
|
add_arg(c_compiler_get_highest_c_standard_flag(c_compiler));
|
|
|
|
switch (options.windowing_backend)
|
|
{
|
|
case WINDOWING_BACKEND_NONE:
|
|
{
|
|
add_arg("-DBB_WINDOWING_BACKEND_NONE=1");
|
|
} break;
|
|
case WINDOWING_BACKEND_WIN32:
|
|
{
|
|
add_arg("-DBB_WINDOWING_BACKEND_WIN32=1");
|
|
} break;
|
|
case WINDOWING_BACKEND_COCOA:
|
|
{
|
|
add_arg("-DBB_WINDOWING_BACKEND_COCOA=1");
|
|
} break;
|
|
case WINDOWING_BACKEND_X11:
|
|
{
|
|
add_arg("-DBB_WINDOWING_BACKEND_X11=1");
|
|
} break;
|
|
case WINDOWING_BACKEND_WAYLAND:
|
|
{
|
|
add_arg("-DBB_WINDOWING_BACKEND_WAYLAND=1");
|
|
} break;
|
|
case WINDOWING_BACKEND_COUNT: unreachable();
|
|
}
|
|
|
|
switch (options.rendering_backend)
|
|
{
|
|
case RENDERING_BACKEND_NONE:
|
|
{
|
|
add_arg("-DBB_RENDERING_BACKEND_NONE=1");
|
|
} break;
|
|
case RENDERING_BACKEND_METAL:
|
|
{
|
|
add_arg("-DBB_RENDERING_BACKEND_METAL=1");
|
|
} break;
|
|
case RENDERING_BACKEND_DIRECTX12:
|
|
{
|
|
add_arg("-DBB_RENDERING_BACKEND_DIRECTX12=1");
|
|
} break;
|
|
case RENDERING_BACKEND_VULKAN:
|
|
{
|
|
add_arg("-DBB_RENDERING_BACKEND_VULKAN=1");
|
|
#if _WIN32
|
|
char* vk_sdk_path = getenv("VK_SDK_PATH");
|
|
if (vk_sdk_path)
|
|
{
|
|
if (c_compiler == C_COMPILER_MSVC)
|
|
{
|
|
String strings[] = {
|
|
strlit("-I"),
|
|
cstr(vk_sdk_path),
|
|
strlit("\\Include"),
|
|
};
|
|
String arg = arena_join_string(arena, (Slice(String))array_to_slice(strings));
|
|
add_arg(string_to_c(arg));
|
|
}
|
|
else
|
|
{
|
|
todo();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
print("VK_SDK_PATH environment variable not found\n");
|
|
}
|
|
#endif
|
|
} break;
|
|
case RENDERING_BACKEND_COUNT: unreachable();
|
|
}
|
|
|
|
#ifndef _WIN32
|
|
add_arg("-lm");
|
|
#endif
|
|
|
|
switch (options.windowing_backend)
|
|
{
|
|
case WINDOWING_BACKEND_NONE:
|
|
{
|
|
} break;
|
|
case WINDOWING_BACKEND_WIN32:
|
|
{
|
|
} break;
|
|
case WINDOWING_BACKEND_COCOA:
|
|
{
|
|
add_arg("-framework");
|
|
add_arg("AppKit");
|
|
} break;
|
|
case WINDOWING_BACKEND_X11:
|
|
{
|
|
add_arg("-lxcb");
|
|
} break;
|
|
case WINDOWING_BACKEND_WAYLAND:
|
|
{
|
|
} break;
|
|
case WINDOWING_BACKEND_COUNT: unreachable();
|
|
}
|
|
|
|
switch (options.rendering_backend)
|
|
{
|
|
case RENDERING_BACKEND_NONE:
|
|
{
|
|
} break;
|
|
case RENDERING_BACKEND_METAL:
|
|
{
|
|
add_arg("-framework");
|
|
add_arg("Metal");
|
|
add_arg("-framework");
|
|
add_arg("QuartzCore");
|
|
} break;
|
|
case RENDERING_BACKEND_DIRECTX12:
|
|
{
|
|
} break;
|
|
case RENDERING_BACKEND_VULKAN:
|
|
{
|
|
#if __APPLE__
|
|
add_arg("-framework");
|
|
add_arg("QuartzCore");
|
|
#endif
|
|
} break;
|
|
case RENDERING_BACKEND_COUNT: unreachable();
|
|
}
|
|
|
|
add_arg(0);
|
|
CStringSlice arguments = { .pointer = args, .length = arg_i };
|
|
RunCommandOptions run_options = {
|
|
.debug = options.flags.debug,
|
|
};
|
|
run_command(arena, arguments, environment_pointer, run_options);
|
|
}
|
|
|
|
int main(int argc, char* argv[], char** envp)
|
|
{
|
|
environment_pointer = envp;
|
|
Arena* arena = arena_initialize_default(KB(64));
|
|
|
|
CompileOptions compile_options = {
|
|
.compiler_path = get_c_compiler_path(arena),
|
|
.source_path = strlit("bootstrap/bloat-buster/bb.c"),
|
|
.output_path = strlit("cache/bb" EXECUTABLE_EXTENSION),
|
|
.windowing_backend = windowing_backend_pick(),
|
|
.rendering_backend = rendering_backend_pick(),
|
|
.build_type = build_type_pick(),
|
|
.flags = {
|
|
.colored_output = 1,
|
|
.error_limit = 1,
|
|
.debug = 1,
|
|
.time_trace = BB_TIMETRACE,
|
|
},
|
|
};
|
|
compile_program(arena, compile_options);
|
|
return 0;
|
|
}
|