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 along
17 * with this program. If not, see <http://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 path = wxString::FromUTF8Unchecked( KICAD_LIBRARY_DATA );
291#endif
292
293 return path;
294}
295
296
298{
299 wxFileName fn;
300
301 fn.AssignDir( GetStockEDALibraryPath() );
302 fn.AppendDir( "symbols" );
303
304 return fn.GetPathWithSep();
305}
306
307
309{
310 wxFileName fn;
311
312 fn.AssignDir( GetStockEDALibraryPath() );
313 fn.AppendDir( "footprints" );
314
315 return fn.GetPathWithSep();
316}
317
318
320{
321 wxFileName fn;
322
323 fn.AssignDir( GetStockEDALibraryPath() );
324 fn.AppendDir( "blocks" );
325
326 return fn.GetPathWithSep();
327}
328
329
331{
332 wxFileName fn;
333
334 fn.AssignDir( GetStockEDALibraryPath() );
335 fn.AppendDir( "3dmodels" );
336
337 return fn.GetPathWithSep();
338}
339
340
342{
343 wxFileName fn;
344
345 fn.AssignDir( GetStockDataPath() );
346 fn.AppendDir( "scripting" );
347
348 return fn.GetPathWithSep();
349}
350
351
353{
354 wxFileName fn;
355
356 fn.AssignDir( GetStockEDALibraryPath() );
357 fn.AppendDir( "template" );
358
359 return fn.GetPathWithSep();
360}
361
362
364{
365 wxFileName fn;
366
367 fn.AssignDir( GetStockDataPath() );
368 fn.AppendDir( "internat" );
369
370 return fn.GetPathWithSep();
371}
372
373
375{
376 wxFileName fn;
377
378#if defined( __WXMSW__ )
379 fn.AssignDir( GetExecutablePath() );
380 fn.AppendDir( wxT( "scripting" ) );
381#else
382 fn.AssignDir( PATHS::GetStockDataPath( false ) );
383#endif
384 fn.AppendDir( wxT( "plugins" ) );
385
386 return fn.GetPathWithSep();
387}
388
389
391{
392 wxFileName fn;
393
394#if defined( __WXMSW__ )
395 if( wxGetEnv( wxT( "KICAD_RUN_FROM_BUILD_DIR" ), nullptr ) )
396 {
397 fn.AssignDir( getWindowsKiCadRoot() );
398 }
399 else
400 {
401 fn.AssignDir( GetExecutablePath() );
402 }
403
404 fn.AppendDir( wxT( "plugins" ) );
405#elif defined( __WXMAC__ )
406 fn.AssignDir( getOSXBundleRoot() );
407 fn.AppendDir( wxT( "Contents" ) );
408 fn.AppendDir( wxT( "PlugIns" ) );
409#else
410 wxString envPath;
411
412 if( wxGetEnv( wxT( "KICAD_RUN_FROM_BUILD_DIR" ), nullptr ) )
413 {
414 fn.Assign( wxStandardPaths::Get().GetExecutablePath() );
415 fn.AppendDir( wxT( ".." ) );
416 fn.AppendDir( wxT( "plugins" ) );
417 }
418 // AppImages have a different path to the plugins, otherwise we end up with host system
419 // plugins being loaded.
420 else if( wxGetEnv( wxT( "APPDIR" ), &envPath ) )
421 {
422 fn.Assign( envPath, wxEmptyString );
423 fn.AppendDir( wxT( "usr" ) );
424 fn.AppendDir( wxT( "lib" ) );
425 fn.AppendDir( wxT( "x86_64-linux-gnu" ) );
426 fn.AppendDir( wxT( "kicad" ) );
427 fn.AppendDir( wxT( "plugins" ) );
428 }
429 else
430 {
431 // KICAD_PLUGINDIR = CMAKE_INSTALL_FULL_LIBDIR path is the absolute path
432 // corresponding to the install path used for constructing KICAD_USER_PLUGIN
433 wxString tfname = wxString::FromUTF8Unchecked( KICAD_PLUGINDIR );
434 fn.Assign( tfname, "" );
435 fn.AppendDir( wxT( "kicad" ) );
436 fn.AppendDir( wxT( "plugins" ) );
437 }
438#endif
439
440 fn.AppendDir( wxT( "3d" ) );
441
442 return fn.GetPathWithSep();
443}
444
445
447{
448 wxFileName fn;
449
450 fn.AssignDir( PATHS::GetStockDataPath( false ) );
451 fn.AppendDir( wxT( "demos" ) );
452
453 return fn.GetPathWithSep();
454}
455
456
458{
459 wxString envPath;
460 wxFileName tmp;
461
462 tmp.AssignDir( KIPLATFORM::ENV::GetUserCachePath() );
463
464 // Use KICAD_CACHE_HOME to allow the user to force a specific cache path.
465 if( wxGetEnv( wxT( "KICAD_CACHE_HOME" ), &envPath ) && !envPath.IsEmpty() )
466 {
467 // Override the assignment above with KICAD_CACHE_HOME
468 tmp.AssignDir( envPath );
469 }
470
471 tmp.AppendDir( KICAD_PATH_STR );
472 tmp.AppendDir( GetMajorMinorVersion().ToStdString() );
473
474 return tmp.GetPathWithSep();
475}
476
477
479{
480 wxString path;
481
482#if defined( __WXMAC__ )
483 path = GetOSXKicadDataDir();
484#elif defined( __WXMSW__ )
485 path = getWindowsKiCadRoot() + wxT( "share/doc/kicad" );
486#else
487 path = wxString::FromUTF8Unchecked( KICAD_DOCS );
488#endif
489
490 return path;
491}
492
493
495{
496 wxFileName path;
497 path.AssignDir( wxStandardPaths::Get().GetTempDir() );
498 path.AppendDir( "org.kicad.kicad" );
499 path.AppendDir( "instances" );
500 return path.GetPathWithSep();
501}
502
503
505{
506 wxFileName tmp;
507 getUserDocumentPath( tmp );
508
509 tmp.AppendDir( wxT( "logs" ) );
510
511 return tmp.GetPath();
512}
513
514
515bool PATHS::EnsurePathExists( const wxString& aPath, bool aPathToFile )
516{
517 wxString pathString = aPath;
518 if( !aPathToFile )
519 {
520 // ensures the path is treated fully as directory
521 pathString += wxFileName::GetPathSeparator();
522 }
523
524 wxFileName path( pathString );
525 if( !path.MakeAbsolute() )
526 {
527 return false;
528 }
529
530 if( !wxFileName::DirExists( path.GetPath() ) )
531 {
532 if( !wxFileName::Mkdir( path.GetPath(), wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) )
533 {
534 return false;
535 }
536 }
537
538 return true;
539}
540
541
543{
553
554#ifdef _WIN32
555 // Warn about Controlled folder access
556 wxFileName tmp;
557 getUserDocumentPath( tmp );
558
559 if( !tmp.DirExists() )
560 {
561 wxString msg = wxString::Format(
562 _( "KiCad was unable to use '%s'.\n"
563 "\n"
564 "1. Disable 'Controlled folder access' in Windows settings or Group Policy\n"
565 "2. Make sure no other antivirus software interferes with KiCad\n"
566 "3. Make sure you have correct permissions set up" ),
567 tmp.GetPath() );
568
569 wxMessageBox( msg, _( "Warning" ), wxICON_WARNING );
570 }
571#endif
572}
573
574
575#ifdef __WXMAC__
576wxString PATHS::GetOSXKicadUserDataDir()
577{
578 // According to wxWidgets documentation for GetUserDataDir:
579 // Mac: ~/Library/Application Support/appname
580 wxFileName udir( wxStandardPaths::Get().GetUserDataDir(), wxEmptyString );
581
582 // Since appname is different if started via launcher or standalone binary
583 // map all to "kicad" here
584 udir.RemoveLastDir();
585 udir.AppendDir( wxT( "kicad" ) );
586
587 return udir.GetPath();
588}
589
590
591wxString PATHS::GetOSXKicadMachineDataDir()
592{
593 // 6.0 forward: Same as the main data dir
594 return GetOSXKicadDataDir();
595}
596
597
598wxString PATHS::GetOSXKicadDataDir()
599{
600 wxFileName ddir;
601 ddir.AssignDir( getOSXBundleRoot() );
602 ddir.AppendDir( wxT( "Contents" ) );
603 ddir.AppendDir( wxT( "SharedSupport" ) );
604 return ddir.GetPath();
605}
606#endif
607
608
609#ifdef _WIN32
610wxString PATHS::GetWindowsFontConfigDir()
611{
612 wxFileName fn;
613 fn.AssignDir( getWindowsKiCadRoot() );
614 fn.AppendDir( wxS( "etc" ) );
615 fn.AppendDir( wxS( "fonts" ) );
616
617 return fn.GetPathWithSep();
618}
619
620
621wxString PATHS::getWindowsKiCadRoot()
622{
623 wxFileName root( GetExecutablePath() + wxT( "/../" ) );
624 root.MakeAbsolute();
625
626 return root.GetPathWithSep();
627}
628#endif
629
630
632{
633 static wxString user_settings_path;
634
635 if( user_settings_path.empty() )
636 user_settings_path = CalculateUserSettingsPath();
637
638 return user_settings_path;
639}
640
641
642wxString PATHS::CalculateUserSettingsPath( bool aIncludeVer, bool aUseEnv )
643{
644 wxFileName cfgpath;
645
646 // http://docs.wxwidgets.org/3.0/classwx_standard_paths.html#a7c7cf595d94d29147360d031647476b0
647
648 wxString envstr;
649 if( aUseEnv && wxGetEnv( wxT( "KICAD_CONFIG_HOME" ), &envstr ) && !envstr.IsEmpty() )
650 {
651 // Override the assignment above with KICAD_CONFIG_HOME
652 cfgpath.AssignDir( envstr );
653 }
654 else
655 {
656 cfgpath.AssignDir( KIPLATFORM::ENV::GetUserConfigPath() );
657
658 cfgpath.AppendDir( TO_STR( KICAD_CONFIG_DIR ) );
659 }
660
661 if( aIncludeVer )
662 cfgpath.AppendDir( GetMajorMinorVersion().ToStdString() );
663
664 return cfgpath.GetPath();
665}
666
667
669{
670 static wxString exe_path;
671
672 if( exe_path.empty() )
673 {
674#ifdef __WXMAC__
675 // Use bundle root helper which handles symlink resolution and aux binaries
676 exe_path = getOSXBundleRoot() + wxT( "/" );
677#else
678 wxString envPath;
679
680 // When running inside an AppImage, the bundled ld-linux is invoked as a wrapper
681 // which causes /proc/self/exe to resolve to the dynamic linker rather than the
682 // actual binary. Use APPDIR to construct the correct executable path.
683 if( wxGetEnv( wxT( "APPDIR" ), &envPath ) )
684 {
685 envPath.Replace( WIN_STRING_DIR_SEP, UNIX_STRING_DIR_SEP );
686
687 if( !envPath.EndsWith( wxT( "/" ) ) )
688 envPath += wxT( "/" );
689
690 exe_path = envPath + wxT( "usr/bin/" );
691 }
692 else
693 {
694 wxString bin_dir = wxStandardPaths::Get().GetExecutablePath();
695
696 // Use unix notation for paths. I am not sure this is a good idea,
697 // but it simplifies compatibility between Windows and Unices.
698 // However it is a potential problem in path handling under Windows.
699 bin_dir.Replace( WIN_STRING_DIR_SEP, UNIX_STRING_DIR_SEP );
700
701 // Remove file name form command line:
702 while( bin_dir.Last() != '/' && !bin_dir.IsEmpty() )
703 bin_dir.RemoveLast();
704
705 exe_path = bin_dir;
706 }
707#endif
708 }
709
710 return exe_path;
711}
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:297
static wxString GetDefaultUser3DModelsPath()
Gets the default path we point users to create projects.
Definition paths.cpp:115
static wxString GetInstanceCheckerPath()
Gets the path used for wxSingleInstanceChecker lock files.
Definition paths.cpp:494
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:642
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:374
static wxString GetLogsPath()
Gets a path to use for user-visible log files.
Definition paths.cpp:504
static void EnsureUserPathsExist()
Ensures/creates user default paths.
Definition paths.cpp:542
static wxString GetDocumentationPath()
Gets the documentation path, which is the base path for help files.
Definition paths.cpp:478
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:515
static wxString GetStockPlugins3DPath()
Gets the stock (install) 3d viewer plugins path.
Definition paths.cpp:390
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:330
static wxString GetStockTemplatesPath()
Gets the stock (install) templates path.
Definition paths.cpp:352
static wxString GetUserCachePath()
Gets the stock (install) 3d viewer plugins path.
Definition paths.cpp:457
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:446
static wxString GetLocaleDataPath()
Gets the locales translation data path.
Definition paths.cpp:363
static wxString GetUserSettingsPath()
Return the user configuration path used to store KiCad's configuration files.
Definition paths.cpp:631
static wxString GetStockDesignBlocksPath()
Gets the stock (install) footprints path.
Definition paths.cpp:319
static wxString GetStockFootprintsPath()
Gets the stock (install) footprints path.
Definition paths.cpp:308
static const wxString & GetExecutablePath()
Definition paths.cpp:668
static wxString GetStockScriptingPath()
Gets the stock (install) scripting path.
Definition paths.cpp:341
static void ResolvePossibleSymlinks(wxFileName &aFilename)
#define _(s)
This file contains miscellaneous commonly used macros and functions.
#define TO_STR(x)
Definition macros.h:94
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