clay/bindings/jai/clay-jai/generate.jai

165 lines
5.3 KiB
Plaintext
Raw Normal View History

2024-12-22 10:49:53 +00:00
AT_COMPILE_TIME :: true;
SOURCE_PATH :: "source";
2024-12-22 17:20:31 +00:00
DECLARATIONS_TO_OMIT :: string.[
// These have custom declaration in module.jai
2024-12-22 17:20:31 +00:00
"Clay_Vector2",
"Clay__ElementConfigType",
"Clay__AlignClay__ElementConfigType",
2025-01-02 22:36:49 +00:00
"Clay_Border",
"Clay__AlignClay_Border",
"Clay_BorderElementConfig",
"Clay__AlignClay_BorderElementConfig",
// These are not supported yet
"Clay_OnHover",
"Clay_Hovered",
2024-12-22 17:20:31 +00:00
];
2024-12-22 10:49:53 +00:00
#if AT_COMPILE_TIME {
2025-01-09 22:51:58 +00:00
#if !#exists(JAILS_DIAGNOSTICS_BUILD) {
#run,stallable {
Compiler.set_build_options_dc(.{do_output=false});
options := Compiler.get_build_options();
args := options.compile_time_command_line;
if !generate_bindings(args, options.minimum_os_version) {
Compiler.compiler_set_workspace_status(.FAILED);
}
2024-12-22 10:49:53 +00:00
}
}
} else {
#import "System";
main :: () {
set_working_directory(path_strip_filename(get_path_of_running_executable()));
if !generate_bindings(get_command_line_arguments(), #run get_build_options().minimum_os_version) {
exit(1);
}
}
}
generate_bindings :: (args: [] string, minimum_os_version: type_of(Compiler.Build_Options.minimum_os_version)) -> bool {
2024-12-22 17:20:31 +00:00
compile := array_find(args, "-compile");
compile_debug := array_find(args, "-debug");
2024-12-22 10:49:53 +00:00
2025-01-03 11:24:17 +00:00
could_copy := FileUtils.copy_file("../../../clay.h", "source/clay.h");
if !could_copy then return false;
2024-12-31 13:35:03 +00:00
defer if !compile_debug then File.file_delete("source/clay.h");
2024-12-22 10:49:53 +00:00
if compile {
2024-12-22 17:20:31 +00:00
source_file := tprint("%/clay.c", SOURCE_PATH);
2024-12-22 10:49:53 +00:00
success := true;
#if OS == .WINDOWS {
2025-01-09 22:51:58 +00:00
// TODO try to use BuildCpp module again
2025-01-03 11:24:17 +00:00
File.make_directory_if_it_does_not_exist("windows", true);
2024-12-22 10:49:53 +00:00
2024-12-22 17:20:31 +00:00
command := ifx compile_debug {
2024-12-31 13:35:03 +00:00
write_string("Compiling debug...\n");
Process.break_command_into_strings("clang -g -gcodeview -c source\\clay.c");
2024-12-22 17:20:31 +00:00
} else {
2024-12-31 13:35:03 +00:00
write_string("Compiling release...\n");
2024-12-22 17:20:31 +00:00
Process.break_command_into_strings("clang -O3 -c source\\clay.c");
}
result := Process.run_command(..command, capture_and_return_output=true, print_captured_output=true);
if result.exit_code != 0 then return false;
defer File.file_delete("clay.o");
2024-12-22 10:49:53 +00:00
2024-12-31 13:35:03 +00:00
write_string("Linking...\n");
2025-01-03 11:24:17 +00:00
command = Process.break_command_into_strings("llvm-ar -rcs windows/clay.lib clay.o");
2024-12-22 17:20:31 +00:00
result = Process.run_command(..command, capture_and_return_output=true, print_captured_output=true);
2024-12-31 13:35:03 +00:00
if result.exit_code != 0 then return false;
2025-01-09 22:51:58 +00:00
} else #if OS == .LINUX {
File.make_directory_if_it_does_not_exist("linux", true);
could_build := BuildCpp.build_cpp_static_lib("linux/clay", "source/clay.c",
debug = compile_debug,
);
assert(could_build);
2024-12-22 10:49:53 +00:00
} else {
// TODO MacOS
assert(false);
}
if !success then return false;
2024-12-31 13:35:03 +00:00
write_string("Succesfully built clay\n");
2024-12-22 10:49:53 +00:00
}
output_filename: string;
options: Generator.Generate_Bindings_Options;
{
2025-01-09 22:51:58 +00:00
write_string("Generating bindings...\n");
2024-12-22 10:49:53 +00:00
using options;
#if OS == .WINDOWS {
2025-01-03 11:24:17 +00:00
array_add(*libpaths, "windows");
2024-12-22 10:49:53 +00:00
output_filename = "windows.jai";
2025-01-09 22:51:58 +00:00
} else #if OS == .LINUX {
array_add(*libpaths, "linux");
output_filename = "linux.jai";
2024-12-22 10:49:53 +00:00
} else {
assert(false);
}
2024-12-22 17:20:31 +00:00
array_add(*libnames, "clay");
array_add(*include_paths, SOURCE_PATH);
array_add(*source_files, tprint("%/clay.h", SOURCE_PATH));
array_add(*strip_prefixes, "Clay_");
2024-12-22 10:49:53 +00:00
auto_detect_enum_prefixes = true;
log_stripped_declarations = true;
2024-12-22 17:20:31 +00:00
generate_compile_time_struct_checks = true;
visitor = clay_visitor;
2024-12-22 10:49:53 +00:00
}
could_generate := Generator.generate_bindings(options, output_filename);
return could_generate;
}
2024-12-22 17:20:31 +00:00
clay_visitor :: (decl: *Generator.Declaration, parent_decl: *Generator.Declaration) -> Generator.Declaration_Visit_Result {
if !parent_decl {
if array_find(DECLARATIONS_TO_OMIT, decl.name) {
decl.decl_flags |= .OMIT_FROM_OUTPUT;
return .STOP;
}
2025-01-09 22:51:58 +00:00
// We don't want the align and wrapper strucs
if String.begins_with(decl.name, "Clay__Align") || String.ends_with(decl.name, "Wrapper") {
decl.decl_flags |= .OMIT_FROM_OUTPUT;
return .STOP;
}
2024-12-31 13:35:03 +00:00
if String.begins_with(decl.name, "Clay__") {
2025-01-09 22:51:58 +00:00
// The way bindings generator strip prefixes mean that something like `Clay__Foo` will be turned to `Foo`
// but what we want is `_Foo`
2024-12-31 13:35:03 +00:00
decl.output_name = String.slice(decl.name, 5, decl.name.count - 5);
2024-12-22 17:20:31 +00:00
}
}
return .RECURSE;
}
2024-12-22 10:49:53 +00:00
#scope_file
using Basic :: #import "Basic";
Generator :: #import "Bindings_Generator";
Compiler :: #import "Compiler";
File :: #import "File";
FileUtils :: #import "File_Utilities";
BuildCpp :: #import "BuildCpp";
Process :: #import "Process";
String :: #import "String";
#if OS == .WINDOWS {
Windows :: #import "Windows";
2025-01-09 22:51:58 +00:00
WindowsResources :: #import "Windows_Resources";
2024-12-22 10:49:53 +00:00
getenv :: Windows.getenv;
} else {
Posix :: #import "POSIX";
getenv :: Posix.getenv;
}