diff --git a/releasenotes.md b/releasenotes.md index 02b78ed80..03364e639 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -16,7 +16,10 @@ - Add `.gitkeep` files to project subfolders. - Add `env::COMPILER_BUILD_HASH` and `env::COMPILER_BUILD_DATE` - Support linking .o files in compilation command. #1417 -- Slicing constant strings and bytes at compile time works. +- Slicing constant strings at compile time works. +- Add `project fetch` subcommand to fetch missing project dependencies (general and target specific) +- Ability of `vendor-fetch` to download the dependencies in the first specified path `dependencies-search-path` +- Ability of `vendor-fetch` to register the fetched dependencies in the project file. - Allow the "self" parameter to be $/# for macro methods. - Support compile time slicing of untyped lists. diff --git a/src/build/build.h b/src/build/build.h index e91fab22f..af5243879 100644 --- a/src/build/build.h +++ b/src/build/build.h @@ -53,7 +53,8 @@ typedef enum { SUBCOMMAND_MISSING = 0, SUBCOMMAND_VIEW, - SUBCOMMAND_ADD + SUBCOMMAND_ADD, + SUBCOMMAND_FETCH } ProjectSubcommand; typedef enum @@ -733,3 +734,4 @@ void create_library(BuildOptions *build_options); void resolve_libraries(BuildTarget *build_target); void view_project(BuildOptions *build_options); void add_target_project(BuildOptions *build_options); +void fetch_project(BuildOptions* options); \ No newline at end of file diff --git a/src/build/build_options.c b/src/build/build_options.c index ba86cc25d..7cda98ea4 100644 --- a/src/build/build_options.c +++ b/src/build/build_options.c @@ -4,6 +4,7 @@ #include "../utils/whereami.h" #include "build.h" +#include "project.h" #include "build_internal.h" #include "git_hash.h" @@ -187,6 +188,9 @@ static void project_usage() PRINTF("Project Subcommands:"); PRINTF(" view view the current projects structure"); PRINTF(" add-target add a new target to the project"); + #if FETCH_AVAILABLE + PRINTF(" fetch fetch missing project libraries"); + #endif } static void parse_project_subcommand(BuildOptions *options) @@ -208,6 +212,11 @@ static void parse_project_subcommand(BuildOptions *options) return; } + if (arg_match("fetch")) + { + options->project_options.command = SUBCOMMAND_FETCH; + return; + } PROJECT_FAIL_WITH_ERR("Cannot process the unknown subcommand \"%s\".", current_arg); } diff --git a/src/build/project.h b/src/build/project.h index 8130c4ffc..8c49c330f 100644 --- a/src/build/project.h +++ b/src/build/project.h @@ -3,4 +3,10 @@ const char** get_project_dependency_directories(); -void add_libraries_to_project_file(const char** libs, const char* target_name); \ No newline at end of file +const char** get_project_dependencies(); + +static void print_vec(const char *header, const char **vec, bool opt); + +void add_libraries_to_project_file(const char** libs, const char* target_name); + +const char* vendor_fetch_single(const char* lib, const char* path); diff --git a/src/build/project_manipulation.c b/src/build/project_manipulation.c index e79c1806f..e4b3988e3 100644 --- a/src/build/project_manipulation.c +++ b/src/build/project_manipulation.c @@ -52,6 +52,21 @@ static void print_vec(const char *header, const char **vec, bool opt) PRINTFN(""); } +const char** get_project_dependencies() +{ + const char *filename; + const char** dependencies = NULL; + + JSONObject *project_json = read_project(&filename); + JSONObject *dependencies_json = json_map_get(project_json, "dependencies"); + + FOREACH(JSONObject *, element, dependencies_json->elements) + { + vec_add(dependencies, element->str); + } + return dependencies; +} + static void print_opt_str(const char *header, const char *str) { if (!str) return; @@ -252,6 +267,95 @@ static void view_target(const char *filename, const char *name, JSONObject *targ TARGET_VIEW_BOOL("Return structs on the stack", "x86-stack-struct-return"); } + + +#if FETCH_AVAILABLE +void fetch_project(BuildOptions* options) +{ + if (!file_exists(PROJECT_JSON5) && !file_exists(PROJECT_JSON)) + { + error_exit("Failed: no project file found."); + } + + if (str_eq(options->path, DEFAULT_PATH)) + { + { + const char** deps_dirs = get_project_dependency_directories(); + int num_lib = vec_size(deps_dirs); + if (num_lib > 0) options->vendor_download_path = deps_dirs[0]; + + } + + } + + const char** libdirs = get_project_dependency_directories(); + const char** deps = get_project_dependencies(); + const char *filename; + JSONObject *project_json = read_project(&filename); + + JSONObject *targets_json = json_map_get(project_json, "targets"); + + if (targets_json && targets_json->type == J_OBJECT) + { + + FOREACH_IDX(i, JSONObject *, target, targets_json->members) + { + const char *key = targets_json->keys[i]; + if (target->type != J_OBJECT) + { + error_exit("Invalid data in target '%s'", key); + } + + const char** target_deps = get_optional_string_array(filename, key, target, "dependencies"); + + FOREACH(const char*, dep, target_deps) { + vec_add(deps, dep); + } + } + + } + + // dependency check tree + while (vec_size(deps) > 0) + { + + FOREACH(const char*, dir, libdirs) + { + + const char* dep = deps[vec_size(deps)-1]; + if (file_exists(file_append_path(dir, str_printf("%s.c3l", dep)))) + { + vec_pop(deps); + break; + }; + + printf("Fetching missing library '%s'...", dep); + fflush(stdout); + + const char* error = vendor_fetch_single(dep, options->vendor_download_path); + + if (!error) + { + puts(" finished."); + } + else + { + printf("Failed: '%s'\n", error); + } + + vec_pop(deps); + break; + } + } +} +#else +void fetch_project(BuildOptions* options) +{ + error_exit("Error: project fetch only available when compiled with cURL."); +} +#endif + + void add_libraries_to_project_file(const char** libs, const char* target_name) { if (!file_exists(PROJECT_JSON5) && !file_exists(PROJECT_JSON)) return; diff --git a/src/main.c b/src/main.c index e9cb06d21..d2b7b31de 100644 --- a/src/main.c +++ b/src/main.c @@ -108,6 +108,9 @@ int main_real(int argc, const char *argv[]) case SUBCOMMAND_ADD: add_target_project(&build_options); break; + case SUBCOMMAND_FETCH: + fetch_project(&build_options); + break; case SUBCOMMAND_MISSING: break; }