Skip to content
Draft
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/vcpkg/base/contractual-constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,7 @@ namespace vcpkg
inline constexpr StringLiteral CMakeVariableEditable = "_VCPKG_EDITABLE";
inline constexpr StringLiteral CMakeVariableEnvPassthrough = "VCPKG_ENV_PASSTHROUGH";
inline constexpr StringLiteral CMakeVariableEnvPassthroughUntracked = "VCPKG_ENV_PASSTHROUGH_UNTRACKED";
inline constexpr StringLiteral CMakeVariableEnvSetupScripts = "VCPKG_ENVIRONMENT_SETUP_SCRIPTS";
inline constexpr StringLiteral CMakeVariableFeatures = "FEATURES";
inline constexpr StringLiteral CMakeVariableFilename = "FILENAME";
inline constexpr StringLiteral CMakeVariableGit = "GIT";
Expand Down
4 changes: 4 additions & 0 deletions include/vcpkg/base/message-data.inc.h
Original file line number Diff line number Diff line change
Expand Up @@ -1840,6 +1840,10 @@ DECLARE_MESSAGE(InvalidCommentStyle,
"comments.")
DECLARE_MESSAGE(InvalidCommitId, (msg::commit_sha), "", "Invalid commit id: {commit_sha}")
DECLARE_MESSAGE(InvalidDefaultFeatureName, (), "", "'default' is a reserved feature name")
DECLARE_MESSAGE(InvalidEnvSetupScripts, (msg::path),
"",
"Variable VCPKG_ENVIRONMENT_SETUP_SCRIPTS contains invalid file path: '{path}'. The value must be "
"an absolute path to an existent file.")
DECLARE_MESSAGE(InvalidFeature,
(),
"",
Expand Down
2 changes: 0 additions & 2 deletions include/vcpkg/base/system.process.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,7 @@ namespace vcpkg
ExpectedL<int> cmd_execute(const Command& cmd);
ExpectedL<int> cmd_execute(const Command& cmd, const ProcessLaunchSettings& settings);

#if defined(_WIN32)
Environment cmd_execute_and_capture_environment(const Command& cmd, const Environment& env);
#endif

void cmd_execute_background(const Command& cmd_line);

Expand Down
6 changes: 4 additions & 2 deletions include/vcpkg/commands.build.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,10 @@ namespace vcpkg
Optional<std::string> public_abi_override;
std::vector<std::string> passthrough_env_vars;
std::vector<std::string> passthrough_env_vars_tracked;
std::vector<std::string> environment_setup_scripts;
std::vector<Path> hash_additional_files;

Comment thread
Neumann-A marked this conversation as resolved.
Outdated

Comment thread
Neumann-A marked this conversation as resolved.
Outdated
Optional<Path> gamedk_latest_path;

Path toolchain_file() const;
Expand All @@ -143,6 +146,7 @@ namespace vcpkg
};

vcpkg::Command make_build_env_cmd(const PreBuildInfo& pre_build_info, const Toolset& toolset);
vcpkg::Command make_setup_env_cmd(const VcpkgPaths& paths, const Path& script);

struct ExtendedBuildResult
{
Expand Down Expand Up @@ -284,15 +288,13 @@ namespace vcpkg

const TripletMapEntry& get_triplet_cache(const ReadOnlyFilesystem& fs, const Path& p) const;

#if defined(_WIN32)
struct EnvMapEntry
{
std::unordered_map<std::string, std::string> env_map;
Cache<vcpkg::Command, Environment, CommandLess> cmd_cache;
};

Cache<std::vector<std::string>, EnvMapEntry> envs;
#endif

bool m_compiler_tracking;
};
Expand Down
18 changes: 12 additions & 6 deletions src/vcpkg/base/system.process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1256,38 +1256,41 @@ namespace

