Shove kicad2step into pcbnew itself with a new cli

This commit is contained in:
Mark Roszko 2022-10-04 01:53:37 +00:00
parent c5f8587898
commit fb8a4c10f7
132 changed files with 15052 additions and 312 deletions

View File

@ -155,10 +155,6 @@ cmake_dependent_option( KICAD_WIN32_INSTALL_PDBS
OFF "WIN32" OFF "WIN32"
OFF ) OFF )
option( KICAD_STEP_EXPORT_LIB
"Build and use kicad2step as a library, meant for debugging"
OFF )
option( KICAD_USE_3DCONNEXION option( KICAD_USE_3DCONNEXION
"Build KiCad with support for 3Dconnexion devices (Currently only for Mac/MSW)" "Build KiCad with support for 3Dconnexion devices (Currently only for Mac/MSW)"
OFF ) OFF )

View File

@ -53,6 +53,7 @@ add_executable( bitmap2component WIN32 MACOSX_BUNDLE
target_link_libraries( bitmap2component target_link_libraries( bitmap2component
common common
argparse::argparse
${wxWidgets_LIBRARIES} ${wxWidgets_LIBRARIES}
potrace potrace
) )

View File

@ -287,6 +287,12 @@ set( COMMON_SRCS
${PLUGINS_CADSTAR_SRCS} ${PLUGINS_CADSTAR_SRCS}
${PLUGINS_EAGLE_SRCS} ${PLUGINS_EAGLE_SRCS}
${FONT_SRCS} ${FONT_SRCS}
cli/command_export_kicad_pcbnew.cpp
cli/command_export_pcb_svg.cpp
cli/command_export_pcbnew.cpp
cli/command_export_step.cpp
jobs/job_export_step.cpp
jobs/job_dispatcher.cpp
advanced_config.cpp advanced_config.cpp
array_axis.cpp array_axis.cpp
array_options.cpp array_options.cpp
@ -481,6 +487,7 @@ target_link_libraries( common
compoundfilereader compoundfilereader
pcm_settings pcm_settings
nanodbc # for now; maybe hoist out of common nanodbc # for now; maybe hoist out of common
argparse::argparse
${Boost_LIBRARIES} ${Boost_LIBRARIES}
${CURL_LIBRARIES} ${CURL_LIBRARIES}
${wxWidgets_LIBRARIES} ${wxWidgets_LIBRARIES}
@ -574,6 +581,7 @@ set( PCB_COMMON_SRCS
${CMAKE_SOURCE_DIR}/pcbnew/pcb_painter.cpp ${CMAKE_SOURCE_DIR}/pcbnew/pcb_painter.cpp
${CMAKE_SOURCE_DIR}/pcbnew/plugins/kicad/pcb_parser.cpp ${CMAKE_SOURCE_DIR}/pcbnew/plugins/kicad/pcb_parser.cpp
${CMAKE_SOURCE_DIR}/pcbnew/pcb_plot_params.cpp ${CMAKE_SOURCE_DIR}/pcbnew/pcb_plot_params.cpp
${CMAKE_SOURCE_DIR}/pcbnew/pcb_plot_svg.cpp
${CMAKE_SOURCE_DIR}/pcbnew/pcb_screen.cpp ${CMAKE_SOURCE_DIR}/pcbnew/pcb_screen.cpp
${CMAKE_SOURCE_DIR}/pcbnew/pcb_view.cpp ${CMAKE_SOURCE_DIR}/pcbnew/pcb_view.cpp
${CMAKE_SOURCE_DIR}/pcbnew/pcbnew_settings.cpp ${CMAKE_SOURCE_DIR}/pcbnew/pcbnew_settings.cpp

48
common/cli/command.h Normal file
View File

@ -0,0 +1,48 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2022 Mark Roszko <mark.roszko@gmail.com>
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CLI_COMMAND_H
#define CLI_COMMAND_H
#include <argparse/argparse.hpp>
#include <kiway.h>
namespace CLI
{
struct COMMAND
{
COMMAND( std::string aName ) : m_name( aName ), m_argParser( aName ){};
virtual int Perform( KIWAY& aKiway ) const = 0;
virtual ~COMMAND() = default;
argparse::ArgumentParser& GetArgParser() { return m_argParser; }
const std::string& GetName() const { return m_name; }
protected:
std::string m_name;
argparse::ArgumentParser m_argParser;
};
}
#endif

View File

@ -0,0 +1,31 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2022 Mark Roszko <mark.roszko@gmail.com>
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "command_export_kicad_pcbnew.h"
CLI::EXPORT_KICAD_PCBNEW_COMMAND::EXPORT_KICAD_PCBNEW_COMMAND() : COMMAND( "export-pcb" )
{
}
int CLI::EXPORT_KICAD_PCBNEW_COMMAND::Perform( KIWAY& aKiway ) const
{
return 0;
}

View File

@ -0,0 +1,36 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2022 Mark Roszko <mark.roszko@gmail.com>
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef COMMAND_EXPORT_KICAD_PCBNEW_H
#define COMMAND_EXPORT_KICAD_PCBNEW_H
#include "command.h"
namespace CLI
{
struct EXPORT_KICAD_PCBNEW_COMMAND : public COMMAND
{
EXPORT_KICAD_PCBNEW_COMMAND();
int Perform( KIWAY& aKiway ) const override;
};
}
#endif

View File

@ -0,0 +1,126 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2022 Mark Roszko <mark.roszko@gmail.com>
* Copyright (C) 2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "command_export_pcb_svg.h"
#include "exit_codes.h"
#include "jobs/job_export_pcb_svg.h"
#include <kiface_base.h>
#include <layer_ids.h>
#include <regex>
#include <macros.h>
#include <wx/tokenzr.h>
#define ARG_PAGE_SIZE "--page-size-mode"
#define ARG_MIRROR "--mirror"
#define ARG_BLACKANDWHITE "--black-and-white"
#define ARG_OUTPUT "--output"
#define ARG_THEME "--theme"
#define ARG_LAYERS "--layers"
#define ARG_INPUT "input"
CLI::EXPORT_PCB_SVG_COMMAND::EXPORT_PCB_SVG_COMMAND() : COMMAND( "svg" )
{
m_argParser.add_argument( "-o", ARG_OUTPUT )
.default_value( std::string() )
.help( "output file name" );
m_argParser.add_argument( "-l", ARG_LAYERS )
.default_value( std::string() )
.help( "comma separated list of untranslated layer names to include such as F.Cu,B.Cu" );
m_argParser.add_argument( "-m", ARG_MIRROR )
.help( "Mirror the board (useful for trying to show bottom layers)" )
.implicit_value( true )
.default_value( false );
m_argParser.add_argument( "-t", ARG_THEME )
.default_value( std::string() )
.help( "Color theme to use (will default to pcbnew settings)" );
m_argParser.add_argument( ARG_BLACKANDWHITE )
.help( "Black and white only" )
.implicit_value( true )
.default_value( false );
m_argParser.add_argument( ARG_PAGE_SIZE )
.help( "Set page sizing mode (0 = page with frame and title block, 1 = current page size, 2 = board area only)" )
.default_value( 0 );
m_argParser.add_argument( ARG_INPUT ).help( "input file" );
}
int CLI::EXPORT_PCB_SVG_COMMAND::Perform( KIWAY& aKiway ) const
{
std::map<std::string, LSET> layerMasks;
for( int layer = 0; layer < PCB_LAYER_ID_COUNT; ++layer )
{
std::string untranslated = TO_UTF8( wxString( LSET::Name( PCB_LAYER_ID( layer ) ) ) );
//m_layerIndices[untranslated] = PCB_LAYER_ID( layer );
layerMasks[untranslated] = LSET( PCB_LAYER_ID( layer ) );
}
layerMasks["*.Cu"] = LSET::AllCuMask();
layerMasks["*In.Cu"] = LSET::InternalCuMask();
layerMasks["F&B.Cu"] = LSET( 2, F_Cu, B_Cu );
layerMasks["*.Adhes"] = LSET( 2, B_Adhes, F_Adhes );
layerMasks["*.Paste"] = LSET( 2, B_Paste, F_Paste );
layerMasks["*.Mask"] = LSET( 2, B_Mask, F_Mask );
layerMasks["*.SilkS"] = LSET( 2, B_SilkS, F_SilkS );
layerMasks["*.Fab"] = LSET( 2, B_Fab, F_Fab );
layerMasks["*.CrtYd"] = LSET( 2, B_CrtYd, F_CrtYd );
JOB_EXPORT_PCB_SVG* svgJob = new JOB_EXPORT_PCB_SVG( true );
svgJob->m_mirror = m_argParser.get<bool>( ARG_MIRROR );
svgJob->m_blackAndWhite = m_argParser.get<bool>( ARG_BLACKANDWHITE );
svgJob->m_pageSizeMode = m_argParser.get<int>( ARG_PAGE_SIZE );
svgJob->m_filename = FROM_UTF8( m_argParser.get<std::string>( ARG_INPUT ).c_str() );
svgJob->m_outputFile = FROM_UTF8( m_argParser.get<std::string>( ARG_OUTPUT ).c_str() );
svgJob->m_colorTheme = FROM_UTF8( m_argParser.get<std::string>( ARG_THEME ).c_str() );
wxString layers = FROM_UTF8( m_argParser.get<std::string>( ARG_LAYERS ).c_str() );
LSET layerMask = LSET::AllCuMask();
if( !layers.IsEmpty() )
{
layerMask.reset();
wxStringTokenizer layerTokens( layers, "," );
while( layerTokens.HasMoreTokens() )
{
std::string token = TO_UTF8(layerTokens.GetNextToken());
if( layerMasks.count( token ) )
{
layerMask |= layerMasks[token];
}
}
}
svgJob->m_printMaskLayer = layerMask;
int exitCode = aKiway.ProcessJob( KIWAY::FACE_PCB, svgJob );
return exitCode;
}

View File

@ -0,0 +1,36 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2022 Mark Roszko <mark.roszko@gmail.com>
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef COMMAND_EXPORT_PCB_SVG_H
#define COMMAND_EXPORT_PCB_SVG_H
#include "command.h"
namespace CLI
{
struct EXPORT_PCB_SVG_COMMAND : public COMMAND
{
EXPORT_PCB_SVG_COMMAND();
int Perform( KIWAY& aKiway ) const override;
};
} // namespace CLI
#endif

View File

@ -0,0 +1,30 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2022 Mark Roszko <mark.roszko@gmail.com>
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "command_export_pcbnew.h"
CLI::EXPORT_PCBNEW_COMMAND::EXPORT_PCBNEW_COMMAND() : COMMAND( "export" )
{
}
int CLI::EXPORT_PCBNEW_COMMAND::Perform( KIWAY& aKiway ) const
{
return 0;
}

View File

@ -0,0 +1,36 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2022 Mark Roszko <mark.roszko@gmail.com>
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef COMMAND_EXPORT_PCBNEW_H
#define COMMAND_EXPORT_PCBNEW_H
#include "command.h"
namespace CLI
{
struct EXPORT_PCBNEW_COMMAND : public COMMAND
{
EXPORT_PCBNEW_COMMAND();
int Perform( KIWAY& aKiway ) const override;
};
}
#endif

View File

@ -0,0 +1,174 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2022 Mark Roszko <mark.roszko@gmail.com>
* Copyright (C) 2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "command_export_step.h"
#include "exit_codes.h"
#include "jobs/job_export_step.h"
#include <kiface_base.h>
#include <regex>
#include <macros.h>
#define ARG_DRILL_ORIGIN "--drill-origin"
#define ARG_GRID_ORIGIN "--grid-origin"
#define ARG_NO_VIRTUAL "--no-virtual"
#define ARG_SUBST_MODELS "--subst-models"
#define ARG_FORCE "--force"
#define ARG_OUTPUT "--output"
#define ARG_INPUT "input"
#define ARG_MIN_DISTANCE "--min-distance"
#define ARG_USER_ORIGIN "--user-origin"
#define ARG_GUI "--gui"
#define REGEX_QUANTITY "([\\s]*[+-]?[\\d]*[.]?[\\d]*)"
#define REGEX_DELIMITER "(?:[\\s]*x)"
#define REGEX_UNIT "([m]{2}|(?:in))"
CLI::EXPORT_STEP_COMMAND::EXPORT_STEP_COMMAND() : COMMAND( "step" )
{
m_argParser.add_argument( ARG_DRILL_ORIGIN )
.help( "Use Drill Origin for output origin" )
.implicit_value( true )
.default_value( false );
m_argParser.add_argument( ARG_GRID_ORIGIN )
.help( "Use Grid Origin for output origin" )
.implicit_value( true )
.default_value( false );
m_argParser.add_argument( ARG_NO_VIRTUAL )
.help( "Exclude 3D models for components with 'virtual' attribute" )
.implicit_value( true )
.default_value( false );
m_argParser.add_argument( "--subst-models" )
.help( "Substitute STEP or IGS models with the same name in place of VRML models" )
.implicit_value( true )
.default_value( false );
m_argParser.add_argument( ARG_FORCE, "-f" )
.help( "overwrite output file" )
.implicit_value( true )
.default_value( false );
m_argParser.add_argument( ARG_GUI )
.help( "Show GUI (log window)" )
.implicit_value( true )
.default_value( false );
m_argParser.add_argument( ARG_MIN_DISTANCE )
.default_value( std::string() )
.help( "Minimum distance between points to treat them as separate ones (default 0.01mm)" );
m_argParser.add_argument( ARG_USER_ORIGIN )
.default_value( std::string() )
.help( "User-specified output origin ex. 1x1in, 1x1inch, 25.4x25.4mm (default mm)" );
m_argParser.add_argument( "-o", ARG_OUTPUT )
.default_value( std::string() )
.help( "output file name" );
m_argParser.add_argument( ARG_INPUT ).help( "input file" );
}
int CLI::EXPORT_STEP_COMMAND::Perform( KIWAY& aKiway ) const
{
JOB_EXPORT_STEP* step = new JOB_EXPORT_STEP( true );
step->m_useDrillOrigin = m_argParser.get<bool>( ARG_DRILL_ORIGIN );
step->m_useGridOrigin = m_argParser.get<bool>( ARG_GRID_ORIGIN );
step->m_includeVirtual = !m_argParser.get<bool>( ARG_NO_VIRTUAL );
step->m_substModels = m_argParser.get<bool>( ARG_SUBST_MODELS );
step->m_overwrite = m_argParser.get<bool>( ARG_FORCE );
step->m_filename = FROM_UTF8( m_argParser.get<std::string>( ARG_INPUT ).c_str() );
step->m_outputFile = FROM_UTF8( m_argParser.get<std::string>( ARG_OUTPUT ).c_str() );
step->m_gui = m_argParser.get<bool>( ARG_GUI );
wxString userOrigin = FROM_UTF8( m_argParser.get<std::string>( ARG_USER_ORIGIN ).c_str() );
if( !userOrigin.IsEmpty() )
{
std::regex re_pattern( REGEX_QUANTITY REGEX_DELIMITER REGEX_QUANTITY REGEX_UNIT,
std::regex_constants::icase );
std::smatch sm;
std::string str( userOrigin.ToUTF8() );
std::regex_search( str, sm, re_pattern );
step->m_xOrigin = atof( sm.str( 1 ).c_str() );
step->m_yOrigin = atof( sm.str( 2 ).c_str() );
std::string tunit( sm[3] );
if( tunit.size() > 0 ) // No unit accepted ( default = mm )
{
if( ( !sm.str( 1 ).compare( " " ) || !sm.str( 2 ).compare( " " ) )
|| ( sm.size() != 4 ) )
{
std::cout << m_argParser;
return CLI::EXIT_CODES::ERR_ARGS;
}
// only in, inch and mm are valid:
if( !tunit.compare( "in" ) || !tunit.compare( "inch" ) )
{
step->m_xOrigin *= 25.4;
step->m_yOrigin *= 25.4;
}
else if( tunit.compare( "mm" ) )
{
std::cout << m_argParser;
return CLI::EXIT_CODES::ERR_ARGS;
}
}
}
wxString minDistance = FROM_UTF8( m_argParser.get<std::string>( ARG_MIN_DISTANCE ).c_str() );
if( !minDistance.IsEmpty() )
{
std::istringstream istr;
istr.str( std::string( minDistance.ToUTF8() ) );
istr >> step->m_minDistance;
if( istr.fail() )
{
std::cout << m_argParser;
return CLI::EXIT_CODES::ERR_ARGS;
}
if( !istr.eof() )
{
std::string tunit;
istr >> tunit;
if( !tunit.compare( "in" ) || !tunit.compare( "inch" ) )
{
step->m_minDistance *= 25.4;
}
else if( tunit.compare( "mm" ) )
{
std::cout << m_argParser;
return CLI::EXIT_CODES::ERR_ARGS;
}
}
}
int exitCode = aKiway.ProcessJob( KIWAY::FACE_PCB, step );
return exitCode;
}

View File

@ -0,0 +1,36 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2022 Mark Roszko <mark.roszko@gmail.com>
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef COMMAND_EXPORT_STEP_H
#define COMMAND_EXPORT_STEP_H
#include "command.h"
namespace CLI
{
struct EXPORT_STEP_COMMAND : public COMMAND
{
EXPORT_STEP_COMMAND();
int Perform( KIWAY& aKiway ) const override;
};
}
#endif

38
common/cli/exit_codes.h Normal file
View File

@ -0,0 +1,38 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2022 Mark Roszko <mark.roszko@gmail.com>
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CLI_EXIT_CODES_H
#define CLI_EXIT_CODES_H
namespace CLI
{
namespace EXIT_CODES
{
static const int AVOID_CLOSING = -1;
static const int SUCCESS = 0;
static const int OK = 0;
static const int ERR_ARGS = 1;
static const int ERR_UNKNOWN = 2;
static const int ERR_INVALID_INPUT_FILE = 3;
static const int ERR_INVALID_OUTPUT_CONFLICT = 4;
};
}
#endif

42
common/jobs/job.h Normal file
View File

@ -0,0 +1,42 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2022 Mark Roszko <mark.roszko@gmail.com>
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef JOB_H
#define JOB_H
/**
* An simple container class that lets us dispatch output jobs to kifaces
*/
class JOB
{
public:
JOB( const std::string& aType, bool aIsCli ) : m_type( aType ), m_isCli( aIsCli ) {}
virtual ~JOB() {}
const std::string& GetType() const { return m_type; };
bool IsCli() const { return m_isCli; };
private:
std::string m_type;
bool m_isCli;
};
#endif

View File

@ -0,0 +1,38 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2022 Mark Roszko <mark.roszko@gmail.com>
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cli/exit_codes.h>
#include <jobs/job_dispatcher.h>
void JOB_DISPATCHER::Register( const std::string& aJobTypeName,
std::function<int( JOB* job )> aHandler )
{
m_jobHandlers.emplace( aJobTypeName, aHandler );
}
int JOB_DISPATCHER::RunJob( JOB* job )
{
if( m_jobHandlers.count( job->GetType() ) )
{
return m_jobHandlers[job->GetType()]( job );
}
return CLI::EXIT_CODES::ERR_UNKNOWN;
}

View File

@ -0,0 +1,39 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2022 Mark Roszko <mark.roszko@gmail.com>
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef JOB_DISPATCHER_H
#define JOB_DISPATCHER_H
#include <functional>
#include <string>
#include <map>
#include <jobs/job.h>
class JOB_DISPATCHER
{
public:
void Register( const std::string& aJobTypeName, std::function<int( JOB* job )> aHandler );
int RunJob( JOB* job );
private:
std::map<std::string, std::function<int( JOB* job )>> m_jobHandlers;
};
#endif

View File

@ -0,0 +1,49 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2022 Mark Roszko <mark.roszko@gmail.com>
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef JOB_EXPORT_PCB_SVG_H
#define JOB_EXPORT_PCB_SVG_H
#include <layer_ids.h>
#include <wx/string.h>
#include "job.h"
class JOB_EXPORT_PCB_SVG : public JOB
{
public:
JOB_EXPORT_PCB_SVG( bool aIsCli ) :
JOB( "svg", aIsCli ), m_filename(), m_outputFile(), m_colorTheme(), m_mirror( false ),
m_blackAndWhite( false ), m_pageSizeMode( 0 ), m_printMaskLayer()
{
}
wxString m_filename;
wxString m_outputFile;
wxString m_colorTheme;
bool m_mirror;
bool m_blackAndWhite;
int m_pageSizeMode;
LSET m_printMaskLayer;
};
#endif

View File

@ -0,0 +1,34 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2022 Mark Roszko <mark.roszko@gmail.com>
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "jobs/job_export_step.h"
JOB_EXPORT_STEP::JOB_EXPORT_STEP( bool aIsCli ) : JOB( "step", aIsCli )
{
m_overwrite = false;
m_useGridOrigin = false;
m_useDrillOrigin = false;
m_includeVirtual = true;
m_substModels = false;
m_xOrigin = 0.0;
m_yOrigin = 0.0;
m_minDistance = 0.0;
m_gui = false;
}

View File

@ -0,0 +1,45 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2022 Mark Roszko <mark.roszko@gmail.com>
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef JOB_EXPORT_STEP_H
#define JOB_EXPORT_STEP_H
#include <wx/string.h>
#include "job.h"
class JOB_EXPORT_STEP : public JOB
{
public:
JOB_EXPORT_STEP( bool aIsCli );
bool m_overwrite;
bool m_useGridOrigin;
bool m_useDrillOrigin;
bool m_includeVirtual;
bool m_substModels;
wxString m_filename;
wxString m_outputFile;
double m_xOrigin;
double m_yOrigin;
double m_minDistance;
bool m_gui;
};
#endif

View File

@ -654,6 +654,14 @@ bool KIWAY::ProcessEvent( wxEvent& aEvent )
} }
int KIWAY::ProcessJob( KIWAY::FACE_T aFace, JOB* job )
{
KIFACE* kiface = KiFACE( aFace );
return kiface->HandleJob( job );
}
void KIWAY::OnKiCadExit() void KIWAY::OnKiCadExit()
{ {
if( m_ctl & KFCTL_CPP_PROJECT_SUITE ) if( m_ctl & KFCTL_CPP_PROJECT_SUITE )

View File

@ -124,6 +124,8 @@ PGM_BASE::PGM_BASE()
m_Printing = false; m_Printing = false;
m_Quitting = false; m_Quitting = false;
m_ModalDialogCount = 0; m_ModalDialogCount = 0;
m_argcUtf8 = 0;
m_argvUtf8 = nullptr;
setLanguageId( wxLANGUAGE_DEFAULT ); setLanguageId( wxLANGUAGE_DEFAULT );
@ -134,6 +136,13 @@ PGM_BASE::PGM_BASE()
PGM_BASE::~PGM_BASE() PGM_BASE::~PGM_BASE()
{ {
Destroy(); Destroy();
for( size_t n = 0; n < m_argcUtf8; n++ )
{
delete m_argvUtf8[n];
}
delete m_argvUtf8;
} }
@ -370,6 +379,21 @@ void PGM_BASE::sentryPrompt()
#endif #endif
void PGM_BASE::BuildArgvUtf8()
{
const wxArrayString& argArray = App().argv.GetArguments();
m_argcUtf8 = argArray.size();
m_argvUtf8 = new char*[m_argcUtf8 + 1];
for( size_t n = 0; n < m_argcUtf8; n++ )
{
m_argvUtf8[n] = wxStrdup( argArray[n].ToUTF8() );
}
m_argvUtf8[m_argcUtf8] = NULL; // null terminator at end of argv
}
bool PGM_BASE::InitPgm( bool aHeadless, bool aSkipPyInit ) bool PGM_BASE::InitPgm( bool aHeadless, bool aSkipPyInit )
{ {
// Just make sure we init precreate any folders early for later code // Just make sure we init precreate any folders early for later code

View File

@ -40,6 +40,7 @@
#include <wx/stdpaths.h> #include <wx/stdpaths.h>
#include <wx/snglinst.h> #include <wx/snglinst.h>
#include <wx/html/htmlwin.h> #include <wx/html/htmlwin.h>
#include <argparse/argparse.hpp>
#include <kiway.h> #include <kiway.h>
#include <pgm_base.h> #include <pgm_base.h>
@ -48,9 +49,14 @@
#include <confirm.h> #include <confirm.h>
#include <settings/settings_manager.h> #include <settings/settings_manager.h>
#include <kicad_build_version.h>
#include <kiplatform/app.h> #include <kiplatform/app.h>
#include <kiplatform/environment.h> #include <kiplatform/environment.h>
#include "cli/command_export_pcbnew.h"
#include "cli/command_export_pcb_svg.h"
#include "cli/command_export_step.h"
#include "cli/exit_codes.h"
// Only a single KIWAY is supported in this single_top top level component, // Only a single KIWAY is supported in this single_top top level component,
// which is dedicated to loading only a single DSO. // which is dedicated to loading only a single DSO.
@ -274,8 +280,36 @@ struct APP_SINGLE_TOP : public wxApp
IMPLEMENT_APP( APP_SINGLE_TOP ) IMPLEMENT_APP( APP_SINGLE_TOP )
struct COMMAND_ENTRY
{
CLI::COMMAND* handler;
std::vector<COMMAND_ENTRY> subCommands;
COMMAND_ENTRY( CLI::COMMAND* aHandler ) : handler( aHandler ){};
COMMAND_ENTRY( CLI::COMMAND* aHandler, std::vector<COMMAND_ENTRY> aSub ) :
handler( aHandler ), subCommands( aSub ) {};
};
#ifdef PCBNEW
static CLI::EXPORT_STEP_COMMAND stepCmd{};
static CLI::EXPORT_PCB_SVG_COMMAND svgCmd{};
static CLI::EXPORT_PCBNEW_COMMAND exportCmd{};
static std::vector<COMMAND_ENTRY> commandStack = {
{ &exportCmd, { &stepCmd, &svgCmd } }
};
#else
static std::vector<COMMAND_ENTRY> commandStack = {
};
#endif
bool PGM_SINGLE_TOP::OnPgmInit() bool PGM_SINGLE_TOP::OnPgmInit()
{ {
PGM_BASE::BuildArgvUtf8();
#if defined(DEBUG) #if defined(DEBUG)
wxString absoluteArgv0 = wxStandardPaths::Get().GetExecutablePath(); wxString absoluteArgv0 = wxStandardPaths::Get().GetExecutablePath();
@ -285,10 +319,62 @@ bool PGM_SINGLE_TOP::OnPgmInit()
return false; return false;
} }
#endif #endif
wxString pgm_name;
if( App().argc == 0 )
pgm_name = wxT( "kicad" );
else
pgm_name = wxFileName( App().argv[0] ).GetName().Lower();
argparse::ArgumentParser argParser( std::string( pgm_name.utf8_str() ), KICAD_MAJOR_MINOR_VERSION );
for(COMMAND_ENTRY& entry : commandStack)
{
argParser.add_subparser( entry.handler->GetArgParser() );
for( COMMAND_ENTRY& subentry : entry.subCommands )
{
entry.handler->GetArgParser().add_subparser( subentry.handler->GetArgParser() );
}
}
try
{
argParser.parse_args( m_argcUtf8, m_argvUtf8 );
}
catch( const std::runtime_error& err )
{
// this provides the nice pretty print
std::cerr << err.what() << std::endl;
std::cerr << argParser;
std::exit( CLI::EXIT_CODES::ERR_ARGS );
}
bool cliCmdRequested = false;
CLI::COMMAND* cliCmd = nullptr;
for( COMMAND_ENTRY& entry : commandStack )
{
if( argParser.is_subcommand_used( entry.handler->GetName() ) )
{
for( COMMAND_ENTRY& subentry : entry.subCommands )
{
if( entry.handler->GetArgParser().is_subcommand_used( subentry.handler->GetName() ) )
{
cliCmd = subentry.handler;
cliCmdRequested = true;
}
}
if( !cliCmdRequested )
{
cliCmd = entry.handler;
}
}
}
// Not all kicad applications use the python stuff. skip python init // Not all kicad applications use the python stuff. skip python init
// for these apps. // for these apps.
bool skip_python_initialization = false; bool skip_python_initialization = cliCmdRequested;
#if defined( BITMAP_2_CMP ) || defined( PL_EDITOR ) || defined( GERBVIEW ) ||\ #if defined( BITMAP_2_CMP ) || defined( PL_EDITOR ) || defined( GERBVIEW ) ||\
defined( PCB_CALCULATOR_BUILD ) defined( PCB_CALCULATOR_BUILD )
skip_python_initialization = true; skip_python_initialization = true;
@ -320,53 +406,29 @@ bool PGM_SINGLE_TOP::OnPgmInit()
Kiway.set_kiface( KIWAY::KifaceType( TOP_FRAME ), kiface ); Kiway.set_kiface( KIWAY::KifaceType( TOP_FRAME ), kiface );
#endif #endif
static const wxCmdLineEntryDesc desc[] = {
{ wxCMD_LINE_OPTION, "f", "frame", "Frame to load", wxCMD_LINE_VAL_STRING, 0 },
{ wxCMD_LINE_PARAM, nullptr, nullptr, "File to load", wxCMD_LINE_VAL_STRING,
wxCMD_LINE_PARAM_MULTIPLE | wxCMD_LINE_PARAM_OPTIONAL },
{ wxCMD_LINE_NONE, nullptr, nullptr, nullptr, wxCMD_LINE_VAL_NONE, 0 }
};
wxCmdLineParser parser( App().argc, App().argv );
parser.SetDesc( desc );
parser.Parse( false );
FRAME_T appType = TOP_FRAME; FRAME_T appType = TOP_FRAME;
const struct
{
wxString name;
FRAME_T type;
} frameTypes[] = {
{ wxT( "pcb" ), FRAME_PCB_EDITOR },
{ wxT( "fpedit" ), FRAME_FOOTPRINT_EDITOR },
{ wxT( "" ), FRAME_T_COUNT }
};
wxString frameName;
if( parser.Found( "frame", &frameName ) )
{
appType = FRAME_T_COUNT;
for( const auto& it : frameTypes )
{
if( it.name == frameName )
appType = it.type;
}
if( appType == FRAME_T_COUNT )
{
wxLogError( wxT( "Unknown frame: %s" ), frameName );
// Clean up
OnPgmExit();
return false;
}
}
// Tell the settings manager about the current Kiway // Tell the settings manager about the current Kiway
GetSettingsManager().SetKiway( &Kiway ); GetSettingsManager().SetKiway( &Kiway );
if( cliCmdRequested )
{
int exitCode = CLI::EXIT_CODES::ERR_UNKNOWN;
if( cliCmd )
{
exitCode = cliCmd->Perform( Kiway );
}
if( exitCode != CLI::EXIT_CODES::AVOID_CLOSING )
{
std::exit( exitCode );
}
else
{
return true;
}
}
// Use KIWAY to create a top window, which registers its existence also. // Use KIWAY to create a top window, which registers its existence also.
// "TOP_FRAME" is a macro that is passed on compiler command line from CMake, // "TOP_FRAME" is a macro that is passed on compiler command line from CMake,
// and is one of the types in FRAME_T. // and is one of the types in FRAME_T.
@ -390,14 +452,10 @@ bool PGM_SINGLE_TOP::OnPgmInit()
frame->Show(); frame->Show();
wxSafeYield(); wxSafeYield();
// Individual frames may provide additional option/switch processing, but for compatibility,
// any positional arguments are treated as a list of files to pass to OpenProjectFiles
frame->ParseArgs( parser );
// Now after the frame processing, the rest of the positional args are files // Now after the frame processing, the rest of the positional args are files
std::vector<wxString> fileArgs; std::vector<wxString> fileArgs;
if( parser.GetParamCount() ) if( App().argc > 1 )
{ {
/* /*
gerbview handles multiple project data files, i.e. gerber files on gerbview handles multiple project data files, i.e. gerber files on
@ -408,8 +466,8 @@ bool PGM_SINGLE_TOP::OnPgmInit()
launcher. launcher.
*/ */
for( size_t i = 0; i < parser.GetParamCount(); i++ ) for( size_t i = 1; i < App().argc; i++ )
fileArgs.push_back( parser.GetParam( i ) ); fileArgs.push_back( App().argv[i] );
// special attention to a single argument: argv[1] (==argSet[0]) // special attention to a single argument: argv[1] (==argSet[0])
if( fileArgs.size() == 1 ) if( fileArgs.size() == 1 )

View File

@ -427,6 +427,7 @@ target_link_libraries( eeschema
# There's way too much crap coming in from common yet. # There's way too much crap coming in from common yet.
gal gal
common common
argparse::argparse
${wxWidgets_LIBRARIES} ${wxWidgets_LIBRARIES}
) )

View File

@ -298,6 +298,9 @@ static struct IFACE : public KIFACE_BASE
const wxString& aNewProjectBasePath, const wxString& aNewProjectName, const wxString& aNewProjectBasePath, const wxString& aNewProjectName,
const wxString& aSrcFilePath, wxString& aErrors ) override; const wxString& aSrcFilePath, wxString& aErrors ) override;
int HandleJob( JOB* aJob ) override;
} kiface( "eeschema", KIWAY::FACE_SCH ); } kiface( "eeschema", KIWAY::FACE_SCH );
} // namespace } // namespace
@ -560,3 +563,7 @@ void IFACE::SaveFileAs( const wxString& aProjectBasePath, const wxString& aProje
} }
} }
int IFACE::HandleJob( JOB* aJob )
{
return 0;
}

