diff --git a/releasenotes.md b/releasenotes.md index da947c593..f76c17040 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -20,6 +20,8 @@ - Array comparison now uses built-in memcmp on LLVM to enable optimizations. - Prevent implicit array casts to pointers with higher alignment #1237. - Macro `$case` statements now pick the first match and does not evaluate the rest. +- `mainfest.json` is now checked for incorrect keys. +- Added `--list-manifest-properties` to list the available properties in `manifest.json`. ### Fixes - Error with unsigned compare in `@ensure` when early returning 0 #1207. diff --git a/resources/testproject/lib/clib.c3l/manifest.json b/resources/testproject/lib/clib.c3l/manifest.json index afaf59e3e..16eff63ac 100644 --- a/resources/testproject/lib/clib.c3l/manifest.json +++ b/resources/testproject/lib/clib.c3l/manifest.json @@ -6,7 +6,7 @@ }, "macos-aarch64" : {}, "linux-x64" : { - "c-flags-override": "-fPIE" + "cflags-override": "-fPIE" }, "windows-x64" : { } } diff --git a/resources/testproject/lib/clib2.c3l b/resources/testproject/lib/clib2.c3l index 0e64c8eba..ec52baeab 100644 Binary files a/resources/testproject/lib/clib2.c3l and b/resources/testproject/lib/clib2.c3l differ diff --git a/src/build/build.h b/src/build/build.h index a5f1b8765..4b67a77f0 100644 --- a/src/build/build.h +++ b/src/build/build.h @@ -400,6 +400,7 @@ typedef struct BuildOptions_ bool print_operators; bool print_type_properties; bool print_project_properties; + bool print_manifest_properties; bool print_precedence; bool print_build_settings; bool print_linking; diff --git a/src/build/build_internal.h b/src/build/build_internal.h index 7e142bd70..482a15e1b 100644 --- a/src/build/build_internal.h +++ b/src/build/build_internal.h @@ -99,3 +99,4 @@ const char *get_cflags(const char *file, const char *target, JSONObject *json, c void get_list_append_strings(const char *file, const char *target, JSONObject *json, const char ***list_ptr, const char *base, const char *override, const char *add); int get_valid_string_setting(const char *file, const char *target, JSONObject *json, const char *key, const char** values, int first_result, int count, const char *expected); +void check_json_keys(const char* valid_keys[][2], size_t key_count, JSONObject *json, const char *target_name, const char *option); diff --git a/src/build/build_options.c b/src/build/build_options.c index f51735b37..1d7308251 100644 --- a/src/build/build_options.c +++ b/src/build/build_options.c @@ -165,6 +165,7 @@ static void usage(void) PRINTF(" --list-operators - List all operators."); PRINTF(" --list-precedence - List operator precedence order."); PRINTF(" --list-project-properties - List all available keys used in project.json files."); + PRINTF(" --list-manifest-properties - List all available keys used in manifest.json files."); PRINTF(" --list-targets - List all architectures the compiler supports."); PRINTF(" --list-type-properties - List all type properties."); PRINTF(""); @@ -819,6 +820,12 @@ static void parse_option(BuildOptions *options) options->command = COMMAND_PRINT_SYNTAX; return; } + if (match_longopt("list-manifest-properties")) + { + options->print_manifest_properties = true; + options->command = COMMAND_PRINT_SYNTAX; + return; + } if (match_longopt("list-operators")) { options->print_operators = true; diff --git a/src/build/common_build.c b/src/build/common_build.c index aac546a7e..4384b94d8 100644 --- a/src/build/common_build.c +++ b/src/build/common_build.c @@ -1,6 +1,28 @@ #include "build_internal.h" #include "utils/common.h" +void check_json_keys(const char* valid_keys[][2], size_t key_count, JSONObject *json, const char *target_name, const char *option) +{ + static bool failed_shown = false; + bool failed = false; + for (size_t i = 0; i < json->member_len; i++) + { + const char *key = json->keys[i]; + for (size_t j = 0; j < key_count; j++) + { + if (strcmp(key, valid_keys[j][0]) == 0) goto OK; + } + eprintf("WARNING: Unknown parameter '%s' in '%s'.\n", key, target_name); + failed = true; + OK:; + } + if (failed && !failed_shown) + { + eprintf("You can use '%s' to list all valid properties.\n", option); + failed_shown = true; + } +} + const char *get_optional_string(const char *file, const char *category, JSONObject *table, const char *key) { JSONObject *value = json_obj_get(table, key); diff --git a/src/build/libraries.c b/src/build/libraries.c index cdf638bb1..876f7fc69 100644 --- a/src/build/libraries.c +++ b/src/build/libraries.c @@ -3,6 +3,32 @@ #define MANIFEST_FILE "manifest.json" +const char *manifest_default_keys[][2] = { + {"c-sources", "Set the C sources to be compiled."}, + {"cc", "Set C compiler (defaults to 'cc')."}, + {"cflags", "C compiler flags."}, + {"depends", "List of C3 libraries to also include."}, + {"exec", "Scripts run for all platforms."}, + {"provides", "The library name"}, + {"targets", "The map of supported platforms"} +}; + +const int manifest_default_keys_count = ELEMENTLEN(manifest_default_keys); + +const char *manifest_target_keys[][2] = { + {"c-sources-add", "Additional C sources to be compiled for the target."}, + {"c-sources-override", "C sources to be compiled, overriding global settings."}, + {"cc", "Set C compiler (defaults to 'cc')."}, + {"cflags-add", "Additional C compiler flags for the target."}, + {"cflags-override", "C compiler flags for the target, overriding global settings."}, + {"depends", "List of C3 libraries to also include for this target."}, + {"exec", "Scripts to also run for the target."}, + {"linked-libraries", "Libraries linked by the linker for this target, overriding global settings."}, + {"link-args", "Linker arguments for this target."}, +}; + +const int manifest_target_keys_count = ELEMENTLEN(manifest_target_keys); + static inline void parse_library_target(Library *library, LibraryTarget *target, const char *target_name, JSONObject *object); @@ -15,6 +41,7 @@ static inline void parse_library_type(Library *library, LibraryTarget ***target_ JSONObject *member = object->members[i]; const char *key = object->keys[i]; if (member->type != J_OBJECT) error_exit("Expected a list of properties for a target in %s.", library->dir); + check_json_keys(manifest_target_keys, manifest_target_keys_count, member, key, "--list-library-properties"); LibraryTarget *library_target = CALLOCS(LibraryTarget); library_target->parent = library; ArchOsTarget target = arch_os_target_from_string(key); @@ -31,10 +58,10 @@ static inline void parse_library_type(Library *library, LibraryTarget ***target_ static inline void parse_library_target(Library *library, LibraryTarget *target, const char *target_name, JSONObject *object) { - target->link_flags = get_string_array(library->dir, target_name, object, "linkflags", false); - target->linked_libs = get_string_array(library->dir, target_name, object, "linked-libs", false); + target->link_flags = get_string_array(library->dir, target_name, object, "link-args", false); + target->linked_libs = get_string_array(library->dir, target_name, object, "linked-libraries", false); target->depends = get_string_array(library->dir, target_name, object, "depends", false); - target->execs = get_string_array(library->dir, target_name, object, "execs", false); + target->execs = get_string_array(library->dir, target_name, object, "exec", false); target->cc = get_string(library->dir, target_name, object, "cc", library->cc); target->cflags = get_cflags(library->dir, target_name, object, library->cflags); target->csource_dirs = library->csource_dirs; @@ -43,6 +70,7 @@ static inline void parse_library_target(Library *library, LibraryTarget *target, static Library *add_library(JSONObject *object, const char *dir) { + check_json_keys(manifest_default_keys, manifest_default_keys_count, object, "library", "--list-library-properties"); Library *library = CALLOCS(Library); library->dir = dir; const char *provides = get_mandatory_string(dir, NULL, object, "provides"); @@ -54,7 +82,7 @@ static Library *add_library(JSONObject *object, const char *dir) error_exit("Invalid 'provides' module name in %s, was '%s'.", library->dir, res); } library->provides = provides; - library->execs = get_optional_string_array(library->dir, NULL, object, "execs"); + library->execs = get_optional_string_array(library->dir, NULL, object, "exec"); library->depends = get_optional_string_array(library->dir, NULL, object, "depends"); library->cc = get_optional_string(dir, NULL, object, "cc"); library->cflags = get_cflags(library->dir, NULL, object, NULL); diff --git a/src/build/project.c b/src/build/project.c index cca127336..186df521f 100644 --- a/src/build/project.c +++ b/src/build/project.c @@ -144,37 +144,16 @@ long get_valid_integer(JSONObject *table, const char *key, const char *category, return (long)trunc(value->f); } -static void check_json_keys(const char* valid_keys[][2], size_t key_count, JSONObject *json, const char *target_name) -{ - static bool failed_shown = false; - bool failed = false; - for (size_t i = 0; i < json->member_len; i++) - { - const char *key = json->keys[i]; - for (size_t j = 0; j < key_count; j++) - { - if (strcmp(key, valid_keys[j][0]) == 0) goto OK; - } - eprintf("WARNING: Unknown parameter '%s' in '%s'.\n", key, target_name ? target_name : "default_target"); - failed = true; - OK:; - } - if (failed && !failed_shown) - { - eprintf("You can use '--list-project-properties' to list all valid properties.\n"); - failed_shown = true; - } -} static void load_into_build_target(JSONObject *json, const char *target_name, BuildTarget *target) { if (target_name) { - check_json_keys(project_target_keys, project_target_keys_count, json, target_name); + check_json_keys(project_target_keys, project_target_keys_count, json, target_name, "--list-project-properties"); } else { - check_json_keys(project_default_keys, project_default_keys_count, json, NULL); + check_json_keys(project_default_keys, project_default_keys_count, json, "default target", "--list-project-properties"); } target->cc = get_string(PROJECT_JSON, target_name, json, "cc", target->cc); diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index 73df7246b..1063ceb1e 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -898,6 +898,24 @@ void print_syntax(BuildOptions *options) } puts(""); } + if (options->print_manifest_properties) + { + int width; + puts("Manifest properties"); + puts("------------------"); + for (int i = 0; i < manifest_default_keys_count; i++) + { + printf("%-*s%s\n", 35, manifest_default_keys[i][0], manifest_default_keys[i][1]); + } + puts(""); + puts("Target properties"); + puts("-----------------"); + for (int i = 0; i < manifest_target_keys_count; i++) + { + printf("%-*s%s\n", 35, manifest_target_keys[i][0], manifest_target_keys[i][1]); + } + puts(""); + } if (options->print_precedence) { puts("precedence | operators"); diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index b508f1dd0..a0e9e4f69 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -49,8 +49,12 @@ typedef uint16_t SectionId; extern const char *project_default_keys[][2]; extern const int project_default_keys_count; -extern const char* project_target_keys[][2]; +extern const char *project_target_keys[][2]; extern const int project_target_keys_count; +extern const char *manifest_default_keys[][2]; +extern const int manifest_default_keys_count; +extern const char *manifest_target_keys[][2]; +extern const int manifest_target_keys_count; typedef struct Ast_ Ast; typedef struct Decl_ Decl;