fix: Create Printer finds no system vendors in release builds (#16175)

Co-authored-by: Rodrigo Faselli <162915171+RF47@users.noreply.github.com>
This commit is contained in:
Kris Austin
2026-10-07 17:30:36 -03:00
committed by GitHub
co-authored by Rodrigo Faselli
parent e027f8b225
commit c33515914d
6 changed files with 190 additions and 81 deletions
+60 -52
View File
@@ -2806,19 +2806,13 @@ std::pair<PresetsConfigSubstitutions, std::string> PresetBundle::load_system_mod
boost::filesystem::path dir = (boost::filesystem::path(resources_dir()) / "profiles").make_preferred();
PresetsConfigSubstitutions substitutions;
std::string errors_cummulative;
for (auto &dir_entry : boost::filesystem::directory_iterator(dir)) {
std::string vendor_file = dir_entry.path().string();
if (Slic3r::is_json_file(vendor_file)) {
std::string vendor_name = dir_entry.path().filename().string();
// Remove the .json suffix.
vendor_name.erase(vendor_name.size() - 5);
try {
// Load the config bundle, flatten it.
append(substitutions, load_vendor_configs_from_json(dir.string(), vendor_name, PresetBundle::LoadVendorOnly, compatibility_rule).first);
} catch (const std::runtime_error &err) {
errors_cummulative += err.what();
errors_cummulative += "\n";
}
for (const std::string &vendor_name : vendor_names_in(dir)) {
try {
// Load the config bundle, flatten it.
append(substitutions, load_vendor_configs_from_json(dir.string(), vendor_name, PresetBundle::LoadVendorOnly, compatibility_rule).first);
} catch (const std::runtime_error &err) {
errors_cummulative += err.what();
errors_cummulative += "\n";
}
}
@@ -2841,35 +2835,33 @@ std::pair<PresetsConfigSubstitutions, std::string> PresetBundle::load_system_fil
PresetsConfigSubstitutions substitutions;
std::string errors_cummulative;
bool first = true;
for (auto &dir_entry : boost::filesystem::directory_iterator(dir)) {
std::string vendor_file = dir_entry.path().string();
if (Slic3r::is_json_file(vendor_file)) {
std::string vendor_name = dir_entry.path().filename().string();
// Remove the .json suffix.
vendor_name.erase(vendor_name.size() - 5);
try {
if (first) {
// Reset this PresetBundle and load the first vendor config.
append(substitutions, this->load_vendor_configs_from_json(dir.string(), vendor_name, PresetBundle::LoadSystem | PresetBundle::LoadFilamentOnly, compatibility_rule).first);
first = false;
} else {
// Load the other vendor configs, merge them with this PresetBundle.
// Report duplicate profiles.
PresetBundle other;
append(substitutions, other.load_vendor_configs_from_json(dir.string(), vendor_name, PresetBundle::LoadSystem | PresetBundle::LoadFilamentOnly, compatibility_rule).first);
std::vector<std::string> duplicates = std::move(this->merge_presets({ &other }).front());
if (!duplicates.empty()) {
errors_cummulative += "Found duplicated settings in vendor " + vendor_name + "'s json file lists: ";
for (size_t i = 0; i < duplicates.size(); ++i) {
if (i > 0) errors_cummulative += ", ";
errors_cummulative += duplicates[i];
}
// The filament library loads first, so the filaments that inherit its bases resolve.
std::vector<std::string> vendor_names;
for (const std::string &vendor_name : vendor_names_in(dir))
vendor_names.insert(vendor_name == ORCA_FILAMENT_LIBRARY ? vendor_names.begin() : vendor_names.end(), vendor_name);
for (const std::string &vendor_name : vendor_names) {
try {
if (first) {
// Reset this PresetBundle and load the first vendor config.
append(substitutions, this->load_vendor_configs_from_json(dir.string(), vendor_name, PresetBundle::LoadSystem | PresetBundle::LoadFilamentOnly, compatibility_rule).first);
first = false;
} else {
// Load the other vendor configs, merge them with this PresetBundle.
// Report duplicate profiles.
PresetBundle other;
append(substitutions, other.load_vendor_configs_from_json(dir.string(), vendor_name, PresetBundle::LoadSystem | PresetBundle::LoadFilamentOnly, compatibility_rule, this).first);
std::vector<std::string> duplicates = std::move(this->merge_presets({ &other }).front());
if (!duplicates.empty()) {
errors_cummulative += "Found duplicated settings in vendor " + vendor_name + "'s json file lists: ";
for (size_t i = 0; i < duplicates.size(); ++i) {
if (i > 0) errors_cummulative += ", ";
errors_cummulative += duplicates[i];
}
}
} catch (const std::runtime_error &err) {
errors_cummulative += err.what();
errors_cummulative += "\n";
}
} catch (const std::runtime_error &err) {
errors_cummulative += err.what();
errors_cummulative += "\n";
}
}
@@ -7149,22 +7141,38 @@ PresetBundle::VendorRead PresetBundle::read_vendor(const std::string& dir, const
// Reset this bundle, delete user profile files if SaveImported.
this->reset(flags.has(LoadConfigBundleAttribute::SaveImported));
// Orca: only a whole-vendor load has a cache — the vendor-only and filament-only
// scans want a slice of one. Validation reads the JSONs whatever is cached.
read.cacheable = allow_cache && flags.has(LoadConfigBundleAttribute::LoadSystem) && ! flags.has(LoadConfigBundleAttribute::LoadFilamentOnly);
if (read.cacheable && ! validation_mode) {
// A vendor is loaded from where it is installed and nowhere else; resources
// reaches the app by being installed into `dir` first. The cache there is
// judged against the profile beside it — or, where the cache is the whole
// of the installation, against nothing, since nothing on disk can then be
// Orca: only a whole-vendor load writes a cache, and a vendor-only or filament-only
// scan reads one only where it is the whole installation, as in a shipped build.
// Validation reads the JSONs whatever is cached.
const bool vendor_only = flags.has(LoadConfigBundleAttribute::LoadVendorOnly);
const bool filament_only = flags.has(LoadConfigBundleAttribute::LoadFilamentOnly);
read.cacheable = allow_cache && flags.has(LoadConfigBundleAttribute::LoadSystem) && ! filament_only;
const boost::filesystem::path dir_path(dir);
const boost::filesystem::path profile = dir_path / (vendor_name + ".json");
const bool has_profile = boost::filesystem::exists(profile);
if (allow_cache && ! validation_mode && (read.cacheable || ((vendor_only || filament_only) && ! has_profile))) {
// The cache is judged against the profile beside it, or, where the cache is the
// whole of the installation, against nothing, since nothing on disk can then be
// newer than it. That state is Semver::inf(), which no real profile carries.
const boost::filesystem::path dir_path(dir);
const boost::filesystem::path profile = dir_path / (vendor_name + ".json");
const Semver version = boost::filesystem::exists(profile) ? get_version_from_json(profile.string()) : Semver::inf();
const Semver version = has_profile ? get_version_from_json(profile.string()) : Semver::inf();
read.cache_path = (dir_path / (vendor_name + ".opc")).string();
read.from_cache = VendorCacheFile::load(read.cache_path, vendor_name, version, read.data);
if (read.from_cache)
if (vendor_only) {
VendorProfile vendor_profile;
if (VendorCacheFile::load_vendor_profile(read.cache_path, vendor_name, version, vendor_profile)) {
this->vendors.emplace(vendor_name, std::move(vendor_profile));
read.vendor_only = true;
return read;
}
} else if (VendorCacheFile::load(read.cache_path, vendor_name, version, read.data)) {
read.from_cache = true;
if (filament_only) {
read.data.process_entries.clear();
read.data.machine_entries.clear();
// The stamp counts errors across the whole vendor.
read.data.parse_errors = 0;
}
return read;
}
}
this->parse_vendor_json(read);
return read;