View File

@ -112,6 +112,7 @@ target_link_libraries( gerbview
gal gal
common common
nlohmann_json nlohmann_json
argparse::argparse
${wxWidgets_LIBRARIES} ${wxWidgets_LIBRARIES}
) )

View File

@ -104,6 +104,7 @@
#include <frame_type.h> #include <frame_type.h>
#include <mail_type.h> #include <mail_type.h>
#include <ki_exception.h> #include <ki_exception.h>
#include <jobs/job.h>
#define KIFACE_VERSION 1 #define KIFACE_VERSION 1
@ -233,6 +234,11 @@ struct KIFACE
* Append this Kiface's registered actions to the given list. * Append this Kiface's registered actions to the given list.
*/ */
virtual void GetActions( std::vector<TOOL_ACTION*>& aActions ) const = 0; virtual void GetActions( std::vector<TOOL_ACTION*>& aActions ) const = 0;
virtual int HandleJob( JOB* aJob )
{
return 0;
}
}; };
@ -403,6 +409,8 @@ public:
bool ProcessEvent( wxEvent& aEvent ) override; bool ProcessEvent( wxEvent& aEvent ) override;
int ProcessJob( KIWAY::FACE_T aFace, JOB* job );
/** /**
* Gets the window pointer to the blocking dialog (to send it signals) * Gets the window pointer to the blocking dialog (to send it signals)
* @return Pointer to blocking dialog window or null if none * @return Pointer to blocking dialog window or null if none

View File

@ -127,20 +127,6 @@ public:
return false; return false;
} }
/**
* Handle command-line arguments in a frame-specific way.
*
* The given argument parser has already been initialized with the command line and any
* options/switches that are handled by the top-level launcher before passing control to
* the child frame.
*
* @param aParser is the argument parser created by the top-level launcher.
*/
virtual void ParseArgs( wxCmdLineParser& aParser )
{
WXUNUSED( aParser );
}
/** /**
* Show this wxFrame as if it were a modal dialog, with all other instantiated wxFrames * Show this wxFrame as if it were a modal dialog, with all other instantiated wxFrames

View File

@ -118,6 +118,11 @@ public:
virtual void OnPgmExit() = 0; // call this from wxApp::OnExit() virtual void OnPgmExit() = 0; // call this from wxApp::OnExit()
#endif #endif
/**
* Builds the UTF8 based argv variable
*/
void BuildArgvUtf8();
/** /**
* Specific to MacOSX (not used under Linux or Windows). * Specific to MacOSX (not used under Linux or Windows).
* *
@ -342,6 +347,11 @@ protected:
wxFileName m_sentry_uid_fn; wxFileName m_sentry_uid_fn;
wxString m_sentryUid; wxString m_sentryUid;
#endif #endif
char** m_argvUtf8; /// argv parameters converted to utf8 form, because wxwidgets has opinions
/// and will return argv as either force converted to ascii in char* or wchar_t only
int m_argcUtf8;
}; };

View File

@ -107,11 +107,12 @@ if( KICAD_WIN32_INSTALL_PDBS )
install(FILES $<TARGET_PDB_FILE:kicad> DESTINATION ${KICAD_BIN}) install(FILES $<TARGET_PDB_FILE:kicad> DESTINATION ${KICAD_BIN})
endif() endif()
if( MSVC ) if( WIN32 )
# Allow for MSVC to run from the build directory
add_custom_command( TARGET kicad POST_BUILD add_custom_command( TARGET kicad POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/pcm/schemas" "${CMAKE_BINARY_DIR}/schemas" COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_SOURCE_DIR}/resources/msw/cmd-wrappers/kicad.cmd" "$<TARGET_FILE_DIR:kicad>"
) )
install(FILES "${CMAKE_SOURCE_DIR}/resources/msw/cmd-wrappers/kicad.cmd" DESTINATION ${KICAD_BIN})
endif() endif()
if( APPLE ) if( APPLE )

View File

@ -51,9 +51,13 @@
#include "pgm_kicad.h" #include "pgm_kicad.h"
#include "kicad_manager_frame.h" #include "kicad_manager_frame.h"
#include <kicad_build_version.h>
#include <kiplatform/app.h> #include <kiplatform/app.h>
#include <kiplatform/environment.h> #include <kiplatform/environment.h>
#include "cli/command_export_kicad_pcbnew.h"
#include "cli/command_export_step.h"
#include "cli/exit_codes.h"
// a dummy to quiet linking with EDA_BASE_FRAME::config(); // a dummy to quiet linking with EDA_BASE_FRAME::config();
#include <kiface_base.h> #include <kiface_base.h>
@ -89,9 +93,25 @@ PGM_KICAD& PgmTop()
return program; return program;
} }
struct COMMAND_ENTRY
{
CLI::COMMAND* handler;
std::vector<COMMAND_ENTRY> subCommands;
COMMAND_ENTRY( CLI::COMMAND* aHandler ) : handler( aHandler ){};
COMMAND_ENTRY( CLI::COMMAND* aHandler, std::vector<COMMAND_ENTRY> aSub ) :
handler( aHandler ), subCommands( aSub ){};
};
static CLI::EXPORT_STEP_COMMAND stepCmd{};
static CLI::EXPORT_KICAD_PCBNEW_COMMAND exportPcbCmd{};
static std::vector<COMMAND_ENTRY> commandStack = { { &exportPcbCmd, { &stepCmd } } };
bool PGM_KICAD::OnPgmInit() bool PGM_KICAD::OnPgmInit()
{ {
PGM_BASE::BuildArgvUtf8();
App().SetAppDisplayName( wxT( "KiCad" ) ); App().SetAppDisplayName( wxT( "KiCad" ) );
#if defined(DEBUG) #if defined(DEBUG)
@ -104,6 +124,55 @@ bool PGM_KICAD::OnPgmInit()
} }
#endif #endif
argparse::ArgumentParser argParser( std::string( "kicad" ),
KICAD_MAJOR_MINOR_VERSION );
for( COMMAND_ENTRY& entry : commandStack )
{
argParser.add_subparser( entry.handler->GetArgParser() );
for( COMMAND_ENTRY& subentry : entry.subCommands )
{
entry.handler->GetArgParser().add_subparser( subentry.handler->GetArgParser() );
}
}
try
{
argParser.parse_args( m_argcUtf8, m_argvUtf8 );
}
catch( const std::runtime_error& err )
{
// this provides the nice pretty print
std::cerr << err.what() << std::endl;
std::cerr << argParser;
std::exit( CLI::EXIT_CODES::ERR_ARGS );
}
bool cliCmdRequested = false;
CLI::COMMAND* cliCmd = nullptr;
for( COMMAND_ENTRY& entry : commandStack )
{
if( argParser.is_subcommand_used( entry.handler->GetName() ) )
{
for( COMMAND_ENTRY& subentry : entry.subCommands )
{
if( entry.handler->GetArgParser().is_subcommand_used(
subentry.handler->GetName() ) )
{
cliCmd = subentry.handler;
cliCmdRequested = true;
}
}
if( !cliCmdRequested )
{
cliCmd = entry.handler;
}
}
}
if( !InitPgm() ) if( !InitPgm() )
return false; return false;
@ -148,6 +217,24 @@ bool PGM_KICAD::OnPgmInit()
m_bm.m_search.Insert( it->second.GetValue(), 0 ); m_bm.m_search.Insert( it->second.GetValue(), 0 );
} }
if( cliCmdRequested )
{
int exitCode = CLI::EXIT_CODES::ERR_UNKNOWN;
if( cliCmd )
{
exitCode = cliCmd->Perform( Kiway );
}
if( exitCode != CLI::EXIT_CODES::AVOID_CLOSING )
{
std::exit( exitCode );
}
else
{
return true;
}
}
KICAD_MANAGER_FRAME* frame = new KICAD_MANAGER_FRAME( nullptr, wxT( "KiCad" ), KICAD_MANAGER_FRAME* frame = new KICAD_MANAGER_FRAME( nullptr, wxT( "KiCad" ),
wxDefaultPosition, wxSize( 775, -1 ) ); wxDefaultPosition, wxSize( 775, -1 ) );
App().SetTopWindow( frame ); App().SetTopWindow( frame );

View File

@ -28,6 +28,8 @@
#include <strsafe.h> #include <strsafe.h>
#include <config.h> #include <config.h>
#include <VersionHelpers.h> #include <VersionHelpers.h>
#include <iostream>
#include <cstdio>
#if defined( _MSC_VER ) #if defined( _MSC_VER )
#include <werapi.h> // issues on msys2 #include <werapi.h> // issues on msys2
@ -63,22 +65,35 @@ bool KIPLATFORM::APP::Init()
// In order to support GUI and CLI // In order to support GUI and CLI
// Let's attach to console when it's possible // Let's attach to console when it's possible
HANDLE handleStdOut, handleStdErr; HANDLE handle;
if( AttachConsole( ATTACH_PARENT_PROCESS ) ) if( AttachConsole( ATTACH_PARENT_PROCESS ) )
{ {
handleStdOut = GetStdHandle( STD_OUTPUT_HANDLE ); if( GetStdHandle( STD_INPUT_HANDLE ) != INVALID_HANDLE_VALUE )
if( handleStdOut != INVALID_HANDLE_VALUE ) {
freopen( "CONIN$", "r", stdin );
setvbuf( stdin, NULL, _IONBF, 0 );
}
if( GetStdHandle( STD_OUTPUT_HANDLE ) != INVALID_HANDLE_VALUE )
{ {
freopen( "CONOUT$", "w", stdout ); freopen( "CONOUT$", "w", stdout );
setvbuf( stdout, NULL, _IONBF, 0 ); setvbuf( stdout, NULL, _IONBF, 0 );
} }
handleStdErr = GetStdHandle( STD_ERROR_HANDLE ); if( GetStdHandle( STD_ERROR_HANDLE ) != INVALID_HANDLE_VALUE )
if( handleStdErr != INVALID_HANDLE_VALUE )
{ {
freopen( "CONOUT$", "w", stderr ); freopen( "CONOUT$", "w", stderr );
setvbuf( stderr, NULL, _IONBF, 0 ); setvbuf( stderr, NULL, _IONBF, 0 );
} }
std::ios::sync_with_stdio( true );
std::wcout.clear();
std::cout.clear();
std::wcerr.clear();
std::cerr.clear();
std::wcin.clear();
std::cin.clear();
} }
return true; return true;

View File

@ -85,6 +85,7 @@ target_link_libraries( pl_editor
# There's way too much crap coming in from common yet. # There's way too much crap coming in from common yet.
gal gal
common common
argparse::argparse
${wxWidgets_LIBRARIES} ${wxWidgets_LIBRARIES}
) )

View File

@ -90,6 +90,7 @@ target_link_libraries( pcb_calculator
#singletop # replaces common, giving us restrictive control and link warnings. #singletop # replaces common, giving us restrictive control and link warnings.
# There's way too much crap coming in from common yet. # There's way too much crap coming in from common yet.
common common
argparse::argparse
${wxWidgets_LIBRARIES} ${wxWidgets_LIBRARIES}
) )

View File

@ -13,6 +13,7 @@ add_definitions( -DPCBNEW )
add_subdirectory(connectivity) add_subdirectory(connectivity)
add_subdirectory(router) add_subdirectory(router)
add_subdirectory(exporters/step)
# psnrouter depends on make_lexer outputs in common (bug #1285878 ) # psnrouter depends on make_lexer outputs in common (bug #1285878 )
add_dependencies( pnsrouter pcbcommon ) add_dependencies( pnsrouter pcbcommon )
@ -313,6 +314,7 @@ set( PCBNEW_CLASS_SRCS
pcb_layer_box_selector.cpp pcb_layer_box_selector.cpp
pcb_edit_frame.cpp pcb_edit_frame.cpp
pcbnew_config.cpp pcbnew_config.cpp
pcbnew_jobs_handler.cpp
pcbnew_printout.cpp pcbnew_printout.cpp
pcbnew_settings.cpp pcbnew_settings.cpp
pcbplot.cpp pcbplot.cpp
@ -639,6 +641,7 @@ target_link_libraries( pcbnew
scripting scripting
nlohmann_json nlohmann_json
rectpack2d rectpack2d
argparse::argparse
${wxWidgets_LIBRARIES} ${wxWidgets_LIBRARIES}
) )
@ -674,16 +677,13 @@ target_link_libraries( pcbnew_kiface_objects
tinyspline_lib tinyspline_lib
nlohmann_json nlohmann_json
rectpack2d rectpack2d
kicad2step_lib
) )
target_include_directories( pcbnew_kiface_objects PRIVATE target_include_directories( pcbnew_kiface_objects PRIVATE
$<TARGET_PROPERTY:thread-pool,INTERFACE_INCLUDE_DIRECTORIES> $<TARGET_PROPERTY:thread-pool,INTERFACE_INCLUDE_DIRECTORIES>
) )
if( KICAD_STEP_EXPORT_LIB )
add_definitions( -DKICAD_STEP_EXPORT_LIB )
endif()
add_library( pcbnew_kiface MODULE ) add_library( pcbnew_kiface MODULE )
set_target_properties( pcbnew_kiface PROPERTIES set_target_properties( pcbnew_kiface PROPERTIES
@ -756,6 +756,12 @@ if( WIN32 )
add_custom_command( TARGET pcbnew POST_BUILD add_custom_command( TARGET pcbnew POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different "$<TARGET_FILE:kicad_3dsg>" "$<TARGET_FILE_DIR:pcbnew>" COMMAND ${CMAKE_COMMAND} -E copy_if_different "$<TARGET_FILE:kicad_3dsg>" "$<TARGET_FILE_DIR:pcbnew>"
) )
add_custom_command( TARGET pcbnew POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_SOURCE_DIR}/resources/msw/cmd-wrappers/pcbnew.cmd" "$<TARGET_FILE_DIR:pcbnew>"
)
install(FILES "${CMAKE_SOURCE_DIR}/resources/msw/cmd-wrappers/pcbnew.cmd" DESTINATION ${KICAD_BIN})
endif() endif()
# these 2 binaries are a matched set, keep them together: # these 2 binaries are a matched set, keep them together:

View File

@ -46,9 +46,7 @@
#include <filename_resolver.h> #include <filename_resolver.h>
#ifdef KICAD_STEP_EXPORT_LIB
#include <kicad2step.h> #include <kicad2step.h>
#endif
class DIALOG_EXPORT_STEP : public DIALOG_EXPORT_STEP_BASE class DIALOG_EXPORT_STEP : public DIALOG_EXPORT_STEP_BASE
@ -371,7 +369,6 @@ void DIALOG_EXPORT_STEP::onExportButton( wxCommandEvent& aEvent )
double xOrg = 0.0; double xOrg = 0.0;
double yOrg = 0.0; double yOrg = 0.0;
#ifndef KICAD_STEP_EXPORT_LIB
wxFileName appK2S( wxStandardPaths::Get().GetExecutablePath() ); wxFileName appK2S( wxStandardPaths::Get().GetExecutablePath() );
#ifdef __WXMAC__ #ifdef __WXMAC__
// On macOS, we have standalone applications inside the main bundle, so we handle that here: // On macOS, we have standalone applications inside the main bundle, so we handle that here:
@ -385,12 +382,16 @@ void DIALOG_EXPORT_STEP::onExportButton( wxCommandEvent& aEvent )
} }
#endif #endif
appK2S.SetName( wxT( "kicad2step" ) ); appK2S.SetName( wxT( "pcbnew" ) );
wxString cmdK2S = wxT( "\"" ); wxString cmdK2S = wxT( "\"" );
cmdK2S.Append( appK2S.GetFullPath() ); cmdK2S.Append( appK2S.GetFullPath() );
cmdK2S.Append( wxT( "\"" ) ); cmdK2S.Append( wxT( "\"" ) );
cmdK2S.Append( wxT( " export" ) );
cmdK2S.Append( wxT( " step" ) );
cmdK2S.Append( wxT( " --gui" ) );
if( GetNoVirtOption() ) if( GetNoVirtOption() )
cmdK2S.Append( wxT( " --no-virtual" ) ); cmdK2S.Append( wxT( " --no-virtual" ) );
@ -458,65 +459,8 @@ void DIALOG_EXPORT_STEP::onExportButton( wxCommandEvent& aEvent )
// Output file path. // Output file path.
cmdK2S.Append( wxString::Format( wxT( " %c%s%c" ), quote, m_boardPath, quote ) ); cmdK2S.Append( wxString::Format( wxT( " %c%s%c" ), quote, m_boardPath, quote ) );
wxLogTrace( traceKiCad2Step, wxT( "KiCad2Step command: %s" ), cmdK2S ); wxLogTrace( traceKiCad2Step, wxT( "export step command: %s" ), cmdK2S );
wxExecute( cmdK2S, wxEXEC_ASYNC | wxEXEC_SHOW_CONSOLE ); wxExecute( cmdK2S, wxEXEC_ASYNC | wxEXEC_SHOW_CONSOLE );
#else
KICAD2MCAD_PRMS params;
params.m_filename = m_boardPath;
params.m_outputFile = m_filePickerSTEP->GetPath();
params.m_includeVirtual = !GetNoVirtOption();
params.m_substModels = GetSubstOption();
params.m_minDistance = tolerance;
params.m_overwrite = true;
switch( orgOpt )
{
case DIALOG_EXPORT_STEP::STEP_ORG_0:
break;
case DIALOG_EXPORT_STEP::STEP_ORG_PLOT_AXIS:
params.m_useDrillOrigin = true;
break;
case DIALOG_EXPORT_STEP::STEP_ORG_GRID_AXIS:
params.m_useGridOrigin = true;
break;
case DIALOG_EXPORT_STEP::STEP_ORG_USER:
{
xOrg = GetXOrg();
yOrg = GetYOrg();
if( GetOrgUnitsChoice() == 1 )
{
// selected reference unit is in inches, and STEP units are mm
xOrg *= 25.4;
yOrg *= 25.4;
}
params.m_xOrigin = xOrg;
params.m_yOrigin = yOrg;
break;
}
case DIALOG_EXPORT_STEP::STEP_ORG_BOARD_CENTER:
{
BOX2I bbox = m_parent->GetBoard()->ComputeBoundingBox( true );
xOrg = pcbIUScale.IUTomm( bbox.GetCenter().x );
yOrg = pcbIUScale.IUTomm( bbox.GetCenter().y );
params.m_xOrigin = xOrg;
params.m_yOrigin = yOrg;
break;
}
}
KICAD2STEP converter( params );
converter.Run();
#endif
aEvent.Skip(); // Close the dialog aEvent.Skip(); // Close the dialog
} }

View File

@ -41,6 +41,7 @@
#include <plotters/plotters_pslike.h> #include <plotters/plotters_pslike.h>
#include <wx/dirdlg.h> #include <wx/dirdlg.h>
#include <pgm_base.h> #include <pgm_base.h>
#include <pcb_plot_svg.h>
class DIALOG_EXPORT_SVG : public DIALOG_EXPORT_SVG_BASE class DIALOG_EXPORT_SVG : public DIALOG_EXPORT_SVG_BASE
{ {
@ -68,8 +69,6 @@ private:
void OnOutputDirectoryBrowseClicked( wxCommandEvent& event ) override; void OnOutputDirectoryBrowseClicked( wxCommandEvent& event ) override;
void ExportSVGFile( bool aOnlyOneFile ); void ExportSVGFile( bool aOnlyOneFile );
bool CreateSVGFile( const wxString& FullFileName );
LSET getCheckBoxSelectedLayers() const; LSET getCheckBoxSelectedLayers() const;
}; };
@ -281,6 +280,13 @@ void DIALOG_EXPORT_SVG::ExportSVGFile( bool aOnlyOneFile )
LSET all_selected = getCheckBoxSelectedLayers(); LSET all_selected = getCheckBoxSelectedLayers();
PCB_PLOT_SVG_OPTIONS svgPlotOptions;
svgPlotOptions.m_blackAndWhite = m_printBW;
svgPlotOptions.m_printMaskLayer = m_printMaskLayer;
svgPlotOptions.m_pageSizeMode = m_rbSvgPageSizeOpt->GetSelection();
svgPlotOptions.m_colorTheme = ""; // will use default
svgPlotOptions.m_mirror = m_printMirror;
for( LSEQ seq = all_selected.Seq(); seq; ++seq ) for( LSEQ seq = all_selected.Seq(); seq; ++seq )
{ {
PCB_LAYER_ID layer = *seq; PCB_LAYER_ID layer = *seq;
@ -295,7 +301,10 @@ void DIALOG_EXPORT_SVG::ExportSVGFile( bool aOnlyOneFile )
if( m_checkboxEdgesOnAllPages->GetValue() ) if( m_checkboxEdgesOnAllPages->GetValue() )
m_printMaskLayer.set( Edge_Cuts ); m_printMaskLayer.set( Edge_Cuts );
if( CreateSVGFile( svgPath ) ) svgPlotOptions.m_outputFile = svgPath;
svgPlotOptions.m_printMaskLayer = m_printMaskLayer;
if( PCB_PLOT_SVG::Plot(m_board, svgPlotOptions ) )
{ {
reporter.Report( wxString::Format( _( "Exported '%s'." ), svgPath ), reporter.Report( wxString::Format( _( "Exported '%s'." ), svgPath ),
RPT_SEVERITY_ACTION ); RPT_SEVERITY_ACTION );
@ -312,72 +321,6 @@ void DIALOG_EXPORT_SVG::ExportSVGFile( bool aOnlyOneFile )
} }
// Actual SVG file export function.
bool DIALOG_EXPORT_SVG::CreateSVGFile( const wxString& aFullFileName )
{
PCB_PLOT_PARAMS plot_opts;
plot_opts.SetPlotFrameRef( m_rbSvgPageSizeOpt->GetSelection() == 0 );
// Adding drill marks, for copper layers
if( ( m_printMaskLayer & LSET::AllCuMask() ).any() )
plot_opts.SetDrillMarksType( PCB_PLOT_PARAMS::FULL_DRILL_SHAPE );
else
plot_opts.SetDrillMarksType( PCB_PLOT_PARAMS::NO_DRILL_SHAPE );
plot_opts.SetSkipPlotNPTH_Pads( false );
plot_opts.SetMirror( m_printMirror );
plot_opts.SetFormat( PLOT_FORMAT::SVG );
// coord format: 4 digits in mantissa (units always in mm). This is a good choice.
plot_opts.SetSvgPrecision( 4 );
PAGE_INFO savedPageInfo = m_board->GetPageSettings();
VECTOR2I savedAuxOrigin = m_board->GetDesignSettings().GetAuxOrigin();
if( m_rbSvgPageSizeOpt->GetSelection() == 2 ) // Page is board boundary size
{
BOX2I bbox = m_board->ComputeBoundingBox();
PAGE_INFO currpageInfo = m_board->GetPageSettings();
currpageInfo.SetWidthMils( bbox.GetWidth() / pcbIUScale.IU_PER_MILS );
currpageInfo.SetHeightMils( bbox.GetHeight() / pcbIUScale.IU_PER_MILS );
m_board->SetPageSettings( currpageInfo );
plot_opts.SetUseAuxOrigin( true );
VECTOR2I origin = bbox.GetOrigin();
m_board->GetDesignSettings().SetAuxOrigin( origin );
}
SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager();
PCBNEW_SETTINGS* cfg = mgr.GetAppSettings<PCBNEW_SETTINGS>();
plot_opts.SetColorSettings( mgr.GetColorSettings( cfg->m_ColorTheme ) );
LOCALE_IO toggle;
//@todo allow controlling the sheet name and path that will be displayed in the title block
// Leave blank for now
SVG_PLOTTER* plotter = (SVG_PLOTTER*) StartPlotBoard( m_board, &plot_opts, UNDEFINED_LAYER,
aFullFileName, wxEmptyString,
wxEmptyString );
if( plotter )
{
plotter->SetColorMode( !m_printBW );
PlotBoardLayers( m_board, plotter, m_printMaskLayer.SeqStackupBottom2Top(), plot_opts );
plotter->EndPlot();
}
delete plotter;
// reset to the values saved earlier
m_board->GetDesignSettings().SetAuxOrigin( savedAuxOrigin );
m_board->SetPageSettings( savedPageInfo );
return true;
}
void DIALOG_EXPORT_SVG::OnButtonPlot( wxCommandEvent& event ) void DIALOG_EXPORT_SVG::OnButtonPlot( wxCommandEvent& event )
{ {
m_oneFileOnly = !m_checkboxPagePerLayer->GetValue(); m_oneFileOnly = !m_checkboxPagePerLayer->GetValue();

View File

@ -16,7 +16,6 @@ set( KS2_LIB_FILES
pcb/oce_utils.cpp pcb/oce_utils.cpp
) )
# Break the library out for re-use by both kicad2step and any qa that needs it # Break the library out for re-use by both kicad2step and any qa that needs it
# In future, this could move for re-use by other programs needing s-expr support (?) # In future, this could move for re-use by other programs needing s-expr support (?)
add_library( kicad2step_lib STATIC add_library( kicad2step_lib STATIC
@ -33,45 +32,14 @@ target_include_directories( kicad2step_lib PUBLIC
target_link_libraries( kicad2step_lib target_link_libraries( kicad2step_lib
sexpr sexpr
common
${wxWidgets_LIBRARIES} ${wxWidgets_LIBRARIES}
${OCC_LIBRARIES} ${OCC_LIBRARIES}
${ZLIB_LIBRARIES} ${ZLIB_LIBRARIES}
kimath kimath
) )
set( K2S_FILES
kicad2step_app.cpp
)
if( MINGW )
list( APPEND K2S_FILES ${CMAKE_SOURCE_DIR}/common/streamwrapper.cpp )
endif( MINGW )
add_executable( kicad2step_bin WIN32 ${K2S_FILES} )
target_link_libraries( kicad2step_bin
kicad2step_lib )
target_include_directories( kicad2step_lib PRIVATE target_include_directories( kicad2step_lib PRIVATE
$<TARGET_PROPERTY:gzip-hpp,INTERFACE_INCLUDE_DIRECTORIES> $<TARGET_PROPERTY:gzip-hpp,INTERFACE_INCLUDE_DIRECTORIES>
) )
set_target_properties( kicad2step_bin
PROPERTIES OUTPUT_NAME kicad2step)
if( APPLE )
# puts binaries into the *.app bundle while linking
set_target_properties( kicad2step_bin PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${OSX_BUNDLE_BUILD_BIN_DIR}
)
else()
install( TARGETS kicad2step_bin
RUNTIME DESTINATION ${KICAD_BIN}
ARCHIVE DESTINATION ${KICAD_LIB}
COMPONENT binary )
endif()
if( KICAD_WIN32_INSTALL_PDBS )
# Get the PDBs to copy over for MSVC
install(FILES $<TARGET_PDB_FILE:kicad2step_bin> DESTINATION ${KICAD_BIN})
endif()

View File

@ -28,11 +28,14 @@
#include <wx/msgdlg.h> #include <wx/msgdlg.h>
#include <wx/string.h> #include <wx/string.h>
#include <wx/filename.h> #include <wx/filename.h>
#include <wx/crt.h>
#include <algorithm> #include <algorithm>
#include <sstream> #include <sstream>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <cli/exit_codes.h>
#include <pgm_base.h>
#include "kicad2step.h" #include "kicad2step.h"
#include "pcb/kicadpcb.h" #include "pcb/kicadpcb.h"
#include "kicad2step_frame_base.h" #include "kicad2step_frame_base.h"
@ -52,26 +55,33 @@
class KICAD2STEP_FRAME : public KICAD2STEP_FRAME_BASE class KICAD2STEP_FRAME : public KICAD2STEP_FRAME_BASE
{ {
public: public:
KICAD2STEP_FRAME( const wxString& title ); KICAD2STEP_FRAME( KICAD2STEP* aConverter, const wxString& title );
protected: protected:
virtual void OnOKButtonClick( wxCommandEvent& aEvent ) override; virtual void OnOKButtonClick( wxCommandEvent& aEvent ) override;
virtual void OnIdle( wxIdleEvent& aEvent ) override;
KICAD2STEP* m_converter;
bool m_running;
}; };
// Horrible hack until we decouple things more // Horrible hack until we decouple things more
static PANEL_KICAD2STEP* openPanel = nullptr; static KICAD2STEP* k2sInstance = nullptr;
void ReportMessage( const wxString& aMessage ) void ReportMessage( const wxString& aMessage )
{ {
if( openPanel != nullptr ) if( k2sInstance != nullptr )
openPanel->AppendMessage( aMessage ); k2sInstance->ReportMessage( aMessage );
} }
class KiCadPrinter : public Message_Printer class KiCadPrinter : public Message_Printer
{ {
public:
KiCadPrinter( KICAD2STEP* aConverter ) : m_converter( aConverter ) {}
protected: protected:
#if OCC_VERSION_HEX < OCC_VERSION_MIN #if OCC_VERSION_HEX < OCC_VERSION_MIN
virtual void Send( const TCollection_ExtendedString& theString, virtual void Send( const TCollection_ExtendedString& theString,
@ -91,24 +101,28 @@ protected:
{ {
if( theGravity >= Message_Info ) if( theGravity >= Message_Info )
{ {
ReportMessage( theString.ToCString() ); m_converter->ReportMessage( theString.ToCString() );
#if OCC_VERSION_HEX < OCC_VERSION_MIN #if OCC_VERSION_HEX < OCC_VERSION_MIN
if( theToPutEol ) if( theToPutEol )
ReportMessage( wxT( "\n" ) ); ReportMessage( wxT( "\n" ) );
#else #else
ReportMessage( wxT( "\n" ) ); m_converter->ReportMessage( wxT( "\n" ) );
#endif #endif
} }
if( theGravity >= Message_Alarm ) if( theGravity >= Message_Alarm )
openPanel->m_error = true; m_converter->SetError();
if( theGravity == Message_Fail ) if( theGravity == Message_Fail )
openPanel->m_fail = true; m_converter->SetFail();
} }
private:
KICAD2STEP* m_converter;
}; };
KICAD2MCAD_PRMS::KICAD2MCAD_PRMS() KICAD2MCAD_PRMS::KICAD2MCAD_PRMS()
{ {
#ifdef SUPPORTS_IGES #ifdef SUPPORTS_IGES
@ -126,8 +140,8 @@ KICAD2MCAD_PRMS::KICAD2MCAD_PRMS()
} }
KICAD2STEP_FRAME::KICAD2STEP_FRAME( const wxString& title ) : KICAD2STEP_FRAME::KICAD2STEP_FRAME( KICAD2STEP* aConverter, const wxString& title ) :
KICAD2STEP_FRAME_BASE( nullptr, wxID_ANY, title ) KICAD2STEP_FRAME_BASE( nullptr, wxID_ANY, title ), m_converter( aConverter ), m_running( false )
{ {
} }
@ -138,9 +152,21 @@ void KICAD2STEP_FRAME::OnOKButtonClick( wxCommandEvent& aEvent )
} }
PANEL_KICAD2STEP::PANEL_KICAD2STEP( wxWindow* parent, wxWindowID id, const wxPoint& pos, void KICAD2STEP_FRAME::OnIdle( wxIdleEvent& aEvent )
{
if( !m_running )
{
m_running = true;
m_converter->DoRun();
}
}
PANEL_KICAD2STEP::PANEL_KICAD2STEP( wxWindow* parent, wxWindowID id,
const wxPoint& pos,
const wxSize& size, long style ) : const wxSize& size, long style ) :
wxPanel( parent, id, pos, size, style ), m_error( false ), m_fail( false ) wxPanel( parent, id, pos, size, style ),
m_error( false ), m_fail( false )
{ {
wxBoxSizer* bSizer = new wxBoxSizer( wxVERTICAL ); wxBoxSizer* bSizer = new wxBoxSizer( wxVERTICAL );
@ -161,14 +187,33 @@ void PANEL_KICAD2STEP::AppendMessage( const wxString& aMessage )
} }
int PANEL_KICAD2STEP::RunConverter()
wxString KICAD2MCAD_PRMS::getOutputExt() const
{
#ifdef SUPPORTS_IGES
if( m_fmtIGES )
return wxT( "igs" );
else
#endif
return wxT( "step" );
}
KICAD2STEP::KICAD2STEP( KICAD2MCAD_PRMS aParams ) :
m_params( aParams ), m_panel( nullptr ), m_error( false ), m_fail( false )
{
}
int KICAD2STEP::DoRun()
{ {
wxFileName fname( m_params.m_filename ); wxFileName fname( m_params.m_filename );
if( !fname.FileExists() ) if( !fname.FileExists() )
{ {
wxMessageBox( wxString::Format( _( "No such file: %s" ), m_params.m_filename ) ); ReportMessage( wxString::Format( _( "No such file: %s" ), m_params.m_filename ) );
return -1;
return CLI::EXIT_CODES::ERR_INVALID_INPUT_FILE;
} }
wxFileName out_fname; wxFileName out_fname;
@ -192,7 +237,7 @@ int PANEL_KICAD2STEP::RunConverter()
ReportMessage( _( "** Output already exists. Export aborted. **\n" ReportMessage( _( "** Output already exists. Export aborted. **\n"
"Enable the force overwrite flag to overwrite it." ) ); "Enable the force overwrite flag to overwrite it." ) );
return -1; return CLI::EXIT_CODES::ERR_INVALID_OUTPUT_CONFLICT;
} }
wxString outfile = out_fname.GetFullPath(); wxString outfile = out_fname.GetFullPath();
@ -203,7 +248,7 @@ int PANEL_KICAD2STEP::RunConverter()
ReportMessage( wxString::Format( _( "Read file: '%s'\n" ), m_params.m_filename ) ); ReportMessage( wxString::Format( _( "Read file: '%s'\n" ), m_params.m_filename ) );
Message::DefaultMessenger()->RemovePrinters( STANDARD_TYPE( Message_PrinterOStream ) ); Message::DefaultMessenger()->RemovePrinters( STANDARD_TYPE( Message_PrinterOStream ) );
Message::DefaultMessenger()->AddPrinter( new KiCadPrinter ); Message::DefaultMessenger()->AddPrinter( new KiCadPrinter( this ) );
if( pcb.ReadFile( m_params.m_filename ) ) if( pcb.ReadFile( m_params.m_filename ) )
{ {
@ -224,7 +269,8 @@ int PANEL_KICAD2STEP::RunConverter()
if( !res ) if( !res )
{ {
ReportMessage( _( "\n** Error building STEP board model. Export aborted. **\n" ) ); ReportMessage( _( "\n** Error building STEP board model. Export aborted. **\n" ) );
return -1;
return CLI::EXIT_CODES::ERR_UNKNOWN;
} }
ReportMessage( _( "Write STEP file\n" ) ); ReportMessage( _( "Write STEP file\n" ) );
@ -239,7 +285,7 @@ int PANEL_KICAD2STEP::RunConverter()
if( !res ) if( !res )
{ {
ReportMessage( _( "\n** Error writing STEP file. **\n" ) ); ReportMessage( _( "\n** Error writing STEP file. **\n" ) );
return -1; return CLI::EXIT_CODES::ERR_UNKNOWN;
} }
else else
{ {
@ -250,18 +296,18 @@ int PANEL_KICAD2STEP::RunConverter()
{ {
ReportMessage( e.GetMessageString() ); ReportMessage( e.GetMessageString() );
ReportMessage( _( "\n** Error exporting STEP file. Export aborted. **\n" ) ); ReportMessage( _( "\n** Error exporting STEP file. Export aborted. **\n" ) );
return -1; return CLI::EXIT_CODES::ERR_UNKNOWN;
} }
catch( ... ) catch( ... )
{ {
ReportMessage( _( "\n** Error exporting STEP file. Export aborted. **\n" ) ); ReportMessage( _( "\n** Error exporting STEP file. Export aborted. **\n" ) );
return -1; return CLI::EXIT_CODES::ERR_INVALID_INPUT_FILE;
} }
} }
else else
{ {
ReportMessage( _( "\n** Error reading kicad_pcb file. **\n" ) ); ReportMessage( _( "\n** Error reading kicad_pcb file. **\n" ) );
return -1; return CLI::EXIT_CODES::ERR_UNKNOWN;
} }
wxString msg; wxString msg;
@ -278,49 +324,45 @@ int PANEL_KICAD2STEP::RunConverter()
ReportMessage( msg ); ReportMessage( msg );
return 0; return CLI::EXIT_CODES::SUCCESS;
}
wxString KICAD2MCAD_PRMS::getOutputExt() const
{
#ifdef SUPPORTS_IGES
if( m_fmtIGES )
return wxT( "igs" );
else
#endif
return wxT( "step" );
}
KICAD2STEP::KICAD2STEP( KICAD2MCAD_PRMS aParams ) : m_params( aParams ), m_panel( nullptr )
{
} }
int KICAD2STEP::Run() int KICAD2STEP::Run()
{
k2sInstance = this;
if( m_params.m_gui )
{ {
// create the main application window // create the main application window
KICAD2STEP_FRAME* frame = new KICAD2STEP_FRAME( wxT( "Kicad2step" ) ); KICAD2STEP_FRAME* frame = new KICAD2STEP_FRAME( this, wxT( "PCB Step Export" ) );
m_panel = frame->m_panelKicad2Step; m_panel = frame->m_panelKicad2Step;
m_panel->m_params = m_params; m_panel->m_params = m_params;
// and show it (a wxFrame is not shown when created initially) Pgm().App().SetTopWindow( frame );
frame->Show( true );
frame->Iconize( false ); frame->Iconize( false );
frame->Show( true );
openPanel = m_panel; return CLI::EXIT_CODES::AVOID_CLOSING;
}
int diag = m_panel->RunConverter(); else
{
openPanel = nullptr; int diag = DoRun();
return diag; return diag;
} }
}
void KICAD2STEP::ReportMessage( const wxString& aMessage ) void KICAD2STEP::ReportMessage( const wxString& aMessage )
{
if( m_params.m_gui )
{ {
m_panel->AppendMessage( aMessage ); m_panel->AppendMessage( aMessage );
} }
else
{
wxPrintf( aMessage );
}
}

View File

@ -51,6 +51,7 @@ public:
double m_xOrigin; double m_xOrigin;
double m_yOrigin; double m_yOrigin;
double m_minDistance; double m_minDistance;
bool m_gui;
}; };
class APIEXPORT KICAD2STEP class APIEXPORT KICAD2STEP
@ -61,9 +62,19 @@ public:
int Run(); int Run();
void ReportMessage( const wxString& aMessage ); void ReportMessage( const wxString& aMessage );
void SetError() { m_error = true; }
void SetFail() { m_error = true; }
private: private:
int DoRun();
KICAD2MCAD_PRMS m_params; KICAD2MCAD_PRMS m_params;
PANEL_KICAD2STEP* m_panel; PANEL_KICAD2STEP* m_panel;
bool m_error;
bool m_fail;
friend class KICAD2STEP_FRAME;
}; };
#endif #endif

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Oct 26 2018) // C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b3)
// http://www.wxformbuilder.org/ // http://www.wxformbuilder.org/
// //
// PLEASE DO *NOT* EDIT THIS FILE! // PLEASE DO *NOT* EDIT THIS FILE!
@ -34,12 +34,14 @@ KICAD2STEP_FRAME_BASE::KICAD2STEP_FRAME_BASE( wxWindow* parent, wxWindowID id, c
this->Centre( wxBOTH ); this->Centre( wxBOTH );
// Connect Events // Connect Events
this->Connect( wxEVT_IDLE, wxIdleEventHandler( KICAD2STEP_FRAME_BASE::OnIdle ) );
m_sdbSizer1OK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( KICAD2STEP_FRAME_BASE::OnOKButtonClick ), NULL, this ); m_sdbSizer1OK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( KICAD2STEP_FRAME_BASE::OnOKButtonClick ), NULL, this );
} }
KICAD2STEP_FRAME_BASE::~KICAD2STEP_FRAME_BASE() KICAD2STEP_FRAME_BASE::~KICAD2STEP_FRAME_BASE()
{ {
// Disconnect Events // Disconnect Events
this->Disconnect( wxEVT_IDLE, wxIdleEventHandler( KICAD2STEP_FRAME_BASE::OnIdle ) );
m_sdbSizer1OK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( KICAD2STEP_FRAME_BASE::OnOKButtonClick ), NULL, this ); m_sdbSizer1OK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( KICAD2STEP_FRAME_BASE::OnOKButtonClick ), NULL, this );
} }

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> <?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<wxFormBuilder_Project> <wxFormBuilder_Project>
<FileVersion major="1" minor="15" /> <FileVersion major="1" minor="16" />
<object class="Project" expanded="1"> <object class="Project" expanded="1">
<property name="class_decoration"></property> <property name="class_decoration"></property>
<property name="code_generation">C++</property> <property name="code_generation">C++</property>
@ -14,6 +14,7 @@
<property name="file">kicad2step_frame_base</property> <property name="file">kicad2step_frame_base</property>
<property name="first_id">1000</property> <property name="first_id">1000</property>
<property name="help_provider">none</property> <property name="help_provider">none</property>
<property name="image_path_wrapper_function_name"></property>
<property name="indent_with_spaces"></property> <property name="indent_with_spaces"></property>
<property name="internationalize">1</property> <property name="internationalize">1</property>
<property name="name">kicad2step_frame</property> <property name="name">kicad2step_frame</property>
@ -25,6 +26,7 @@
<property name="skip_php_events">1</property> <property name="skip_php_events">1</property>
<property name="skip_python_events">1</property> <property name="skip_python_events">1</property>
<property name="ui_table">UI</property> <property name="ui_table">UI</property>
<property name="use_array_enum">0</property>
<property name="use_enum">0</property> <property name="use_enum">0</property>
<property name="use_microsoft_bom">0</property> <property name="use_microsoft_bom">0</property>
<object class="Frame" expanded="1"> <object class="Frame" expanded="1">
@ -50,10 +52,12 @@
<property name="subclass">; forward_declare; forward_declare</property> <property name="subclass">; forward_declare; forward_declare</property>
<property name="title">Kicad2step Converter</property> <property name="title">Kicad2step Converter</property>
<property name="tooltip"></property> <property name="tooltip"></property>
<property name="two_step_creation">0</property>
<property name="window_extra_style"></property> <property name="window_extra_style"></property>
<property name="window_name"></property> <property name="window_name"></property>
<property name="window_style">wxTAB_TRAVERSAL</property> <property name="window_style">wxTAB_TRAVERSAL</property>
<property name="xrc_skip_sizer">1</property> <property name="xrc_skip_sizer">1</property>
<event name="OnIdle">OnIdle</event>
<object class="wxBoxSizer" expanded="1"> <object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property> <property name="minimum_size"></property>
<property name="name">bSizerMain</property> <property name="name">bSizerMain</property>

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Oct 26 2018) // C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b3)
// http://www.wxformbuilder.org/ // http://www.wxformbuilder.org/
// //
// PLEASE DO *NOT* EDIT THIS FILE! // PLEASE DO *NOT* EDIT THIS FILE!
@ -36,6 +36,7 @@ class KICAD2STEP_FRAME_BASE : public wxFrame
wxButton* m_sdbSizer1OK; wxButton* m_sdbSizer1OK;
// Virtual event handlers, override them in your derived class // Virtual event handlers, override them in your derived class
virtual void OnIdle( wxIdleEvent& event ) { event.Skip(); }
virtual void OnOKButtonClick( wxCommandEvent& event ) { event.Skip(); } virtual void OnOKButtonClick( wxCommandEvent& event ) { event.Skip(); }

View File

@ -44,10 +44,6 @@ public:
const wxSize& size = wxSize( 500,300 ), const wxSize& size = wxSize( 500,300 ),
long style = wxTAB_TRAVERSAL ); long style = wxTAB_TRAVERSAL );
/**
* Run the KiCad to STEP converter.
*/
int RunConverter();
/** /**
* Add a message to m_tcMessages. * Add a message to m_tcMessages.

View File

@ -374,7 +374,7 @@ bool S3D_RESOLVER::readPathList( void )
if( !wxFileName::Exists( cfgname ) ) if( !wxFileName::Exists( cfgname ) )
{ {
wxLogTrace( trace3dResolver, wxT( "%s:%s:d\n * no 3D configuration file '%s'" ), wxLogTrace( trace3dResolver, wxT( "%s:%s:%d\n * no 3D configuration file '%s'" ),
__FILE__, __FUNCTION__, __LINE__, cfgname ); __FILE__, __FUNCTION__, __LINE__, cfgname );
return false; return false;

106
pcbnew/pcb_plot_svg.cpp Normal file
View File

@ -0,0 +1,106 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2012 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <board.h>
#include <board_design_settings.h>
#include <locale_io.h>
#include <pcbnew_settings.h>
#include <pcb_plot_params.h>
#include <pcb_plot_svg.h>
#include <pcbplot.h>
#include <pgm_base.h>
#include <plotters/plotters_pslike.h>
bool PCB_PLOT_SVG::Plot( BOARD* aBoard, const PCB_PLOT_SVG_OPTIONS& aSvgPlotOptions )
{
PCB_PLOT_PARAMS plot_opts;
plot_opts.SetPlotFrameRef( aSvgPlotOptions.m_pageSizeMode );
// Adding drill marks, for copper layers
if( ( aSvgPlotOptions.m_printMaskLayer & LSET::AllCuMask() ).any() )
plot_opts.SetDrillMarksType( PCB_PLOT_PARAMS::FULL_DRILL_SHAPE );
else
plot_opts.SetDrillMarksType( PCB_PLOT_PARAMS::NO_DRILL_SHAPE );
plot_opts.SetSkipPlotNPTH_Pads( false );
plot_opts.SetMirror( aSvgPlotOptions.m_mirror );
plot_opts.SetFormat( PLOT_FORMAT::SVG );
// coord format: 4 digits in mantissa (units always in mm). This is a good choice.
plot_opts.SetSvgPrecision( 4 );
PAGE_INFO savedPageInfo = aBoard->GetPageSettings();
VECTOR2I savedAuxOrigin = aBoard->GetDesignSettings().GetAuxOrigin();
if( aSvgPlotOptions.m_pageSizeMode == 2 ) // Page is board boundary size
{
BOX2I bbox = aBoard->ComputeBoundingBox();
PAGE_INFO currpageInfo = aBoard->GetPageSettings();
currpageInfo.SetWidthMils( bbox.GetWidth() / pcbIUScale.IU_PER_MILS );
currpageInfo.SetHeightMils( bbox.GetHeight() / pcbIUScale.IU_PER_MILS );
aBoard->SetPageSettings( currpageInfo );
plot_opts.SetUseAuxOrigin( true );
VECTOR2I origin = bbox.GetOrigin();
aBoard->GetDesignSettings().SetAuxOrigin( origin );
}
SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager();
PCBNEW_SETTINGS* cfg = mgr.GetAppSettings<PCBNEW_SETTINGS>();
plot_opts.SetColorSettings( mgr.GetColorSettings( cfg->m_ColorTheme ) );
COLOR_SETTINGS* theme = nullptr;
if( !aSvgPlotOptions.m_colorTheme.IsEmpty() )
{
theme = mgr.GetColorSettings( aSvgPlotOptions.m_colorTheme );
}
if( !theme )
{
theme = mgr.GetColorSettings( cfg->m_ColorTheme );
}
LOCALE_IO toggle;
//@todo allow controlling the sheet name and path that will be displayed in the title block
// Leave blank for now
SVG_PLOTTER* plotter = (SVG_PLOTTER*) StartPlotBoard( aBoard, &plot_opts, UNDEFINED_LAYER,
aSvgPlotOptions.m_outputFile,
wxEmptyString, wxEmptyString );
if( plotter )
{
plotter->SetColorMode( !aSvgPlotOptions.m_blackAndWhite );
PlotBoardLayers( aBoard, plotter, aSvgPlotOptions.m_printMaskLayer.SeqStackupBottom2Top(),
plot_opts );
plotter->EndPlot();
}
delete plotter;
// reset to the values saved earlier
aBoard->GetDesignSettings().SetAuxOrigin( savedAuxOrigin );
aBoard->SetPageSettings( savedPageInfo );
return true;
}

43
pcbnew/pcb_plot_svg.h Normal file
View File

@ -0,0 +1,43 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2012 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PCB_PLOT_SVG_H
#define PCB_PLOT_SVG_H
struct PCB_PLOT_SVG_OPTIONS
{
wxString m_outputFile;
wxString m_colorTheme;
bool m_mirror;
bool m_blackAndWhite;
int m_pageSizeMode;
LSET m_printMaskLayer;
};
class PCB_PLOT_SVG
{
public:
static bool Plot( BOARD* aBoard, const PCB_PLOT_SVG_OPTIONS& aSvgPlotOptions );
};
#endif

View File

@ -60,6 +60,7 @@
#include "invoke_pcb_dialog.h" #include "invoke_pcb_dialog.h"
#include <wildcards_and_files_ext.h> #include <wildcards_and_files_ext.h>
#include "pcbnew_jobs_handler.h"
/* init functions defined by swig */ /* init functions defined by swig */
@ -290,6 +291,11 @@ static struct IFACE : public KIFACE_BASE
const wxString& aNewProjectBasePath, const wxString& aNewProjectName, const wxString& aNewProjectBasePath, const wxString& aNewProjectName,
const wxString& aSrcFilePath, wxString& aErrors ) override; const wxString& aSrcFilePath, wxString& aErrors ) override;
int HandleJob( JOB* aJob ) override;
private:
std::unique_ptr<PCBNEW_JOBS_HANDLER> m_jobHandler;
} kiface( "pcbnew", KIWAY::FACE_PCB ); } kiface( "pcbnew", KIWAY::FACE_PCB );
} // namespace } // namespace
@ -381,6 +387,8 @@ bool IFACE::OnKifaceStart( PGM_BASE* aProgram, int aCtlBits )
} }
} }
m_jobHandler = std::make_unique<PCBNEW_JOBS_HANDLER>();
return true; return true;
} }
@ -478,3 +486,8 @@ void IFACE::SaveFileAs( const wxString& aProjectBasePath, const wxString& aSrcPr
} }
} }
int IFACE::HandleJob( JOB* aJob )
{
return m_jobHandler->RunJob( aJob );
}

