diff --git a/releasenotes.md b/releasenotes.md index cb02f08ca..857d72320 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -26,6 +26,7 @@ - Add `+++` `&&&` `|||` as replacement for `$concat`, `$and` and `$or`. - Add `methodsof` to type info for struct, union and bitstruct. - Added `@tag` `tagof` and `has_tagof` to user defined types and members. +- Added `c-include-dirs` project/manifest setting. - The compiler now skips UTF8 BOM. ### Fixes diff --git a/resources/examples/project_all_settings.json b/resources/examples/project_all_settings.json index 94a84319b..782431a4b 100644 --- a/resources/examples/project_all_settings.json +++ b/resources/examples/project_all_settings.json @@ -16,6 +16,8 @@ // C sources if the project also compiles C sources // relative to the project file. // "c-sources": [ "csource/**" ], + // Include directories for C sources relative to the project file. + // "c-include-dirs: [ "csource/include" ], // Output location, relative to project file. "output": "../build", // Architecture and OS target. diff --git a/src/build/build.h b/src/build/build.h index b5b7763b7..90d336c09 100644 --- a/src/build/build.h +++ b/src/build/build.h @@ -478,6 +478,7 @@ typedef struct WinCrtLinking win_crt; const char **csource_dirs; const char **csources; + const char **cinclude_dirs; const char **execs; const char **link_flags; const char **linked_libs; @@ -493,6 +494,7 @@ typedef struct Library__ const char *cc; const char *cflags; const char **csource_dirs; + const char **cinclude_dirs; WinCrtLinking win_crt; LibraryTarget *target_used; LibraryTarget **targets; @@ -503,7 +505,7 @@ typedef struct { TargetType type; Library **library_list; - LibraryTarget **ccompling_libraries; + LibraryTarget **ccompiling_libraries; const char *name; const char *version; const char *langrev; @@ -576,6 +578,7 @@ typedef struct const char *cflags; const char **csource_dirs; const char **csources; + const char **cinclude_dirs; const char **exec; const char **feature_list; const char *custom_linker_path; diff --git a/src/build/libraries.c b/src/build/libraries.c index 3b4c7affd..820676342 100644 --- a/src/build/libraries.c +++ b/src/build/libraries.c @@ -5,6 +5,7 @@ const char *manifest_default_keys[][2] = { {"c-sources", "Set the C sources to be compiled."}, + {"c-include-dirs", "Set the include directories for C sources."}, {"cc", "Set C compiler (defaults to 'cc')."}, {"cflags", "C compiler flags."}, {"dependencies", "List of C3 libraries to also include."}, @@ -19,6 +20,8 @@ const int manifest_default_keys_count = ELEMENTLEN(manifest_default_keys); const char *manifest_target_keys[][2] = { {"c-sources", "Additional C sources to be compiled for the target."}, {"c-sources-override", "C sources to be compiled, overriding global settings."}, + {"c-include-dirs", "C source include directories for the target."}, + {"c-include-dirs-override", "Additional C source include directories for the target, overriding global settings."}, {"cc", "Set C compiler (defaults to 'cc')."}, {"cflags", "Additional C compiler flags for the target."}, {"cflags-override", "C compiler flags for the target, overriding global settings."}, @@ -33,7 +36,7 @@ const char *manifest_target_keys[][2] = { const int manifest_target_keys_count = ELEMENTLEN(manifest_target_keys); const char *manifest_deprecated_target_keys[] = { - "c-sources-add", "cflags-add", "linkflags", "linked-libs" }; + "c-sources-add", "c-include-dirs-add", "cflags-add", "linkflags", "linked-libs" }; const int manifest_deprecated_target_key_count = ELEMENTLEN(manifest_deprecated_target_keys); @@ -49,7 +52,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, manifest_deprecated_target_keys, manifest_deprecated_target_key_count, member, key, "--list-library-properties"); + check_json_keys(manifest_target_keys, manifest_target_keys_count, manifest_deprecated_target_keys, manifest_deprecated_target_key_count, member, key, "--list-manifest-properties"); LibraryTarget *library_target = CALLOCS(LibraryTarget); library_target->parent = library; library_target->win_crt = WIN_CRT_DEFAULT; @@ -83,13 +86,15 @@ static inline void parse_library_target(Library *library, LibraryTarget *target, 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; + target->cinclude_dirs = library->cinclude_dirs; target->win_crt = (WinCrtLinking)get_valid_string_setting(library->dir, target_name, object, "wincrt", wincrt_linking, 0, 3, "'none', 'static' or 'dynamic'."); get_list_append_strings(library->dir, target_name, object, &target->csource_dirs, "c-sources", "c-sources-override", "c-sources-add"); + get_list_append_strings(library->dir, target_name, object, &target->cinclude_dirs, "c-include-dirs", "c-include-dirs-override", "c-include-dirs-add"); } static Library *add_library(JSONObject *object, const char *dir) { - check_json_keys(manifest_default_keys, manifest_default_keys_count, NULL, 0, object, "library", "--list-library-properties"); + check_json_keys(manifest_default_keys, manifest_default_keys_count, NULL, 0, object, "library", "--list-manifest-properties"); Library *library = CALLOCS(Library); library->dir = dir; const char *provides = get_mandatory_string(dir, NULL, object, "provides"); @@ -107,6 +112,7 @@ static Library *add_library(JSONObject *object, const char *dir) library->cflags = get_cflags(library->dir, NULL, object, NULL); library->win_crt = (WinCrtLinking)get_valid_string_setting(library->dir, NULL, object, "wincrt", wincrt_linking, 0, 3, "'none', 'static' or 'dynamic'."); get_list_append_strings(library->dir, NULL, object, &library->csource_dirs, "c-sources", "c-sources-override", "c-sources-add"); + get_list_append_strings(library->dir, NULL, object, &library->cinclude_dirs, "c-include-dirs", "c-include-dirs-override", "c-include-dirs-add"); parse_library_type(library, &library->targets, json_obj_get(object, "targets")); return library; } @@ -274,7 +280,7 @@ void resolve_libraries(BuildTarget *build_target) } if (vec_size(target->csource_dirs)) { - vec_add(build_target->ccompling_libraries, target); + vec_add(build_target->ccompiling_libraries, target); } file_add_wildcard_files(&build_target->sources, library->dir, false, c3_suffix_list, 3); vec_add(build_target->library_list, library); diff --git a/src/build/project.c b/src/build/project.c index d1fcaa9f8..15c465505 100644 --- a/src/build/project.c +++ b/src/build/project.c @@ -15,6 +15,7 @@ const char *project_default_keys[][2] = { {"authors", "Authors, optionally with email."}, {"benchfn", "Override the benchmark function."}, {"c-sources", "Set the C sources to be compiled."}, + {"c-include-dirs", "Set the include directories for C sources."}, {"cc", "Set C compiler (defaults to 'cc')."}, {"cflags", "C compiler flags."}, {"cpu", "CPU name, used for optimizations in the compiler backend."}, @@ -73,6 +74,8 @@ const char* project_target_keys[][2] = { {"benchfn", "Override the benchmark function."}, {"c-sources", "Additional C sources to be compiled for the target."}, {"c-sources-override", "C sources to be compiled, overriding global settings."}, + {"c-include-dirs", "C sources include directories for the target."}, + {"c-include-dirs-override", "Additional C sources include directories for the target, overriding global settings."}, {"cc", "Set C compiler (defaults to 'cc')."}, {"cflags", "Additional C compiler flags for the target."}, {"cflags-override", "C compiler flags for the target, overriding global settings."}, @@ -159,6 +162,9 @@ static void load_into_build_target(JSONObject *json, const char *target_name, Bu // C source dirs. get_list_append_strings(PROJECT_JSON, target_name, json, &target->csource_dirs, "c-sources", "c-sources-override", "c-sources-add"); + // C include dirs. + get_list_append_strings(PROJECT_JSON, target_name, json, &target->cinclude_dirs, "c-include-dirs", "c-include-dirs-override", "c-include-dirs-add"); + // Sources get_list_append_strings(PROJECT_JSON, target_name, json, &target->source_dirs, "sources", "sources-override", "sources-add"); diff --git a/src/build/project_creation.c b/src/build/project_creation.c index 72eba9dcd..28df2eccb 100644 --- a/src/build/project_creation.c +++ b/src/build/project_creation.c @@ -23,6 +23,8 @@ const char* JSON_EXE = " // C sources if the project also compiles C sources\n" " // relative to the project file.\n" " // \"c-sources\": [ \"csource/**\" ],\n" + " // Include directories for C sources relative to the project file.\n" + " // \"c-include-dirs\": [ \"csource/include\" ],\n" " // Output location, relative to project file.\n" " \"output\": \"build\",\n" " // Architecture and OS target.\n" @@ -64,6 +66,8 @@ const char* JSON_STATIC = " // C sources if the project also compiles C sources\n" " // relative to the project file.\n" " // \"c-sources\": [ \"csource/**\" ],\n" + " // Include directories for C sources relative to the project file.\n" + " // \"c-include-dirs\": [ \"csource/include\" ],\n" " // Output location, relative to project file.\n" " \"output\": \"build\",\n" " // Architecture and OS target.\n" @@ -103,6 +107,8 @@ const char* JSON_DYNAMIC = " // C sources if the project also compiles C sources\n" " // relative to the project file.\n" " // \"c-sources\": [ \"csource/**\" ],\n" + " // Include directories for C sources relative to the project file.\n" + " // \"c-include-dirs\": [ \"csource/include\" ],\n" " // Output location, relative to project file.\n" " \"output\": \"build\",\n" " // Architecture and OS target.\n" diff --git a/src/build/project_manipulation.c b/src/build/project_manipulation.c index 5f2e44947..8f3a7789d 100644 --- a/src/build/project_manipulation.c +++ b/src/build/project_manipulation.c @@ -187,6 +187,8 @@ static void view_target(const char* name, JSONObject* target) TARGET_VIEW_STRING_ARRAY("Source paths (override)", "sources-override"); TARGET_VIEW_STRING_ARRAY("Additional C source paths", "c-sources"); TARGET_VIEW_STRING_ARRAY("C source paths (override)", "c-sources-override"); + TARGET_VIEW_STRING_ARRAY("Additional C source include directories", "c-include-dirs"); + TARGET_VIEW_STRING_ARRAY("C source include directories (override)", "c-include-dirs-override"); TARGET_VIEW_SETTING("Optimization level", "opt", optimization_levels); /* Extended target information */ diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index 1aaf66ae1..0ba4bed26 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -254,13 +254,13 @@ static void free_arenas(void) if (debug_stats) print_arena_status(); } -static int compile_cfiles(const char *compiler, const char **files, const char *flags, const char **out_files, - const char *output_subdir) +static int compile_cfiles(const char *compiler, const char **files, const char *flags, const char **include_dirs, + const char **out_files, const char *output_subdir) { int total = 0; FOREACH(const char *, file, files) { - out_files[total++] = cc_compiler(compiler, file, flags, output_subdir); + out_files[total++] = cc_compiler(compiler, file, flags, include_dirs, output_subdir); } return total; } @@ -496,7 +496,7 @@ void compiler_compile(void) uint32_t output_file_count = vec_size(gen_contexts); unsigned cfiles = vec_size(active_target.csources); unsigned cfiles_library = 0; - FOREACH(LibraryTarget *, lib, active_target.ccompling_libraries) + FOREACH(LibraryTarget *, lib, active_target.ccompiling_libraries) { cfiles_library += vec_size(lib->csources); } @@ -514,15 +514,16 @@ void compiler_compile(void) if (cfiles) { - int compiled = compile_cfiles(active_target.cc, active_target.csources, active_target.cflags, &obj_files[output_file_count], "tmp_c_compile"); + int compiled = compile_cfiles(active_target.cc, active_target.csources, + active_target.cflags, active_target.cinclude_dirs, &obj_files[output_file_count], "tmp_c_compile"); assert(cfiles == compiled); (void)compiled; } const char **obj_file_next = &obj_files[output_file_count + cfiles]; - FOREACH(LibraryTarget *, lib, active_target.ccompling_libraries) + FOREACH(LibraryTarget *, lib, active_target.ccompiling_libraries) { obj_file_next += compile_cfiles(lib->cc ? lib->cc : active_target.cc, lib->csources, - lib->cflags, obj_file_next, lib->parent->provides); + lib->cflags, lib->cinclude_dirs, obj_file_next, lib->parent->provides); } Task **tasks = NULL; @@ -765,6 +766,16 @@ INLINE void expand_csources(const char *base_dir, const char **source_dirs, cons } } +INLINE void expand_cinclude_dirs(const char *base_dir, const char **include_dirs, const char ***include_dirs_ref) +{ + const char **expanded_include_dirs = NULL; + FOREACH(const char *, include_dir, include_dirs) + { + vec_add(expanded_include_dirs, file_append_path(base_dir, include_dir)); + } + *include_dirs_ref = expanded_include_dirs; +} + void compile_target(BuildOptions *options) { init_default_build_target(&active_target, options); @@ -1081,9 +1092,10 @@ void compile() target_setup(&active_target); resolve_libraries(&active_target); global_context.sources = active_target.sources; - FOREACH(LibraryTarget *, lib, active_target.ccompling_libraries) + FOREACH(LibraryTarget *, lib, active_target.ccompiling_libraries) { expand_csources(lib->parent->dir, lib->csource_dirs, &lib->csources); + expand_cinclude_dirs(lib->parent->dir, lib->cinclude_dirs, &lib->cinclude_dirs); } TokenType type = TOKEN_CONST_IDENT; FOREACH(const char *, feature_flag, active_target.feature_list) diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 3026c09d9..34890d6c7 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -3549,7 +3549,7 @@ bool static_lib_linker(const char *output_file, const char **files, unsigned fil bool dynamic_lib_linker(const char *output_file, const char **files, unsigned file_count); bool linker(const char *output_file, const char **files, unsigned file_count); void platform_linker(const char *output_file, const char **files, unsigned file_count); -const char *cc_compiler(const char *cc, const char *file, const char *flags, const char *output_subdir); +const char *cc_compiler(const char *cc, const char *file, const char *flags, const char **include_dirs, const char *output_subdir); const char *arch_to_linker_arch(ArchType arch); #define CAT(a,b) CAT2(a,b) // force expand diff --git a/src/compiler/linker.c b/src/compiler/linker.c index e66ff835e..d3b1425b1 100644 --- a/src/compiler/linker.c +++ b/src/compiler/linker.c @@ -761,7 +761,7 @@ void platform_linker(const char *output_file, const char **files, unsigned file_ printf("Program linked to executable '%s'.\n", output_file); } -const char *cc_compiler(const char *cc, const char *file, const char *flags, const char *output_subdir) +const char *cc_compiler(const char *cc, const char *file, const char *flags, const char **include_dirs, const char *output_subdir) { const char *dir = active_target.object_file_dir; if (!dir) dir = active_target.build_dir; @@ -789,6 +789,11 @@ const char *cc_compiler(const char *cc, const char *file, const char *flags, con const char **parts = NULL; vec_add(parts, cc); + FOREACH(const char *, include_dir, include_dirs) + { + vec_add(parts, str_printf(is_cl_exe ? "/I\"%s\"" : "-I\"%s\"", include_dir)); + } + const bool pie_set = flags != NULL && (strstr(flags, "-fno-PIE") || // This is a weird case, but probably don't set PIE if