From 3201fd052ede04ec1d4da2d201540813d64a6956 Mon Sep 17 00:00:00 2001 From: cursey Date: Sun, 26 Dec 2021 15:40:45 -0800 Subject: [PATCH 1/8] Add support for vcpkg package features --- include/project_parser.hpp | 8 +++++++- src/cmake_generator.cpp | 29 ++++++++++++++++++++++------- src/project_parser.cpp | 21 ++++++++++++++++++++- 3 files changed, 49 insertions(+), 9 deletions(-) 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..e0a3a79 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,13 +611,28 @@ 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 + "'"); + if (!vcpkg_valid_identifier(package.name)) { + throw std::runtime_error("Invalid vcpkg package name '" + package.name + "'"); } - ofs << " \"" << package << '\"'; - if (i + 1 < packages.size()) { - ofs << ','; + if (package.features.empty()) { + ofs << " \"" << package.name << '\"'; + } else { + ofs << " {\n"; + ofs << " \"name\": \"" << package.name << "\",\n"; + ofs << " \"features\": ["; + for (size_t j = 0; j < package.features.size(); j++) { + const auto &feature = package.features[j]; + ofs << '\"' << feature << '\"'; + if (j + 1 < package.features.size()) { + ofs << ','; + } + } + ofs << "]\n"; + ofs << " }"; } + if (i + 1 < packages.size()) { + ofs << ','; + } ofs << '\n'; } diff --git a/src/project_parser.cpp b/src/project_parser.cpp index ad067e4..6f5cb03 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); + 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("Badly formed vcpkg package name"); + } + vcpkg.packages.emplace_back(std::move(package)); + } } checker.check(conditions); From 61dfb0eb60207637f47605413a1928448e80013a Mon Sep 17 00:00:00 2001 From: cursey Date: Sun, 26 Dec 2021 16:32:38 -0800 Subject: [PATCH 2/8] Fix tabbing in vcpkg.json for packages that have features --- src/cmake_generator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmake_generator.cpp b/src/cmake_generator.cpp index e0a3a79..ed0d59f 100644 --- a/src/cmake_generator.cpp +++ b/src/cmake_generator.cpp @@ -618,8 +618,8 @@ void generate_cmake(const char *path, const parser::Project *parent_project) { ofs << " \"" << package.name << '\"'; } else { ofs << " {\n"; - ofs << " \"name\": \"" << package.name << "\",\n"; - ofs << " \"features\": ["; + ofs << " \"name\": \"" << package.name << "\",\n"; + ofs << " \"features\": ["; for (size_t j = 0; j < package.features.size(); j++) { const auto &feature = package.features[j]; ofs << '\"' << feature << '\"'; From 0acc9b4e5aab41f38656427d68ae77e1c673b374 Mon Sep 17 00:00:00 2001 From: cursey Date: Mon, 27 Dec 2021 00:53:29 -0800 Subject: [PATCH 3/8] Report the badly formed package name to the user --- src/project_parser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/project_parser.cpp b/src/project_parser.cpp index 6f5cb03..98d4c0d 100644 --- a/src/project_parser.cpp +++ b/src/project_parser.cpp @@ -511,7 +511,7 @@ Project::Project(const Project *parent, const std::string &path, bool build) { package.features.emplace_back(feature); } } else { - throw std::runtime_error("Badly formed vcpkg package name"); + throw std::runtime_error("Invalid vcpkg package '" + package_str + "'"); } vcpkg.packages.emplace_back(std::move(package)); } From b4b0f533a9d3b65ff0ac53c296d617c69f99c876 Mon Sep 17 00:00:00 2001 From: cursey Date: Mon, 27 Dec 2021 01:02:05 -0800 Subject: [PATCH 4/8] Validate vcpkg features --- src/cmake_generator.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/cmake_generator.cpp b/src/cmake_generator.cpp index ed0d59f..ea9df19 100644 --- a/src/cmake_generator.cpp +++ b/src/cmake_generator.cpp @@ -614,6 +614,11 @@ void generate_cmake(const char *path, const parser::Project *parent_project) { if (!vcpkg_valid_identifier(package.name)) { throw std::runtime_error("Invalid vcpkg package name '" + package.name + "'"); } + for (const auto &feature : package.features) { + if (!vcpkg_valid_identifier(feature)) { + throw std::runtime_error("Invalid vcpkg package feature '" + feature + "'"); + } + } if (package.features.empty()) { ofs << " \"" << package.name << '\"'; } else { From 084cbd6159cce011f4d6ae9a53d0f882fd60e266 Mon Sep 17 00:00:00 2001 From: cursey Date: Mon, 27 Dec 2021 01:08:56 -0800 Subject: [PATCH 5/8] Cleanup vcpkg.json generation a little --- src/cmake_generator.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/cmake_generator.cpp b/src/cmake_generator.cpp index ea9df19..a07143b 100644 --- a/src/cmake_generator.cpp +++ b/src/cmake_generator.cpp @@ -611,24 +611,25 @@ 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]; + 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 : package.features) { + for (const auto &feature : features) { if (!vcpkg_valid_identifier(feature)) { throw std::runtime_error("Invalid vcpkg package feature '" + feature + "'"); } } - if (package.features.empty()) { + if (features.empty()) { ofs << " \"" << package.name << '\"'; } else { ofs << " {\n"; ofs << " \"name\": \"" << package.name << "\",\n"; ofs << " \"features\": ["; - for (size_t j = 0; j < package.features.size(); j++) { - const auto &feature = package.features[j]; + for (size_t j = 0; j < features.size(); j++) { + const auto &feature = features[j]; ofs << '\"' << feature << '\"'; - if (j + 1 < package.features.size()) { + if (j + 1 < features.size()) { ofs << ','; } } From 2cd8ad0f18e98316b1187d8597cba70a680856d9 Mon Sep 17 00:00:00 2001 From: cursey Date: Mon, 27 Dec 2021 01:13:16 -0800 Subject: [PATCH 6/8] Add missing const --- src/project_parser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/project_parser.cpp b/src/project_parser.cpp index 98d4c0d..00c7735 100644 --- a/src/project_parser.cpp +++ b/src/project_parser.cpp @@ -504,7 +504,7 @@ Project::Project(const Project *parent, const std::string &path, bool build) { package.name = package_str; } else if (close_bracket != std::string::npos) { package.name = package_str.substr(0, open_bracket); - auto features = package_str.substr(open_bracket + 1, close_bracket - open_bracket - 1); + 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, ',')) { From 66621a9818fb6d75784f2959063869d2a0ea5091 Mon Sep 17 00:00:00 2001 From: cursey Date: Mon, 27 Dec 2021 01:50:25 -0800 Subject: [PATCH 7/8] Fix spacing --- src/cmake_generator.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cmake_generator.cpp b/src/cmake_generator.cpp index a07143b..00aff0c 100644 --- a/src/cmake_generator.cpp +++ b/src/cmake_generator.cpp @@ -636,9 +636,9 @@ void generate_cmake(const char *path, const parser::Project *parent_project) { ofs << "]\n"; ofs << " }"; } - if (i + 1 < packages.size()) { - ofs << ','; - } + if (i + 1 < packages.size()) { + ofs << ','; + } ofs << '\n'; } From dc852b9a2f47efefc7c7ce521f2c03e5024205b6 Mon Sep 17 00:00:00 2001 From: Duncan Ogilvie Date: Mon, 27 Dec 2021 10:54:46 +0100 Subject: [PATCH 8/8] Run clang-format --- src/cmake_generator.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cmake_generator.cpp b/src/cmake_generator.cpp index 00aff0c..1c1d815 100644 --- a/src/cmake_generator.cpp +++ b/src/cmake_generator.cpp @@ -616,9 +616,9 @@ void generate_cmake(const char *path, const parser::Project *parent_project) { 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 (!vcpkg_valid_identifier(feature)) { + throw std::runtime_error("Invalid vcpkg package feature '" + feature + "'"); + } } if (features.empty()) { ofs << " \"" << package.name << '\"';