View File

@ -0,0 +1,102 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2022 Mark Roszko <mark.roszko@gmail.com>
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pcbnew_jobs_handler.h"
#include <kicad2step.h>
#include <jobs/job_export_pcb_svg.h>
#include <jobs/job_export_step.h>
#include <cli/exit_codes.h>
#include <plotters/plotters_pslike.h>
#include <pgm_base.h>
#include <pcbplot.h>
#include <board_design_settings.h>
#include <pcbnew_settings.h>
#include <wx/crt.h>
#include <pcb_plot_svg.h>
#include "pcbnew_scripting_helpers.h"
PCBNEW_JOBS_HANDLER::PCBNEW_JOBS_HANDLER()
{
Register( "step",
std::bind( &PCBNEW_JOBS_HANDLER::JobExportStep, this, std::placeholders::_1 ) );
Register( "svg",
std::bind( &PCBNEW_JOBS_HANDLER::JobExportSvg, this, std::placeholders::_1 ) );
}
int PCBNEW_JOBS_HANDLER::JobExportStep( JOB* aJob )
{
JOB_EXPORT_STEP* aStepJob = dynamic_cast<JOB_EXPORT_STEP*>( aJob );
if( aStepJob == nullptr )
return CLI::EXIT_CODES::ERR_UNKNOWN;
KICAD2MCAD_PRMS params;
params.m_useDrillOrigin = aStepJob->m_useDrillOrigin;
params.m_useGridOrigin = aStepJob->m_useGridOrigin;
params.m_overwrite = aStepJob->m_overwrite;
params.m_includeVirtual = aStepJob->m_includeVirtual;
params.m_filename = aStepJob->m_filename;
params.m_outputFile = aStepJob->m_outputFile;
params.m_xOrigin = aStepJob->m_xOrigin;
params.m_yOrigin = aStepJob->m_yOrigin;
params.m_minDistance = aStepJob->m_minDistance;
params.m_substModels = aStepJob->m_substModels;
params.m_gui = aStepJob->m_gui;
// we might need the lifetime of the converter to continue until frame destruction
// due to the gui parameter
KICAD2STEP* converter = new KICAD2STEP( params );
return converter->Run();
}
int PCBNEW_JOBS_HANDLER::JobExportSvg( JOB* aJob )
{
JOB_EXPORT_PCB_SVG* aSvgJob = dynamic_cast<JOB_EXPORT_PCB_SVG*>( aJob );
if( aSvgJob == nullptr )
return CLI::EXIT_CODES::ERR_UNKNOWN;
PCB_PLOT_SVG_OPTIONS svgPlotOptions;
svgPlotOptions.m_blackAndWhite = aSvgJob->m_blackAndWhite;
svgPlotOptions.m_colorTheme = aSvgJob->m_colorTheme;
svgPlotOptions.m_outputFile = aSvgJob->m_outputFile;
svgPlotOptions.m_mirror = aSvgJob->m_mirror;
svgPlotOptions.m_pageSizeMode = aSvgJob->m_pageSizeMode;
svgPlotOptions.m_printMaskLayer = aSvgJob->m_printMaskLayer;
if( aJob->IsCli() )
wxPrintf( _( "Loading board\n" ) );
BOARD* brd = LoadBoard( aSvgJob->m_filename );
if( aJob->IsCli() )
{
if( PCB_PLOT_SVG::Plot( brd, svgPlotOptions ) )
wxPrintf( _( "Successfully created svg file" ) );
else
wxPrintf( _( "Error creating svg file" ) );
}
return CLI::EXIT_CODES::OK;
}

