forked from sinara-hw/kirdy
flake: Generate prod files with flake.nix
- Generate production files with nix build .
This commit is contained in:
parent
a0c1ca1c58
commit
9e1f359d78
|
@ -3,6 +3,9 @@
|
||||||
|
|
||||||
# Temporary files
|
# Temporary files
|
||||||
*.000
|
*.000
|
||||||
|
*.cache
|
||||||
|
*.config
|
||||||
|
*.local
|
||||||
*.bak
|
*.bak
|
||||||
*.bck
|
*.bck
|
||||||
*.kicad_pcb-bak
|
*.kicad_pcb-bak
|
||||||
|
@ -28,4 +31,4 @@ __pycache__
|
||||||
*.ses
|
*.ses
|
||||||
|
|
||||||
# Generated Production Files
|
# Generated Production Files
|
||||||
production
|
result
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"kicad_bom_generator": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1702353729,
|
||||||
|
"narHash": "sha256-NIM/GLC71VdGdMletBBv9lSPuHpgD9zzeGiVQLEAULA=",
|
||||||
|
"ref": "refs/heads/main",
|
||||||
|
"rev": "72686f5556785c9aa13678dc42757dddfb7d7c23",
|
||||||
|
"revCount": 2,
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://git.m-labs.hk/linuswck/KiCAD_BOM_Generator.git"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://git.m-labs.hk/linuswck/KiCAD_BOM_Generator.git"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1701952659,
|
||||||
|
"narHash": "sha256-TJv2srXt6fYPUjxgLAL0cy4nuf1OZD4KuA1TrCiQqg0=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "b4372c4924d9182034066c823df76d6eaf1f4ec4",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixos-23.11",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"kicad_bom_generator": "kicad_bom_generator",
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
{
|
||||||
|
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
|
||||||
|
inputs.kicad_bom_generator = {
|
||||||
|
url = "git+https://git.m-labs.hk/linuswck/KiCAD_BOM_Generator.git";
|
||||||
|
flake = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self, nixpkgs, kicad_bom_generator }: {
|
||||||
|
formatter.x86_64-linux = nixpkgs.legacyPackages.x86_64-linux.nixfmt;
|
||||||
|
|
||||||
|
devShells.x86_64-linux.default =
|
||||||
|
let pkgs = nixpkgs.legacyPackages.x86_64-linux;
|
||||||
|
in pkgs.mkShell {
|
||||||
|
name = "kicad-dev-shell";
|
||||||
|
buildInputs = [ pkgs.kicad ];
|
||||||
|
};
|
||||||
|
|
||||||
|
defaultPackage.x86_64-linux =
|
||||||
|
with import nixpkgs { system = "x86_64-linux"; };
|
||||||
|
stdenv.mkDerivation {
|
||||||
|
name = "production_files";
|
||||||
|
src = ./src;
|
||||||
|
|
||||||
|
nativeBuildInputs = [ pkgs.kicad pkgs.zip pkgs.python3 ];
|
||||||
|
|
||||||
|
buildPhase = ''
|
||||||
|
# kicad-cli requires the use of $HOME
|
||||||
|
export HOME=/tmp
|
||||||
|
|
||||||
|
SCH=kirdy.kicad_sch
|
||||||
|
PCB=kirdy.kicad_pcb
|
||||||
|
|
||||||
|
# Get Revision Number from the Title Block in KiCAD Top Schematics
|
||||||
|
REV=$(cat $SCH | grep rev | cut -d'"' -f 2)
|
||||||
|
PREFIX=kirdy_$REV
|
||||||
|
|
||||||
|
kicad-cli sch export python-bom $SCH -o $PREFIX"_bom".xml
|
||||||
|
export PYTHONPATH=${pkgs.kicad.base}/share/kicad/plugins
|
||||||
|
python ${kicad_bom_generator}/generate_bom_from_xml.py $PREFIX"_bom".xml $PREFIX"_bom".csv
|
||||||
|
|
||||||
|
kicad-cli sch export pdf $SCH -o $PREFIX.pdf
|
||||||
|
kicad-cli pcb export pos $PCB --format csv --units mm -o $PREFIX"_pos".csv
|
||||||
|
|
||||||
|
export KICAD7_3DMODEL_DIR=${pkgs.kicad.libraries.packages3d}/share/kicad/3dmodels
|
||||||
|
kicad-cli pcb export step $PCB --subst-models --force -o $PREFIX.step
|
||||||
|
|
||||||
|
mkdir -p $PREFIX"_gerber_drill"
|
||||||
|
kicad-cli pcb export gerbers $PCB -l 'F.Cu,In1.Cu,In2.Cu,B.Cu,F.Paste,B.Paste,F.Silkscreen,B.Silkscreen,F.Mask,B.Mask,Edge.Cuts' --no-x2 --subtract-soldermask -o ./$PREFIX"_gerber_drill"
|
||||||
|
|
||||||
|
# The additional trailing slash is due to a bug in the kicad-cli tool. https://gitlab.com/kicad/code/kicad/-/issues/14438
|
||||||
|
kicad-cli pcb export drill $PCB -u mm --generate-map --map-format gerberx2 -o ./$PREFIX"_gerber_drill"/
|
||||||
|
|
||||||
|
zip -r -j $PREFIX"_gerber_drill" $PREFIX"_gerber_drill"
|
||||||
|
'';
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
mkdir -p $out/production_files
|
||||||
|
cp $PREFIX"_bom".csv $out/production_files/$PREFIX"_bom".csv
|
||||||
|
cp $PREFIX.pdf $out/production_files/$PREFIX.pdf
|
||||||
|
cp $PREFIX"_pos".csv $out/production_files/$PREFIX"_pos.csv"
|
||||||
|
cp $PREFIX.step $out/production_files/$PREFIX.step
|
||||||
|
cp $PREFIX"_gerber_drill".zip $out/production_files/$PREFIX"_gerber_drill".zip
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,15 +0,0 @@
|
||||||
import os
|
|
||||||
|
|
||||||
dir1 = "./production/svg"
|
|
||||||
dir2 = "./production/svg_org"
|
|
||||||
|
|
||||||
svg_sch_files = os.popen("ls ./production/svg").read().split("\n")
|
|
||||||
svg_org_sch_files = os.popen("ls ./production/svg_org").read().split("\n")
|
|
||||||
|
|
||||||
print(svg_sch_files)
|
|
||||||
print(svg_org_sch_files)
|
|
||||||
for org_svg in svg_org_sch_files:
|
|
||||||
print("#############")
|
|
||||||
#print(os.path.join('./production/svg', svg))
|
|
||||||
print(os.path.join('./production/svg', org_svg))
|
|
||||||
os.system(f"python -m scripts.k-eediff-svg {os.path.join('./production/svg', org_svg)} {os.path.join('./production/svg_org', org_svg)}")
|
|
|
@ -1,63 +0,0 @@
|
||||||
# Modified from "bom_csv_grouped_by_value_with_fp.py" Example BOM Generation Script
|
|
||||||
|
|
||||||
"""
|
|
||||||
@package
|
|
||||||
Output: CSV (comma-separated)
|
|
||||||
The BOM does not include components with DNP or excluded from BOM field(s) checked.
|
|
||||||
Grouped By: Value, Footprint, MFR_PN, MFR_ALT
|
|
||||||
Sorted By: Ref
|
|
||||||
Fields: Ref, Value, MFR_PN, MFR_PN_ALT, Qnty, LibPart, Footprint, Comment
|
|
||||||
|
|
||||||
Command line:
|
|
||||||
python "pathToFile/generate_bom_from_xml.py" "%I" "%O.csv"
|
|
||||||
"""
|
|
||||||
|
|
||||||
import kicad_netlist_reader
|
|
||||||
import csv
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
|
|
||||||
try:
|
|
||||||
if not os.path.isdir(os.path.dirname(sys.argv[2])):
|
|
||||||
os.makedirs(os.path.dirname(sys.argv[2]))
|
|
||||||
f = open(sys.argv[2], 'w', encoding='utf-8')
|
|
||||||
except IOError:
|
|
||||||
raise IOError("Can't open output file for writing: " + sys.argv[2])
|
|
||||||
|
|
||||||
# Custom Equal Operator for "groupComponents" method
|
|
||||||
def __eq__(self, other):
|
|
||||||
result = False
|
|
||||||
if self.getValue() == other.getValue():
|
|
||||||
if self.getFootprint() == other.getFootprint():
|
|
||||||
if self.getField("MFR_PN") == other.getField("MFR_PN"):
|
|
||||||
if self.getField("MFR_PN_ALT") == other.getField("MFR_PN_ALT"):
|
|
||||||
result = True
|
|
||||||
return result
|
|
||||||
kicad_netlist_reader.comp.__eq__ = __eq__
|
|
||||||
|
|
||||||
net = kicad_netlist_reader.netlist(sys.argv[1])
|
|
||||||
|
|
||||||
out = csv.writer(f, lineterminator='\n', delimiter=',', quotechar='\"', quoting=csv.QUOTE_ALL)
|
|
||||||
out.writerow(['Source:', net.getSource()])
|
|
||||||
out.writerow(['Date:', net.getDate()])
|
|
||||||
out.writerow(['Tool:', net.getTool()])
|
|
||||||
out.writerow(['Ref', 'Value', 'MFR_PN', 'MFR_PN_ALT', 'Qnty', 'LibPart', 'Footprint', 'Comment'])
|
|
||||||
|
|
||||||
grouped = net.groupComponents(components=net.getInterestingComponents(excludeBOM=True, DNP=True))
|
|
||||||
|
|
||||||
for group in grouped:
|
|
||||||
refs = ""
|
|
||||||
for component in group:
|
|
||||||
if refs != "":
|
|
||||||
refs += ", "
|
|
||||||
refs += component.getRef()
|
|
||||||
c = component
|
|
||||||
|
|
||||||
out.writerow([refs,
|
|
||||||
c.getValue(),
|
|
||||||
c.getField("MFR_PN"),
|
|
||||||
c.getField("MFR_PN_ALT"),
|
|
||||||
len(group),
|
|
||||||
c.getLibName() + ":" + c.getPartName(),
|
|
||||||
c.getFootprint(),
|
|
||||||
c.getField("Comment")])
|
|
|
@ -1,112 +0,0 @@
|
||||||
import os
|
|
||||||
import argparse
|
|
||||||
|
|
||||||
__cmd_get_kicad_bin_path = "which kicad | xargs readlink | sed 's/$/-cli/' | xargs readlink"
|
|
||||||
|
|
||||||
def setup_env(prefix, sch, out_dir, dir_kicad_plugins, dir_3d_models):
|
|
||||||
# Get the path to "kicad_netlist_reader.py" script in NixOs
|
|
||||||
if dir_kicad_plugins is None:
|
|
||||||
dir_kicad_plugins = os.path.join(os.popen(__cmd_get_kicad_bin_path).read().replace("\n", ""),
|
|
||||||
"../../share/kicad/plugins")
|
|
||||||
|
|
||||||
# Setup the PYTHONPATH for "generate_bom_from_xml.py" to import "kicad_netlist_reader"
|
|
||||||
try:
|
|
||||||
pythonpath = os.environ['PYTHONPATH']
|
|
||||||
except KeyError:
|
|
||||||
pythonpath = ''
|
|
||||||
pathlist = [dir_kicad_plugins]
|
|
||||||
if pythonpath:
|
|
||||||
pathlist.extend(pythonpath.split(os.pathsep))
|
|
||||||
os.environ['PYTHONPATH'] = os.pathsep.join(pathlist)
|
|
||||||
|
|
||||||
# NIXOS installs KiCAD Built-in 3D models in a separated folder
|
|
||||||
if dir_3d_models is None:
|
|
||||||
temp = os.popen("ls /nix/store | grep kicad-packages3d").read().split()
|
|
||||||
for model_3d_path in temp:
|
|
||||||
if model_3d_path.find(".drv") == -1:
|
|
||||||
# Setup the KICAD7_3DMODEL_DIR for step file to be generated with kicad-cli"
|
|
||||||
os.environ['KICAD7_3DMODEL_DIR'] = os.path.join("/nix/store", model_3d_path, "share/kicad/3dmodels")
|
|
||||||
break
|
|
||||||
|
|
||||||
# Generate the prefix from the title and revision fields in title block of the schematics top
|
|
||||||
if prefix is None:
|
|
||||||
with open (sch, "r") as f:
|
|
||||||
data = f.read().splitlines()
|
|
||||||
title_line = data[7][1:-1].split()
|
|
||||||
revision_line = data[9][1:-1].split()
|
|
||||||
if title_line[0].find("title") and revision_line[0].find("rev"):
|
|
||||||
ret_prefix = f"{title_line[1][1:-1]}_{revision_line[1][1:-1]}"
|
|
||||||
else:
|
|
||||||
raise ValueError("Prefix cannot be generated from schematic file.")
|
|
||||||
else:
|
|
||||||
ret_prefix = prefix
|
|
||||||
|
|
||||||
gerber_drill_dir = os.path.join(out_dir, f"{ret_prefix}_gerber_drill")
|
|
||||||
if not os.path.exists(out_dir):
|
|
||||||
os.makedirs(out_dir)
|
|
||||||
if not os.path.exists(gerber_drill_dir):
|
|
||||||
os.makedirs(gerber_drill_dir)
|
|
||||||
|
|
||||||
return ret_prefix
|
|
||||||
|
|
||||||
def generate_production_files(prefix, sch, pcb, out_dir):
|
|
||||||
out_path = os.path.join(out_dir, prefix)
|
|
||||||
|
|
||||||
bom_ret_code = os.system(f"kicad-cli sch export python-bom {sch} -o {out_path}_bom.xml")
|
|
||||||
bom_ret_code |= os.system(f"python -m scripts.generate_bom_from_xml {out_path}_bom.xml {out_path}_bom.csv")
|
|
||||||
os.system(f"rm {out_path}_bom.xml")
|
|
||||||
|
|
||||||
pdf_ret_code = os.system(f"kicad-cli sch export pdf {sch} -o {out_path}.pdf")
|
|
||||||
|
|
||||||
pos_ret_code = os.system(f"kicad-cli pcb export pos {pcb} --format csv --units mm -o {out_path}_pos.csv")
|
|
||||||
|
|
||||||
step_ret_code = os.system(f"kicad-cli pcb export step {pcb} --subst-models --force -o {out_path}.step")
|
|
||||||
|
|
||||||
out_path = os.path.join(out_dir, f"{prefix}_gerber_drill")
|
|
||||||
|
|
||||||
gerber_ret_code = os.system(f"kicad-cli pcb export gerbers {pcb} -l 'F.Cu,In1.Cu,In2.Cu,B.Cu,F.Paste,B.Paste,F.Silkscreen,B.Silkscreen,F.Mask,B.Mask,Edge.Cuts' --no-x2 --subtract-soldermask -o {out_path}")
|
|
||||||
|
|
||||||
# The additional trailing slash is due to a bug in the kicad-cli tool. https://gitlab.com/kicad/code/kicad/-/issues/14438
|
|
||||||
drill_ret_code = os.system(f"kicad-cli pcb export drill {pcb} -u mm --generate-map --map-format gerberx2 -o {out_path}/")
|
|
||||||
zip_ret_code = os.system(f"zip -r -j {out_path} {out_path}")
|
|
||||||
os.system(f"rm -r {out_path}")
|
|
||||||
|
|
||||||
print("=== File Generation Status === ")
|
|
||||||
print("Gerber: {}".format("Success" if gerber_ret_code == 0 else "Failed"))
|
|
||||||
print("Drill: {}".format("Success" if drill_ret_code == 0 else "Failed"))
|
|
||||||
print("Zip_Gerber_Drill: {}".format("Success" if zip_ret_code == 0 else "Failed"))
|
|
||||||
print("Bom: {}".format("Success" if bom_ret_code == 0 else "Failed"))
|
|
||||||
print("Pdf: {}".format("Success" if pdf_ret_code == 0 else "Failed"))
|
|
||||||
print("Pos: {}".format("Success" if pos_ret_code == 0 else "Failed"))
|
|
||||||
print("Step: {}".format("Success" if step_ret_code == 0 else "Failed"))
|
|
||||||
|
|
||||||
def main():
|
|
||||||
parser = argparse.ArgumentParser(
|
|
||||||
description="Python Script to Generate Production Files(Gerber, Drill, Drill Map, Bom, Component Placement, Schematics PDF, Step Files)")
|
|
||||||
parser.add_argument("-s", "--sch",
|
|
||||||
default="kirdy.kicad_sch",
|
|
||||||
help="schematics top file. defaults to 'kirdy.kicad_sch' if omitted")
|
|
||||||
parser.add_argument("-p", "--pcb",
|
|
||||||
default="kirdy.kicad_pcb",
|
|
||||||
help="pcb file. defaults to 'kirdy.kicad_pcb' if omitted")
|
|
||||||
parser.add_argument("-o", "--output",
|
|
||||||
default="./production",
|
|
||||||
help="output folder, defaults to './production' if omitted")
|
|
||||||
parser.add_argument("-pre", "--prefix",
|
|
||||||
default=None,
|
|
||||||
help="output filename prefix, attempts to generated from schematics top file if omitted")
|
|
||||||
parser.add_argument("-dir_plugins", "--dir_kicad_plugins",
|
|
||||||
default=None,
|
|
||||||
help="path to kicad_netlist_reader.py, attempts to find the required path in the system if omitted")
|
|
||||||
parser.add_argument("-dir_3d", "--dir_3d_models",
|
|
||||||
default=None,
|
|
||||||
help="path to kicad 3d models folder, attempts to find the required path in the system if omitted")
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
prefix = setup_env(args.prefix, args.sch, args.output, args.dir_kicad_plugins, args.dir_3d_models)
|
|
||||||
|
|
||||||
generate_production_files(prefix, args.sch, args.pcb, args.output)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1701952659,
|
||||||
|
"narHash": "sha256-TJv2srXt6fYPUjxgLAL0cy4nuf1OZD4KuA1TrCiQqg0=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "b4372c4924d9182034066c823df76d6eaf1f4ec4",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixos-23.11",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
{
|
||||||
|
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
|
||||||
|
|
||||||
|
outputs = { self, nixpkgs }: {
|
||||||
|
|
||||||
|
devShells.x86_64-linux.default =
|
||||||
|
let pkgs = nixpkgs.legacyPackages.x86_64-linux;
|
||||||
|
in pkgs.mkShell {
|
||||||
|
name = "kicad-dev-shell";
|
||||||
|
buildInputs = [ pkgs.kicad ];
|
||||||
|
shellHook = ''
|
||||||
|
export KICAD7_3DMODEL_DIR=${pkgs.kicad.libraries.packages3d}
|
||||||
|
export PYTHONPATH=${pkgs.kicad.base}/share/kicad/plugins
|
||||||
|
export OUTPUT_DIR=$(pwd)/production
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
defaultPackage.x86_64-linux = # Notice the reference to nixpkgs here.
|
||||||
|
with import nixpkgs { system = "x86_64-linux"; };
|
||||||
|
stdenv.mkDerivation {
|
||||||
|
name = "proj";
|
||||||
|
src = self;
|
||||||
|
|
||||||
|
nativeBuildInputs = [ pkgs.kicad pkgs.python3 ];
|
||||||
|
buildPhase = ''
|
||||||
|
export HOME=/tmp
|
||||||
|
echo ${src}
|
||||||
|
kicad-cli sch export pdf ${src}/kirdy.kicad_sch -o kirdy.pdf
|
||||||
|
'';
|
||||||
|
installPhase = "echo test";
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
# pkgs = nixpkgs.legacyPackages.x86_64-linux;
|
||||||
|
# nativeBuildInputs = [
|
||||||
|
# pkgs.kicad pkgs.python3
|
||||||
|
# ];
|
||||||
|
|
||||||
|
}
|
Before Width: | Height: | Size: 263 KiB After Width: | Height: | Size: 263 KiB |
Loading…
Reference in New Issue