namespace vcpkg
{
#if defined(_WIN32)
Environment cmd_execute_and_capture_environment(const Command& cmd, const Environment& env)
{
static StringLiteral magic_string = "cdARN4xjKueKScMy9C6H";

Command actual_cmd = cmd;
#ifdef _WIN32
actual_cmd.raw_arg(Strings::concat(" & echo ", magic_string, " & set"));

#else
actual_cmd.raw_arg(Strings::concat(" && echo ", magic_string, " && printenv"));
#endif
Debug::print("command line: ", actual_cmd.command_line(), "\n");

RedirectedProcessLaunchSettings settings;
settings.environment = env;
settings.create_new_console = CreateNewConsole::Yes;
auto maybe_rc_output = cmd_execute_and_capture_output(actual_cmd, settings);

Comment thread
Neumann-A marked this conversation as resolved.
Outdated
Comment thread
Neumann-A marked this conversation as resolved.
Outdated
if (!maybe_rc_output)
{
Checks::msg_exit_with_error(
VCPKG_LINE_INFO, msg::format(msgVcvarsRunFailed).append_raw("\n").append(maybe_rc_output.error()));
VCPKG_LINE_INFO, msg::format(msgVcvarsRunFailed).append_raw("\n").append(maybe_rc_output.error())); // This msg is incorrect
}

auto& rc_output = maybe_rc_output.value_or_exit(VCPKG_LINE_INFO);
Debug::print(rc_output.output, "\n");
if (rc_output.exit_code != 0)
{
Checks::msg_exit_with_error(
VCPKG_LINE_INFO, msgVcvarsRunFailedExitCode, msg::exit_code = rc_output.exit_code);
VCPKG_LINE_INFO, msgVcvarsRunFailedExitCode, msg::exit_code = rc_output.exit_code); // This msg is incorrect
}

auto it = Strings::search(rc_output.output, magic_string);
const char* const last = rc_output.output.data() + rc_output.output.size();

Checks::check_exit(VCPKG_LINE_INFO, it != last);
Checks::check_exit(VCPKG_LINE_INFO, it != last); // magic string not found !
// find the first non-whitespace character after the magic string
it = std::find_if_not(it + magic_string.size(), last, ::isspace);
Checks::check_exit(VCPKG_LINE_INFO, it != last);
Expand All @@ -1299,7 +1302,11 @@ namespace vcpkg
auto equal_it = std::find(it, last, '=');
if (equal_it == last) break;
StringView variable_name(it, equal_it);
#ifdef _WIN32
auto newline_it = std::find(equal_it + 1, last, '\r');
#else
auto newline_it = std::find(equal_it + 1, last, '\n');
#endif
if (newline_it == last) break;
StringView value(equal_it + 1, newline_it);

Expand All @@ -1311,7 +1318,6 @@ namespace vcpkg

return new_env;
}
#endif
} // namespace vcpkg

namespace
Expand Down
1 change: 1 addition & 0 deletions src/vcpkg/cmakevars.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ VCPKG_ENV_PASSTHROUGH=${VCPKG_ENV_PASSTHROUGH}
VCPKG_ENV_PASSTHROUGH_UNTRACKED=${VCPKG_ENV_PASSTHROUGH_UNTRACKED}
VCPKG_LOAD_VCVARS_ENV=${VCPKG_LOAD_VCVARS_ENV}
VCPKG_DISABLE_COMPILER_TRACKING=${VCPKG_DISABLE_COMPILER_TRACKING}
VCPKG_ENVIRONMENT_SETUP_SCRIPTS=${VCPKG_ENVIRONMENT_SETUP_SCRIPTS}
VCPKG_HASH_ADDITIONAL_FILES=${VCPKG_HASH_ADDITIONAL_FILES}
VCPKG_XBOX_CONSOLE_TARGET=${VCPKG_XBOX_CONSOLE_TARGET}
Z_VCPKG_GameDKLatest=$ENV{GameDKLatest}
Expand Down
77 changes: 70 additions & 7 deletions src/vcpkg/commands.build.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -470,16 +470,47 @@ namespace vcpkg
return base_env.cmd_cache.get_lazy(build_env_cmd, [&]() {
const Path& powershell_exe_path = paths.get_tool_exe("powershell-core", out_sink);
auto clean_env = get_modified_clean_environment(base_env.env_map, powershell_exe_path.parent_path());
if (build_env_cmd.empty())
return clean_env;
else
return cmd_execute_and_capture_environment(build_env_cmd, clean_env);
auto action_env = build_env_cmd.empty() ? clean_env : cmd_execute_and_capture_environment(build_env_cmd, clean_env);
for(const auto& env_setup_script : pre_build_info.environment_setup_scripts)
{
const auto env_setup_cmd = make_setup_env_cmd(paths, env_setup_script);
if(vcpkg::Strings::ends_with(env_setup_script,".cmake"))
{
cmd_execute(env_setup_cmd, default_working_directory, action_env);
}
else
{
action_env = cmd_execute_and_capture_environment(env_setup_cmd, action_env);
}

}
return action_env;
});
}
#else
const Environment& EnvCache::get_action_env(const VcpkgPaths&, const PreBuildInfo&, const Toolset&)
const Environment& EnvCache::get_action_env(const VcpkgPaths& paths, const PreBuildInfo& pre_build_info, const Toolset&)
{
return get_clean_environment();
auto action_env = get_clean_environment();
const auto& base_env = envs.get_lazy(pre_build_info.environment_setup_scripts,[] () {return EnvMapEntry{};});

// I think this should be done differently but I don't exactly know how to build the commands beforehand.
// Can I stack base_env.cmd_cache.get_lazy in a loop?

return base_env.cmd_cache.get_lazy(vcpkg::Command{}, [&]() {
for(const auto& env_setup_script : pre_build_info.environment_setup_scripts)
{
const auto env_setup_cmd = make_setup_env_cmd(paths, env_setup_script);
if(vcpkg::Strings::ends_with(env_setup_script,".cmake"))
{
cmd_execute(env_setup_cmd, default_working_directory, action_env);
}
else
{
action_env = cmd_execute_and_capture_environment(env_setup_cmd, action_env);
}
}
return action_env;
});
}
#endif

