mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-21 13:55:19 +00:00
Support subtargets in build tags: #build darwin:generic and #build linux:android, darwin:ios
This commit is contained in:
@@ -559,10 +559,14 @@ ALL_ODIN_OS_TYPES :: Odin_OS_Types{
|
||||
Odin_Platform_Subtarget_Type :: enum int {
|
||||
Default,
|
||||
iOS,
|
||||
Android,
|
||||
}
|
||||
*/
|
||||
Odin_Platform_Subtarget_Type :: type_of(ODIN_PLATFORM_SUBTARGET)
|
||||
|
||||
Odin_Platform_Subtarget_Types :: bit_set[Odin_Platform_Subtarget_Type]
|
||||
|
||||
|
||||
/*
|
||||
// Defined internally by the compiler
|
||||
Odin_Sanitizer_Flag :: enum u32 {
|
||||
|
||||
@@ -30,14 +30,27 @@ File_Tags :: struct {
|
||||
}
|
||||
|
||||
@require_results
|
||||
get_build_os_from_string :: proc(str: string) -> runtime.Odin_OS_Type {
|
||||
get_build_os_from_string :: proc(str: string) -> (found_os: runtime.Odin_OS_Type, found_subtarget: runtime.Odin_Platform_Subtarget_Type) {
|
||||
str_os, _, str_subtarget := strings.partition(str, ":")
|
||||
|
||||
fields := reflect.enum_fields_zipped(runtime.Odin_OS_Type)
|
||||
for os in fields {
|
||||
if strings.equal_fold(os.name, str) {
|
||||
return runtime.Odin_OS_Type(os.value)
|
||||
if strings.equal_fold(os.name, str_os) {
|
||||
found_os = runtime.Odin_OS_Type(os.value)
|
||||
break
|
||||
}
|
||||
}
|
||||
return .Unknown
|
||||
if str_subtarget != "" {
|
||||
fields := reflect.enum_fields_zipped(runtime.Odin_Platform_Subtarget_Type)
|
||||
for subtarget in fields {
|
||||
if strings.equal_fold(subtarget.name, str_subtarget) {
|
||||
found_subtarget = runtime.Odin_Platform_Subtarget_Type(subtarget.value)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
@require_results
|
||||
get_build_arch_from_string :: proc(str: string) -> runtime.Odin_Arch_Type {
|
||||
@@ -187,7 +200,8 @@ parse_file_tags :: proc(file: ast.File, allocator := context.allocator) -> (tags
|
||||
|
||||
if value == "ignore" {
|
||||
tags.ignore = true
|
||||
} else if os := get_build_os_from_string(value); os != .Unknown {
|
||||
} else if os, subtarget := get_build_os_from_string(value); os != .Unknown {
|
||||
_ = subtarget // TODO(bill): figure out how to handle the subtarget logic
|
||||
if is_notted {
|
||||
os_negative += {os}
|
||||
} else {
|
||||
|
||||
@@ -847,13 +847,39 @@ gb_global NamedTargetMetrics *selected_target_metrics;
|
||||
gb_global Subtarget selected_subtarget;
|
||||
|
||||
|
||||
gb_internal TargetOsKind get_target_os_from_string(String str) {
|
||||
gb_internal TargetOsKind get_target_os_from_string(String str, Subtarget *subtarget_ = nullptr) {
|
||||
String os_name = str;
|
||||
String subtarget = {};
|
||||
auto part = string_partition(str, str_lit(":"));
|
||||
if (part.match.len == 1) {
|
||||
os_name = part.head;
|
||||
subtarget = part.tail;
|
||||
}
|
||||
|
||||
TargetOsKind kind = TargetOs_Invalid;
|
||||
|
||||
for (isize i = 0; i < TargetOs_COUNT; i++) {
|
||||
if (str_eq_ignore_case(target_os_names[i], str)) {
|
||||
return cast(TargetOsKind)i;
|
||||
if (str_eq_ignore_case(target_os_names[i], os_name)) {
|
||||
kind = cast(TargetOsKind)i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return TargetOs_Invalid;
|
||||
if (subtarget_) *subtarget_ = Subtarget_Default;
|
||||
|
||||
if (subtarget.len != 0) {
|
||||
if (str_eq_ignore_case(subtarget, "generic") || str_eq_ignore_case(subtarget, "default")) {
|
||||
if (subtarget_) *subtarget_ = Subtarget_Default;
|
||||
} else {
|
||||
for (isize i = 1; i < Subtarget_COUNT; i++) {
|
||||
if (str_eq_ignore_case(subtarget_strings[i], subtarget)) {
|
||||
if (subtarget_) *subtarget_ = cast(Subtarget)i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return kind;
|
||||
}
|
||||
|
||||
gb_internal TargetArchKind get_target_arch_from_string(String str) {
|
||||
|
||||
@@ -6157,7 +6157,7 @@ gb_internal String build_tag_get_token(String s, String *out) {
|
||||
isize width = utf8_decode(&s[n], s.len-n, &rune);
|
||||
if (n == 0 && rune == '!') {
|
||||
|
||||
} else if (!rune_is_letter(rune) && !rune_is_digit(rune)) {
|
||||
} else if (!rune_is_letter(rune) && !rune_is_digit(rune) && rune != ':') {
|
||||
isize k = gb_max(gb_max(n, width), 1);
|
||||
*out = substring(s, k, s.len);
|
||||
return substring(s, 0, k);
|
||||
@@ -6209,7 +6209,9 @@ gb_internal bool parse_build_tag(Token token_for_pos, String s) {
|
||||
continue;
|
||||
}
|
||||
|
||||
TargetOsKind os = get_target_os_from_string(p);
|
||||
Subtarget subtarget = Subtarget_Default;
|
||||
|
||||
TargetOsKind os = get_target_os_from_string(p, &subtarget);
|
||||
TargetArchKind arch = get_target_arch_from_string(p);
|
||||
num_tokens += 1;
|
||||
|
||||
@@ -6223,11 +6225,13 @@ gb_internal bool parse_build_tag(Token token_for_pos, String s) {
|
||||
if (os != TargetOs_Invalid) {
|
||||
this_kind_os_seen = true;
|
||||
|
||||
bool same_subtarget = (subtarget == Subtarget_Default) || (subtarget == selected_subtarget);
|
||||
|
||||
GB_ASSERT(arch == TargetArch_Invalid);
|
||||
if (is_notted) {
|
||||
this_kind_correct = this_kind_correct && (os != build_context.metrics.os);
|
||||
this_kind_correct = this_kind_correct && (os != build_context.metrics.os || !same_subtarget);
|
||||
} else {
|
||||
this_kind_correct = this_kind_correct && (os == build_context.metrics.os);
|
||||
this_kind_correct = this_kind_correct && (os == build_context.metrics.os && same_subtarget);
|
||||
}
|
||||
} else if (arch != TargetArch_Invalid) {
|
||||
this_kind_arch_seen = true;
|
||||
|
||||
@@ -336,6 +336,83 @@ gb_internal Array<String> split_lines_from_array(Array<u8> const &array, gbAlloc
|
||||
return lines;
|
||||
}
|
||||
|
||||
enum : u32 { PRIME_RABIN_KARP = 16777619u };
|
||||
|
||||
gb_internal u32 hash_str_rabin_karp(String const &s, u32 *pow_) {
|
||||
u32 hash = 0;
|
||||
u32 pow = 1;
|
||||
for (isize i = 0; i < s.len; i++) {
|
||||
hash = hash*PRIME_RABIN_KARP + cast(u32)s.text[i];
|
||||
}
|
||||
u32 sq = PRIME_RABIN_KARP;
|
||||
for (isize i = s.len; i > 0; i >>= 1) {
|
||||
if ((i & 1) != 0) {
|
||||
pow *= sq;
|
||||
}
|
||||
sq *= sq;
|
||||
}
|
||||
if (pow_) *pow_ = pow;
|
||||
return hash;
|
||||
|
||||
}
|
||||
|
||||
|
||||
gb_internal isize string_index(String const &s, String const &substr) {
|
||||
isize n = substr.len;
|
||||
if (n == 0) {
|
||||
return 0;
|
||||
} else if (n == 1) {
|
||||
return string_index_byte(s, substr[0]);
|
||||
} else if (n == s.len) {
|
||||
if (s == substr) {
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
} else if (n > s.len) {
|
||||
return -1;
|
||||
}
|
||||
u32 pow = 1;
|
||||
u32 hash = hash_str_rabin_karp(s, &pow);
|
||||
u32 h = 0;
|
||||
for (isize i = 0; i < n; i++) {
|
||||
h = h*PRIME_RABIN_KARP + cast(u32)s.text[i];
|
||||
}
|
||||
if (h == hash && substring(s, 0, n) == substr) {
|
||||
return 0;
|
||||
}
|
||||
for (isize i = n; i < s.len; /**/) {
|
||||
h *= PRIME_RABIN_KARP;
|
||||
h += cast(u32)s.text[i];
|
||||
h -= pow * u32(s.text[i-n]);
|
||||
i += 1;
|
||||
if (h == hash && substring(s, i-n, i) == substr) {
|
||||
return i - n;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
struct StringPartition {
|
||||
String head;
|
||||
String match;
|
||||
String tail;
|
||||
};
|
||||
|
||||
gb_internal StringPartition string_partition(String const &str, String const &sep) {
|
||||
StringPartition res = {};
|
||||
isize i = string_index(str, sep);
|
||||
if (i < 0) {
|
||||
res.head = str;
|
||||
return res;
|
||||
}
|
||||
|
||||
res.head = substring(str, 0, i);
|
||||
res.match = substring(str, i, i+sep.len);
|
||||
res.tail = substring(str, i+sep.len, str.len);
|
||||
return res;
|
||||
}
|
||||
|
||||
gb_internal bool string_contains_char(String const &s, u8 c) {
|
||||
isize i;
|
||||
for (i = 0; i < s.len; i++) {
|
||||
|
||||
Reference in New Issue
Block a user