use additional env param
MODIFY
include/vcpkg/build.h
include/vcpkg/build.h
@@ -117,6 +117,29 @@ namespace vcpkg::Build
std::string create_error_message(const BuildResult build_result, const PackageSpec& spec);
std::string create_user_troubleshooting_message(const PackageSpec& spec);
+ enum class VcpkgTripletVar
+ {
+ TARGET_ARCHITECTURE = 0,
+ CMAKE_SYSTEM_NAME,
+ CMAKE_SYSTEM_VERSION,
+ PLATFORM_TOOLSET,
+ VISUAL_STUDIO_PATH,
+ CHAINLOAD_TOOLCHAIN_FILE,
+ BUILD_TYPE,
+ ENV_PASSTHROUGH,
+ };
+
+ const std::unordered_map<std::string, VcpkgTripletVar> VCPKG_OPTIONS = {
+ {"VCPKG_TARGET_ARCHITECTURE", VcpkgTripletVar::TARGET_ARCHITECTURE},
+ {"VCPKG_CMAKE_SYSTEM_NAME", VcpkgTripletVar::CMAKE_SYSTEM_NAME},
+ {"VCPKG_CMAKE_SYSTEM_VERSION", VcpkgTripletVar::CMAKE_SYSTEM_VERSION},
+ {"VCPKG_PLATFORM_TOOLSET", VcpkgTripletVar::PLATFORM_TOOLSET},
+ {"VCPKG_VISUAL_STUDIO_PATH", VcpkgTripletVar::VISUAL_STUDIO_PATH},
+ {"VCPKG_CHAINLOAD_TOOLCHAIN_FILE", VcpkgTripletVar::CHAINLOAD_TOOLCHAIN_FILE},
+ {"VCPKG_BUILD_TYPE", VcpkgTripletVar::BUILD_TYPE},
+ {"VCPKG_ENV_PASSTHROUGH", VcpkgTripletVar::ENV_PASSTHROUGH},
+ };
+
/// <summary>
/// Settings from the triplet file which impact the build environment and post-build checks
/// </summary>
@@ -135,6 +158,7 @@ namespace vcpkg::Build
Optional<fs::path> visual_studio_path;
Optional<std::string> external_toolchain_file;
Optional<ConfigurationType> build_type;
+ std::vector<std::string> passthrough_env_vars;
};
std::string make_build_env_cmd(const PreBuildInfo& pre_build_info, const Toolset& toolset);

MODIFY
include/vcpkg/sourceparagraph.h
include/vcpkg/sourceparagraph.h
@@ -23,6 +23,8 @@ namespace vcpkg
std::vector<std::string> filter_dependencies(const std::vector<Dependency>& deps, const Triplet& t);
std::vector<FeatureSpec> filter_dependencies_to_specs(const std::vector<Dependency>& deps, const Triplet& t);
+ std::vector<Features> filter_dependencies_to_features(const std::vector<vcpkg::Dependency>& deps,
+ const Triplet& t);
// zlib[uwp] becomes Dependency{"zlib", "uwp"}
std::vector<Dependency> expand_qualified_dependencies(const std::vector<std::string>& depends);

