diff --git a/include/project_parser.hpp b/include/project_parser.hpp index fe45cf7..dc25a61 100644 --- a/include/project_parser.hpp +++ b/include/project_parser.hpp @@ -33,7 +33,13 @@ struct Package { struct Vcpkg { std::string version; std::string url; - std::vector packages; + + struct Package { + std::string name; + std::vector features; + }; + + std::vector packages; }; enum TargetType { diff --git a/src/cmake_generator.cpp b/src/cmake_generator.cpp index 508dbc3..1c1d815 100644 --- a/src/cmake_generator.cpp +++ b/src/cmake_generator.cpp @@ -579,8 +579,8 @@ void generate_cmake(const char *path, const parser::Project *parent_project) { // Show a nicer error than vcpkg when specifying an invalid package name for (const auto &package : project.vcpkg.packages) { - if (!vcpkg_valid_identifier(package)) { - throw std::runtime_error("Invalid [vcpkg].packages name '" + package + "' (needs to be lowercase alphanumeric)"); + if (!vcpkg_valid_identifier(package.name)) { + throw std::runtime_error("Invalid [vcpkg].packages name '" + package.name + "' (needs to be lowercase alphanumeric)"); } } @@ -611,10 +611,31 @@ void generate_cmake(const char *path, const parser::Project *parent_project) { const auto &packages = project.vcpkg.packages; for (size_t i = 0; i < packages.size(); i++) { const auto &package = packages[i]; - if (!vcpkg_valid_identifier(package)) { - throw std::runtime_error("Invalid vcpkg package name '" + package + "'"); + const auto &features = package.features; + if (!vcpkg_valid_identifier(package.name)) { + throw std::runtime_error("Invalid vcpkg package name '" + package.name + "'"); + } + for (const auto &feature : features) { + if (!vcpkg_valid_identifier(feature)) { + throw std::runtime_error("Invalid vcpkg package feature '" + feature + "'"); + } + } + if (features.empty()) { + ofs << " \"" << package.name << '\"'; + } else { + ofs << " {\n"; + ofs << " \"name\": \"" << package.name << "\",\n"; + ofs << " \"features\": ["; + for (size_t j = 0; j < features.size(); j++) { + const auto &feature = features[j]; + ofs << '\"' << feature << '\"'; + if (j + 1 < features.size()) { + ofs << ','; + } + } + ofs << "]\n"; + ofs << " }"; } - ofs << " \"" << package << '\"'; if (i + 1 < packages.size()) { ofs << ','; } diff --git a/src/project_parser.cpp b/src/project_parser.cpp index ad067e4..00c7735 100644 --- a/src/project_parser.cpp +++ b/src/project_parser.cpp @@ -495,7 +495,26 @@ Project::Project(const Project *parent, const std::string &path, bool build) { auto &v = checker.create(toml, "vcpkg"); v.optional("url", vcpkg.url); v.optional("version", vcpkg.version); - v.required("packages", vcpkg.packages); + for (const auto &p : v.find("packages").as_array()) { + Vcpkg::Package package; + const auto &package_str = p.as_string().str; + const auto open_bracket = package_str.find('['); + const auto close_bracket = package_str.find(']', open_bracket); + if (open_bracket == std::string::npos && close_bracket == std::string::npos) { + package.name = package_str; + } else if (close_bracket != std::string::npos) { + package.name = package_str.substr(0, open_bracket); + const auto features = package_str.substr(open_bracket + 1, close_bracket - open_bracket - 1); + std::istringstream feature_stream{features}; + std::string feature; + while (std::getline(feature_stream, feature, ',')) { + package.features.emplace_back(feature); + } + } else { + throw std::runtime_error("Invalid vcpkg package '" + package_str + "'"); + } + vcpkg.packages.emplace_back(std::move(package)); + } } checker.check(conditions);