diff --git a/src/build_settings.cpp b/src/build_settings.cpp index c12107bf7..006b0ea0a 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -2215,18 +2215,18 @@ gb_internal bool check_target_feature_is_enabled(String const &feature, String * } if (feature_str == "") break; - if (!string_set_exists(&build_context.target_features_set, str)) { - String plus_str = concatenate_strings(temporary_allocator(), make_string_c("+"), feature_str); - - if (want_enabled && !string_set_exists(&build_context.target_features_set, plus_str)) { - if (not_enabled) *not_enabled = str; - return false; - } - } - + String plus_str = concatenate_strings(temporary_allocator(), make_string_c("+"), feature_str); String minus_str = concatenate_strings(temporary_allocator(), make_string_c("-"), feature_str); - - if (!want_enabled && !string_set_exists(&build_context.target_features_set, minus_str)) { + + bool has_raw = string_set_exists(&build_context.target_features_set, feature_str); + bool has_plus = string_set_exists(&build_context.target_features_set, plus_str); + bool has_minus = string_set_exists(&build_context.target_features_set, minus_str); + + // NOTE(jakubtomsu): this way "feature" and "+feature" is ALWAYS equivalent, + // and also allows the minus sign to do a final override. + bool is_enabled = (has_plus || has_raw) && !has_minus; + + if (want_enabled != is_enabled) { if (not_enabled) *not_enabled = str; return false; } diff --git a/src/main.cpp b/src/main.cpp index 18381f5ee..b4ad8168b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3973,15 +3973,16 @@ int main(int arg_count, char const **arg_ptr) { for (;;) { String item = string_split_iterator(&target_it, ','); if (item == "") break; - - if (*item.text == '+' || *item.text == '-') { - item.text++; - item.len--; + + String stripped_item = item; + if (*stripped_item.text == '+' || *stripped_item.text == '-') { + stripped_item.text++; + stripped_item.len--; } String invalid; - if (!check_target_feature_is_valid_for_target_arch(item, &invalid) && item != str_lit("help")) { - if (item != str_lit("?")) { + if (!check_target_feature_is_valid_for_target_arch(stripped_item, &invalid) && stripped_item != str_lit("help")) { + if (stripped_item != str_lit("?")) { gb_printf_err("Unkown target feature '%.*s'.\n", LIT(invalid)); } gb_printf("Possible -target-features for target %.*s are:\n", LIT(target_arch_names[build_context.metrics.arch])); @@ -4005,8 +4006,25 @@ int main(int arg_count, char const **arg_ptr) { return 1; } - - string_set_add(&build_context.target_features_set, item); + + // Ensure the feature name always has +/- prefix. If there isn't, default to '+' + String feature_str = item; + if (*feature_str.text != '+' && *feature_str.text != '-') { + feature_str = concatenate_strings(temporary_allocator(), make_string_c("+"), feature_str); + } + + // Ensure there is only a single entry for each feature in the target set. + // If the negative exists, override the existing value with the current one. + String neg_feature_str = clone_string(temporary_allocator(), feature_str); + switch (*neg_feature_str.text) { + case '+': *neg_feature_str.text = '-'; break; + case '-': *neg_feature_str.text = '+'; break; + default: GB_ASSERT(false); break; + } + + string_set_remove(&build_context.target_features_set, neg_feature_str); + + string_set_add(&build_context.target_features_set, feature_str); } } diff --git a/src/string.cpp b/src/string.cpp index a4fa85871..977327bcd 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -508,6 +508,13 @@ gb_internal String filename_without_directory(String s) { return substring(s, gb_max(j+1, 0), s.len); } +gb_internal String clone_string(gbAllocator a, String const &x) { + u8 *data = gb_alloc_array(a, u8, x.len+1); + gb_memmove(data, x.text, x.len); + data[x.len] = 0; + return make_string(data, x.len); +} + gb_internal String concatenate_strings(gbAllocator a, String const &x, String const &y) { isize len = x.len+y.len; u8 *data = gb_alloc_array(a, u8, len+1);