MODIFY
src/vcpkg/build.cpp
src/vcpkg/build.cpp
@@ -32,24 +32,14 @@ namespace vcpkg::Build::Command
using Dependencies::InstallPlanAction;
using Dependencies::InstallPlanType;
- static constexpr StringLiteral OPTION_CHECKS_ONLY = "--checks-only";
-
void perform_and_exit_ex(const FullPackageSpec& full_spec,
const SourceControlFileLocation& scfl,
const ParsedArguments& options,
const VcpkgPaths& paths)
{
+ const StatusParagraphs status_db = database_load_check(paths);
const PackageSpec& spec = full_spec.package_spec;
- const auto& scf = *scfl.source_control_file;
- if (Util::Sets::contains(options.switches, OPTION_CHECKS_ONLY))
- {
- const auto pre_build_info = Build::PreBuildInfo::from_triplet_file(paths, spec.triplet());
- const auto build_info = Build::read_build_info(paths.get_filesystem(), paths.build_info_file_path(spec));
- const size_t error_count =
- PostBuildLint::perform_all_checks(spec, paths, pre_build_info, build_info, scfl.source_location);
- Checks::check_exit(VCPKG_LINE_INFO, error_count == 0);
- Checks::exit_success(VCPKG_LINE_INFO);
- }
+ const SourceControlFile& scf = *scfl.source_control_file;
Checks::check_exit(VCPKG_LINE_INFO,
spec.name() == scf.core_paragraph->name,
@@ -57,7 +47,6 @@ namespace vcpkg::Build::Command
scf.core_paragraph->name,
spec.name());
- const StatusParagraphs status_db = database_load_check(paths);
const Build::BuildPackageOptions build_package_options{
Build::UseHeadVersion::NO,
Build::AllowDownloads::YES,
@@ -104,15 +93,11 @@ namespace vcpkg::Build::Command
Checks::exit_success(VCPKG_LINE_INFO);
}
- static constexpr std::array<CommandSwitch, 1> BUILD_SWITCHES = {{
- {OPTION_CHECKS_ONLY, "Only run checks, do not rebuild package"},
- }};
-
const CommandStructure COMMAND_STRUCTURE = {
Help::create_example_string("build zlib:x64-windows"),
1,
1,
- {BUILD_SWITCHES, {}},
+ {{}, {}},
nullptr,
};
@@ -230,6 +215,23 @@ namespace vcpkg::Build
}));
}
+ std::unordered_map<std::string, std::string> make_env_passthrough(const PreBuildInfo& pre_build_info)
+ {
+ std::unordered_map<std::string, std::string> env;
+
+ for (auto&& env_var : pre_build_info.passthrough_env_vars)
+ {
+ auto env_val = System::get_environment_variable(env_var);
+
+ if (env_val)
+ {
+ env[env_var] = env_val.value_or_exit(VCPKG_LINE_INFO);
+ }
+ }
+
+ return env;
+ }
+
std::string make_build_env_cmd(const PreBuildInfo& pre_build_info, const Toolset& toolset)
{
if (pre_build_info.external_toolchain_file.has_value()) return "";
@@ -274,7 +276,7 @@ namespace vcpkg::Build
return bcf;
}
- static void write_binary_control_file(const VcpkgPaths& paths, BinaryControlFile bcf)
+ static void write_binary_control_file(const VcpkgPaths& paths, const BinaryControlFile& bcf)
{
std::string start = Strings::serialize(bcf.core_paragraph);
for (auto&& feature : bcf.features)
@@ -285,23 +287,63 @@ namespace vcpkg::Build
paths.get_filesystem().write_contents(binary_control_file, start, VCPKG_LINE_INFO);
}
- static std::vector<FeatureSpec> compute_required_feature_specs(const BuildPackageConfig& config,
- const StatusParagraphs& status_db)
+ static std::vector<Features> get_dependencies(const SourceControlFile& scf,
+ const std::set<std::string>& feature_list,
+ const Triplet& triplet)
{
- const Triplet& triplet = config.triplet;
-
- const std::vector<std::string> dep_strings =
- Util::fmap_flatten(config.feature_list, [&](std::string const& feature) -> std::vector<std::string> {
+ return Util::fmap_flatten(feature_list,
+ [&](std::string const& feature) -> std::vector<Features> {
if (feature == "core")
{
- return filter_dependencies(config.scf.core_paragraph->depends, triplet);
+ return filter_dependencies_to_features(scf.core_paragraph->depends, triplet);
}
- auto maybe_feature = config.scf.find_feature(feature);
+ auto maybe_feature = scf.find_feature(feature);
Checks::check_exit(VCPKG_LINE_INFO, maybe_feature.has_value());
- return filter_dependencies(maybe_feature.get()->depends, triplet);
- });
+ return filter_dependencies_to_features(maybe_feature.get()->depends, triplet);
+ }
+ );
+ }
+
+ static std::vector<std::string> get_dependency_names(const SourceControlFile& scf,
+ const std::set<std::string>& feature_list,
+ const Triplet& triplet)
+ {
+ return Util::fmap(get_dependencies(scf, feature_list, triplet),
+ [&](const Features& feat) {
+ return feat.name;
+ }
+ );
+ }
+
+ static std::vector<fs::path> get_partials(const VcpkgPaths& paths,
+ const std::vector<std::string>& dependencies,
+ const Triplet& triplet)
+ {
+ std::vector<fs::path> ret;
+ Files::Filesystem& fs = paths.get_filesystem();
+
+ for (const std::string& dependency : dependencies)
+ {
+ fs::path partial =
+ paths.buildtrees / dependency / triplet.canonical_name() / "partial_triplet.cmake";
+ if (fs.is_regular_file(partial))
+ {
+ ret.emplace_back(std::move(partial));
+ }
+ }
+
+ return ret;
+ }
+
+ static std::vector<FeatureSpec> compute_required_feature_specs(const BuildPackageConfig& config,
+ const StatusParagraphs& status_db)
+ {
+ const Triplet& triplet = config.triplet;
+
+ const std::vector<std::string> dep_strings =
+ get_dependency_names(config.scf, config.feature_list, triplet);
auto dep_fspecs = FeatureSpec::from_strings_and_triplet(dep_strings, triplet);
Util::sort_unique_erase(dep_fspecs);
@@ -353,40 +395,19 @@ namespace vcpkg::Build
return concurrency;
}
- static ExtendedBuildResult do_build_package(const VcpkgPaths& paths,
+ static std::vector<System::CMakeVariable> get_cmake_vars(const VcpkgPaths& paths,
const PreBuildInfo& pre_build_info,
- const PackageSpec& spec,
- const std::string& abi_tag,
- const BuildPackageConfig& config)
- {
- auto& fs = paths.get_filesystem();
- const Triplet& triplet = spec.triplet();
- const auto& triplet_file_path = paths.get_triplet_file_path(spec.triplet()).u8string();
-
- if (!Strings::case_insensitive_ascii_starts_with(triplet_file_path, paths.triplets.u8string()))
- {
- System::printf("-- Loading triplet configuration from: %s\n", triplet_file_path);
- }
- if (!Strings::case_insensitive_ascii_starts_with(config.port_dir.u8string(), paths.ports.u8string()))
+ const BuildPackageConfig& config,
+ const Triplet& triplet,
+ const Toolset& toolset)
{
- System::printf("-- Installing port from location: %s\n", config.port_dir.u8string());
- }
-
#if !defined(_WIN32)
// TODO: remove when vcpkg.exe is in charge for acquiring tools. Change introduced in vcpkg v0.0.107.
// bootstrap should have already downloaded ninja, but making sure it is present in case it was deleted.
vcpkg::Util::unused(paths.get_tool_exe(Tools::NINJA));
#endif
- const fs::path& cmake_exe_path = paths.get_tool_exe(Tools::CMAKE);
const fs::path& git_exe_path = paths.get_tool_exe(Tools::GIT);
-#if defined(_WIN32)
- const fs::path& powershell_exe_path = paths.get_tool_exe("powershell-core");
- if (!fs.exists(powershell_exe_path.parent_path() / "powershell.exe"))
- {
- fs.copy(powershell_exe_path, powershell_exe_path.parent_path() / "powershell.exe", fs::copy_options::none);
- }
-#endif
std::string all_features;
for (auto& feature : config.scf.feature_paragraphs)
@@ -394,14 +415,21 @@ namespace vcpkg::Build
all_features.append(feature->name + ";");
}
- const Toolset& toolset = paths.get_toolset(pre_build_info);
+ std::vector<std::string> partials =
+ Util::fmap(
+ get_partials(paths, get_dependency_names(config.scf, config.feature_list, triplet), triplet),
+ [&](const fs::path& path)
+ {
+ return path.u8string();
+ }
+ );
std::vector<System::CMakeVariable> variables{
{"CMD", "BUILD"},
{"PORT", config.scf.core_paragraph->name},
{"CURRENT_PORT_DIR", config.port_dir},
- {"TARGET_TRIPLET", spec.triplet().canonical_name()},
- {"TARGET_TRIPLET_FILE", triplet_file_path},
+ {"TARGET_TRIPLET", triplet.canonical_name()},
+ {"TARGET_TRIPLET_FILE", paths.get_triplet_file_path(triplet).u8string()},
{"VCPKG_PLATFORM_TOOLSET", toolset.version.c_str()},
{"VCPKG_USE_HEAD_VERSION", Util::Enum::to_bool(config.build_package_options.use_head_version) ? "1" : "0"},
{"DOWNLOADS", paths.downloads},
@@ -410,6 +438,7 @@ namespace vcpkg::Build
{"FEATURES", Strings::join(";", config.feature_list)},
{"ALL_FEATURES", all_features},
{"VCPKG_CONCURRENCY", std::to_string(get_concurrency())},
+ {"VCPKG_PARTIAL_TRIPLETS", Strings::join(";", partials)},
};
if (!System::get_environment_variable("VCPKG_FORCE_SYSTEM_BINARIES").has_value())
@@ -417,9 +446,22 @@ namespace vcpkg::Build
variables.push_back({"GIT", git_exe_path});
}
+ return variables;
+ }
+
+ static std::string make_build_cmd(const VcpkgPaths& paths,
+ const PreBuildInfo& pre_build_info,
+ const BuildPackageConfig& config,
+ const Triplet& triplet)
+ {
+ const Toolset& toolset = paths.get_toolset(pre_build_info);
+ const fs::path& cmake_exe_path = paths.get_tool_exe(Tools::CMAKE);
+ std::vector<System::CMakeVariable> variables =
+ get_cmake_vars(paths, pre_build_info, config, triplet, toolset);
+
const std::string cmd_launch_cmake = System::make_cmake_cmd(cmake_exe_path, paths.ports_cmake, variables);
- auto command = make_build_env_cmd(pre_build_info, toolset);
+ std::string command = make_build_env_cmd(pre_build_info, toolset);
if (!command.empty())
{
#ifdef _WIN32
@@ -428,16 +470,93 @@ namespace vcpkg::Build
command.append(" && ");
#endif
}
+
command.append(cmd_launch_cmake);
+
+ return command;
+ }
+
+ static std::string get_triplet_abi(const VcpkgPaths& paths,
+ const PreBuildInfo& pre_build_info,
+ const Triplet& triplet)
+ {
+ static std::map<fs::path, std::string> s_hash_cache;
+
+ const fs::path triplet_file_path = paths.get_triplet_file_path(triplet);
+ const auto& fs = paths.get_filesystem();
+
+ std::string hash;
+
+ auto it_hash = s_hash_cache.find(triplet_file_path);
+ if (it_hash != s_hash_cache.end())
+ {
+ hash = it_hash->second;
+ }
+ else
+ {
+ hash = Hash::get_file_hash(fs, triplet_file_path, "SHA1");
+
+ if (auto p = pre_build_info.external_toolchain_file.get())
+ {
+ hash += "-";
+ hash += Hash::get_file_hash(fs, *p, "SHA1");
+ }
+ else if (pre_build_info.cmake_system_name == "Linux")
+ {
+ hash += "-";
+ hash += Hash::get_file_hash(fs, paths.scripts / "toolchains" / "linux.cmake", "SHA1");
+ }
+ else if (pre_build_info.cmake_system_name == "Darwin")
+ {
+ hash += "-";
+ hash += Hash::get_file_hash(fs, paths.scripts / "toolchains" / "osx.cmake", "SHA1");
+ }
+ else if (pre_build_info.cmake_system_name == "FreeBSD")
+ {
+ hash += "-";
+ hash += Hash::get_file_hash(fs, paths.scripts / "toolchains" / "freebsd.cmake", "SHA1");
+ }
+ else if (pre_build_info.cmake_system_name == "Android")
+ {
+ hash += "-";
+ hash += Hash::get_file_hash(fs, paths.scripts / "toolchains" / "android.cmake", "SHA1");
+ }
+
+ s_hash_cache.emplace(triplet_file_path, hash);
+ }
+
+ return hash;
+ }
+
+ static ExtendedBuildResult do_build_package(const VcpkgPaths& paths,
+ const PreBuildInfo& pre_build_info,
+ const PackageSpec& spec,
+ const std::string& abi_tag,
+ const BuildPackageConfig& config)
+ {
+ auto& fs = paths.get_filesystem();
+ const Triplet& triplet = spec.triplet();
+ const auto& triplet_file_path = paths.get_triplet_file_path(spec.triplet()).u8string();
+
+ if (!Strings::case_insensitive_ascii_starts_with(triplet_file_path, paths.triplets.u8string()))
+ {
+ System::printf("-- Loading triplet configuration from: %s\n", triplet_file_path);
+ }
+ if (!Strings::case_insensitive_ascii_starts_with(config.port_dir.u8string(), paths.ports.u8string()))
+ {
+ System::printf("-- Installing port from location: %s\n", config.port_dir.u8string());
+ }
+
const auto timer = Chrono::ElapsedTimer::create_started();
- const int return_code = System::cmd_execute_clean(
- command,
- {}
-#ifdef _WIN32
- ,
- powershell_exe_path.parent_path().u8string() + ";"
-#endif
- );
+
+ std::string command =
+ make_build_cmd(paths, pre_build_info, config, triplet);
+ std::unordered_map<std::string, std::string> env =
+ make_env_passthrough(pre_build_info);
+
+ const int return_code =
+ System::cmd_execute_clean(command, env);
+
const auto buildtimeus = timer.microseconds();
const auto spec_string = spec.to_string();
@@ -711,7 +830,7 @@ namespace vcpkg::Build
{
System::print2("Using cached binary package: ", archive_path.u8string(), "\n");
- auto archive_result = decompress_archive(paths, spec, archive_path);
+ int archive_result = decompress_archive(paths, spec, archive_path);
if (archive_result != 0)
{
@@ -946,47 +1065,33 @@ namespace vcpkg::Build
const std::string variable_name = s.at(0);
const std::string variable_value = variable_with_no_value ? "" : s.at(1);
- if (variable_name == "VCPKG_TARGET_ARCHITECTURE")
+ auto maybe_option = VCPKG_OPTIONS.find(variable_name);
+ if (maybe_option != VCPKG_OPTIONS.end())
{
- pre_build_info.target_architecture = variable_value;
- continue;
- }
-
- if (variable_name == "VCPKG_CMAKE_SYSTEM_NAME")
+ switch (maybe_option->second)
{
+ case VcpkgTripletVar::TARGET_ARCHITECTURE :
+ pre_build_info.target_architecture = variable_value;
+ break;
+ case VcpkgTripletVar::CMAKE_SYSTEM_NAME :
pre_build_info.cmake_system_name = variable_value;
- continue;
- }
-
- if (variable_name == "VCPKG_CMAKE_SYSTEM_VERSION")
- {
+ break;
+ case VcpkgTripletVar::CMAKE_SYSTEM_VERSION :
pre_build_info.cmake_system_version = variable_value;
- continue;
- }
-
- if (variable_name == "VCPKG_PLATFORM_TOOLSET")
- {
+ break;
+ case VcpkgTripletVar::PLATFORM_TOOLSET :
pre_build_info.platform_toolset =
variable_value.empty() ? nullopt : Optional<std::string>{variable_value};
- continue;
- }
-
- if (variable_name == "VCPKG_VISUAL_STUDIO_PATH")
- {
+ break;
+ case VcpkgTripletVar::VISUAL_STUDIO_PATH :
pre_build_info.visual_studio_path =
variable_value.empty() ? nullopt : Optional<fs::path>{variable_value};
- continue;
- }
-
- if (variable_name == "VCPKG_CHAINLOAD_TOOLCHAIN_FILE")
- {
+ break;
+ case VcpkgTripletVar::CHAINLOAD_TOOLCHAIN_FILE :
pre_build_info.external_toolchain_file =
variable_value.empty() ? nullopt : Optional<std::string>{variable_value};
- continue;
- }
-
- if (variable_name == "VCPKG_BUILD_TYPE")
- {
+ break;
+ case VcpkgTripletVar::BUILD_TYPE :
if (variable_value.empty())
pre_build_info.build_type = nullopt;
else if (Strings::case_insensitive_ascii_equals(variable_value, "debug"))
@@ -996,61 +1101,24 @@ namespace vcpkg::Build
else
Checks::exit_with_message(
VCPKG_LINE_INFO, "Unknown setting for VCPKG_BUILD_TYPE: %s", variable_value);
- continue;
- }
-
- Checks::exit_with_message(VCPKG_LINE_INFO, "Unknown variable name %s", line);
- }
-
- pre_build_info.triplet_abi_tag = [&]() {
- const auto& fs = paths.get_filesystem();
- static std::map<fs::path, std::string> s_hash_cache;
-
- auto it_hash = s_hash_cache.find(triplet_file_path);
- if (it_hash != s_hash_cache.end())
- {
- return it_hash->second;
- }
- auto hash = Hash::get_file_hash(fs, triplet_file_path, "SHA1");
-
- if (auto p = pre_build_info.external_toolchain_file.get())
- {
- hash += "-";
- hash += Hash::get_file_hash(fs, *p, "SHA1");
+ break;
+ case VcpkgTripletVar::ENV_PASSTHROUGH :
+ pre_build_info.passthrough_env_vars = Strings::split(variable_value, ";");
+ break;
}
- else if (pre_build_info.cmake_system_name.empty() ||
- pre_build_info.cmake_system_name == "WindowsStore")
- {
- hash += "-";
- hash += Hash::get_file_hash(fs, paths.scripts / "toolchains" / "windows.cmake", "SHA1");
}
- else if (pre_build_info.cmake_system_name == "Linux")
- {
- hash += "-";
- hash += Hash::get_file_hash(fs, paths.scripts / "toolchains" / "linux.cmake", "SHA1");
- }
- else if (pre_build_info.cmake_system_name == "Darwin")
- {
- hash += "-";
- hash += Hash::get_file_hash(fs, paths.scripts / "toolchains" / "osx.cmake", "SHA1");
- }
- else if (pre_build_info.cmake_system_name == "FreeBSD")
+ else
{
- hash += "-";
- hash += Hash::get_file_hash(fs, paths.scripts / "toolchains" / "freebsd.cmake", "SHA1");
+ Checks::exit_with_message(VCPKG_LINE_INFO, "Unknown variable name %s", line);
}
- else if (pre_build_info.cmake_system_name == "Android")
- {
- hash += "-";
- hash += Hash::get_file_hash(fs, paths.scripts / "toolchains" / "android.cmake", "SHA1");
}
- s_hash_cache.emplace(triplet_file_path, hash);
- return hash;
- }();
+ pre_build_info.triplet_abi_tag =
+ get_triplet_abi(paths, pre_build_info, triplet);
return pre_build_info;
}
+
ExtendedBuildResult::ExtendedBuildResult(BuildResult code) : code(code) {}
ExtendedBuildResult::ExtendedBuildResult(BuildResult code, std::unique_ptr<BinaryControlFile>&& bcf)
: code(code), binary_control_file(std::move(bcf))

MODIFY
src/vcpkg/sourceparagraph.cpp
src/vcpkg/sourceparagraph.cpp
@@ -238,6 +238,28 @@ namespace vcpkg
return ret;
}
+ std::vector<Features> filter_dependencies_to_features(const std::vector<vcpkg::Dependency>& deps,
+ const Triplet& t)
+ {
+ std::vector<Features> ret;
+ for (auto&& dep : deps)
+ {
+ auto qualifiers = Strings::split(dep.qualifier, "&");
+ if (std::all_of(qualifiers.begin(), qualifiers.end(), [&](const std::string& qualifier) {
+ if (qualifier.empty()) return true;
+ if (qualifier[0] == '!')
+ {
+ return t.canonical_name().find(qualifier.substr(1)) == std::string::npos;
+ }
+ return t.canonical_name().find(qualifier) != std::string::npos;
+ }))
+ {
+ ret.emplace_back(dep.depend);
+ }
+ }
+ return ret;
+ }
+
std::vector<FeatureSpec> filter_dependencies_to_specs(const std::vector<Dependency>& deps, const Triplet& t)
{
return FeatureSpec::from_strings_and_triplet(filter_dependencies(deps, t), t);

use additional env param