Reusing libraries inside Library#library_from_file and Library#library:from_files for conservative reloading.

This commit is contained in:
Matthias Koefferlein 2026-04-03 17:49:29 +02:00
parent 62e45daaea
commit a39bc587c1
3 changed files with 63 additions and 4 deletions

View File

@ -53,6 +53,27 @@ FileBasedLibrary::merge_with_other_layout (const std::string &path)
}
}
bool
FileBasedLibrary::is_for_path (const std::string &path)
{
return m_other_paths.empty () && m_path == path;
}
bool
FileBasedLibrary::is_for_paths (const std::vector<std::string> &paths)
{
if (paths.size () != m_other_paths.size () + 1) {
return false;
}
// this check is purely based on path strings
std::set<std::string> p1 (paths.begin (), paths.end ());
std::set<std::string> p2;
p2.insert (m_path);
p2.insert (m_other_paths.begin (), m_other_paths.end ());
return p1 == p2;
}
std::string
FileBasedLibrary::load ()
{

View File

@ -89,6 +89,16 @@ public:
m_other_paths = other_paths;
}
/**
* @brief Gets a value indicating whether the library is for the given path
*/
bool is_for_path (const std::string &path);
/**
* @brief Gets a value indicating whether the library is for the given path
*/
bool is_for_paths (const std::vector<std::string> &paths);
private:
std::string m_name;
std::string m_path;

View File

@ -157,9 +157,21 @@ static LibraryImpl *new_lib ()
return new LibraryImpl ();
}
static db::Library *library_from_file (const std::string &path, const std::string &name)
static db::Library *library_from_file (const std::string &path, const std::string &name, const std::string &for_technology)
{
// Check if a library with this specification already is installed and reuse in that case.
if (! name.empty ()) {
db::FileBasedLibrary *old_lib = dynamic_cast<db::FileBasedLibrary *> (library_by_name (name, for_technology));
if (old_lib && old_lib->is_for_path (path)) {
old_lib->load ();
return old_lib;
}
}
std::unique_ptr<db::FileBasedLibrary> lib (new db::FileBasedLibrary (path, name));
lib->set_technology (for_technology);
std::string n = lib->load ();
db::Library *ret = lib.get ();
@ -168,17 +180,30 @@ static db::Library *library_from_file (const std::string &path, const std::strin
return ret;
}
static db::Library *library_from_files (const std::vector<std::string> &paths, const std::string &name)
static db::Library *library_from_files (const std::vector<std::string> &paths, const std::string &name, const std::string &for_technology)
{
if (paths.empty ()) {
throw tl::Exception (tl::to_string (tr ("At least one path must be given")));
}
// Check if a library with this specification already is installed and reuse in that case.
if (! name.empty ()) {
db::FileBasedLibrary *old_lib = dynamic_cast<db::FileBasedLibrary *> (library_by_name (name, for_technology));
if (old_lib && old_lib->is_for_paths (paths)) {
old_lib->load ();
return old_lib;
}
}
std::unique_ptr<db::FileBasedLibrary> lib (new db::FileBasedLibrary (paths.front (), name));
for (auto i = paths.begin () + 1; i != paths.end (); ++i) {
lib->merge_with_other_layout (*i);
}
lib->set_technology (for_technology);
std::string n = lib->load ();
db::Library *ret = lib.get ();
register_lib (lib.release (), n);
@ -191,7 +216,7 @@ static db::Library *library_from_files (const std::vector<std::string> &paths,
*/
LibraryClass<db::Library> decl_Library ("db", "LibraryBase",
gsi::method ("library_from_file", &library_from_file, gsi::arg ("path"), gsi::arg ("name", std::string (), "auto"),
gsi::method ("library_from_file", &library_from_file, gsi::arg ("path"), gsi::arg ("name", std::string (), "auto"), gsi::arg ("for_technology", std::string (), "none"),
"@brief Creates a library from a file\n"
"@param path The path to the file from which to create the library from.\n"
"@param name The name of the library. If empty, the name will be derived from the GDS LIBNAME or the file name.\n"
@ -200,9 +225,12 @@ LibraryClass<db::Library> decl_Library ("db", "LibraryBase",
"This method will create a \\Library object which is tied to a specific file. This object supports "
"automatic reloading when the \\Library#refresh method is called.\n"
"\n"
"If a file-based library with the same name and path is registered already, this method will not reload again "
"and return the library that was already registered.\n"
"\n"
"This convenience method has been added in version 0.30.8.\n"
) +
gsi::method ("library_from_files", &library_from_files, gsi::arg ("paths"), gsi::arg ("name", std::string (), "auto"),
gsi::method ("library_from_files", &library_from_files, gsi::arg ("paths"), gsi::arg ("name", std::string (), "auto"), gsi::arg ("for_technology", std::string (), "none"),
"@brief Creates a library from a set of files\n"
"@param paths The paths to the files from which to create the library from. At least one file needs to be given.\n"
"@param name The name of the library. If empty, the name will be derived from the GDS LIBNAME or the file name.\n"