IPC-2581 export: Surface finish data not exported
Description
The board's surface finish data (Board Setup > Board Stackup > copper_finish) is not included in the IPC2581 export. The more fab data we encode in structured form, the fewer boards require separate artifacts (stackup PDFs, fab drawings). Surface finish is a commonly needed detail and encoding it properly improves coverage for standard boards.
Steps to reproduce
- Create or open a PCB with a surface finish specified in Board Setup > Board Stackup (e.g., "ENIG")
- Export to IPC-2581:
kicad-cli pcb export ipc2581 layout.kicad_pcb -o output.xml- Examine the generated XML
Expected
Surface finish encoded as structured stackup data per IPC-2581C Section 8.1.1.16:
<Spec name="SURFACE_FINISH">
<SurfaceFinish>
<Finish type="ENIG-N"/>
</SurfaceFinish>
</Spec>
<Layer name="COATING_TOP" layerFunction="COATINGCOND" side="TOP" polarity="POSITIVE"/>
<Layer name="COATING_BOTTOM" layerFunction="COATINGCOND" side="BOTTOM" polarity="POSITIVE"/>
<StackupLayer layerOrGroupRef="COATING_TOP">
<SpecRef id="SURFACE_FINISH"/>
</StackupLayer>Actual
No surface finish information appears in the exported IPC-2581 file.
Suggested Fix
Generate structured IPC-2581 surface finish data from KiCad's copper_finish stackup field. This requires:
<Spec>element containing a<SurfaceFinish>specification with the appropriate IPC-6012 finish type- Two
<Layer>elements withlayerFunction="COATINGCOND"for top and bottom coating - Two
<StackupLayer>entries positioned adjacent to the outer copper layers, referencing the finish spec.
KiCad stores surface finish as a freeform string. These need to be mapped to the enumerated surfaceFinishType values defined in IPC-2581C (per IPC-6012 Table 3-3):
KiCad copper_finish |
IPC-2581 type |
|---|---|
| "ENIG" | ENIG-N |
| "ENEPIG" | ENEPIG-N |
| "OSP" | OSP |
| "Immersion silver" | IAg |
| "Immersion tin" | ISn |
| "HASL" / "HASL lead free" | S |
| "Hard gold" | G |
| "None" / empty | Skip coating layer generation |
| Unrecognized | OTHER (with original string in comment attribute) |
For stackup positioning, insert COATING_TOP immediately before F.Cu and COATING_BOTTOM immediately after B.Cu, placing the coating on the exposed face of each outer copper layer.
Unlike dielectric layers (which exist in KiCad's stackup model with thickness, material, epsilon_r, etc.), these coating layers would be fully synthetic since KiCad only stores surface finish as a single string attribute, not as discrete layers. Creating IPC-2581 layers without a direct counterpart in KiCad's data model isn't ideal. However, I think this is still reasonable because KiCad's stackup model is well-constrained: F.Cu and B.Cu are always the outer copper layers, so coating layer placement can be reliably inferred.
KiCad Version
> kicad-cli version --format about
Application: kicad-cli arm64 on arm64
Version: 9.0.7, release build
Libraries:
wxWidgets 3.2.8
FreeType 2.13.3
HarfBuzz 10.1.0
FontConfig 2.15.0
libcurl/8.7.1 (SecureTransport) LibreSSL/3.3.6 zlib/1.2.12 nghttp2/1.67.1
Platform: macOS Version 26.2 (Build 25C56), 64 bit, Little endian, wxBase
Build Info:
Date: Jan 1 2026 21:36:00
wxWidgets: 3.2.8 (wchar_t,wx containers)
Boost: 1.87.0
OCC: 7.8.1
Curl: 8.7.1
ngspice: 44.2
Compiler: Clang 16.0.0 with C++ ABI 1002
KICAD_IPC_API=ON