Expand Down Expand Up @@ -589,6 +620,33 @@ namespace vcpkg
#endif
}

vcpkg::Command make_setup_env_cmd(const VcpkgPaths& paths, const Path& script)
{
vcpkg::Command env_setup_cmd;
const auto& fs = paths.get_filesystem();

if(script.is_relative() || !fs.is_regular_file(script)) {
// Throw error
Comment thread
Neumann-A marked this conversation as resolved.
Outdated
Checks::msg_exit_with_message(VCPKG_LINE_INFO, msgInvalidEnvSetupScripts, msg::path = script);
}

if(script.extension() == ".cmake")
{
env_setup_cmd = vcpkg::make_cmake_cmd(paths, script, {});
}
else
{
#ifdef _WIN32
env_setup_cmd = vcpkg::Command{"cmd"}.string_arg("/d").string_arg("/c");
env_setup_cmd.raw_arg(fmt::format(R"("{}" 2>&1 <NUL)",script));
#else
env_setup_cmd = vcpkg::Command{"."}.raw_arg(fmt::format(R"({} 2>&1 </dev/null)",script));
#endif

}
return env_setup_cmd;
}

static std::vector<PackageSpec> fspecs_to_pspecs(View<FeatureSpec> fspecs)
{
std::set<PackageSpec> set;
Expand Down Expand Up @@ -837,7 +895,7 @@ namespace vcpkg

bool PreBuildInfo::using_vcvars() const
{
return (!external_toolchain_file.has_value() || load_vcvars_env) &&
return (!external_toolchain_file.has_value() || !environment_setup_scripts.empty() || load_vcvars_env) &&
(cmake_system_name.empty() || cmake_system_name == "WindowsStore");
}

Expand Down Expand Up @@ -1833,6 +1891,11 @@ namespace vcpkg
Util::Vectors::append(&passthrough_env_vars, Strings::split(*value, ';'));
}

if (auto value = Util::value_if_set_and_nonempty(cmakevars, CMakeVariableHashAdditionalFiles))
{
Util::Vectors::append(&environment_setup_scripts, Strings::split(*value, ';'));
}

Util::assign_if_set_and_nonempty(public_abi_override, cmakevars, CMakeVariablePublicAbiOverride);
if (auto value = Util::value_if_set_and_nonempty(cmakevars, CMakeVariableHashAdditionalFiles))
{
Expand Down
6 changes: 5 additions & 1 deletion src/vcpkg/vcpkgcmdarguments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -710,8 +710,12 @@ namespace vcpkg
obj.insert(JsonIdVcpkgDisableMetrics, Json::Value::boolean(true));
}

// Remove newlines from JSON so that environment can be captured on !windows
auto json_str = Json::stringify(obj, Json::JsonStyle::with_spaces(0));
std::replace(json_str.begin(), json_str.end(), '\n',' ');

set_environment_variable(EnvironmentVariableXVcpkgRecursiveData,
Json::stringify(obj, Json::JsonStyle::with_spaces(0)));
std::move(json_str));
}
}

Expand Down