Skip to content

Commit

Permalink
Allow building configurations other than RelWithDebInfo.
Browse files Browse the repository at this point in the history
  • Loading branch information
Holt59 committed Jun 9, 2024
1 parent 77bd210 commit 2de230c
Show file tree
Hide file tree
Showing 13 changed files with 206 additions and 162 deletions.
15 changes: 8 additions & 7 deletions mob.ini
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,14 @@ super = cmake_common modorganizer* githubpp
plugins = check_fnis bsapacker bsa_extractor diagnose_basic installer_* plugin_python preview_base preview_bsa tool_* game_*

[task]
enabled = true
mo_org = ModOrganizer2
mo_branch = master
mo_fallback =
no_pull = false
ignore_ts = false
revert_ts = false
enabled = true
mo_org = ModOrganizer2
mo_branch = master
mo_fallback =
no_pull = false
ignore_ts = false
revert_ts = false
configuration = RelWithDebInfo

git_url_prefix = https://github.com/
git_shallow = true
Expand Down
9 changes: 5 additions & 4 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ aqt install-qt --outputdir "C:\Qt" windows desktop 6.7.0 win64_msvc2019_64 -m qt
- Optional:
- Qt Source Files
- Qt Debug Files

### Visual Studio
- Install Visual Studio 2022 ([Installer](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community&channel=Release&version=VS2022&source=VSLandingPage&cid=2030&passive=false))
- Desktop development with C++
Expand Down Expand Up @@ -141,9 +141,10 @@ Inside the INI file are `[sections]` and `key = value` pairs. The `[task]` secti
### `[task]`
Options for individual tasks. Can be `[task_name:task]`, where `task_name` is the name of a task (see `mob list`) , `super` for all MO tasks or a glob like `installer_*`.

| Option | Type | Description |
| --- | --- | --- |
| `enabled` | bool | Whether this task is enabled. Disabled tasks are never built. When specifying task names with `mob build task1 task2...`, all tasks except those given are turned off. |
| Option | Type | Description |
| --- | --- | --- |
| `enabled` | bool | Whether this task is enabled. Disabled tasks are never built. When specifying task names with `mob build task1 task2...`, all tasks except those given are turned off. |
| `configuration` | enum | Which configuration to build, should be one of Debug, Release or RelWithDebInfo with RelWithDebInfo being the default.|

#### Common git options
Unless otherwise stated, applies to any task that is a git repo.
Expand Down
99 changes: 66 additions & 33 deletions src/core/conf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,40 @@ namespace mob::details {
g_tasks[task_name][key] = std::move(value);
}

// check if the two given string are equals case-insensitive
//
bool case_insensitive_equals(std::string_view lhs, std::string_view rhs)
{
// _strcmpi does not have a n-overload, and since string_view is not
// necessarily null-terminated, _strmcpi cannot be safely used
return std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs),
std::end(rhs), [](auto&& c1, auto&& c2) {
return ::tolower(c1) == ::tolower(c2);
});
}

// read a CMake constant from the configuration
//
template <typename T>
T parse_cmake_value(std::string_view section, std::string_view key,
std::string_view value,
std::unordered_map<T, std::string_view> const& values)
{
for (const auto& [value_c, value_s] : values) {
if (case_insensitive_equals(value_s, value)) {
return value_c;
}
}

// build a string containing allowed value for logging
std::vector<std::string_view> values_s;
for (const auto& [value_c, value_s] : values) {
values_s.push_back(value_s);
}
gcx().bail_out(context::conf, "bad value '{}' for {}/{} (expected one of {})",
value, section, key, join(values_s, ", ", std::string{}));
}

} // namespace mob::details

