Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More flexibility to build Debug components #136

Merged
merged 13 commits into from
Jun 15, 2024
Merged
21 changes: 13 additions & 8 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 Expand Up @@ -118,7 +119,6 @@ zlib = v1.3.1
libbsarch = 0.0.9
usvfs = master
explorerpp = 1.4.0

ss_paper_lad_6788 = 7.2
ss_paper_automata_6788 = 3.2
ss_paper_mono_6788 = 3.2
Expand All @@ -129,6 +129,11 @@ ss_starfield_trosski = V1.11
ss_fallout3_trosski = v1.11
ss_fallout4_trosski = v1.11

[build-types]
libbsarch = release
pyqt = release
python = release

[paths]
third_party =
prefix =
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
118 changes: 85 additions & 33 deletions src/core/conf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ namespace mob::details {
using key_value_map = std::map<std::string, std::string, std::less<>>;
using section_map = std::map<std::string, key_value_map, std::less<>>;

static std::unordered_map<mob::config, std::string_view> s_configuration_values{
{mob::config::release, "Release"},
{mob::config::debug, "Debug"},
{mob::config::relwithdebinfo, "RelWithDebInfo"}};

// holds all the options not related to tasks (global, tools, paths, etc.)
static section_map g_conf;

Expand All @@ -27,6 +32,18 @@ namespace mob::details {
static int g_file_log_level = 5;
static bool g_dry = false;

// 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);
});
}

bool bool_from_string(std::string_view s)
{
return (s == "true" || s == "yes" || s == "1");
Expand Down Expand Up @@ -85,6 +102,17 @@ namespace mob::details {
kitor->second = value;
}

config string_to_config(std::string_view value)
{
for (const auto& [c, v] : s_configuration_values) {
if (case_insensitive_equals(value, v)) {
return c;
}
}

gcx().bail_out(context::conf, "invalid configuration '{}'", value);
}

// sets the given option, adds it if it doesn't exist; used when setting options
// from the master ini
//
Expand Down Expand Up @@ -184,6 +212,28 @@ namespace mob::details {
g_tasks[task_name][key] = std::move(value);
}

// 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 @@ -644,6 +694,11 @@ namespace mob {
return {};
}

conf_build_types conf::build_types()
{
return {};
}

conf_paths conf::path()
{
return {};
Expand All @@ -666,57 +721,52 @@ 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{}));
return details::parse_cmake_value(
names_[0], "configuration",
details::get_string_for_task(names_, "configuration"),
details::s_configuration_values);
}

conf_tools::conf_tools() : conf_section("tools") {}
Expand All @@ -725,6 +775,8 @@ namespace mob {

conf_versions::conf_versions() : conf_section("versions") {}

conf_build_types::conf_build_types() : conf_section("build-types") {}

conf_prebuilt::conf_prebuilt() : conf_section("prebuilt") {}

conf_paths::conf_paths() : conf_section("paths") {}
Expand Down
Loading
Loading