KiCad PCB EDA Suite
Loading...
Searching...
No Matches
paths.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20#include <wx/dir.h>
21#include <wx/filename.h>
22#include <wx/stdpaths.h>
23#include <wx/string.h>
24#include <wx/utils.h>
25#include <wx/msgdlg.h>
26
28#include <paths.h>
29#include <config.h>
30#include <build_version.h>
31#include <macros.h>
32#include <wx_filename.h>
33
34
35void PATHS::getUserDocumentPath( wxFileName& aPath )
36{
37 wxString envPath;
38
39 if( wxGetEnv( wxT( "KICAD_DOCUMENTS_HOME" ), &envPath ) )
40 aPath.AssignDir( envPath );
41 else
42 aPath.AssignDir( KIPLATFORM::ENV::GetDocumentsPath() );
43
44 aPath.AppendDir( KICAD_PATH_STR );
45 aPath.AppendDir( GetMajorMinorVersion().ToStdString() );
46}
47
48
50{
51 wxFileName tmp;
53
54 tmp.AppendDir( wxT( "plugins" ) );
55
56 return tmp.GetPath();
57}
58
59
61{
62 wxFileName tmp;
64
65 tmp.AppendDir( wxT( "scripting" ) );
66
67 return tmp.GetPath();
68}
69
70
72{
73 wxFileName tmp;
75
76 tmp.AppendDir( wxT( "template" ) );
77
78 return tmp.GetPathWithSep();
79}
80
81
83{
84 wxFileName tmp;
86
87 tmp.AppendDir( wxT( "symbols" ) );
88
89 return tmp.GetPath();
90}
91
92
94{
95 wxFileName tmp;
97
98 tmp.AppendDir( wxT( "footprints" ) );
99
100 return tmp.GetPath();
101}
102
103
105{
106 wxFileName tmp;
107 getUserDocumentPath( tmp );
108
109 tmp.AppendDir( wxT( "blocks" ) );
110
111 return tmp.GetPath();
112}
113
114
116{
117 wxFileName tmp;
118 getUserDocumentPath( tmp );
119
120 tmp.AppendDir( wxT( "3dmodels" ) );
121
122 return tmp.GetPath();
123}
124
125
127{
128 wxFileName tmp;
129 getUserDocumentPath( tmp );
130
131 tmp.AppendDir( wxT( "3rdparty" ) );
132
133 return tmp.GetAbsolutePath();
134}
135
136
138{
139 wxFileName tmp;
140 getUserDocumentPath( tmp );
141
142 tmp.AppendDir( wxT( "projects" ) );
143
144 return tmp.GetPath();
145}
146
147
148#if !defined( __WXMAC__ ) && !defined( __WXMSW__ )
156static wxString getBuildDirectoryRoot()
157{
158 // We don't have a perfect way to spot a build directory (e.g. when archived as artifacts in
159 // CI) but we can assume that the build directory will have a schemas directory that contains
160 // JSON files, as that's one of the things that we use this path for.
161 const auto looksLikeBuildDir = []( const wxFileName& aPath ) -> bool
162 {
163 const wxDir schema_dir( aPath.GetPathWithSep() + wxT( "schemas" ) );
164
165 if( !schema_dir.IsOpened() )
166 return false;
167
168 wxString filename;
169 const bool found = schema_dir.GetFirst( &filename, wxT( "*.json" ), wxDIR_FILES );
170 return found;
171 };
172
173 const wxString execPath = PATHS::GetExecutablePath();
174 wxFileName fn = execPath;
175
176 // Climb the directory tree until we find a directory that looks like a build directory
177 // Normally we expect to climb one or two levels only.
178 while( fn.GetDirCount() > 0 && !looksLikeBuildDir( fn ) )
179 {
180 fn.RemoveLastDir();
181 }
182
183 wxASSERT_MSG(
184 fn.GetDirCount() > 0,
185 wxString::Format( wxT( "Could not find build root directory above %s" ), execPath ) );
186
187 return fn.GetPath();
188}
189#elif defined( __WXMAC__ )
195static wxString getOSXBundleRoot()
196{
197 static wxString bundleRoot;
198
199 if( bundleRoot.empty() )
200 {
201 wxFileName fn( wxStandardPaths::Get().GetExecutablePath() );
203 fn.SetFullName( wxEmptyString ); // Remove binary name
204
205 // Navigate from .../Contents/MacOS/ up to the .app bundle root
206 // e.g., /Applications/KiCad/KiCad.app/Contents/MacOS -> /Applications/KiCad/KiCad.app
207 if( fn.GetDirCount() >= 2 && fn.GetDirs().Last() == wxT( "MacOS" ) )
208 {
209 fn.RemoveLastDir(); // MacOS
210 fn.RemoveLastDir(); // Contents
211 }
212
213 // Handle aux binaries inside main bundle
214 // From: .../main.app/Contents/Applications/standalone.app
215 // To: .../main.app
216 const wxArrayString dirs = fn.GetDirs();
217 if( dirs.GetCount() >= 4 && dirs[dirs.GetCount() - 2] == wxT( "Applications" )
218 && dirs[dirs.GetCount() - 4].Lower().EndsWith( wxT( "app" ) ) )
219 {
220 fn.RemoveLastDir(); // standalone.app
221 fn.RemoveLastDir(); // Applications
222 fn.RemoveLastDir(); // Contents
223 }
224
225 bundleRoot = fn.GetPath();
226 }
227
228 return bundleRoot;
229}
230#endif
231
232
233wxString PATHS::GetStockDataPath( bool aRespectRunFromBuildDir )
234{
235 wxString path;
236
237 if( aRespectRunFromBuildDir && wxGetEnv( wxT( "KICAD_RUN_FROM_BUILD_DIR" ), nullptr ) )
238 {
239 // Allow debugging from build dir by placing relevant files/folders in the build root
240#if defined( __WXMAC__ )
241 wxFileName fn;
242 fn.AssignDir( getOSXBundleRoot() );
243 fn.RemoveLastDir(); // Above the .app bundle
244 fn.RemoveLastDir(); // Above the target subdirectory to build root
245 path = fn.GetPath();
246#elif defined( __WXMSW__ )
247 path = getWindowsKiCadRoot();
248#else
250#endif
251 }
252 else if( wxGetEnv( wxT( "KICAD_STOCK_DATA_HOME" ), &path ) && !path.IsEmpty() )
253 {
254 return path;
255 }
256 else
257 {
258#if defined( __WXMAC__ )
259 path = GetOSXKicadDataDir();
260#elif defined( __WXMSW__ )
261 path = getWindowsKiCadRoot() + wxT( "share/kicad" );
262#else
263 path = wxString::FromUTF8Unchecked( KICAD_DATA );
264#endif
265 }
266
267 return path;
268}
269
270
271#ifdef _WIN32
272
273wxString PATHS::GetWindowsBaseSharePath()
274{
275 return getWindowsKiCadRoot() + wxT( "share\\" );
276}
277
278#endif
279
280
282{
283 wxString path;
284
285#if defined( __WXMAC__ )
286 path = GetOSXKicadMachineDataDir();
287#elif defined( __WXMSW__ )
288 path = GetStockDataPath( false );
289#else
290 if( wxGetEnv( wxT( "APPDIR" ), &path ) )
291 path += wxT( "/share/kicad" );
292 else
293 path = wxString::FromUTF8Unchecked( KICAD_LIBRARY_DATA );
294#endif
295
296 return path;
297}
298
299
301{
302 wxFileName fn;
303
304 fn.AssignDir( GetStockEDALibraryPath() );
305 fn.AppendDir( "symbols" );
306
307 return fn.GetPathWithSep();
308}
309
310
312{
313 wxFileName fn;
314
315 fn.AssignDir( GetStockEDALibraryPath() );
316 fn.AppendDir( "footprints" );
317
318 return fn.GetPathWithSep();
319}
320
321
323{
324 wxFileName fn;
325
326 fn.AssignDir( GetStockEDALibraryPath() );
327 fn.AppendDir( "blocks" );
328
329 return fn.GetPathWithSep();
330}
331
332
334{
335 wxFileName fn;
336
337 fn.AssignDir( GetStockEDALibraryPath() );
338 fn.AppendDir( "3dmodels" );
339
340 return fn.GetPathWithSep();
341}
342
343
345{
346 wxFileName fn;
347
348 fn.AssignDir( GetStockDataPath() );
349 fn.AppendDir( "scripting" );
350
351 return fn.GetPathWithSep();
352}
353
354
356{
357 wxFileName fn;
358
359 fn.AssignDir( GetStockEDALibraryPath() );
360 fn.AppendDir( "template" );
361
362 return fn.GetPathWithSep();
363}
364
365
367{
368 wxFileName fn;
369
370 fn.AssignDir( GetStockDataPath() );
371 fn.AppendDir( "internat" );
372
373 return fn.GetPathWithSep();
374}
375
376
378{
379 wxFileName fn;
380
381#if defined( __WXMSW__ )
382 fn.AssignDir( GetExecutablePath() );
383 fn.AppendDir( wxT( "scripting" ) );
384#else
385 fn.AssignDir( PATHS::GetStockDataPath( false ) );
386#endif
387 fn.AppendDir( wxT( "plugins" ) );
388
389 return fn.GetPathWithSep();
390}
391
392
394{
395 wxFileName fn;
396
397#if defined( __WXMSW__ )
398 if( wxGetEnv( wxT( "KICAD_RUN_FROM_BUILD_DIR" ), nullptr ) )
399 {
400 fn.AssignDir( getWindowsKiCadRoot() );
401 }
402 else
403 {
404 fn.AssignDir( GetExecutablePath() );
405 }
406
407 fn.AppendDir( wxT( "plugins" ) );
408#elif defined( __WXMAC__ )
409 fn.AssignDir( getOSXBundleRoot() );
410 fn.AppendDir( wxT( "Contents" ) );
411 fn.AppendDir( wxT( "PlugIns" ) );
412#else
413 wxString envPath;
414
415 if( wxGetEnv( wxT( "KICAD_RUN_FROM_BUILD_DIR" ), nullptr ) )
416 {
417 fn.Assign( wxStandardPaths::Get().GetExecutablePath() );
418 fn.AppendDir( wxT( ".." ) );
419 fn.AppendDir( wxT( "plugins" ) );
420 }
421 // AppImages have a different path to the plugins, otherwise we end up with host system
422 // plugins being loaded.
423 else if( wxGetEnv( wxT( "APPDIR" ), &envPath ) )
424 {
425 fn.Assign( envPath, wxEmptyString );
426 fn.AppendDir( wxT( "usr" ) );
427 fn.AppendDir( wxT( "lib" ) );
428 fn.AppendDir( wxT( "x86_64-linux-gnu" ) );
429 fn.AppendDir( wxT( "kicad" ) );
430 fn.AppendDir( wxT( "plugins" ) );
431 }
432 else
433 {
434 // KICAD_PLUGINDIR = CMAKE_INSTALL_FULL_LIBDIR path is the absolute path
435 // corresponding to the install path used for constructing KICAD_USER_PLUGIN
436 wxString tfname = wxString::FromUTF8Unchecked( KICAD_PLUGINDIR );
437 fn.Assign( tfname, "" );
438 fn.AppendDir( wxT( "kicad" ) );
439 fn.AppendDir( wxT( "plugins" ) );
440 }
441#endif
442
443 fn.AppendDir( wxT( "3d" ) );
444
445 return fn.GetPathWithSep();
446}
447
448
450{
451 wxFileName fn;
452
453 fn.AssignDir( PATHS::GetStockDataPath( false ) );
454 fn.AppendDir( wxT( "demos" ) );
455
456 return fn.GetPathWithSep();
457}
458
459
461{
462 wxString envPath;
463 wxFileName tmp;
464
465 tmp.AssignDir( KIPLATFORM::ENV::GetUserCachePath() );
466
467 // Use KICAD_CACHE_HOME to allow the user to force a specific cache path.
468 if( wxGetEnv( wxT( "KICAD_CACHE_HOME" ), &envPath ) && !envPath.IsEmpty() )
469 {
470 // Override the assignment above with KICAD_CACHE_HOME
471 tmp.AssignDir( envPath );
472 }
473
474 tmp.AppendDir( KICAD_PATH_STR );
475 tmp.AppendDir( GetMajorMinorVersion().ToStdString() );
476
477 return tmp.GetPathWithSep();
478}
479
480
482{
483 wxString path;
484
485#if defined( __WXMAC__ )
486 path = GetOSXKicadDataDir();
487#elif defined( __WXMSW__ )
488 path = getWindowsKiCadRoot() + wxT( "share/doc/kicad" );
489#else
490 path = wxString::FromUTF8Unchecked( KICAD_DOCS );
491#endif
492
493 return path;
494}
495
496
498{
499 wxFileName tmp;
500 getUserDocumentPath( tmp );
501
502 tmp.AppendDir( wxT( "logs" ) );
503
504 return tmp.GetPath();
505}
506
507
508bool PATHS::EnsurePathExists( const wxString& aPath, bool aPathToFile )
509{
510 wxString pathString = aPath;
511 if( !aPathToFile )
512 {
513 // ensures the path is treated fully as directory
514 pathString += wxFileName::GetPathSeparator();
515 }
516
517 wxFileName path( pathString );
518 if( !path.MakeAbsolute() )
519 {
520 return false;
521 }
522
523 if( !wxFileName::DirExists( path.GetPath() ) )
524 {
525 if( !wxFileName::Mkdir( path.GetPath(), wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) )
526 {
527 return false;
528 }
529 }
530
531 return true;
532}
533
534
536{
546
547#ifdef _WIN32
548 // Warn about Controlled folder access
549 wxFileName tmp;
550 getUserDocumentPath( tmp );
551
552 if( !tmp.DirExists() )
553 {
554 wxString msg = wxString::Format(
555 _( "KiCad was unable to use '%s'.\n"
556 "\n"
557 "1. Disable 'Controlled folder access' in Windows settings or Group Policy\n"
558 "2. Make sure no other antivirus software interferes with KiCad\n"
559 "3. Make sure you have correct permissions set up" ),
560 tmp.GetPath() );
561
562 wxMessageBox( msg, _( "Warning" ), wxICON_WARNING );
563 }
564#endif
565}
566
567
568#ifdef __WXMAC__
569wxString PATHS::GetOSXKicadUserDataDir()
570{
571 // According to wxWidgets documentation for GetUserDataDir:
572 // Mac: ~/Library/Application Support/appname
573 wxFileName udir( wxStandardPaths::Get().GetUserDataDir(), wxEmptyString );
574
575 // Since appname is different if started via launcher or standalone binary
576 // map all to "kicad" here
577 udir.RemoveLastDir();
578 udir.AppendDir( wxT( "kicad" ) );
579
580 return udir.GetPath();
581}
582
583
584wxString PATHS::GetOSXKicadMachineDataDir()
585{
586 // 6.0 forward: Same as the main data dir
587 return GetOSXKicadDataDir();
588}
589
590
591wxString PATHS::GetOSXKicadDataDir()
592{
593 wxFileName ddir;
594 ddir.AssignDir( getOSXBundleRoot() );
595 ddir.AppendDir( wxT( "Contents" ) );
596 ddir.AppendDir( wxT( "SharedSupport" ) );
597 return ddir.GetPath();
598}
599#endif
600
601
602#ifdef _WIN32
603wxString PATHS::GetWindowsFontConfigDir()
604{
605 wxFileName fn;
606 fn.AssignDir( getWindowsKiCadRoot() );
607 fn.AppendDir( wxS( "etc" ) );
608 fn.AppendDir( wxS( "fonts" ) );
609
610 return fn.GetPathWithSep();
611}
612
613
614wxString PATHS::getWindowsKiCadRoot()
615{
616 wxFileName root( GetExecutablePath() + wxT( "/../" ) );
617 root.MakeAbsolute();
618
619 return root.GetPathWithSep();
620}
621#endif
622
623
625{
626 static wxString user_settings_path;
627
628 if( user_settings_path.empty() )
629 user_settings_path = CalculateUserSettingsPath();
630
631 return user_settings_path;
632}
633
634
635wxString PATHS::CalculateUserSettingsPath( bool aIncludeVer, bool aUseEnv )
636{
637 wxFileName cfgpath;
638
639 // http://docs.wxwidgets.org/3.0/classwx_standard_paths.html#a7c7cf595d94d29147360d031647476b0
640
641 wxString envstr;
642 if( aUseEnv && wxGetEnv( wxT( "KICAD_CONFIG_HOME" ), &envstr ) && !envstr.IsEmpty() )
643 {
644 // Override the assignment above with KICAD_CONFIG_HOME
645 cfgpath.AssignDir( envstr );
646 }
647 else
648 {
649 cfgpath.AssignDir( KIPLATFORM::ENV::GetUserConfigPath() );
650
651 cfgpath.AppendDir( TO_STR( KICAD_CONFIG_DIR ) );
652 }
653
654 if( aIncludeVer )
655 cfgpath.AppendDir( GetMajorMinorVersion().ToStdString() );
656
657 return cfgpath.GetPath();
658}
659
660
662{
663 static wxString exe_path;
664
665 if( exe_path.empty() )
666 {
667#ifdef __WXMAC__
668 // Use bundle root helper which handles symlink resolution and aux binaries
669 exe_path = getOSXBundleRoot() + wxT( "/" );
670#else
671 wxString envPath;
672
673 // When running inside an AppImage, the bundled ld-linux is invoked as a wrapper
674 // which causes /proc/self/exe to resolve to the dynamic linker rather than the
675 // actual binary. Use APPDIR to construct the correct executable path.
676 if( wxGetEnv( wxT( "APPDIR" ), &envPath ) )
677 {
678 envPath.Replace( WIN_STRING_DIR_SEP, UNIX_STRING_DIR_SEP );
679
680 if( !envPath.EndsWith( wxT( "/" ) ) )
681 envPath += wxT( "/" );
682
683 exe_path = envPath + wxT( "usr/bin/" );
684 }
685 else
686 {
687 wxString bin_dir = wxStandardPaths::Get().GetExecutablePath();
688
689 // Use unix notation for paths. I am not sure this is a good idea,
690 // but it simplifies compatibility between Windows and Unices.
691 // However it is a potential problem in path handling under Windows.
692 bin_dir.Replace( WIN_STRING_DIR_SEP, UNIX_STRING_DIR_SEP );
693
694 // Remove file name form command line:
695 while( bin_dir.Last() != '/' && !bin_dir.IsEmpty() )
696 bin_dir.RemoveLast();
697
698 exe_path = bin_dir;
699 }
700#endif
701 }
702
703 return exe_path;
704}
705
706
707wxString PATHS::ResolveSiblingExecutable( const wxString& aBaseName )
708{
709#ifdef __WXMAC__
710 // GetExecutablePath() returns the bundle root on macOS, but sibling binaries
711 // live next to the running executable in Contents/MacOS.
712 wxFileName sibling( wxFileName( wxStandardPaths::Get().GetExecutablePath() ).GetPath(), aBaseName );
713#else
714 wxFileName sibling( GetExecutablePath(), aBaseName );
715#endif
716
717#ifdef _WIN32
718 sibling.SetExt( wxT( "exe" ) );
719#endif
720
721 if( !sibling.FileExists() )
722 return wxEmptyString;
723
724 return sibling.GetFullPath();
725}
wxString GetMajorMinorVersion()
Get only the major and minor version in a string major.minor.
static wxString GetUserPluginsPath()
Gets the user path for plugins.
Definition paths.cpp:49
static wxString GetStockSymbolsPath()
Gets the stock (install) symbols path.
Definition paths.cpp:300
static wxString ResolveSiblingExecutable(const wxString &aBaseName)
Resolve a sibling executable alongside the running process.
Definition paths.cpp:707
static wxString GetDefaultUser3DModelsPath()
Gets the default path we point users to create projects.
Definition paths.cpp:115
static wxString GetUserTemplatesPath()
Gets the user path for custom templates.
Definition paths.cpp:71
static void getUserDocumentPath(wxFileName &aPath)
Gets the user path for the current kicad version which acts as the root for other user paths.
Definition paths.cpp:35
static wxString GetStockEDALibraryPath()
Gets the stock (install) EDA library data path, which is the base path for templates,...
Definition paths.cpp:281
static wxString CalculateUserSettingsPath(bool aIncludeVer=true, bool aUseEnv=true)
Determines the base path for user settings files.
Definition paths.cpp:635
static wxString GetDefaultUserProjectsPath()
Gets the default path we point users to create projects.
Definition paths.cpp:137
static wxString GetStockPluginsPath()
Gets the stock (install) plugins path.
Definition paths.cpp:377
static wxString GetLogsPath()
Gets a path to use for user-visible log files.
Definition paths.cpp:497
static void EnsureUserPathsExist()
Ensures/creates user default paths.
Definition paths.cpp:535
static wxString GetDocumentationPath()
Gets the documentation path, which is the base path for help files.
Definition paths.cpp:481
static wxString GetDefaultUserDesignBlocksPath()
Gets the default path we point users to create projects.
Definition paths.cpp:104
static wxString GetDefault3rdPartyPath()
Gets the default path for PCM packages.
Definition paths.cpp:126
static bool EnsurePathExists(const wxString &aPath, bool aPathToFile=false)
Attempts to create a given path if it does not exist.
Definition paths.cpp:508
static wxString GetStockPlugins3DPath()
Gets the stock (install) 3d viewer plugins path.
Definition paths.cpp:393
static wxString GetStockDataPath(bool aRespectRunFromBuildDir=true)
Gets the stock (install) data path, which is the base path for things like scripting,...
Definition paths.cpp:233
static wxString GetDefaultUserFootprintsPath()
Gets the default path we point users to create projects.
Definition paths.cpp:93
static wxString GetStock3dmodelsPath()
Gets the stock (install) 3dmodels path.
Definition paths.cpp:333
static wxString GetStockTemplatesPath()
Gets the stock (install) templates path.
Definition paths.cpp:355
static wxString GetUserCachePath()
Gets the stock (install) 3d viewer plugins path.
Definition paths.cpp:460
static wxString GetUserScriptingPath()
Gets the user path for python scripts.
Definition paths.cpp:60
static wxString GetDefaultUserSymbolsPath()
Gets the default path we point users to create projects.
Definition paths.cpp:82
static wxString GetStockDemosPath()
Gets the stock (install) demos path.
Definition paths.cpp:449
static wxString GetLocaleDataPath()
Gets the locales translation data path.
Definition paths.cpp:366
static wxString GetUserSettingsPath()
Return the user configuration path used to store KiCad's configuration files.
Definition paths.cpp:624
static wxString GetStockDesignBlocksPath()
Gets the stock (install) footprints path.
Definition paths.cpp:322
static wxString GetStockFootprintsPath()
Gets the stock (install) footprints path.
Definition paths.cpp:311
static const wxString & GetExecutablePath()
Definition paths.cpp:661
static wxString GetStockScriptingPath()
Gets the stock (install) scripting path.
Definition paths.cpp:344
static void ResolvePossibleSymlinks(wxFileName &aFilename)
static std::string ToStdString(const wxString &aStr)
#define _(s)
This file contains miscellaneous commonly used macros and functions.
#define TO_STR(x)
Definition macros.h:90
wxString GetDocumentsPath()
Retrieves the operating system specific path for a user's documents.
wxString GetUserConfigPath()
Retrieves the operating system specific path for a user's configuration store.
wxString GetUserCachePath()
Retrieves the operating system specific path for user's application cache.
static wxString getBuildDirectoryRoot()
Get the CMake build root directory for the current executable (which assumes the executable is in a b...
Definition paths.cpp:156
#define KICAD_PATH_STR
Definition paths.h:38
#define WIN_STRING_DIR_SEP
Definition paths.h:31
#define UNIX_STRING_DIR_SEP
Definition paths.h:30
std::string path