Add missing IPC2581 cli support

This commit is contained in:
Marek Roszko 2024-01-30 20:42:18 -05:00
parent f07a0e0021
commit c8d24b7613
9 changed files with 396 additions and 2 deletions

View File

@ -77,6 +77,7 @@ set( KICOMMON_SRCS
jobs/job_export_pcb_dxf.cpp
jobs/job_export_pcb_gerber.cpp
jobs/job_export_pcb_gerbers.cpp
jobs/job_export_pcb_ipc2581.cpp
jobs/job_export_pcb_pdf.cpp
jobs/job_export_pcb_pos.cpp
jobs/job_export_pcb_svg.cpp

View File

@ -0,0 +1,38 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2024 Mark Roszko <mark.roszko@gmail.com>
* Copyright (C) 2024 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_pcb_ipc2581.h>
JOB_EXPORT_PCB_IPC2581::JOB_EXPORT_PCB_IPC2581( bool aIsCli ) :
JOB( "ipc2581", aIsCli ),
m_filename(),
m_outputFile(),
m_drawingSheet(),
m_units( IPC2581_UNITS::MILLIMETERS ),
m_version( IPC2581_VERSION::C ),
m_precision( 3 ),
m_compress( false ),
m_colInternalId(),
m_colMfgPn(),
m_colMfg(),
m_colDistPn(),
m_colDist()
{
}

View File

@ -0,0 +1,62 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2024 Mark Roszko <mark.roszko@gmail.com>
* Copyright (C) 1992-2024 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_IPC2581_H
#define JOB_EXPORT_PCB_IPC2581_H
#include <kicommon.h>
#include <wx/string.h>
#include "job.h"
class KICOMMON_API JOB_EXPORT_PCB_IPC2581 : public JOB
{
public:
JOB_EXPORT_PCB_IPC2581( bool aIsCli );
enum class IPC2581_UNITS
{
INCHES,
MILLIMETERS
};
enum class IPC2581_VERSION
{
B,
C
};
wxString m_filename;
wxString m_outputFile;
wxString m_drawingSheet;
IPC2581_UNITS m_units;
IPC2581_VERSION m_version;
int m_precision;
bool m_compress;
wxString m_colInternalId;
wxString m_colMfgPn;
wxString m_colMfg;
wxString m_colDistPn;
wxString m_colDist;
};
#endif

View File

@ -47,6 +47,7 @@ set( KICAD_CLI_SRCS
cli/command_pcb_export_dxf.cpp
cli/command_pcb_export_gerber.cpp
cli/command_pcb_export_gerbers.cpp
cli/command_pcb_export_ipc2581.cpp
cli/command_pcb_export_pdf.cpp
cli/command_pcb_export_pos.cpp
cli/command_pcb_export_svg.cpp

View File

@ -0,0 +1,152 @@
/*
* 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_pcb_export_ipc2581.h"
#include <cli/exit_codes.h>
#include "jobs/job_export_pcb_ipc2581.h"
#include <kiface_base.h>
#include <string_utils.h>
#include <wx/crt.h>
#include <macros.h>
#include <wx/tokenzr.h>
#include <locale_io.h>
#define ARG_COMPRESS "--compress"
#define ARG_BOM_COL_INT_ID "--bom-col-int-id"
#define ARG_BOM_COL_MFG_PN "--bom-col-mfg-pn"
#define ARG_BOM_COL_MFG "--bom-col-mfg"
#define ARG_BOM_COL_DIST_PN "--bom-col-dist-pn"
#define ARG_BOM_COL_DIST "--bom-col-dist"
#define ARG_UNITS "--units"
CLI::PCB_EXPORT_IPC2581_COMMAND::PCB_EXPORT_IPC2581_COMMAND() :
PCB_EXPORT_BASE_COMMAND( "ipc2581" )
{
addDrawingSheetArg();
addDefineArg();
m_argParser.add_description( std::string( "Export the PCB in IPC2581 format" ) );
m_argParser.add_argument( ARG_PRECISION )
.help( std::string( "Precision" ) )
.scan<'i', int>()
.default_value( 3 )
.metavar( "PRECISION" );
m_argParser.add_argument( ARG_COMPRESS )
.help( std::string( "Subtract soldermask from silkscreen" ) )
.flag();
m_argParser.add_argument( ARG_VERSION )
.default_value( std::string( "C" ) )
.help( std::string( "IPC2581 standard version" ) )
.choices( "B", "C" );
m_argParser.add_argument( ARG_UNITS )
.default_value( std::string( "mm" ) )
.help( std::string( "Units" ) )
.choices( "mm", "in" );
m_argParser.add_argument( ARG_BOM_COL_INT_ID )
.default_value( std::string() )
.help( std::string(
"Name of the part field to use for the Bill of Material Internal Id Column" ) )
.metavar( "FIELD_NAME" );
m_argParser.add_argument( ARG_BOM_COL_MFG_PN )
.default_value( std::string() )
.help( std::string( "Name of the part field to use for the Bill of "
"Material Manufacturer Part Number Column" ) )
.metavar( "FIELD_NAME" );
m_argParser.add_argument( ARG_BOM_COL_MFG )
.default_value( std::string() )
.help( std::string( "Name of the part field to use for the Bill of "
"Material Manufacturer Column" ) )
.metavar( "FIELD_NAME" );
m_argParser.add_argument( ARG_BOM_COL_DIST_PN )
.default_value( std::string() )
.help( std::string( "Name of the part field to use for the Bill of "
"Material Distributor Part Number Column" ) )
.metavar( "FIELD_NAME" );
m_argParser.add_argument( ARG_BOM_COL_DIST )
.default_value( std::string() )
.help( std::string( "Name to insert into Bill of "
"Material Distributor Column" ) )
.metavar( "FIELD_NAME" );
}
int CLI::PCB_EXPORT_IPC2581_COMMAND::doPerform( KIWAY& aKiway )
{
int exitCode = PCB_EXPORT_BASE_COMMAND::doPerform( aKiway );
if( exitCode != EXIT_CODES::OK )
return exitCode;
std::unique_ptr<JOB_EXPORT_PCB_IPC2581> ipc2581Job( new JOB_EXPORT_PCB_IPC2581( true ) );
ipc2581Job->m_filename = m_argInput;
ipc2581Job->m_outputFile = m_argOutput;
ipc2581Job->m_drawingSheet = m_argDrawingSheet;
ipc2581Job->SetVarOverrides( m_argDefineVars );
if( !wxFile::Exists( ipc2581Job->m_filename ) )
{
wxFprintf( stderr, _( "Board file does not exist or is not accessible\n" ) );
return EXIT_CODES::ERR_INVALID_INPUT_FILE;
}
ipc2581Job->m_compress = m_argParser.get<bool>( ARG_COMPRESS );
ipc2581Job->m_precision = m_argParser.get<int>( ARG_PRECISION );
wxString version = From_UTF8( m_argParser.get<std::string>( ARG_VERSION ).c_str() );
if( version == 'B' )
ipc2581Job->m_version = JOB_EXPORT_PCB_IPC2581::IPC2581_VERSION::B;
else if( version == 'C' )
ipc2581Job->m_version = JOB_EXPORT_PCB_IPC2581::IPC2581_VERSION::C;
wxString units = From_UTF8( m_argParser.get<std::string>( ARG_UNITS ).c_str() );
if( version == "mm" )
ipc2581Job->m_units = JOB_EXPORT_PCB_IPC2581::IPC2581_UNITS::MILLIMETERS;
else if( version == "in" )
ipc2581Job->m_units = JOB_EXPORT_PCB_IPC2581::IPC2581_UNITS::INCHES;
ipc2581Job->m_colInternalId =
From_UTF8( m_argParser.get<std::string>( ARG_BOM_COL_INT_ID ).c_str() );
ipc2581Job->m_colMfgPn =
From_UTF8( m_argParser.get<std::string>( ARG_BOM_COL_MFG_PN ).c_str() );
ipc2581Job->m_colMfg = From_UTF8( m_argParser.get<std::string>( ARG_BOM_COL_MFG ).c_str() );
ipc2581Job->m_colDistPn =
From_UTF8( m_argParser.get<std::string>( ARG_BOM_COL_DIST_PN ).c_str() );
ipc2581Job->m_colDist =
From_UTF8( m_argParser.get<std::string>( ARG_BOM_COL_DIST ).c_str() );
LOCALE_IO dummy;
exitCode = aKiway.ProcessJob( KIWAY::FACE_PCB, ipc2581Job.get() );
return exitCode;
}

View File

@ -0,0 +1,47 @@
/*
* 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_IPC2581_H
#define COMMAND_EXPORT_PCB_IPC2581_H
#include "command_pcb_export_base.h"
namespace CLI
{
#define ARG_NO_X2 "--no-x2"
#define ARG_NO_NETLIST "--no-netlist"
#define ARG_SUBTRACT_SOLDERMASK "--subtract-soldermask"
#define ARG_DISABLE_APERTURE_MACROS "--disable-aperture-macros"
#define ARG_USE_DRILL_FILE_ORIGIN "--use-drill-file-origin"
#define ARG_PRECISION "--precision"
#define ARG_NO_PROTEL_EXTENSION "--no-protel-ext"
class PCB_EXPORT_IPC2581_COMMAND : public PCB_EXPORT_BASE_COMMAND
{
public:
PCB_EXPORT_IPC2581_COMMAND();
protected:
int doPerform( KIWAY& aKiway ) override;
};
} // namespace CLI
#endif

View File

@ -54,6 +54,7 @@
#include "cli/command_pcb_export_dxf.h"
#include "cli/command_pcb_export_gerber.h"
#include "cli/command_pcb_export_gerbers.h"
#include "cli/command_pcb_export_ipc2581.h"
#include "cli/command_pcb_export_pdf.h"
#include "cli/command_pcb_export_pos.h"
#include "cli/command_pcb_export_svg.h"
@ -137,6 +138,7 @@ static CLI::PCB_EXPORT_PDF_COMMAND exportPcbPdfCmd{};
static CLI::PCB_EXPORT_POS_COMMAND exportPcbPosCmd{};
static CLI::PCB_EXPORT_GERBER_COMMAND exportPcbGerberCmd{};
static CLI::PCB_EXPORT_GERBERS_COMMAND exportPcbGerbersCmd{};
static CLI::PCB_EXPORT_IPC2581_COMMAND exportPcbIpc2581Cmd{};
static CLI::PCB_EXPORT_COMMAND exportPcbCmd{};
static CLI::SCH_EXPORT_COMMAND exportSchCmd{};
static CLI::SCH_COMMAND schCmd{};
@ -189,6 +191,7 @@ static std::vector<COMMAND_ENTRY> commandStack = {
&exportPcbGerberCmd,
&exportPcbGerbersCmd,
&exportPcbGlbCmd,
&exportPcbIpc2581Cmd,
&exportPcbPdfCmd,
&exportPcbPosCmd,
&exportPcbStepCmd,

View File

@ -2,7 +2,7 @@
* 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-2023 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2024 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
@ -28,6 +28,7 @@
#include <drawing_sheet/ds_proxy_view_item.h>
#include <jobs/job_fp_export_svg.h>
#include <jobs/job_fp_upgrade.h>
#include <jobs/job_export_pcb_ipc2581.h>
#include <jobs/job_export_pcb_gerber.h>
#include <jobs/job_export_pcb_gerbers.h>
#include <jobs/job_export_pcb_drill.h>
@ -60,8 +61,11 @@
#include <pgm_base.h>
#include <pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.h>
#include <reporter.h>
#include <string_utf8_map.h>
#include <wildcards_and_files_ext.h>
#include <export_vrml.h>
#include <wx/wfstream.h>
#include <wx/zipstrm.h>
#include "pcbnew_scripting_helpers.h"
@ -84,6 +88,8 @@ PCBNEW_JOBS_HANDLER::PCBNEW_JOBS_HANDLER()
Register( "fpsvg",
std::bind( &PCBNEW_JOBS_HANDLER::JobExportFpSvg, this, std::placeholders::_1 ) );
Register( "drc", std::bind( &PCBNEW_JOBS_HANDLER::JobExportDrc, this, std::placeholders::_1 ) );
Register( "ipc2581",
std::bind( &PCBNEW_JOBS_HANDLER::JobExportIpc2581, this, std::placeholders::_1 ) );
}
@ -1069,6 +1075,89 @@ int PCBNEW_JOBS_HANDLER::JobExportDrc( JOB* aJob )
}
int PCBNEW_JOBS_HANDLER::JobExportIpc2581( JOB* aJob )
{
JOB_EXPORT_PCB_IPC2581* job = dynamic_cast<JOB_EXPORT_PCB_IPC2581*>( aJob );
if( job == nullptr )
return CLI::EXIT_CODES::ERR_UNKNOWN;
if( job->IsCli() )
m_reporter->Report( _( "Loading board\n" ), RPT_SEVERITY_INFO );
BOARD* brd = LoadBoard( job->m_filename );
if( job->m_outputFile.IsEmpty() )
{
wxFileName fn = brd->GetFileName();
fn.SetName( fn.GetName() );
fn.SetExt( FILEEXT::Ipc2581FileExtension );
job->m_outputFile = fn.GetFullName();
}
STRING_UTF8_MAP props;
props["units"] =
job->m_units == JOB_EXPORT_PCB_IPC2581::IPC2581_UNITS::MILLIMETERS ? "mm" : "inch";
props["sigfig"] = wxString::Format( "%d", job->m_units );
props["version"] = job->m_version == JOB_EXPORT_PCB_IPC2581::IPC2581_VERSION::C ? "C" : "B";
props["OEMRef"] = job->m_colInternalId;
props["mpn"] = job->m_colMfgPn;
props["mfg"] = job->m_colMfg;
props["dist"] = job->m_colDist;
props["distpn"] = job->m_colDistPn;
wxString tempFile = wxFileName::CreateTempFileName( wxS( "pcbnew_ipc" ) );
try
{
IO_RELEASER<PCB_IO> pi( PCB_IO_MGR::PluginFind( PCB_IO_MGR::IPC2581 ) );
pi->SetProgressReporter( m_progressReporter );
pi->SaveBoard( tempFile, brd, &props );
}
catch( const IO_ERROR& ioe )
{
m_reporter->Report( wxString::Format( _( "Error generating IPC2581 file '%s'.\n%s" ),
job->m_filename, ioe.What() ),
RPT_SEVERITY_ERROR );
wxRemoveFile( tempFile );
return CLI::EXIT_CODES::ERR_UNKNOWN;
}
if( job->m_compress )
{
wxFileName tempfn = job->m_outputFile;
tempfn.SetExt( FILEEXT::Ipc2581FileExtension );
wxFileName zipfn = tempFile;
zipfn.SetExt( "zip" );
wxFFileOutputStream fnout( zipfn.GetFullPath() );
wxZipOutputStream zip( fnout );
wxFFileInputStream fnin( tempFile );
zip.PutNextEntry( tempfn.GetFullName() );
fnin.Read( zip );
zip.Close();
fnout.Close();
wxRemoveFile( tempFile );
tempFile = zipfn.GetFullPath();
}
// If save succeeded, replace the original with what we just wrote
if( !wxRenameFile( tempFile, job->m_outputFile ) )
{
m_reporter->Report( wxString::Format( _( "Error generating IPC2581 file '%s'.\n"
"Failed to rename temporary file '%s." ),
job->m_outputFile, tempFile ),
RPT_SEVERITY_ERROR );
}
return CLI::EXIT_CODES::SUCCESS;
}
DS_PROXY_VIEW_ITEM* PCBNEW_JOBS_HANDLER::getDrawingSheetProxyView( BOARD* aBrd )
{
DS_PROXY_VIEW_ITEM* drawingSheet = new DS_PROXY_VIEW_ITEM( pcbIUScale,
@ -1113,4 +1202,4 @@ void PCBNEW_JOBS_HANDLER::loadOverrideDrawingSheet( BOARD* aBrd, const wxString&
// failed loading custom path, revert back to default
loadSheet( aBrd->GetProject()->GetProjectFile().m_BoardDrawingSheetFile );
}
}

View File

@ -45,6 +45,7 @@ public:
int JobExportFpUpgrade( JOB* aJob );
int JobExportFpSvg( JOB* aJob );
int JobExportDrc( JOB* aJob );
int JobExportIpc2581( JOB* aJob );
private:
void populateGerberPlotOptionsFromJob( PCB_PLOT_PARAMS& aPlotOpts,