195 lines
5.1 KiB
Text
195 lines
5.1 KiB
Text
#scope_file;
|
|
|
|
LOWERCASE_FIELD_NAMES :: true;
|
|
|
|
#run {
|
|
set_build_options_dc(.{ do_output = false });
|
|
|
|
files_to_generate :: string.[
|
|
"radians",
|
|
"degrees",
|
|
"turns",
|
|
];
|
|
|
|
for files_to_generate {
|
|
print("building library for unit: %\n", it);
|
|
|
|
assert(build(it, dynamic = true, simd = true), "failed to build library, unit: %", it);
|
|
assert(build(it, dynamic = true, simd = false), "failed to build library, unit: %", it);
|
|
assert(build(it, dynamic = false, simd = false), "failed to build library, unit: %", it);
|
|
assert(build(it, dynamic = false, simd = true), "failed to build library, unit: %", it);
|
|
}
|
|
|
|
print("generating bindings\n");
|
|
assert(generate(simd = true), "failed to generate bindings");
|
|
assert(generate(simd = false), "failed to generate bindings");
|
|
}
|
|
|
|
build :: (unit: string, dynamic: bool, simd: bool) -> bool {
|
|
#if OS == {
|
|
case .WINDOWS;
|
|
export_attribute :: "__declspec(dllexport)";
|
|
case;
|
|
export_attribute :: "__attribute__((visibility(\"default\")))";
|
|
}
|
|
|
|
tmp_data := tprint(#string END
|
|
#define static
|
|
#define inline
|
|
#define COVERAGE(a, b) %1
|
|
|
|
#define HANDMADE_MATH_USE_%2
|
|
%3
|
|
#include "../HandmadeMath.h"
|
|
END,
|
|
export_attribute,
|
|
to_upper_copy(unit),
|
|
ifx !simd then "#define HANDMADE_MATH_NO_SIMD" else "",
|
|
);
|
|
|
|
tmp_file := tprint(".build/tmp_%.c", ifx simd then "simd" else "nosimd");
|
|
if !write_entire_file(tmp_file, tmp_data) return false;
|
|
|
|
#if OS == {
|
|
case .WINDOWS; out_base :: "win";
|
|
case .MACOS; out_base :: "mac";
|
|
case .LINUX; out_base :: "linux";
|
|
}
|
|
|
|
lib_name := tprint("hmm_%", unit);
|
|
if simd lib_name = tprint("%_simd", lib_name);
|
|
else lib_name = tprint("%_nosimd", lib_name);
|
|
|
|
out_path := tprint("%/%", out_base, lib_name);
|
|
|
|
lib_type := Build_Type.STATIC_LIBRARY;
|
|
if dynamic lib_type = .DYNAMIC_LIBRARY;
|
|
|
|
return build_cpp(out_path, tmp_file, type = lib_type);
|
|
}
|
|
|
|
generate :: (simd: bool) -> bool {
|
|
#if OS == {
|
|
case .WINDOWS;
|
|
lib_ext :: "dll";
|
|
case .MACOS;
|
|
lib_ext :: "dylib";
|
|
case .LINUX;
|
|
lib_ext :: "so";
|
|
}
|
|
|
|
#if OS == {
|
|
case .WINDOWS; out_base :: "win";
|
|
case .MACOS; out_base :: "mac";
|
|
case .LINUX; out_base :: "linux";
|
|
}
|
|
|
|
suffix := "simd";
|
|
if !simd suffix = "nosimd";
|
|
|
|
simd_support = simd;
|
|
|
|
opts: Generate_Bindings_Options;
|
|
opts.add_generator_command = false;
|
|
opts.generate_library_declarations = false;
|
|
opts.visitor = fixup_wrong_types;
|
|
array_add(*opts.strip_prefixes, "HMM_", "_HMM_");
|
|
array_add(*opts.extra_clang_arguments, "-x", "c");
|
|
array_add(*opts.libpaths, out_base);
|
|
array_add(*opts.libnames, tprint("hmm_radians_%.%", suffix, lib_ext));
|
|
array_add(*opts.source_files, tprint(".build/tmp_%.c", suffix));
|
|
|
|
if !generate_bindings(opts, tprint("hmm_%.jai", suffix)) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
simd_support := false;
|
|
fixup_wrong_types :: (decl: *Declaration, parent: *Declaration) -> Declaration_Visit_Result {
|
|
if decl.kind == {
|
|
case .TYPEDEF;
|
|
td := decl.(*Typedef);
|
|
if td.name == {
|
|
// when simd support is specified, these are generated incorrectly so we create them manually
|
|
case "HMM_Vec4"; #through;
|
|
case "HMM_Quat";
|
|
if simd_support {
|
|
td.decl_flags = .OMIT_FROM_OUTPUT;
|
|
td.type.type_of_struct.decl_flags = .OMIT_FROM_OUTPUT;
|
|
}
|
|
}
|
|
|
|
#if !LOWERCASE_FIELD_NAMES return .STOP;
|
|
|
|
lower_names_recursive :: (s: *Struct) {
|
|
for s.declarations {
|
|
it.output_name = pascal_to_snake(it.name);
|
|
if it.type.type_of_struct != null {
|
|
lower_names_recursive(it.type.type_of_struct);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if td.type.type_of_struct != null {
|
|
lower_names_recursive(td.type.type_of_struct);
|
|
}
|
|
|
|
return .RECURSE;
|
|
|
|
case .FUNCTION;
|
|
func := decl.(*Function);
|
|
if func.name == {
|
|
case "__hmm_invalid_generic";
|
|
func.decl_flags = .OMIT_FROM_OUTPUT;
|
|
return .STOP;
|
|
}
|
|
|
|
// snake_case argument names
|
|
funct := func.type.type_of_function;
|
|
for funct.arguments {
|
|
it.output_name = pascal_to_snake(it.name);
|
|
}
|
|
}
|
|
|
|
return .STOP;
|
|
}
|
|
|
|
pascal_to_snake :: (name: string) -> string {
|
|
is_upper :: (byte: u8) -> bool {
|
|
return byte >= #char "A" && byte <= #char "Z";
|
|
}
|
|
|
|
b: String_Builder;
|
|
add_underscore := false;
|
|
for 0..name.count - 1 {
|
|
if is_upper(name[it]) {
|
|
if it > 0 && name[it-1] != #char "_" {
|
|
add_underscore = true;
|
|
}
|
|
|
|
if it-1 >= 0 && is_upper(name[it-1]) {
|
|
add_underscore = false;
|
|
}
|
|
}
|
|
|
|
if add_underscore {
|
|
add_underscore = false;
|
|
append(*b, "_");
|
|
}
|
|
|
|
append(*b, to_lower(name[it]));
|
|
}
|
|
|
|
return builder_to_string(*b);
|
|
}
|
|
|
|
#import "File";
|
|
#import "Basic";
|
|
#import "String";
|
|
#import "Compiler";
|
|
#import "BuildCpp";
|
|
#import "Bindings_Generator";
|