namespace mob {
Expand Down Expand Up @@ -666,57 +700,56 @@ namespace mob {
return details::g_dry;
}

conf_task::conf_task(std::vector<std::string> names) : names_(std::move(names)) {}
// use appropriate case for the below constants since we will be using them in
// to_string, although most of cmake and msbuild is case-insensitive so it will
// not matter much in the end

std::string conf_task::get(std::string_view key) const
static std::unordered_map<conf_cmake::constant, std::string_view> constant_values{
{conf_cmake::always, "ALWAYS"},
{conf_cmake::lazy, "LAZY"},
{conf_cmake::never, "NEVER"}};

std::string conf_cmake::to_string(constant c)
{
return details::get_string_for_task(names_, key);
return std::string{constant_values.at(c)};
}

bool conf_task::get_bool(std::string_view key) const
conf_cmake::conf_cmake() : conf_section("cmake") {}

conf_cmake::constant conf_cmake::install_message() const
{
return details::get_bool_for_task(names_, key);
return details::parse_cmake_value(
name(), "install_message", details::get_string(name(), "install_message"),
constant_values);
}

bool conf_cmake::cmake_constant::is_equivalent(std::string_view other) const
std::string conf_cmake::host() const
{
// _strcmpi does not have a n-overload, and since string_view is not
// necessarily null-terminated, _strmcpi cannot be safely used
return std::equal(std::begin(value_), std::end(value_), std::begin(other),
std::end(other), [](auto&& c1, auto&& c2) {
return ::tolower(c1) == ::tolower(c2);
});
return details::get_string(name(), "host");
}

conf_cmake::conf_cmake() : conf_section("cmake") {}

const conf_cmake::cmake_constant conf_cmake::ALWAYS{"always"};
const conf_cmake::cmake_constant conf_cmake::LAZY{"lazy"};
const conf_cmake::cmake_constant conf_cmake::NEVER{"never"};
conf_task::conf_task(std::vector<std::string> names) : names_(std::move(names)) {}

conf_cmake::cmake_constant conf_cmake::install_message() const
std::string conf_task::get(std::string_view key) const
{
return read_cmake_constant("install_message", {ALWAYS, LAZY, NEVER});
return details::get_string_for_task(names_, key);
}

std::string conf_cmake::host() const
bool conf_task::get_bool(std::string_view key) const
{
return details::get_string(name(), "host");
return details::get_bool_for_task(names_, key);
}

conf_cmake::cmake_constant
conf_cmake::read_cmake_constant(std::string_view key,
std::vector<cmake_constant> const& allowed) const
mob::config conf_task::configuration() const
{
const auto value = details::get_string(name(), key);
for (const auto& constant : allowed) {
if (constant.is_equivalent(value)) {
return constant;
}
}

gcx().bail_out(context::conf, "bad value '{}' for {}/{} (expected one of {})",
value, name(), key, join(allowed, ", ", std::string{}));
static std::unordered_map<mob::config, std::string_view> configuration_values{
{mob::config::release, "Release"},
{mob::config::debug, "Debug"},
{mob::config::relwithdebinfo, "RelWithDebInfo"}};
return details::parse_cmake_value(
names_[0], "configuration",
details::get_string_for_task(names_, "configuration"),
configuration_values);
}

conf_tools::conf_tools() : conf_section("tools") {}
Expand Down
85 changes: 30 additions & 55 deletions src/core/conf.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#include "../utility.h"

// these shouldn't be called directly, they're used by some of the template
// below
//
Expand Down Expand Up @@ -102,6 +104,29 @@ namespace mob {
bool build() const { return get<bool>("build_task"); }
};

// options in [cmake]
//
class conf_cmake : conf_section<std::string> {
public:
enum class constant { always, lazy, never };
using enum constant;

static std::string to_string(constant m);

conf_cmake();

// specify the value for CMAKE_INSTALL_MESSAGE
//
constant install_message() const;

// specify the toolset host configuration, if any, this is equivalent
// to -T host=XXX on the command line
//
// an empty string means no host configured
//
std::string host() const;
};

// options in [task] or [task_name:task]
//
class conf_task {
Expand Down Expand Up @@ -141,64 +166,16 @@ namespace mob {
return get<bool>("remote_push_default_origin");
}

// specify the configuration to build
//
mob::config configuration() const;

private:
std::vector<std::string> names_;

bool get_bool(std::string_view name) const;
};

// options in [task] or [task_name:task]
//
class conf_cmake : conf_section<std::string> {
public:
class cmake_constant {
std::string value_;

// check if the given string is equivalent to this constant
//
bool is_equivalent(std::string_view other) const;

friend class conf_cmake;

public:
constexpr cmake_constant(std::string_view value) : value_{value} {}
constexpr const auto& value() const { return value_; }
constexpr operator const std::string&() const { return value(); }

friend bool operator==(cmake_constant const& lhs, cmake_constant const& rhs)
{
return lhs.is_equivalent(rhs.value());
}
friend bool operator!=(cmake_constant const& lhs, cmake_constant const& rhs)
{
return !(lhs == rhs);
}
};

static const cmake_constant ALWAYS;
static const cmake_constant LAZY;
static const cmake_constant NEVER;

public:
conf_cmake();

// specify the value for CMAKE_INSTALL_MESSAGE
//
cmake_constant install_message() const;

// specify the toolset host configuration, if any, this is equivalent
// to -T host=XXX on the command line
//
// an empty string means no host configured
//
std::string host() const;

private:
cmake_constant
read_cmake_constant(std::string_view key,
std::vector<cmake_constant> const& allowed) const;
};

// options in [tools]
//
class conf_tools : public conf_section<fs::path> {
Expand Down Expand Up @@ -234,9 +211,7 @@ namespace mob {
conf_paths();

#define VALUE(NAME) \
fs::path NAME() const \
{ \
return get(#NAME); \
fs::path NAME() const {return get(#NAME); \
}

VALUE(third_party);
Expand Down
40 changes: 20 additions & 20 deletions src/tasks/gtest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ namespace mob::tasks {

namespace {

cmake create_cmake_tool(arch a, const std::string& config,
cmake::ops o = cmake::generate)
cmake create_cmake_tool(arch a, config config, cmake::ops o = cmake::generate)
{
return std::move(cmake(o)
.generator(cmake::vs)
Expand All @@ -17,12 +16,12 @@ namespace mob::tasks {
.root(gtest::source_path()));
}

msbuild create_msbuild_tool(arch a, std::string const& config,
msbuild create_msbuild_tool(arch a, config config,
msbuild::ops o = msbuild::build)
{
const fs::path build_path = create_cmake_tool(a, config).build_path();

return std::move(msbuild(o).architecture(a).config(config).solution(
return std::move(msbuild(o).architecture(a).configuration(config).solution(
build_path / "INSTALL.vcxproj"));
}

Expand All @@ -45,9 +44,10 @@ namespace mob::tasks {
return conf().path().build() / "googletest";
}

fs::path gtest::build_path(arch a, const std::string& c)
fs::path gtest::build_path(arch a, config c)
{
return source_path() / "build" / (a == arch::x64 ? "x64" : "Win32") / c;
return source_path() / "build" / (a == arch::x64 ? "x64" : "Win32") /
msbuild::configuration_name(c);
}

void gtest::do_clean(clean c)
Expand All @@ -58,15 +58,15 @@ namespace mob::tasks {
}

if (is_set(c, clean::reconfigure)) {
run_tool(create_cmake_tool(arch::x86, "Release", cmake::clean));
run_tool(create_cmake_tool(arch::x64, "Release", cmake::clean));
run_tool(create_cmake_tool(arch::x86, config::release, cmake::clean));
run_tool(create_cmake_tool(arch::x64, config::release, cmake::clean));
}

if (is_set(c, clean::rebuild)) {
run_tool(create_msbuild_tool(arch::x86, "Release", msbuild::clean));
run_tool(create_msbuild_tool(arch::x86, "Debug", msbuild::clean));
run_tool(create_msbuild_tool(arch::x64, "Release", msbuild::clean));
run_tool(create_msbuild_tool(arch::x64, "Debug", msbuild::clean));
run_tool(create_msbuild_tool(arch::x86, config::release, msbuild::clean));
run_tool(create_msbuild_tool(arch::x86, config::debug, msbuild::clean));
run_tool(create_msbuild_tool(arch::x64, config::release, msbuild::clean));
run_tool(create_msbuild_tool(arch::x64, config::debug, msbuild::clean));
}
}

Expand All @@ -85,19 +85,19 @@ namespace mob::tasks {

parallel({{"gtest64",
[&] {
run_tool(create_cmake_tool(arch::x64, "Release"));
run_tool(create_msbuild_tool(arch::x64, "Release"));
run_tool(create_cmake_tool(arch::x64, config::release));
run_tool(create_msbuild_tool(arch::x64, config::release));

run_tool(create_cmake_tool(arch::x64, "Debug"));
run_tool(create_msbuild_tool(arch::x64, "Debug"));
run_tool(create_cmake_tool(arch::x64, config::debug));
run_tool(create_msbuild_tool(arch::x64, config::debug));
}},

{"gtest32", [&] {
run_tool(create_cmake_tool(arch::x86, "Release"));
run_tool(create_msbuild_tool(arch::x86, "Release"));
run_tool(create_cmake_tool(arch::x86, config::release));
run_tool(create_msbuild_tool(arch::x86, config::release));

run_tool(create_cmake_tool(arch::x86, "Debug"));
run_tool(create_msbuild_tool(arch::x86, "Debug"));
run_tool(create_cmake_tool(arch::x86, config::debug));
run_tool(create_msbuild_tool(arch::x86, config::debug));
}}});
}

Expand Down
Loading

0 comments on commit 2de230c

Please sign in to comment.