Add VCPKG support for USVFS. (#149)

This commit is contained in:
Mikaël Capelle
2025-05-22 19:02:43 +02:00
committed by GitHub
parent 1087129aac
commit bd6a03d2f8
11 changed files with 195 additions and 51 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ if (!$root) {
$output = if ($Verbose) { "Out-Default" } else { "Out-Null" }
cmake -B $root/build $root | & $output
cmake -B $root/build -G "Visual Studio 17 2022" $root | & $output
$installationPath = & $root\third-party\bin\vswhere.exe -products * -nologo -prerelease -latest -property installationPath
if (! $?) {
+1
View File
@@ -155,6 +155,7 @@ install_licenses =
install_pythoncore =
install_translations =
vs =
vcpkg =
qt_install =
qt_bin =
qt_translations =
+2 -1
View File
@@ -509,6 +509,7 @@ namespace mob {
set_path_if_empty("pf_x86", find_program_files_x86);
set_path_if_empty("pf_x64", find_program_files_x64);
set_path_if_empty("vs", find_vs);
set_path_if_empty("vcpkg", find_vcpkg); // set after vs as it will use the VS
set_path_if_empty("qt_install", find_qt);
set_path_if_empty("temp_dir", find_temp_dir);
set_path_if_empty("patches", find_in_root("patches"));
@@ -530,7 +531,7 @@ namespace mob {
resolve_path("install", p.prefix(), "install");
resolve_path("install_installer", p.install(), "installer");
resolve_path("install_bin", p.install(), "bin");
resolve_path("install_libs", p.install(), "libs");
resolve_path("install_libs", p.install(), "lib");
resolve_path("install_pdbs", p.install(), "pdb");
resolve_path("install_dlls", p.install_bin(), "dlls");
resolve_path("install_loot", p.install_bin(), "loot");
+1
View File
@@ -264,6 +264,7 @@ namespace mob {
VALUE(install_translations);
VALUE(vs);
VALUE(vcpkg);
VALUE(qt_install);
VALUE(qt_bin);
VALUE(qt_translations);
+18
View File
@@ -254,6 +254,24 @@ namespace mob {
}
}
fs::path find_vcpkg()
{
const auto env_path = this_env::get().get("VCPKG_ROOT");
if (!env_path.empty()) {
return fs::absolute(env_path);
}
const auto vs_path = conf().path().vs();
const auto vcpkg_vs_path = vs_path / "VC" / "vcpkg";
if (!exists(vcpkg_vs_path)) {
gcx().bail_out(context::conf, "vcpkg is not part of VS installation at {}",
vs_path);
}
return vcpkg_vs_path;
}
fs::path find_qt()
{
// check from the ini first
+5
View File
@@ -33,6 +33,11 @@ namespace mob {
//
fs::path find_vs();
// returns the absolute path to VCPKG root directory to be used as VCPKG_ROOT when
// building
//
fs::path find_vcpkg();
// returns the absolute path to Qt's root directory, the one that contains
// bin, include, etc.; bails if not found
//
+1 -1
View File
@@ -166,7 +166,7 @@ namespace mob {
for (auto& c : commands)
all_groups.push_back(c->group());
// vs reports a no-op on the left side of the command, which is incorrect
// vs reports a no-op on the left side of the command, which is incorrect
#pragma warning(suppress : 4548)
auto cli = (all_groups, command::common_options_group());
auto pr = clipp::parse(args, cli);
+1
View File
@@ -672,6 +672,7 @@ namespace mob::tasks {
void fetch_from_source();
void build_and_install_from_source();
cmake create_cmake_tool(arch, cmake::ops = cmake::generate) const;
msbuild create_msbuild_tool(arch, msbuild::ops = msbuild::build,
config = config::release) const;
};
+22 -24
View File
@@ -40,6 +40,11 @@ namespace mob::tasks {
return;
}
if (is_set(c, clean::reconfigure)) {
run_tool(create_cmake_tool(arch::x64));
run_tool(create_cmake_tool(arch::x86));
}
if (is_set(c, clean::rebuild)) {
// msbuild clean
run_tool(create_msbuild_tool(arch::x86, msbuild::clean,
@@ -69,35 +74,28 @@ namespace mob::tasks {
void usvfs::build_and_install_from_source()
{
run_tool(create_msbuild_tool(arch::x86));
run_tool(create_cmake_tool(arch::x64));
run_tool(create_cmake_tool(arch::x86));
run_tool(create_msbuild_tool(arch::x64));
run_tool(create_msbuild_tool(arch::x86));
}
cmake usvfs::create_cmake_tool(arch a, cmake::ops o) const
{
return std::move(
cmake(o)
.root(source_path())
.def("CMAKE_INSTALL_PREFIX:PATH", conf().path().install())
.generator(cmake::vs)
.preset(a == arch::x64 ? "vs2022-windows-x64" : "vs2022-windows-x86")
.arg("-DBUILD_TESTING=OFF"));
}
msbuild usvfs::create_msbuild_tool(arch a, msbuild::ops o, config c) const
{
// usvfs doesn't use "Win32" for 32-bit, it uses "x86"
//
// note that usvfs_proxy has a custom build step in Release that runs
// usvfs/vsbuild/stage_helper.cmd, which copies everything into
// install/
const std::string plat = (a == arch::x64 ? "x64" : "x86");
// udis requires python in its custom build step, so make sure it's on the
// path
//
// BOOST_PATH is in the env because external_dependencies.props will
// use it if it exists or reverts to a hardcoded path which might not be using
// the same version as mob if it wasn't updated
return std::move(
msbuild(o)
.platform(plat)
.configuration(c)
.targets({"usvfs_proxy"})
.solution(source_path() / "vsbuild" / "usvfs.sln")
.env(env::vs(a)
.prepend_path(python::build_path())
.set("BOOST_PATH", path_to_utf8(boost::source_path()))));
const std::string vsbuild = (a == arch::x64 ? "vsbuild64" : "vsbuild32");
return std::move(msbuild(o).architecture(a).configuration(c).solution(
source_path() / vsbuild / "usvfs.sln"));
}
} // namespace mob::tasks
+113 -24
View File
@@ -4,8 +4,23 @@
namespace mob {
namespace {
std::string config_to_string(config c)
{
switch (c) {
case config::debug:
return "Debug";
case config::release:
return "Release";
case config::relwithdebinfo:
return "RelWithDebInfo";
}
gcx().bail_out(context::generic, "unknow configuration type {}", c);
}
} // namespace
cmake::cmake(ops o)
: basic_process_runner("cmake"), op_(o), gen_(jom), arch_(arch::def)
: basic_process_runner("cmake"), op_(o), gen_(vs), arch_(arch::def)
{
}
@@ -62,6 +77,12 @@ namespace mob {
return *this;
}
cmake& cmake::preset(const std::string& s)
{
preset_ = s;
return *this;
}
cmake& cmake::arg(std::string s)
{
std::replace(s.begin(), s.end(), '\\', '/');
@@ -75,6 +96,24 @@ namespace mob {
return *this;
}
cmake& cmake::targets(const std::string& target)
{
targets_ = {target};
return *this;
}
cmake& cmake::targets(const std::vector<std::string>& targets)
{
targets_ = targets;
return *this;
}
cmake& cmake::configuration(mob::config config)
{
config_ = config;
return *this;
}
cmake& cmake::cmd(const std::string& s)
{
cmd_ = s;
@@ -110,6 +149,16 @@ namespace mob {
break;
}
case build: {
do_build();
break;
}
case install: {
do_install();
break;
}
default: {
cx().bail_out(context::generic, "bad cmake op {}", op_);
}
@@ -126,43 +175,83 @@ namespace mob {
auto p = process()
.stdout_encoding(encodings::utf8)
.stderr_encoding(encodings::utf8)
.binary(binary())
.arg("-DCMAKE_BUILD_TYPE=Release")
.arg("-DCMAKE_INSTALL_MESSAGE=" +
conf_cmake::to_string(conf().cmake().install_message()))
.arg("--log-level=ERROR")
.arg("--no-warn-unused-cli");
.binary(binary());
if (genstring_.empty()) {
// there's always a generator name, but some generators don't need
// an architecture flag, like jom, so get_arch() might return an empty
// string
p.arg("-G", "\"" + g.name + "\"")
.arg(g.get_arch(arch_))
.arg(g.get_host(conf().cmake().host()));
}
else {
// verbatim generator string
p.arg("-G", "\"" + genstring_ + "\"");
if (!preset_.empty()) {
p = p.arg("--preset").arg(preset_);
}
p = p.arg("-DCMAKE_INSTALL_MESSAGE=" +
conf_cmake::to_string(conf().cmake().install_message()))
.arg("--log-level=ERROR")
.arg("--no-warn-unused-cli");
// prefix
if (!prefix_.empty())
p.arg("-DCMAKE_INSTALL_PREFIX=", prefix_);
p.args(args_);
// `..` by default, overriden by cmd()
if (cmd_.empty())
p.arg("..");
else
p.arg(cmd_);
if (preset_.empty()) {
p.env(env::vs(arch_).set("CXXFLAGS", "/wd4566")).cwd(build_path());
if (genstring_.empty()) {
// there's always a generator name, but some generators don't need
// an architecture flag, like jom, so get_arch() might return an empty
// string
p.arg("-G", "\"" + g.name + "\"")
.arg(g.get_arch(arch_))
.arg(g.get_host(conf().cmake().host()));
}
else {
// verbatim generator string
p.arg("-G", "\"" + genstring_ + "\"");
}
// `..` by default, overriden by cmd()
if (cmd_.empty())
p.arg("..");
else
p.arg(cmd_);
}
p.env(env::vs(arch_)
.set("CXXFLAGS", "/wd4566")
.set("VCPKG_ROOT", absolute(conf().path().vcpkg()).string()))
.cwd(preset_.empty() ? build_path() : root_);
execute_and_join(p);
}
void cmake::do_build()
{
auto p = process()
.stdout_encoding(encodings::utf8)
.stderr_encoding(encodings::utf8)
.binary(binary())
.arg("--build")
.arg(build_path())
.arg("--config")
.arg(config_to_string(config_));
for (auto& target : targets_) {
p = p.arg("--target").arg(target);
}
execute_and_join(p);
}
void cmake::do_install()
{
execute_and_join(process()
.stdout_encoding(encodings::utf8)
.stderr_encoding(encodings::utf8)
.binary(binary())
.arg("--install")
.arg(build_path())
.arg("--config")
.arg(config_to_string(config_)));
}
void cmake::do_clean()
{
cx().trace(context::rebuild, "deleting all generator directories");
+30
View File
@@ -29,6 +29,12 @@ namespace mob {
// generates the build files
generate = 1,
// build
build,
// install
install,
// cleans the build files so they're regenerated from scratch
clean
};
@@ -54,6 +60,15 @@ namespace mob {
//
cmake& root(const fs::path& p);
// set the targets for build
//
cmake& targets(const std::string& target);
cmake& targets(const std::vector<std::string>& target);
// set the configuration to build or install
//
cmake& configuration(mob::config config);
// overrides the directory in which cmake will write build files
//
// by default, this is a directory inside what was given in root() with a
@@ -75,6 +90,10 @@ namespace mob {
cmake& def(const std::string& name, const fs::path& p);
cmake& def(const std::string& name, const char* s);
// set a preset to run with cmake --preset
//
cmake& preset(const std::string& s);
// adds an arbitrary argument, passed verbatim
//
cmake& arg(std::string s);
@@ -146,6 +165,9 @@ namespace mob {
// what run() does
ops op_;
// preset to run
std::string preset_;
// directory where CMakeLists.txt is
fs::path root_;
@@ -156,6 +178,12 @@ namespace mob {
// passed as -DCMAKE_INSTALL_PREFIX
fs::path prefix_;
// targets
std::vector<std::string> targets_;
// configuration
mob::config config_{mob::config::relwithdebinfo};
// passed verbatim
std::vector<std::string> args_;
@@ -175,6 +203,8 @@ namespace mob {
// runs cmake
//
void do_generate();
void do_build();
void do_install();
// returns a list of generators handled by this tool, same ones as in the
// `generators` enum on top