KiCad PCB EDA Suite
Loading...
Searching...
No Matches
kicad_cli.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 (C) 2004-2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25
26#include <wx/filename.h>
27#include <wx/log.h>
28#include <wx/stdpaths.h>
29#include <wx/wxcrtvararg.h> //for wxPrintf
30
31#include <kiway.h>
32#include <string_utils.h>
33#include <paths.h>
36#include <systemdirsappend.h>
37#include <trace_helpers.h>
38
39#include <stdexcept>
40
41#include "pgm_kicad.h"
42#include "kicad_manager_frame.h"
43
44#include <build_version.h>
45#include <kiplatform/app.h>
47#include <locale_io.h>
48
49#include "cli/command_jobset.h"
51#include "cli/command_pcb.h"
53#include "cli/command_pcb_drc.h"
73#include "cli/command_fp.h"
77#include "cli/command_sch.h"
78#include "cli/command_sch_erc.h"
80#include "cli/command_sym.h"
84#include "cli/command_version.h"
85#include "cli/exit_codes.h"
86
87// Add this header after all others, to avoid a collision name in a Windows header
88// on mingw.
89#include <wx/app.h>
90
91// a dummy to quiet linking with EDA_BASE_FRAME::config();
92#include <kiface_base.h>
94{
95 // This function should never be called. It is only referenced from
96 // EDA_BASE_FRAME::config() and this is only provided to satisfy the linker,
97 // not to be actually called.
98 wxLogFatalError( wxT( "Unexpected call to Kiface() in kicad/kicad.cpp" ) );
99
100 throw std::logic_error( "Unexpected call to Kiface() in kicad/kicad.cpp" );
101}
102
103
105{
107
108 std::vector<COMMAND_ENTRY> subCommands;
109
110 COMMAND_ENTRY( CLI::COMMAND* aHandler ) : handler( aHandler ){};
111 COMMAND_ENTRY( CLI::COMMAND* aHandler, std::vector<COMMAND_ENTRY> aSub ) :
112 handler( aHandler ), subCommands( aSub ){};
113};
114
162
163
164// clang-format off
165static std::vector<COMMAND_ENTRY> commandStack = {
166 {
167 &jobsetCmd,
168 {
169 {
171 }
172 }
173 },
174 {
175 &fpCmd,
176 {
177 {
179 {
181 }
182 },
183 {
185 }
186 }
187 },
188 {
189 &pcbCmd,
190 {
191 {
192 &pcbDrcCmd
193 },
194 {
196 },
197 {
199 {
221 }
222 }
223 }
224 },
225 {
226 &schCmd,
227 {
228 {
229 &schErcCmd
230 },
231 {
233 {
242 }
243 }
244 }
245 },
246 {
247 &symCmd,
248 {
249 {
251 {
253 }
254 },
255 {
257 }
258 }
259 },
260 {
261 &versionCmd,
262 }
263};
264// clang-format on
265
266
267static void recurseArgParserBuild( argparse::ArgumentParser& aArgParser, COMMAND_ENTRY& aEntry )
268{
269 aArgParser.add_subparser( aEntry.handler->GetArgParser() );
270
271 for( COMMAND_ENTRY& subEntry : aEntry.subCommands )
272 {
273 recurseArgParserBuild( aEntry.handler->GetArgParser(), subEntry );
274 }
275}
276
277
278static COMMAND_ENTRY* recurseArgParserSubCommandUsed( argparse::ArgumentParser& aArgParser,
279 COMMAND_ENTRY& aEntry )
280{
281 COMMAND_ENTRY* cliCmd = nullptr;
282
283 if( aArgParser.is_subcommand_used( aEntry.handler->GetName() ) )
284 {
285 for( COMMAND_ENTRY& subentry : aEntry.subCommands )
286 {
287 cliCmd = recurseArgParserSubCommandUsed( aEntry.handler->GetArgParser(), subentry );
288 if( cliCmd )
289 break;
290 }
291
292 if(!cliCmd)
293 cliCmd = &aEntry;
294 }
295
296 return cliCmd;
297}
298
299
300static void printHelp( argparse::ArgumentParser& argParser )
301{
302 std::stringstream ss;
303 ss << argParser;
304 wxPrintf( From_UTF8( ss.str().c_str() ) );
305}
306
307
309{
311 App().SetAppDisplayName( wxT( "kicad-cli" ) );
312
313#if defined( DEBUG )
314 wxString absoluteArgv0 = wxStandardPaths::Get().GetExecutablePath();
315
316 if( !wxIsAbsolutePath( absoluteArgv0 ) )
317 {
318 wxLogError( wxT( "No meaningful argv[0]" ) );
319 return false;
320 }
321#endif
322
323 if( !InitPgm( true, true) )
324 return false;
325
329 m_bm.Init();
330
331 return true;
332}
333
334
336{
337 argparse::ArgumentParser argParser( std::string( "kicad-cli" ), GetMajorMinorVersion().ToStdString(),
338 argparse::default_arguments::none );
339
340 argParser.add_argument( "-v", ARG_VERSION )
341 .default_value( false )
342 .help( UTF8STDSTR( _( "prints version information and exits" ) ) )
343 .implicit_value( true )
344 .nargs( 0 );
345
346 argParser.add_argument( ARG_HELP_SHORT, ARG_HELP )
347 .default_value( false )
348 .help( UTF8STDSTR( ARG_HELP_DESC ) )
349 .implicit_value( true )
350 .nargs( 0 );
351
352 for( COMMAND_ENTRY& entry : commandStack )
353 {
354 recurseArgParserBuild( argParser, entry );
355 }
356
357 try
358 {
359 // Use the C locale to parse arguments
360 // Otherwise the decimal separator for the locale will be applied
362 argParser.parse_args( m_argcUtf8, m_argvUtf8 );
363 }
364 // std::runtime_error doesn't seem to be enough for the scan<>()
365 catch( const std::exception& err )
366 {
367 wxPrintf( "%s\n", err.what() );
368
369 // find the correct argparser object to output the command usage info
370 COMMAND_ENTRY* cliCmd = nullptr;
371 for( COMMAND_ENTRY& entry : commandStack )
372 {
373 if( argParser.is_subcommand_used( entry.handler->GetName() ) )
374 {
375 cliCmd = recurseArgParserSubCommandUsed( argParser, entry );
376 }
377 }
378
379 // arg parser uses a stream overload for printing the help
380 // we want to intercept so we can wxString the utf8 contents
381 // because on windows our terminal codepage might not be utf8
382 if( cliCmd )
383 cliCmd->handler->PrintHelp();
384 else
385 {
386 printHelp( argParser );
387 }
388
390 }
391
392 if( argParser[ ARG_HELP ] == true )
393 {
394 std::stringstream ss;
395 ss << argParser;
396 wxPrintf( From_UTF8( ss.str().c_str() ) );
397
398 return 0;
399 }
400
401 CLI::COMMAND* cliCmd = nullptr;
402
403 // the version arg gets redirected to the version subcommand
404 if( argParser[ARG_VERSION] == true )
405 {
406 cliCmd = &versionCmd;
407 }
408
409 if( !cliCmd )
410 {
411 for( COMMAND_ENTRY& entry : commandStack )
412 {
413 if( argParser.is_subcommand_used( entry.handler->GetName() ) )
414 {
415 COMMAND_ENTRY* cmdSubEntry = recurseArgParserSubCommandUsed( argParser, entry );
416 if( cmdSubEntry != nullptr )
417 {
418 cliCmd = cmdSubEntry->handler;
419 break;
420 }
421 }
422 }
423 }
424
425 if( cliCmd )
426 {
427 int exitCode = cliCmd->Perform( Kiway );
428
429 if( exitCode != CLI::EXIT_CODES::AVOID_CLOSING )
430 {
431 return exitCode;
432 }
433 else
434 {
435 return 0;
436 }
437 }
438 else
439 {
440 printHelp( argParser );
441
443 }
444}
445
446
448{
450
452 {
454 m_settings_manager->Save();
455 }
456
457 // Destroy everything in PGM_KICAD,
458 // especially wxSingleInstanceCheckerImpl earlier than wxApp and earlier
459 // than static destruction would.
460 Destroy();
461}
462
463
464void PGM_KICAD::MacOpenFile( const wxString& aFileName )
465{
466#if defined( __WXMAC__ )
467 wxFAIL_MSG( "kicad-cli should not call MacOpenFile" );
468#endif
469}
470
471
473{
474 // unlike a normal destructor, this is designed to be called more
475 // than once safely:
476
477 m_bm.End();
478
480}
481
482
484
486
490struct APP_KICAD_CLI : public wxAppConsole
491{
492 APP_KICAD_CLI() : wxAppConsole()
493 {
494 SetPgm( &program );
495
496 // Init the environment each platform wants
498 }
499
500
501 bool OnInit() override
502 {
503 // Perform platform-specific init tasks
504 if( !KIPLATFORM::APP::Init() )
505 return false;
506
507#ifndef DEBUG
508 // Enable logging traces to the console in release build.
509 // This is usually disabled, but it can be useful for users to run to help
510 // debug issues and other problems.
511 if( wxGetEnv( wxS( "KICAD_ENABLE_WXTRACE" ), nullptr ) )
512 {
513 wxLog::EnableLogging( true );
514 wxLog::SetLogLevel( wxLOG_Trace );
515 }
516#endif
517
518 if( !program.OnPgmInit() )
519 {
521 return false;
522 }
523
524 return true;
525 }
526
527 int OnExit() override
528 {
530
531#if defined( __FreeBSD__ )
532 // Avoid wxLog crashing when used in destructors.
533 wxLog::EnableLogging( false );
534#endif
535
536 return wxAppConsole::OnExit();
537 }
538
539 int OnRun() override
540 {
541 try
542 {
543 return program.OnPgmRun();
544 }
545 catch( ... )
546 {
547 Pgm().HandleException( std::current_exception() );
548 }
549
550 return -1;
551 }
552
553 int FilterEvent( wxEvent& aEvent ) override
554 {
555 return Event_Skip;
556 }
557
558#if defined( DEBUG )
562 bool ProcessEvent( wxEvent& aEvent ) override
563 {
564 if( aEvent.GetEventType() == wxEVT_CHAR || aEvent.GetEventType() == wxEVT_CHAR_HOOK )
565 {
566 wxKeyEvent* keyEvent = static_cast<wxKeyEvent*>( &aEvent );
567
568 if( keyEvent )
569 {
570 wxLogTrace( kicadTraceKeyEvent, "APP_KICAD::ProcessEvent %s", dump( *keyEvent ) );
571 }
572 }
573
574 aEvent.Skip();
575 return false;
576 }
577
585 bool OnExceptionInMainLoop() override
586 {
587 try
588 {
589 throw;
590 }
591 catch( ... )
592 {
593 Pgm().HandleException( std::current_exception() );
594 }
595
596 return false; // continue on. Return false to abort program
597 }
598#endif
599};
600
601IMPLEMENT_APP_CONSOLE( APP_KICAD_CLI )
602
603
604// The C++ project manager supports one open PROJECT, so Prj() calls within
605// this link image need this function.
607{
608 return Kiway.Prj();
609}
wxString GetMajorMinorVersion()
Get only the major and minor version in a string major.minor.
argparse::ArgumentParser & GetArgParser()
Definition: command.h:59
const std::string & GetName() const
Definition: command.h:60
void PrintHelp()
Definition: command.cpp:48
int Perform(KIWAY &aKiway)
Entry point to processing commands from args and doing work.
Definition: command.cpp:56
A KIFACE implementation.
Definition: kiface_base.h:39
A minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the same KiCad...
Definition: kiway.h:286
void OnKiwayEnd()
Definition: kiway.cpp:709
virtual PROJECT & Prj() const
Return the PROJECT associated with this KIWAY.
Definition: kiway.cpp:192
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition: locale_io.h:41
virtual wxApp & App()
Return a bare naked wxApp which may come from wxPython, SINGLE_TOP, or kicad.exe.
Definition: pgm_base.cpp:174
int m_argcUtf8
Definition: pgm_base.h:414
std::unique_ptr< SETTINGS_MANAGER > m_settings_manager
Definition: pgm_base.h:375
void Destroy()
Definition: pgm_base.cpp:164
bool InitPgm(bool aHeadless=false, bool aSkipPyInit=false, bool aIsUnitTest=false)
Initialize this program.
Definition: pgm_base.cpp:328
char ** m_argvUtf8
argv parameters converted to utf8 form because wxWidgets has opinions.
Definition: pgm_base.h:412
void BuildArgvUtf8()
Builds the UTF8 based argv variable.
Definition: pgm_base.cpp:283
void HandleException(std::exception_ptr aPtr)
A exception handler to be used at the top level if exceptions bubble up that for.
Definition: pgm_base.cpp:817
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition: pgm_base.h:125
void SaveCommonSettings()
Save the program (process) settings subset which are stored .kicad_common.
Definition: pgm_base.cpp:547
PGM_KICAD extends PGM_BASE to bring in FileHistory() and PdfBrowser() which were moved from EDA_APP i...
Definition: pgm_kicad.h:42
bool OnPgmInit()
Definition: kicad.cpp:86
void Destroy()
Definition: kicad.cpp:409
void MacOpenFile(const wxString &aFileName) override
Specific to MacOSX (not used under Linux or Windows).
Definition: kicad.cpp:396
void OnPgmExit()
Definition: kicad.cpp:374
APP_SETTINGS_BASE * PgmSettings()
Definition: pgm_kicad.h:59
int OnPgmRun()
Definition: kicad.cpp:368
BIN_MOD m_bm
Definition: pgm_kicad.h:72
Container for project specific data.
Definition: project.h:65
T * RegisterSettings(T *aSettings, bool aLoadNow=true)
Take ownership of the pointer passed in.
void SetKiway(KIWAY *aKiway)
Associate this setting manager with the given Kiway.
#define ARG_HELP
Definition: command.h:30
#define UTF8STDSTR(s)
Definition: command.h:27
#define ARG_HELP_DESC
Definition: command.h:32
#define ARG_VERSION
Definition: command.h:29
#define ARG_HELP_SHORT
Definition: command.h:31
#define _(s)
const wxChar *const kicadTraceKeyEvent
Flag to enable wxKeyEvent debug tracing.
static CLI::PCB_EXPORT_SVG_COMMAND exportPcbSvgCmd
Definition: kicad_cli.cpp:130
static CLI::SCH_EXPORT_PLOT_COMMAND exportSchHpglCmd
Definition: kicad_cli.cpp:149
static CLI::SCH_EXPORT_PLOT_COMMAND exportSchSvgCmd
Definition: kicad_cli.cpp:152
static CLI::PCB_EXPORT_3D_COMMAND exportPcbVrmlCmd
Definition: kicad_cli.cpp:126
static CLI::PCB_EXPORT_DXF_COMMAND exportPcbDxfCmd
Definition: kicad_cli.cpp:121
static CLI::SCH_ERC_COMMAND schErcCmd
Definition: kicad_cli.cpp:144
static CLI::PCB_EXPORT_HPGL_COMMAND exportPcbHpglCmd
Definition: kicad_cli.cpp:136
static CLI::PCB_DRC_COMMAND pcbDrcCmd
Definition: kicad_cli.cpp:118
static CLI::PCB_EXPORT_GERBER_COMMAND exportPcbGerberCmd
Definition: kicad_cli.cpp:134
static CLI::FP_EXPORT_SVG_COMMAND fpExportSvgCmd
Definition: kicad_cli.cpp:155
static CLI::PCB_EXPORT_COMMAND exportPcbCmd
Definition: kicad_cli.cpp:141
static CLI::PCB_RENDER_COMMAND pcbRenderCmd
Definition: kicad_cli.cpp:119
static CLI::SYM_UPGRADE_COMMAND symUpgradeCmd
Definition: kicad_cli.cpp:160
static CLI::FP_EXPORT_COMMAND fpExportCmd
Definition: kicad_cli.cpp:154
static CLI::SCH_EXPORT_PYTHONBOM_COMMAND exportSchPythonBomCmd
Definition: kicad_cli.cpp:146
static CLI::FP_UPGRADE_COMMAND fpUpgradeCmd
Definition: kicad_cli.cpp:156
static CLI::SCH_EXPORT_PLOT_COMMAND exportSchPdfCmd
Definition: kicad_cli.cpp:150
static void printHelp(argparse::ArgumentParser &argParser)
Definition: kicad_cli.cpp:300
static CLI::JOBSET_RUN_COMMAND jobsetRunCmd
Definition: kicad_cli.cpp:116
static CLI::PCB_EXPORT_POS_COMMAND exportPcbPosCmd
Definition: kicad_cli.cpp:132
static CLI::PCB_EXPORT_PS_COMMAND exportPcbPsCmd
Definition: kicad_cli.cpp:133
static CLI::SYM_COMMAND symCmd
Definition: kicad_cli.cpp:157
PROJECT & Prj()
Definition: kicad_cli.cpp:606
static CLI::PCB_EXPORT_3D_COMMAND exportPcbStepCmd
Definition: kicad_cli.cpp:123
static CLI::PCB_EXPORT_3D_COMMAND exportPcbPlyCmd
Definition: kicad_cli.cpp:127
static CLI::PCB_EXPORT_GERBERS_COMMAND exportPcbGerbersCmd
Definition: kicad_cli.cpp:135
static PGM_KICAD program
Definition: kicad_cli.cpp:485
static CLI::SCH_EXPORT_BOM_COMMAND exportSchBomCmd
Definition: kicad_cli.cpp:145
static CLI::PCB_EXPORT_IPCD356_COMMAND exportPcbIpcD356Cmd
Definition: kicad_cli.cpp:139
static CLI::SCH_COMMAND schCmd
Definition: kicad_cli.cpp:143
static CLI::PCB_COMMAND pcbCmd
Definition: kicad_cli.cpp:117
static std::vector< COMMAND_ENTRY > commandStack
Definition: kicad_cli.cpp:165
static CLI::PCB_EXPORT_DRILL_COMMAND exportPcbDrillCmd
Definition: kicad_cli.cpp:120
static CLI::PCB_EXPORT_IPC2581_COMMAND exportPcbIpc2581Cmd
Definition: kicad_cli.cpp:138
static CLI::SCH_EXPORT_PLOT_COMMAND exportSchDxfCmd
Definition: kicad_cli.cpp:148
static CLI::JOBSET_COMMAND jobsetCmd
Definition: kicad_cli.cpp:115
static CLI::SYM_EXPORT_COMMAND symExportCmd
Definition: kicad_cli.cpp:158
static CLI::SYM_EXPORT_SVG_COMMAND symExportSvgCmd
Definition: kicad_cli.cpp:159
static COMMAND_ENTRY * recurseArgParserSubCommandUsed(argparse::ArgumentParser &aArgParser, COMMAND_ENTRY &aEntry)
Definition: kicad_cli.cpp:278
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
Definition: kicad_cli.cpp:93
static CLI::PCB_EXPORT_ODB_COMMAND exportPcbOdbCmd
Definition: kicad_cli.cpp:140
static CLI::VERSION_COMMAND versionCmd
Definition: kicad_cli.cpp:161
static CLI::PCB_EXPORT_3D_COMMAND exportPcbStlCmd
Definition: kicad_cli.cpp:128
static CLI::PCB_EXPORT_PDF_COMMAND exportPcbPdfCmd
Definition: kicad_cli.cpp:131
static CLI::PCB_EXPORT_3D_COMMAND exportPcbXaoCmd
Definition: kicad_cli.cpp:125
static void recurseArgParserBuild(argparse::ArgumentParser &aArgParser, COMMAND_ENTRY &aEntry)
Definition: kicad_cli.cpp:267
static CLI::SCH_EXPORT_NETLIST_COMMAND exportSchNetlistCmd
Definition: kicad_cli.cpp:147
static CLI::SCH_EXPORT_PLOT_COMMAND exportSchPostscriptCmd
Definition: kicad_cli.cpp:151
static CLI::PCB_EXPORT_GENCAD_COMMAND exportPcbGencadCmd
Definition: kicad_cli.cpp:137
static CLI::PCB_EXPORT_3D_COMMAND exportPcbStepzCmd
Definition: kicad_cli.cpp:129
static CLI::FP_COMMAND fpCmd
Definition: kicad_cli.cpp:153
static CLI::PCB_EXPORT_3D_COMMAND exportPcbGlbCmd
Definition: kicad_cli.cpp:122
static CLI::SCH_EXPORT_COMMAND exportSchCmd
Definition: kicad_cli.cpp:142
static CLI::PCB_EXPORT_3D_COMMAND exportPcbBrepCmd
Definition: kicad_cli.cpp:124
#define KFCTL_CPP_PROJECT_SUITE
Running under C++ project mgr, possibly with others.
Definition: kiway.h:161
#define KFCTL_CLI
Running as CLI app.
Definition: kiway.h:162
static const int ERR_ARGS
Definition: exit_codes.h:31
static const int AVOID_CLOSING
Definition: exit_codes.h:28
bool Init()
Perform application-specific initialization tasks.
Definition: unix/app.cpp:40
void Init()
Perform environment initialization tasks.
void SetPgm(PGM_BASE *pgm)
Definition: pgm_base.cpp:907
PGM_BASE & Pgm()
The global program "get" accessor.
Definition: pgm_base.cpp:893
KIWAY Kiway(KFCTL_STANDALONE)
std::vector< FAB_LAYER_COLOR > dummy
wxString From_UTF8(const char *cstring)
Not publicly visible because most of the action is in PGM_KICAD these days.
Definition: kicad_cli.cpp:491
int OnExit() override
Definition: kicad_cli.cpp:527
bool OnInit() override
Definition: kicad_cli.cpp:501
int FilterEvent(wxEvent &aEvent) override
Definition: kicad_cli.cpp:553
int OnRun() override
Definition: kicad_cli.cpp:539
void End()
Definition: bin_mod.cpp:50
void Init()
Definition: bin_mod.cpp:38
void InitSettings(APP_SETTINGS_BASE *aPtr)
Takes ownership of a new application settings object.
Definition: bin_mod.h:53
Definition: kicad_cli.cpp:105
COMMAND_ENTRY(CLI::COMMAND *aHandler)
Definition: kicad_cli.cpp:110
COMMAND_ENTRY(CLI::COMMAND *aHandler, std::vector< COMMAND_ENTRY > aSub)
Definition: kicad_cli.cpp:111
CLI::COMMAND * handler
Definition: kicad_cli.cpp:106
std::vector< COMMAND_ENTRY > subCommands
Definition: kicad_cli.cpp:108
System directories search utilities.
wxString dump(const wxArrayString &aArray)
Debug helper for printing wxArrayString contents.
wxLogTrace helper definitions.