aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmake/kicad_gerber.cmake10
-rwxr-xr-xpy/kicad_gerber.py134
2 files changed, 108 insertions, 36 deletions
diff --git a/cmake/kicad_gerber.cmake b/cmake/kicad_gerber.cmake
index c56ed19..4e8c850 100644
--- a/cmake/kicad_gerber.cmake
+++ b/cmake/kicad_gerber.cmake
@@ -25,6 +25,10 @@ function(kicad_gerber)
get_filename_component(pcb_file "${ARGS_PCB_FILE}" ABSOLUTE BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
get_filename_component(basename "${pcb_file}" NAME_WE)
+ if (NOT DEFINED KicadUtilsPython)
+ set(KicadUtilsPython python)
+ endif ()
+
if (NOT ARGS_TARGET)
set(target "${basename}-gerber")
else ()
@@ -56,10 +60,11 @@ function(kicad_gerber)
endif()
execute_process(
- COMMAND "${KicadUtilsPyDir}/kicad_gerber.py"
+ COMMAND "${KicadUtilsPython}" "${KicadUtilsPyDir}/kicad_gerber.py"
--pcb "${pcb_file}"
--output-directory "${out_dir}"
- --detect-files-only ${CMAKE_CURRENT_BINARY_DIR}/${target}-gerber-index.txt
+ --detect-files-only
+ --index ${CMAKE_CURRENT_BINARY_DIR}/${target}-gerber-index.txt
${protel}
${uppercase_extensions}
${extended_gerber_attributes}
@@ -107,6 +112,7 @@ function(kicad_gerber)
OUTPUT ${ARGS_ZIP_FILE}
MAIN_DEPENDENCY "${pcb_file}"
DEPENDS ${outputs}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMAND cmake -E remove -f ${ARGS_ZIP_FILE}
COMMAND zip -q ${ARGS_ZIP_FILE} -j ${outputs})
endif ()
diff --git a/py/kicad_gerber.py b/py/kicad_gerber.py
index 511f9ee..ac0556d 100755
--- a/py/kicad_gerber.py
+++ b/py/kicad_gerber.py
@@ -1,9 +1,45 @@
#!/usr/bin/env python
from __future__ import print_function
-import sys
-import os
+
import argparse
-from pcbnew import *
+import os
+import sys
+
+try:
+ from pcbnew import *
+except ImportError as e:
+ ee_hack = os.environ.get("EE_HACK", "0")
+ print("ee_hack={}".format(ee_hack), file=sys.stderr)
+ try_p2 = ee_hack == "0"
+ try_system = ee_hack == "1"
+ print("Could not import 'pcbnew' module. Make sure you run this command with KiCAD's python.", file=sys.stderr)
+
+ ret = 1
+ try:
+ import subprocess
+
+ if try_p2:
+ argv = sys.argv[1:]
+ # Try running explicitly with Python 2
+ cmd = "/usr/bin/python2 {} {}".format(__file__, " ".join(argv))
+ env = dict(os.environ)
+ env["EE_HACK"] = "1"
+ print(cmd, file=sys.stderr)
+ ret = subprocess.call(cmd, shell=True, env=env)
+ elif try_system:
+ argv = sys.argv[1:]
+ # Try with the OS's main python, hopefully the KiCAD packages support that
+ cmd = "/usr/bin/python3 {} {}".format(__file__, " ".join(argv))
+ env = dict(os.environ)
+ env["EE_HACK"] = "2"
+ print(cmd, file=sys.stderr)
+ ret = subprocess.call(cmd, shell=True, env=env)
+ finally:
+ pass
+ print("ret={}".format(ret), file=sys.stderr)
+
+ sys.exit(ret)
+
def layer_name_parser(s):
parts = s.split('=')
@@ -12,6 +48,7 @@ def layer_name_parser(s):
else:
return parts
+
parser = argparse.ArgumentParser(description='KiCAD PCB to GERBER converter')
parser.add_argument('--pcb',
@@ -28,8 +65,15 @@ parser.add_argument('--output-directory',
parser.add_argument('--detect-files-only',
dest='detect_files_only',
- action='store',
- help='Don\'t create the GERBER files, just write a list of to be created')
+ action='store_true',
+ help='Don\'t create the GERBER files, just list the files to be created')
+
+parser.add_argument('-M',
+ dest='mkdep',
+ help='Output a Makefile-compatible file')
+
+parser.add_argument('--index',
+ dest='index')
parser.add_argument('--create-drill-map-file',
dest='create_drill_map_file',
@@ -69,6 +113,7 @@ if args.layer_extensions is not None:
board = LoadBoard(args.pcb)
+
class Plan:
def __init__(self, layerNum, layerName, description):
self.layerNum = layerNum
@@ -88,6 +133,7 @@ class Plan:
description = "Copper Layer " + layerName
return Plan(layerNum, layerName, description)
+
plot_plan = [Plan.standard(layerNum, description) for (layerNum, description) in [
(F_SilkS, "Silk front"),
(F_Mask, "Mask front"),
@@ -105,6 +151,7 @@ pctl = PLOT_CONTROLLER(board)
popt = pctl.GetPlotOptions()
output_directory = args.output_directory
+output_directory = os.path.abspath(args.output_directory)
popt.SetOutputDirectory(output_directory)
if not os.path.isdir(output_directory):
@@ -132,6 +179,12 @@ basename = os.path.splitext(filename)[0]
drlFileOut = drlFile = basename + "-PTH.drl"
drlNpthFileOut = drlNpthFile = basename + "-NPTH.drl"
+if args.protel_extensions:
+ n, e = os.path.splitext(drlFileOut)
+ drlFileOut = n + ".txt"
+ n, e = os.path.splitext(drlNpthFileOut)
+ drlNpthFileOut = n + ".txt"
+
if args.uppercase_extensions:
n, e = os.path.splitext(drlFileOut)
drlFileOut = n + e.upper()
@@ -162,43 +215,60 @@ for plan in plot_plan:
# if newExt is not None:
# ext = "." + newExt
+ # if not args.protel_extensions:
plan.postfix = plan.layerName
plan.filename = basename + "-" + plan.postfix + ext
# print "filename = " + plan.filename + ", postfix=" + plan.postfix
# print "filename: " + plan.filename
+if args.mkdep:
+ with open(args.mkdep, "w") as f:
+ pcb = os.path.abspath(args.pcb)
+
+ def w(path):
+ p = path[len(os.path.commonprefix([path, pcb])):]
+ print("{}: {}".format(p, args.pcb), file=f)
+
+ for plan in plot_plan:
+ w(plan.filename)
+
+ w(drlFileOut)
+ w(drlNpthFileOut)
+
+if args.index:
+ with open(args.index, "w") as f:
+ pcb = os.path.abspath(args.pcb)
+
+ def w(path):
+ p = path[len(os.path.commonprefix([path, pcb])):]
+ print("{}".format(p), file=f)
+
+ for plan in plot_plan:
+ w(plan.filename)
+
+ w(drlFileOut)
+ w(drlNpthFileOut)
+
if args.detect_files_only:
- with open(args.detect_files_only, "w") as f:
- for plan in plot_plan:
- print(plan.filename, file=f)
+ for plan in plot_plan:
+ print(plan.filename)
+
+ print(drlFileOut)
+ print(drlNpthFileOut)
- print(drlFileOut, file=f)
- print(drlNpthFileOut, file=f)
sys.exit(0)
# Set some important plot options:
popt.SetPlotFrameRef(False)
-
-# "Default line width (mm)", default=0.1mm
-popt.SetLineWidth(FromMM(0.1))
+popt.SetLineWidth(FromMM(0.35))
popt.SetAutoScale(False)
-
-# "Mirrored plot", default=False. Not applicable for Gerber
+popt.SetScale(1)
popt.SetMirror(False)
-
-# "Include extended attributes", default=False
popt.SetUseGerberAttributes(args.extended_gerber_attributes)
-
-# "Drill marks"
-popt.SetDrillMarksType(PCB_PLOT_PARAMS.NO_DRILL_SHAPE)
-
-# "Scaling"
popt.SetScale(1)
-
-# "Use auxilary axis as origin"
-popt.SetUseAuxOrigin(False)
+popt.SetUseAuxOrigin(True)
# This by gerbers only (also the name is truly horrid!)
popt.SetSubtractMaskFromSilk(False)
@@ -218,20 +288,16 @@ for plan in plot_plan:
pctl.PlotLayer()
pctl.ClosePlot()
+popt.SetDrillMarksType(PCB_PLOT_PARAMS.FULL_DRILL_SHAPE)
+
drlwriter = EXCELLON_WRITER(board)
drlwriter.SetMapFileFormat(PLOT_FORMAT_GERBER)
-# "Drill file options"
-
-# "Mirror y axis", default=False
mirror = False
-
-# "Minimal header", default=True
-minimalHeader = True
-
+minimalHeader = False
offset = wxPoint(0, 0)
-
-# "Merge PTH and NPTH into one file", default=False
+# False to generate 2 separate drill files (one for plated holes, one for non plated holes)
+# True to generate only one drill file
mergeNPTH = False
drlwriter.SetOptions(mirror, minimalHeader, offset, mergeNPTH)