Skip to content

Commit

Permalink
Add wrapper.from_compiler_flags field
Browse files Browse the repository at this point in the history
  • Loading branch information
PucklaJ committed Dec 1, 2024
1 parent 6f0dc25 commit 324e03c
Show file tree
Hide file tree
Showing 9 changed files with 119 additions and 71 deletions.
2 changes: 1 addition & 1 deletion GOALS.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Goals for future versions

+ Wrapper
+ [ ] Add `from_compiler_flags` to import the compiler flags from `from`
+ [x] Add `from_compiler_flags` to import the compiler flags from `from`
+ [ ] Add `includedirs`, `defines`, `flags` fields which get added on top of the `from_compiler_flags`
+ [ ] Add `load_all_includes`
+ [ ] Make more multi platform: Separate files for each platform
Expand Down
123 changes: 64 additions & 59 deletions cpp/wrapper/wrapper.odin
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import "core:io"
import "core:os"
import "core:path/filepath"
import "core:strings"
import cppcdg "root:cpp/codegen"
import "root:errors"
import "root:runic"
import clang "shared:libclang"
Expand All @@ -32,72 +33,76 @@ ClientData :: struct {
source: io.Writer,
}

generate_wrapper :: proc(rn: runic.Wrapper) -> (err: union {
generate_wrapper :: proc(
rn: runic.Wrapper,
rf: Maybe(runic.From),
) -> (
err: union {
errors.Error,
io.Error,
}) {
},
) {
arena: runtime.Arena
errors.wrap(runtime.arena_init(&arena, 0, context.allocator)) or_return
defer runtime.arena_destroy(&arena)
arena_alloc := runtime.arena_allocator(&arena)

clang_flags := [?]cstring {
// Android
"-U__ANDROID__",
// BSD
"-U__FreeBSD__",
"-U__FreeBSD_kernel__",
"-U__NetBSD__",
"-U__OpenBSD__",
"-U__bsdi__",
"-U__DragonFly__",
"-U_SYSTYPE_BSD",
"-UBSD",
// Linux
"-U__GLIBC__",
"-U__gnu_linux__",
"-U__linux__",
"-Ulinux",
"-U__linux",
// MacOS
"-Umacintosh",
"-UMacintosh",
"-U__APPLE__",
"-U__MACH__",
// Windows
"-U_WIN16",
"-U_WIN32",
"-U_WIN64",
// AMD64 & x86_64
"-U__amd64__",
"-U__amd64",
"-U__x86_64__",
"-U__x86_64",
// ARM
"-U__arm__",
"-U__thumb__",
"-U__aarch64__",
// x86
"-Ui386",
"-U__i386",
"-U__i386__",
"-U__i486__",
"-U__i586__",
"-U__i686__",

// Linux
"-D__GLIBC__",
"-D__gnu_linux__",
"-D__linux__",
"-Dlinux",
"-D__linux",
// x86_64
"-D__amd64__",
"-D__amd64",
"-D__x86_64__",
"-D__x86_64",
// Target
"--target=x86_64-linux-gnu",
// TODO: do not hardcode the platform
plat := runic.Platform{.Linux, .x86_64}

defines: map[string]string
include_dirs: []string
flags: []cstring

if rn.from_compiler_flags {
if from, from_ok := rf.?; from_ok {
from_defines, d_ok := runic.platform_value_get(
map[string]string,
from.defines,
plat,
)
if d_ok do defines = from_defines

from_include_dirs, inc_ok := runic.platform_value_get(
[]string,
from.includedirs,
plat,
)
if inc_ok do include_dirs = from_include_dirs

from_flags, f_ok := runic.platform_value_get(
[]cstring,
from.flags,
plat,
)
if f_ok do flags = from_flags
}
}

clang_flags := cppcdg.generate_clang_flags(
plat = plat,
disable_stdint_macros = false,
defines = defines,
include_dirs = include_dirs,
enable_host_includes = false,
stdinc_gen_dir = nil,
flags = flags,
allocator = arena_alloc,
)
defer delete(clang_flags)

when ODIN_DEBUG {
os.write_string(os.stderr, "wrapper clang_flags:")
for flag in clang_flags {
os.write_string(os.stderr, " \"")

flag_str := strings.clone_from_cstring(flag)
defer delete(flag_str)

os.write_string(os.stderr, flag_str)
os.write_rune(os.stderr, '"')
}
os.write_rune(os.stderr, '\n')
}

out_header, out_header_err := os.open(
Expand Down
24 changes: 19 additions & 5 deletions cpp/wrapper/wrapper_test.odin
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,20 @@ test_cpp_wrapper :: proc(t: ^testing.T) {
defer delete(out_source)

rn := runic.Wrapper {
language = "c",
in_headers = {in_header},
out_header = out_header,
out_source = out_source,
language = "c",
in_headers = {in_header},
out_header = out_header,
out_source = out_source,
from_compiler_flags = true,
}

err := generate_wrapper(rn)
rf := runic.From {
defines = {{{} = {"DYNA_FUNC" = "1"}}},
}
defer delete(rf.defines.d)
defer delete(rf.defines.d[{}])

err := generate_wrapper(rn, rf)
expect_value(t, err, nil)

header_data, header_ok := os.read_entire_file(
Expand All @@ -65,8 +72,10 @@ extern void print_stuff_wrapper(int a, int b);
extern const float ** do_other_stuff_wrapper(float c, float ** d);
extern spelling_t alphabet_wrapper();
extern struct foo_t japanese_wrapper();
extern int dyna_func_wrapper(int a, int b);
`


SOURCE_EXPECTED :: `#include "wrapper_out_header.h"
void print_stuff_wrapper(int a, int b) {
Expand All @@ -85,8 +94,13 @@ struct foo_t japanese_wrapper() {
return japanese();
}
int dyna_func_wrapper(int a, int b) {
return dyna_func(a, b);
}
`


if expect_value(t, len(string(header_data)), len(HEADER_EXPECTED)) {
expect_value(t, string(header_data), HEADER_EXPECTED)
}
Expand Down
7 changes: 6 additions & 1 deletion runic.odin
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,12 @@ main :: proc() {
if wrapper, ok := rune.wrapper.?; ok {
switch strings.to_lower(wrapper.language, context.temp_allocator) {
case "c", "cpp", "c++", "cxx":
err = errors.wrap(cppwrap.generate_wrapper(wrapper))
from: Maybe(runic.From)
if rf, rf_ok := rune.from.(runic.From); rf_ok {
from = rf
}

err = errors.wrap(cppwrap.generate_wrapper(wrapper, from))
case:
fmt.eprintfln(
"wrapper language \"{}\" is not supported",
Expand Down
18 changes: 17 additions & 1 deletion runic/rune.odin
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,9 @@ parse_rune :: proc(
}

if wrapper_value, wrapper_ok := y["wrapper"]; wrapper_ok {
wrapper: Wrapper
wrapper := Wrapper {
from_compiler_flags = true,
}

#partial switch wrapper_map in wrapper_value {
case yaml.Mapping:
Expand All @@ -201,6 +203,20 @@ parse_rune :: proc(
return
}

if from_compiler_flags, ok :=
wrapper_map["from_compiler_flags"]; ok {
#partial switch v in from_compiler_flags {
case bool:
wrapper.from_compiler_flags = v
case:
err = errors.message(
"\"wrapper.from_compiler_flags\" has invalid type %T",
v,
)
return
}
}

if in_headers_value, ok := wrapper_map["in_headers"]; ok {
#partial switch in_headers in in_headers_value {
case yaml.Sequence:
Expand Down
1 change: 1 addition & 0 deletions runic/rune_test.odin
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ test_rune :: proc(t: ^testing.T) {

wrapper := rn.wrapper.?
expect_value(t, wrapper.language, "c")
expect_value(t, wrapper.from_compiler_flags, false)
expect_value(t, len(wrapper.in_headers), 1)
expect_value(t, wrapper.in_headers[0], in_header)
expect_value(t, wrapper.out_header, out_header)
Expand Down
10 changes: 6 additions & 4 deletions runic/rune_types.odin
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,14 @@ To :: struct {
add_libs: PlatformValue([]string),
}

// TODO: maybe make all values PlatformValue
Wrapper :: struct {
language: string,
language: string,
// C/C++
in_headers: []string,
out_header: string,
out_source: string,
from_compiler_flags: bool,
in_headers: []string,
out_header: string,
out_source: string,
}

TrimSet :: struct {
Expand Down
1 change: 1 addition & 0 deletions test_data/rune.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ platforms:
- Windows x86_64
wrapper:
language: c
from_compiler_flags: false
in_headers: wrapper.h
out_header: wrapper.gen.h
out_source: wrapper.gen.c
Expand Down
4 changes: 4 additions & 0 deletions test_data/wrapper_in_header.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,7 @@ inline struct foo_t japanese() { return foo_tert{}; }
struct foo_t chinese() {
return foo_t {}
}

#ifdef DYNA_FUNC
inline int dyna_func(int a, int b) { return a + b; }
#endif

0 comments on commit 324e03c

Please sign in to comment.