View File

@ -0,0 +1,34 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2022 Mark Roszko <mark.roszko@gmail.com>
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PCBNEW_JOBS_HANDLER_H
#define PCBNEW_JOBS_HANDLER_H
#include <jobs/job_dispatcher.h>
class PCBNEW_JOBS_HANDLER : public JOB_DISPATCHER
{
public:
PCBNEW_JOBS_HANDLER();
int JobExportStep( JOB* aJob );
int JobExportSvg( JOB* aJob );
};
#endif

View File

@ -29,10 +29,6 @@ add_executable( qa_pcbnew_tools
tools/polygon_generator/polygon_generator.cpp tools/polygon_generator/polygon_generator.cpp
tools/polygon_triangulation/polygon_triangulation.cpp tools/polygon_triangulation/polygon_triangulation.cpp
# Older CMakes cannot link OBJECT libraries
# https://cmake.org/pipermail/cmake/2013-November/056263.html
$<TARGET_OBJECTS:pcbnew_kiface_objects>
) )
# Anytime we link to the kiface_objects, we have to add a dependency on the last object # Anytime we link to the kiface_objects, we have to add a dependency on the last object
@ -41,6 +37,7 @@ add_executable( qa_pcbnew_tools
add_dependencies( qa_pcbnew_tools pcbnew ) add_dependencies( qa_pcbnew_tools pcbnew )
target_link_libraries( qa_pcbnew_tools target_link_libraries( qa_pcbnew_tools
pcbnew_kiface_objects
qa_pcbnew_utils qa_pcbnew_utils
3d-viewer 3d-viewer
connectivity connectivity

View File

@ -0,0 +1 @@
@"%~dp0kicad.exe" %*

View File

@ -0,0 +1 @@
@"%~dp0pcbnew.exe" %*

View File

@ -23,6 +23,7 @@
# Note: The glew folder isn't added here because it is added inside the main CMakeLists.txt # Note: The glew folder isn't added here because it is added inside the main CMakeLists.txt
add_subdirectory( argparse )
add_subdirectory( clipper ) add_subdirectory( clipper )
add_subdirectory( compoundfilereader ) add_subdirectory( compoundfilereader )
add_subdirectory( delaunator ) add_subdirectory( delaunator )

117
thirdparty/argparse/.clang-format vendored Normal file
View File

@ -0,0 +1,117 @@
---
Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Right
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: false
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
- Regex: '.*'
Priority: 1
IncludeIsMainRegex: '(Test)?$'
IndentCaseLabels: false
IndentPPDirectives: None
IndentWidth: 2
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
RawStringFormats:
- Language: TextProto
Delimiters:
- 'pb'
- 'proto'
BasedOnStyle: google
ReflowComments: true
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: c++17
TabWidth: 8
UseTab: Never
...

21
thirdparty/argparse/.clang-tidy vendored Normal file
View File

@ -0,0 +1,21 @@
Checks:
-*,
clang-analyzer-*,
cppcoreguidelines-avoid-c-arrays,
cppcoreguidelines-special-member-functions,
readability-*,
CheckOptions:
- { key: readability-identifier-naming.ClassCase, value: CamelCase }
- { key: readability-identifier-naming.ConstexprVariableCase, value: lower_case }
- { key: readability-identifier-naming.ConstexprVariableIgnoredRegexp, value: "^Is.+" }
- { key: readability-identifier-naming.FunctionCase, value: lower_case }
- { key: readability-identifier-naming.NamespaceCase, value: lower_case }
- { key: readability-identifier-naming.ParameterCase, value: lower_case }
- { key: readability-identifier-naming.PrivateMemberCase, value: lower_case }
- { key: readability-identifier-naming.PrivateMemberPrefix, value: m_ }
- { key: readability-identifier-naming.StructCase, value: CamelCase }
- { key: readability-identifier-naming.StructIgnoredRegexp, value: "parse_number" }
- { key: readability-identifier-naming.VariableCase, value: lower_case }
HeaderFilterRegex: '.*'

View File

@ -0,0 +1,87 @@
name: CI
on: pull_request
jobs:
test:
name: ${{ matrix.toolchain }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
toolchain:
- macos-latest-clang
- macos-12-clang
- ubuntu-latest-clang
- ubuntu-latest-gcc
- windows-2019-msvc
- windows-latest-msvc
- windows-latest-clang
include:
- toolchain: macos-latest-clang
os: macos-latest
c_compiler: clang
cxx_compiler: clang++
- toolchain: macos-12-clang
os: macos-latest
c_compiler: clang
cxx_compiler: clang++
- toolchain: ubuntu-latest-clang
os: ubuntu-latest
c_compiler: clang
cxx_compiler: clang++
- toolchain: ubuntu-latest-gcc
os: ubuntu-latest
c_compiler: cc
cxx_compiler: g++
- toolchain: windows-2019-msvc
os: windows-2019
c_compiler: msvc
cxx_compiler: msvc
- toolchain: windows-latest-msvc
os: windows-latest
c_compiler: msvc
cxx_compiler: msvc
- toolchain: windows-latest-clang
os: windows-latest
c_compiler: clang-cl
cxx_compiler: clang-cl
cmake_opts: -T ClangCL
steps:
- name: Checkout Code
uses: actions/checkout@v2
- name: Configure
working-directory: test
run: cmake -S . -B build ${{ matrix.cmake_opts }}
env:
CC: ${{ matrix.c_compiler }}
CXX: ${{ matrix.cxx_compiler }}
- name: Build for ${{ matrix.os }} with ${{ matrix.compiler }}
working-directory: test
run: cmake --build build
- name: Test
if: ${{ ! startsWith(matrix.os, 'windows') }}
working-directory: test/build
run: ./tests
- name: Test (Windows)
if: ${{ startsWith(matrix.os, 'windows') }}
working-directory: test/build
run: ./Debug/tests.exe

273
thirdparty/argparse/.gitignore vendored Normal file
View File

@ -0,0 +1,273 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015 cache/options directory
.vs/
.vscode/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# DNX
project.lock.json
project.fragment.lock.json
artifacts/
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
#*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignoreable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush
.cr/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# CMake build directory
build
# Cppcheck build directory
analysis-cppcheck-build-dir
# Ideas directory
ideas
desktop.iniimages/

39
thirdparty/argparse/.travis.yml vendored Normal file
View File

@ -0,0 +1,39 @@
matrix:
include:
- os: linux
dist: bionic
language: cpp
compiler: gcc
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-8
env: CXX=g++-8 CC=gcc-8
- os: osx
osx_image: xcode10.2
language: cpp
compiler: clang
- os: windows
language: bash
env: CXX=cl.exe
install:
- |
if [[ $TRAVIS_OS_NAME == 'windows' ]]; then
choco install ninja cmake
elif [[ $TRAVIS_OS_NAME == 'osx' ]]; then
export PATH=~/Library/Python/3.7/bin:$PATH
pip3 install --user ninja cmake
else
pipenv global 3.6
pip install --user ninja cmake
fi
script:
- |
if [[ $TRAVIS_OS_NAME == 'windows' ]]; then
tools/build.bat
else
sh tools/build.sh
fi
- ./build/test/tests

98
thirdparty/argparse/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,98 @@
cmake_minimum_required(VERSION 3.12.4)
project(argparse
VERSION 2.9.0
DESCRIPTION "A single header argument parser for C++17"
HOMEPAGE_URL "https://github.com/p-ranav/argparse"
LANGUAGES CXX
)
option(ARGPARSE_BUILD_TESTS OFF)
option(ARGPARSE_LONG_VERSION_ARG_ONLY OFF)
include(GNUInstallDirs)
include(CMakePackageConfigHelpers)
string(REPLACE "/${CMAKE_LIBRARY_ARCHITECTURE}" "" CMAKE_INSTALL_LIBDIR_ARCHIND "${CMAKE_INSTALL_LIBDIR}")
add_library(argparse INTERFACE)
add_library(argparse::argparse ALIAS argparse)
if (ARGPARSE_LONG_VERSION_ARG_ONLY)
target_compile_definitions(argparse INTERFACE ARGPARSE_LONG_VERSION_ARG_ONLY=true)
endif ()
target_compile_features(argparse INTERFACE cxx_std_17)
target_include_directories(argparse INTERFACE
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>)
if(ARGPARSE_BUILD_SAMPLES)
add_subdirectory(samples)
endif()
if(ARGPARSE_BUILD_TESTS)
add_subdirectory(test)
endif()
install(TARGETS argparse EXPORT argparseConfig)
install(EXPORT argparseConfig
NAMESPACE argparse::
DESTINATION ${CMAKE_INSTALL_LIBDIR_ARCHIND}/cmake/${PROJECT_NAME})
install(FILES ${CMAKE_CURRENT_LIST_DIR}/include/argparse/argparse.hpp
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/argparse)
set(CONFIG_FILE_NAME_WITHOUT_EXT "${PROJECT_NAME}Config")
set(CMAKE_CONFIG_FILE_BASENAME "${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_FILE_NAME_WITHOUT_EXT}")
set(CMAKE_CONFIG_VERSION_FILE_NAME "${CMAKE_CONFIG_FILE_BASENAME}-version.cmake")
set(CMAKE_CONFIG_FILE_NAME "${CMAKE_CONFIG_FILE_BASENAME}.cmake")
if(${CMAKE_VERSION} VERSION_GREATER "3.14")
set(OPTIONAL_ARCH_INDEPENDENT "ARCH_INDEPENDENT")
endif()
write_basic_package_version_file("${CMAKE_CONFIG_VERSION_FILE_NAME}"
COMPATIBILITY ExactVersion
${OPTIONAL_ARCH_INDEPENDENT}
)
export(EXPORT argparseConfig
NAMESPACE argparse::)
install(FILES "${CMAKE_CONFIG_VERSION_FILE_NAME}"
DESTINATION "${CMAKE_INSTALL_LIBDIR_ARCHIND}/cmake/${PROJECT_NAME}")
set(PackagingTemplatesDir "${CMAKE_CURRENT_SOURCE_DIR}/packaging")
set(CPACK_PACKAGE_NAME "${PROJECT_NAME}")
set(CPACK_PACKAGE_VENDOR "argparse (C++) developers")
set(CPACK_PACKAGE_DESCRIPTION "${PROJECT_DESCRIPTION}")
set(CPACK_DEBIAN_PACKAGE_NAME "${CPACK_PACKAGE_NAME}")
set(CPACK_RPM_PACKAGE_NAME "${CPACK_PACKAGE_NAME}")
set(CPACK_PACKAGE_HOMEPAGE_URL "${PROJECT_HOMEPAGE_URL}")
set(CPACK_PACKAGE_MAINTAINER "Pranav Srinivas Kumar")
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "${CPACK_PACKAGE_MAINTAINER}")
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
set(CPACK_DEBIAN_PACKAGE_NAME "lib${PROJECT_NAME}-dev")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6-dev")
set(CPACK_DEBIAN_PACKAGE_SUGGESTS "cmake, pkg-config, pkg-conf")
set(CPACK_RPM_PACKAGE_NAME "lib${PROJECT_NAME}-devel")
set(CPACK_RPM_PACKAGE_SUGGESTS "${CPACK_DEBIAN_PACKAGE_SUGGESTS}")
set(CPACK_DEB_COMPONENT_INSTALL ON)
set(CPACK_RPM_COMPONENT_INSTALL ON)
set(CPACK_NSIS_COMPONENT_INSTALL ON)
set(CPACK_DEBIAN_COMPRESSION_TYPE "xz")
set(PKG_CONFIG_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc")
configure_file("${PackagingTemplatesDir}/pkgconfig.pc.in" "${PKG_CONFIG_FILE_NAME}" @ONLY)
install(FILES "${PKG_CONFIG_FILE_NAME}"
DESTINATION "${CMAKE_INSTALL_LIBDIR_ARCHIND}/pkgconfig"
)
include(CPack)

17
thirdparty/argparse/CONTRIBUTING.md vendored Normal file
View File

@ -0,0 +1,17 @@
# Contributing
Contributions are welcomed. Open a pull-request or an issue.
## Code of conduct
This project adheres to the [Open Code of Conduct][code-of-conduct]. By participating, you are expected to honor this code.
[code-of-conduct]: https://github.com/spotify/code-of-conduct/blob/master/code-of-conduct.md
## Code Style
This project prefers, but does not strictly enforce, a specific source code style. The style is described in `.clang-format` and `.clang-tidy`.
To generate a clang-tidy report:
```bash
clang-tidy --extra-arg=-std=c++17 --config-file=.clang-tidy include/argparse/argparse.hpp
```

7
thirdparty/argparse/LICENSE vendored Normal file
View File

@ -0,0 +1,7 @@
Copyright (c) 2018 Pranav Srinivas Kumar <pranav.srinivas.kumar@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

1143
thirdparty/argparse/README.md vendored Normal file

File diff suppressed because it is too large Load Diff

1
thirdparty/argparse/clang_format.bash vendored Normal file
View File

@ -0,0 +1 @@
clang-format -i include/argparse/*.hpp test/*.cpp samples/*.cpp

10
thirdparty/argparse/conanfile.py vendored Normal file
View File

@ -0,0 +1,10 @@
from conans import ConanFile
class ArgparseConan(ConanFile):
name = "argparse"
version = "2.9"
exports_sources = "include/argparse.hpp"
no_copy_source = True
def package(self):
self.copy("argparse.hpp")

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,7 @@
prefix=@CMAKE_INSTALL_PREFIX@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
Name: @PROJECT_NAME@
Description: @PROJECT_DESCRIPTION@
Version: @PROJECT_VERSION@
Cflags: -I${includedir}

View File

@ -0,0 +1,46 @@
cmake_minimum_required(VERSION 3.6)
project(argparse_samples)
if(MSVC)
# Force to always compile with W4
if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
endif()
elseif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
# Update if necessary
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic -Wsign-conversion -Wshadow -Wconversion")
endif()
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()
# Disable deprecation for windows
if (WIN32)
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
endif()
function(add_sample NAME)
ADD_EXECUTABLE(ARGPARSE_SAMPLE_${NAME} ${NAME}.cpp)
INCLUDE_DIRECTORIES("../include" ".")
TARGET_LINK_LIBRARIES(ARGPARSE_SAMPLE_${NAME} PRIVATE argparse::argparse)
set_target_properties(ARGPARSE_SAMPLE_${NAME} PROPERTIES OUTPUT_NAME ${NAME})
endfunction()
add_sample(positional_argument)
add_sample(optional_flag_argument)
add_sample(required_optional_argument)
add_sample(is_used)
add_sample(joining_repeated_optional_arguments)
add_sample(repeating_argument_to_increase_value)
add_sample(negative_numbers)
add_sample(description_epilog_metavar)
add_sample(list_of_arguments)
add_sample(compound_arguments)
add_sample(gathering_remaining_arguments)
add_sample(subcommands)
add_sample(parse_known_args)
add_sample(custom_prefix_characters)
add_sample(custom_assignment_characters)

View File

@ -0,0 +1,36 @@
#include <argparse/argparse.hpp>
int main(int argc, char *argv[]) {
argparse::ArgumentParser program("test");
program.add_argument("-a").default_value(false).implicit_value(true);
program.add_argument("-b").default_value(false).implicit_value(true);
program.add_argument("-c")
.nargs(2)
.default_value(std::vector<float>{0.0f, 0.0f})
.scan<'g', float>();
try {
program.parse_args(argc, argv); // Example: ./main -abc 1.95 2.47
} catch (const std::runtime_error &err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
}
auto a = program.get<bool>("-a"); // true
auto b = program.get<bool>("-b"); // true
auto c = program.get<std::vector<float>>("-c"); // {1.95, 2.47}
std::cout << "a: " << std::boolalpha << a << "\n";
std::cout << "b: " << b << "\n";
if (!c.empty()) {
std::cout << "c: ";
for (auto &v : c) {
std::cout << v << " ";
}
std::cout << std::endl;
}
}

View File

@ -0,0 +1,27 @@
#include <argparse/argparse.hpp>
#include <cassert>
int main(int argc, char *argv[]) {
argparse::ArgumentParser program("test");
program.set_prefix_chars("-+/");
program.set_assign_chars("=:");
program.add_argument("--foo");
program.add_argument("/B");
try {
program.parse_args(argc, argv);
} catch (const std::runtime_error &err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
}
if (program.is_used("--foo")) {
std::cout << "--foo : " << program.get("--foo") << "\n";
}
if (program.is_used("/B")) {
std::cout << "/B : " << program.get("/B") << "\n";
}
}

View File

@ -0,0 +1,31 @@
#include <argparse/argparse.hpp>
#include <cassert>
int main(int argc, char *argv[]) {
argparse::ArgumentParser program("test");
program.set_prefix_chars("-+/");
program.add_argument("+f");
program.add_argument("--bar");
program.add_argument("/foo");
try {
program.parse_args(argc, argv);
} catch (const std::runtime_error &err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
}
if (program.is_used("+f")) {
std::cout << "+f : " << program.get("+f") << "\n";
}
if (program.is_used("--bar")) {
std::cout << "--bar : " << program.get("--bar") << "\n";
}
if (program.is_used("/foo")) {
std::cout << "/foo : " << program.get("/foo") << "\n";
}
}

View File

@ -0,0 +1,17 @@
#include <argparse/argparse.hpp>
int main(int argc, char *argv[]) {
argparse::ArgumentParser program("main");
program.add_argument("thing").help("Thing to use.").metavar("THING");
program.add_argument("--member")
.help("The alias for the member to pass to.")
.metavar("ALIAS");
program.add_argument("--verbose").default_value(false).implicit_value(true);
program.add_description("Forward a thing to the next member.");
program.add_epilog("Possible things include betingalw, chiz, and res.");
program.parse_args(argc, argv);
std::cout << program << std::endl;
}

View File

@ -0,0 +1,24 @@
#include <argparse/argparse.hpp>
int main(int argc, char *argv[]) {
argparse::ArgumentParser program("compiler");
program.add_argument("files").remaining();
try {
program.parse_args(argc, argv);
} catch (const std::runtime_error &err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
}
try {
auto files = program.get<std::vector<std::string>>("files");
std::cout << files.size() << " files provided" << std::endl;
for (auto &file : files)
std::cout << file << std::endl;
} catch (std::logic_error &e) {
std::cout << "No files provided" << std::endl;
}
}

26
thirdparty/argparse/samples/is_used.cpp vendored Normal file
View File

@ -0,0 +1,26 @@
#include <argparse/argparse.hpp>
int main(int argc, char *argv[]) {
argparse::ArgumentParser program("test");
program.add_argument("--color")
.default_value(std::string{
"orange"}) // might otherwise be type const char* leading to an error
// when trying program.get<std::string>
.help("specify the cat's fur color");
try {
program.parse_args(argc, argv); // Example: ./main --color orange
} catch (const std::runtime_error &err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
}
auto color = program.get<std::string>("--color"); // "orange"
auto explicit_color =
program.is_used("--color"); // true, user provided orange
std::cout << "Color: " << color << "\n";
std::cout << "Argument was explicitly provided by user? " << std::boolalpha
<< explicit_color << "\n";
}

View File

@ -0,0 +1,28 @@
#include <argparse/argparse.hpp>
int main(int argc, char *argv[]) {
argparse::ArgumentParser program("test");
program.add_argument("--color")
.default_value<std::vector<std::string>>({"orange"})
.append()
.help("specify the cat's fur color");
try {
program.parse_args(
argc, argv); // Example: ./main --color red --color green --color blue
} catch (const std::runtime_error &err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
}
auto colors = program.get<std::vector<std::string>>(
"--color"); // {"red", "green", "blue"}
std::cout << "Colors: ";
for (const auto &c : colors) {
std::cout << c << " ";
}
std::cout << "\n";
}

View File

@ -0,0 +1,30 @@
#include <argparse/argparse.hpp>
int main(int argc, char *argv[]) {
argparse::ArgumentParser program("main");
program.add_argument("--input_files")
.help("The list of input files")
.nargs(2);
try {
program.parse_args(
argc, argv); // Example: ./main --input_files config.yml System.xml
} catch (const std::runtime_error &err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
}
auto files = program.get<std::vector<std::string>>(
"--input_files"); // {"config.yml", "System.xml"}
if (!files.empty()) {
std::cout << "Files: ";
for (auto &file : files) {
std::cout << file << " ";
}
std::cout << std::endl;
}
}

View File

@ -0,0 +1,32 @@
#include <argparse/argparse.hpp>
int main(int argc, char *argv[]) {
argparse::ArgumentParser program("test");
program.add_argument("integer").help("Input number").scan<'i', int>();
program.add_argument("floats")
.help("Vector of floats")
.nargs(4)
.scan<'g', float>();
try {
program.parse_args(argc, argv);
} catch (const std::runtime_error &err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
}
if (program.is_used("integer")) {
std::cout << "Integer : " << program.get<int>("integer") << "\n";
}
if (program.is_used("floats")) {
std::cout << "Floats : ";
for (const auto &f : program.get<std::vector<float>>("floats")) {
std::cout << f << " ";
}
std::cout << std::endl;
}
}

View File

@ -0,0 +1,22 @@
#include <argparse/argparse.hpp>
int main(int argc, char *argv[]) {
argparse::ArgumentParser program("test");
program.add_argument("--verbose")
.help("increase output verbosity")
.default_value(false)
.implicit_value(true);
try {
program.parse_args(argc, argv);
} catch (const std::runtime_error &err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
}
if (program["--verbose"] == true) {
std::cout << "Verbosity enabled" << std::endl;
}
}

View File

@ -0,0 +1,26 @@
#include <argparse/argparse.hpp>
#include <cassert>
int main(int argc, char *argv[]) {
argparse::ArgumentParser program("test");
program.add_argument("--foo").implicit_value(true).default_value(false);
program.add_argument("bar");
auto unknown_args = program.parse_known_args(argc, argv);
if (program.is_used("--foo")) {
std::cout << "--foo : " << program.get<bool>("--foo") << "\n";
}
if (program.is_used("bar")) {
std::cout << "bar : " << program.get<std::string>("bar") << "\n";
}
if (!unknown_args.empty()) {
std::cout << "Unknown args : ";
for (const auto &u : unknown_args) {
std::cout << u << " ";
}
std::cout << std::endl;
}
}

View File

@ -0,0 +1,28 @@
#include <argparse/argparse.hpp>
int main(int argc, char *argv[]) {
argparse::ArgumentParser program("main");
program.add_argument("square")
.help("display the square of a given number")
.scan<'i', int>();
program.add_argument("--verbose").default_value(false).implicit_value(true);
try {
program.parse_args(argc, argv);
} catch (const std::runtime_error &err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
}
int input = program.get<int>("square");
if (program["--verbose"] == true) {
std::cout << "The square of " << input << " is " << (input * input)
<< std::endl;
} else {
std::cout << (input * input) << std::endl;
}
}

View File

@ -0,0 +1,17 @@
#include <argparse/argparse.hpp>
int main(int argc, char *argv[]) {
argparse::ArgumentParser program("test");
int verbosity = 0;
program.add_argument("-V", "--verbose")
.action([&](const auto &) { ++verbosity; })
.append()
.default_value(false)
.implicit_value(true)
.nargs(0);
program.parse_args(argc, argv); // Example: ./main -VVVV
std::cout << "verbose level: " << verbosity << std::endl; // verbose level: 4
}

View File

@ -0,0 +1,19 @@
#include <argparse/argparse.hpp>
int main(int argc, char *argv[]) {
argparse::ArgumentParser program("test");
program.add_argument("-o", "--output")
.required()
.help("specify the output file.");
try {
program.parse_args(argc, argv);
} catch (const std::runtime_error &err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
}
std::cout << "Output written to " << program.get("-o") << "\n";
}

View File

@ -0,0 +1,65 @@
#include <argparse/argparse.hpp>
int main(int argc, char *argv[]) {
argparse::ArgumentParser program("git");
// git add subparser
argparse::ArgumentParser add_command("add");
add_command.add_description("Add file contents to the index");
add_command.add_argument("files")
.help("Files to add content from. Fileglobs (e.g. *.c) can be given to "
"add all matching files.")
.remaining();
// git commit subparser
argparse::ArgumentParser commit_command("commit");
commit_command.add_description("Record changes to the repository");
commit_command.add_argument("-a", "--all")
.help("Tell the command to automatically stage files that have been "
"modified and deleted.")
.default_value(false)
.implicit_value(true);
commit_command.add_argument("-m", "--message")
.help("Use the given <msg> as the commit message.");
// git cat-file subparser
argparse::ArgumentParser catfile_command("cat-file");
catfile_command.add_description(
"Provide content or type and size information for repository objects");
catfile_command.add_argument("-t").help(
"Instead of the content, show the object type identified by <object>.");
catfile_command.add_argument("-p").help(
"Pretty-print the contents of <object> based on its type.");
// git submodule subparser
argparse::ArgumentParser submodule_command("submodule");
submodule_command.add_description("Initialize, update or inspect submodules");
argparse::ArgumentParser submodule_update_command("update");
submodule_update_command.add_description(
"Update the registered submodules to match what the superproject "
"expects");
submodule_update_command.add_argument("--init")
.default_value(false)
.implicit_value(true);
submodule_update_command.add_argument("--recursive")
.default_value(false)
.implicit_value(true);
submodule_command.add_subparser(submodule_update_command);
program.add_subparser(add_command);
program.add_subparser(commit_command);
program.add_subparser(catfile_command);
program.add_subparser(submodule_command);
try {
program.parse_args(argc, argv);
} catch (const std::runtime_error &err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
}
// Use arguments
}

2
thirdparty/argparse/test/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
build/
build_linux/

63
thirdparty/argparse/test/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,63 @@
cmake_minimum_required(VERSION 3.6)
project(argparse_tests)
if(MSVC)
# Force to always compile with W4
if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
endif()
elseif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
# Update if necessary
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic -Wsign-conversion -Wshadow -Wconversion")
endif()
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()
# Disable deprecation for windows
if (WIN32)
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
endif()
# ARGPARSE executable
file(GLOB ARGPARSE_TEST_SOURCES
main.cpp
test_actions.cpp
test_append.cpp
test_compound_arguments.cpp
test_container_arguments.cpp
test_const_correct.cpp
test_default_args.cpp
test_get.cpp
test_help.cpp
test_invalid_arguments.cpp
test_is_used.cpp
test_issue_37.cpp
test_negative_numbers.cpp
test_optional_arguments.cpp
test_parent_parsers.cpp
test_parse_args.cpp
test_positional_arguments.cpp
test_repr.cpp
test_required_arguments.cpp
test_scan.cpp
test_value_semantics.cpp
test_version.cpp
test_subparsers.cpp
test_parse_known_args.cpp
test_equals_form.cpp
test_prefix_chars.cpp
)
set_source_files_properties(main.cpp
PROPERTIES
COMPILE_DEFINITIONS DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN)
ADD_EXECUTABLE(ARGPARSE_TESTS ${ARGPARSE_TEST_SOURCES})
INCLUDE_DIRECTORIES("../include" ".")
set_target_properties(ARGPARSE_TESTS PROPERTIES OUTPUT_NAME tests)
set_property(TARGET ARGPARSE_TESTS PROPERTY CXX_STANDARD 17)
# Set ${PROJECT_NAME} as the startup project
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ARGPARSE_TESTS)

Some files were not shown because too many files have changed in this diff Show More