Use project-relative paths in sym-lib-table for imported libraries

When importing Altium projects, the MAIL_ADD_LOCAL_LIB handler stored
absolute paths in the sym-lib-table for native Altium library files
(.SchLib). This caused broken library references when the project was
moved to a different location.

Now library files outside the project directory are copied into it
during import, and the sym-lib-table URI uses ${KIPRJMOD}/ prefix
for project-relative paths. This matches the behavior of the Eagle,
CADSTAR, and EasyEDA Pro importers.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/22941
This commit is contained in:
Seth Hillbrand
2026-02-10 10:40:49 -08:00
parent 1083ae2b52
commit 7db7083cd0
2 changed files with 35 additions and 1 deletions
+31 -1
View File
@@ -46,6 +46,7 @@
#include <libraries/symbol_library_adapter.h>
#include <widgets/sch_design_block_pane.h>
#include <widgets/kistatusbar.h>
#include <wx/filefn.h>
#include <wx/log.h>
#include <trace_helpers.h>
@@ -856,6 +857,12 @@ void SCH_EDIT_FRAME::KiwayMailIn( KIWAY_MAIL_EVENT& mail )
wxCHECK_RET( optTable.has_value(), "Could not load symbol lib table." );
LIBRARY_TABLE* table = optTable.value();
wxString projectPath = Prj().GetProjectPath();
// First line of payload is the source project directory.
std::string srcProjDir;
std::getline( ss, srcProjDir, '\n' );
std::vector<wxString> toLoad;
while( std::getline( ss, file, '\n' ) )
@@ -875,11 +882,34 @@ void SCH_EDIT_FRAME::KiwayMailIn( KIWAY_MAIL_EVENT& mail )
pi.reset( SCH_IO_MGR::FindPlugin( type ) );
wxString libTableUri;
bool isProjectLocal = fn.GetFullPath().StartsWith( wxString( srcProjDir ) );
if( isProjectLocal )
{
// Project-local library: copy into the KiCad project directory and use a
// project-relative path so the sym-lib-table stays portable.
if( !fn.FileExists() )
continue;
wxFileName projectFn( projectPath, fn.GetFullName() );
if( fn.GetFullPath() != projectFn.GetFullPath() && !projectFn.FileExists() )
wxCopyFile( fn.GetFullPath(), projectFn.GetFullPath() );
libTableUri = wxS( "${KIPRJMOD}/" ) + fn.GetFullName();
}
else
{
// External library referenced by absolute path. Preserve the original path.
libTableUri = fn.GetFullPath();
}
if( !table->HasRow( fn.GetName() ) )
{
LIBRARY_TABLE_ROW& row = table->InsertRow();
row.SetNickname( fn.GetName() );
row.SetURI( fn.GetFullPath() );
row.SetURI( libTableUri );
row.SetType( SCH_IO_MGR::ShowType( type ) );
toLoad.emplace_back( fn.GetName() );
}
+4
View File
@@ -208,6 +208,10 @@ void IMPORT_PROJ_HELPER::addLocalLibraries( const std::set<wxString>& aNames, FR
std::stringstream ss;
// First line is the source project directory so the handler can distinguish
// project-local libraries from external fixed-path references.
ss << TO_UTF8( m_InputFile.GetPath() ) << '\n';
for( const wxString& name : aNames )
{
wxFileName fname( name );