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#endif
190
191
192wxString PATHS::GetStockDataPath( bool aRespectRunFromBuildDir )
193{
194 wxString path;
195
196 if( aRespectRunFromBuildDir && wxGetEnv( wxT( "KICAD_RUN_FROM_BUILD_DIR" ), nullptr ) )
197 {
198 // Allow debugging from build dir by placing relevant files/folders in the build root
199#if defined( __WXMAC__ )
200 wxFileName fn = wxStandardPaths::Get().GetExecutablePath();
201
202 fn.RemoveLastDir();
203 fn.RemoveLastDir();
204 fn.RemoveLastDir();
205 fn.RemoveLastDir();
206 path = fn.GetPath();
207#elif defined( __WXMSW__ )
208 path = getWindowsKiCadRoot();
209#else
211#endif
212 }
213 else if( wxGetEnv( wxT( "KICAD_STOCK_DATA_HOME" ), &path ) && !path.IsEmpty() )
214 {
215 return path;
216 }
217 else
218 {
219#if defined( __WXMAC__ )
220 path = GetOSXKicadDataDir();
221#elif defined( __WXMSW__ )
222 path = getWindowsKiCadRoot() + wxT( "share/kicad" );
223#else
224 path = wxString::FromUTF8Unchecked( KICAD_DATA );
225#endif
226 }
227
228 return path;
229}
230
231
232#ifdef _WIN32
233
234wxString PATHS::GetWindowsBaseSharePath()
235{
236 return getWindowsKiCadRoot() + wxT( "share\\" );
237}
238
239#endif
240
241
243{
244 wxString path;
245
246#if defined( __WXMAC__ )
247 path = GetOSXKicadMachineDataDir();
248#elif defined( __WXMSW__ )
249 path = GetStockDataPath( false );
250#else
251 path = wxString::FromUTF8Unchecked( KICAD_LIBRARY_DATA );
252#endif
253
254 return path;
255}
256
257
259{
260 wxString path;
261
262 path = GetStockEDALibraryPath() + wxT( "/symbols" );
263
264 return path;
265}
266
267
269{
270 wxString path;
271
272 path = GetStockEDALibraryPath() + wxT( "/footprints" );
273
274 return path;
275}
276
277
279{
280 wxString path;
281
282 path = GetStockEDALibraryPath() + wxT( "/blocks" );
283
284 return path;
285}
286
287
289{
290 wxString path;
291
292 path = GetStockEDALibraryPath() + wxT( "/3dmodels" );
293
294 return path;
295}
296
297
299{
300 wxString path;
301
302 path = GetStockDataPath() + wxT( "/scripting" );
303
304 return path;
305}
306
307
309{
310 wxString path;
311
312 path = GetStockEDALibraryPath() + wxT( "/template" );
313
314 return path;
315}
316
317
319{
320 wxString path;
321
322 path = GetStockDataPath() + wxT( "/internat" );
323
324 return path;
325}
326
327
329{
330 wxFileName fn;
331
332#if defined( __WXMSW__ )
333 fn.AssignDir( GetExecutablePath() );
334 fn.AppendDir( wxT( "scripting" ) );
335#else
336 fn.AssignDir( PATHS::GetStockDataPath( false ) );
337#endif
338 fn.AppendDir( wxT( "plugins" ) );
339
340 return fn.GetPathWithSep();
341}
342
343
345{
346 wxFileName fn;
347
348#if defined( __WXMSW__ )
349 if( wxGetEnv( wxT( "KICAD_RUN_FROM_BUILD_DIR" ), nullptr ) )
350 {
351 fn.AssignDir( getWindowsKiCadRoot() );
352 }
353 else
354 {
355 fn.AssignDir( GetExecutablePath() );
356 }
357
358 fn.AppendDir( wxT( "plugins" ) );
359#elif defined( __WXMAC__ )
360 fn.Assign( wxStandardPaths::Get().GetPluginsDir(), wxEmptyString );
361
362 // This must be mapped to main bundle for everything but kicad.app
363 const wxArrayString dirs = fn.GetDirs();
364
365 // Check if we are the main kicad binary. in this case, the path will be
366 // /path/to/bundlename.app/Contents/PlugIns
367 // If we are an aux binary, the path will be something like
368 // /path/to/bundlename.app/Contents/Applications/<standalone>.app/Contents/PlugIns
369 if( dirs.GetCount() >= 6 &&
370 dirs[dirs.GetCount() - 4] == wxT( "Applications" ) &&
371 dirs[dirs.GetCount() - 6].Lower().EndsWith( wxT( "app" ) ) )
372 {
373 fn.RemoveLastDir();
374 fn.RemoveLastDir();
375 fn.RemoveLastDir();
376 fn.RemoveLastDir();
377 fn.AppendDir( wxT( "PlugIns" ) );
378 }
379#else
380 wxString envPath;
381
382 // AppImages have a different path to the plugins, otherwise we end up with host sytem
383 // plugins being loaded.
384 if( wxGetEnv( wxT( "APPDIR" ), &envPath ) )
385 {
386 fn.Assign( envPath, wxEmptyString );
387 fn.AppendDir( wxT( "usr" ) );
388 fn.AppendDir( wxT( "lib" ) );
389 fn.AppendDir( wxT( "x86_64-linux-gnu" ) );
390 }
391 else
392 {
393 // KICAD_PLUGINDIR = CMAKE_INSTALL_FULL_LIBDIR path is the absolute path
394 // corresponding to the install path used for constructing KICAD_USER_PLUGIN
395 wxString tfname = wxString::FromUTF8Unchecked( KICAD_PLUGINDIR );
396 fn.Assign( tfname, "" );
397 }
398
399 fn.AppendDir( wxT( "kicad" ) );
400 fn.AppendDir( wxT( "plugins" ) );
401#endif
402
403 fn.AppendDir( wxT( "3d" ) );
404
405 return fn.GetPathWithSep();
406}
407
408
410{
411 wxFileName fn;
412
413 fn.AssignDir( PATHS::GetStockDataPath( false ) );
414 fn.AppendDir( wxT( "demos" ) );
415
416 return fn.GetPathWithSep();
417}
418
419
421{
422 wxString envPath;
423 wxFileName tmp;
424
425 tmp.AssignDir( KIPLATFORM::ENV::GetUserCachePath() );
426
427 // Use KICAD_CACHE_HOME to allow the user to force a specific cache path.
428 if( wxGetEnv( wxT( "KICAD_CACHE_HOME" ), &envPath ) && !envPath.IsEmpty() )
429 {
430 // Override the assignment above with KICAD_CACHE_HOME
431 tmp.AssignDir( envPath );
432 }
433
434 tmp.AppendDir( KICAD_PATH_STR );
435 tmp.AppendDir( GetMajorMinorVersion().ToStdString() );
436
437 return tmp.GetPathWithSep();
438}
439
440
442{
443 wxString path;
444
445#if defined( __WXMAC__ )
446 path = GetOSXKicadDataDir();
447#elif defined( __WXMSW__ )
448 path = getWindowsKiCadRoot() + wxT( "share/doc/kicad" );
449#else
450 path = wxString::FromUTF8Unchecked( KICAD_DOCS );
451#endif
452
453 return path;
454}
455
456
458{
459 wxFileName path;
460 path.AssignDir( wxStandardPaths::Get().GetTempDir() );
461 path.AppendDir( "org.kicad.kicad" );
462 path.AppendDir( "instances" );
463 return path.GetPathWithSep();
464}
465
466
468{
469 wxFileName tmp;
470 getUserDocumentPath( tmp );
471
472 tmp.AppendDir( wxT( "logs" ) );
473
474 return tmp.GetPath();
475}
476
477
478bool PATHS::EnsurePathExists( const wxString& aPath, bool aPathToFile )
479{
480 wxString pathString = aPath;
481 if( !aPathToFile )
482 {
483 // ensures the path is treated fully as directory
484 pathString += wxFileName::GetPathSeparator();
485 }
486
487 wxFileName path( pathString );
488 if( !path.MakeAbsolute() )
489 {
490 return false;
491 }
492
493 if( !wxFileName::DirExists( path.GetPath() ) )
494 {
495 if( !wxFileName::Mkdir( path.GetPath(), wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) )
496 {
497 return false;
498 }
499 }
500
501 return true;
502}
503
504
506{
516
517#ifdef _WIN32
518 // Warn about Controlled folder access
519 wxFileName tmp;
520 getUserDocumentPath( tmp );
521
522 if( !tmp.DirExists() )
523 {
524 wxString msg = wxString::Format(
525 _( "KiCad was unable to use '%s'.\n"
526 "\n"
527 "1. Disable 'Controlled folder access' in Windows settings or Group Policy\n"
528 "2. Make sure no other antivirus software interferes with KiCad\n"
529 "3. Make sure you have correct permissions set up" ),
530 tmp.GetPath() );
531
532 wxMessageBox( msg, _( "Warning" ), wxICON_WARNING );
533 }
534#endif
535}
536
537
538#ifdef __WXMAC__
539wxString PATHS::GetOSXKicadUserDataDir()
540{
541 // According to wxWidgets documentation for GetUserDataDir:
542 // Mac: ~/Library/Application Support/appname
543 wxFileName udir( wxStandardPaths::Get().GetUserDataDir(), wxEmptyString );
544
545 // Since appname is different if started via launcher or standalone binary
546 // map all to "kicad" here
547 udir.RemoveLastDir();
548 udir.AppendDir( wxT( "kicad" ) );
549
550 return udir.GetPath();
551}
552
553
554wxString PATHS::GetOSXKicadMachineDataDir()
555{
556 // 6.0 forward: Same as the main data dir
557 return GetOSXKicadDataDir();
558}
559
560
561wxString PATHS::GetOSXKicadDataDir()
562{
563 // According to wxWidgets documentation for GetDataDir:
564 // Mac: appname.app/Contents/SharedSupport bundle subdirectory
565 wxFileName ddir( wxStandardPaths::Get().GetDataDir(), wxEmptyString );
566
567 // This must be mapped to main bundle for everything but kicad.app
568 const wxArrayString dirs = ddir.GetDirs();
569
570 // Check if we are the main kicad binary. in this case, the path will be
571 // /path/to/bundlename.app/Contents/SharedSupport
572 // If we are an aux binary, the path will be something like
573 // /path/to/bundlename.app/Contents/Applications/<standalone>.app/Contents/SharedSupport
574 if( dirs.GetCount() >= 6 &&
575 dirs[dirs.GetCount() - 4] == wxT( "Applications" ) &&
576 dirs[dirs.GetCount() - 6].Lower().EndsWith( wxT( "app" ) ) )
577 {
578 ddir.RemoveLastDir();
579 ddir.RemoveLastDir();
580 ddir.RemoveLastDir();
581 ddir.RemoveLastDir();
582 ddir.AppendDir( wxT( "SharedSupport" ) );
583 }
584
585 return ddir.GetPath();
586}
587#endif
588
589
590#ifdef _WIN32
591wxString PATHS::GetWindowsFontConfigDir()
592{
593 wxFileName fn;
594 fn.AssignDir( getWindowsKiCadRoot() );
595 fn.AppendDir( wxS( "etc" ) );
596 fn.AppendDir( wxS( "fonts" ) );
597
598 return fn.GetPathWithSep();
599}
600
601
602wxString PATHS::getWindowsKiCadRoot()
603{
604 wxFileName root( GetExecutablePath() + wxT( "/../" ) );
605 root.MakeAbsolute();
606
607 return root.GetPathWithSep();
608}
609#endif
610
611
613{
614 static wxString user_settings_path;
615
616 if( user_settings_path.empty() )
617 user_settings_path = CalculateUserSettingsPath();
618
619 return user_settings_path;
620}
621
622
623wxString PATHS::CalculateUserSettingsPath( bool aIncludeVer, bool aUseEnv )
624{
625 wxFileName cfgpath;
626
627 // http://docs.wxwidgets.org/3.0/classwx_standard_paths.html#a7c7cf595d94d29147360d031647476b0
628
629 wxString envstr;
630 if( aUseEnv && wxGetEnv( wxT( "KICAD_CONFIG_HOME" ), &envstr ) && !envstr.IsEmpty() )
631 {
632 // Override the assignment above with KICAD_CONFIG_HOME
633 cfgpath.AssignDir( envstr );
634 }
635 else
636 {
637 cfgpath.AssignDir( KIPLATFORM::ENV::GetUserConfigPath() );
638
639 cfgpath.AppendDir( TO_STR( KICAD_CONFIG_DIR ) );
640 }
641
642 if( aIncludeVer )
643 cfgpath.AppendDir( GetMajorMinorVersion().ToStdString() );
644
645 return cfgpath.GetPath();
646}
647
648
650{
651 static wxString exe_path;
652
653 if( exe_path.empty() )
654 {
655 wxString bin_dir = wxStandardPaths::Get().GetExecutablePath();
656
657#ifdef __WXMAC__
658 // On OSX GetExecutablePath() will always point to main
659 // bundle directory, e.g., /Applications/kicad.app/
660
661 wxFileName fn( bin_dir );
663
664 if( fn.GetName() == wxT( "kicad" ) || fn.GetName() == wxT( "kicad-cli" ) )
665 {
666 // kicad launcher, so just remove the Contents/MacOS part
667 fn.RemoveLastDir();
668 fn.RemoveLastDir();
669 }
670 else
671 {
672 // standalone binaries live in Contents/Applications/<standalone>.app/Contents/MacOS
673 fn.RemoveLastDir();
674 fn.RemoveLastDir();
675 fn.RemoveLastDir();
676 fn.RemoveLastDir();
677 fn.RemoveLastDir();
678 }
679
680 bin_dir = fn.GetPath() + wxT( "/" );
681#else
682 // Use unix notation for paths. I am not sure this is a good idea,
683 // but it simplifies compatibility between Windows and Unices.
684 // However it is a potential problem in path handling under Windows.
685 bin_dir.Replace( WIN_STRING_DIR_SEP, UNIX_STRING_DIR_SEP );
686
687 // Remove file name form command line:
688 while( bin_dir.Last() != '/' && !bin_dir.IsEmpty() )
689 bin_dir.RemoveLast();
690#endif
691 exe_path = bin_dir;
692 }
693
694 return exe_path;
695}
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:258
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:457
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:242
static wxString CalculateUserSettingsPath(bool aIncludeVer=true, bool aUseEnv=true)
Determines the base path for user settings files.
Definition paths.cpp:623
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:328
static wxString GetLogsPath()
Gets a path to use for user-visible log files.
Definition paths.cpp:467
static void EnsureUserPathsExist()
Ensures/creates user default paths.
Definition paths.cpp:505
static wxString GetDocumentationPath()
Gets the documentation path, which is the base path for help files.
Definition paths.cpp:441
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:478
static wxString GetStockPlugins3DPath()
Gets the stock (install) 3d viewer plugins path.
Definition paths.cpp:344
static wxString GetStockDataPath(bool aRespectRunFromBuildDir=true)
Gets the stock (install) data path, which is the base path for things like scripting,...
Definition paths.cpp:192
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:288
static wxString GetStockTemplatesPath()
Gets the stock (install) templates path.
Definition paths.cpp:308
static wxString GetUserCachePath()
Gets the stock (install) 3d viewer plugins path.
Definition paths.cpp:420
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:409
static wxString GetLocaleDataPath()
Gets the locales translation data path.
Definition paths.cpp:318
static wxString GetUserSettingsPath()
Return the user configuration path used to store KiCad's configuration files.
Definition paths.cpp:612
static wxString GetStockDesignBlocksPath()
Gets the stock (install) footprints path.
Definition paths.cpp:278
static wxString GetStockFootprintsPath()
Gets the stock (install) footprints path.
Definition paths.cpp:268
static const wxString & GetExecutablePath()
Definition paths.cpp:649
static wxString GetStockScriptingPath()
Gets the stock (install) scripting path.
Definition paths.cpp:298
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