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

  1. Create or open a PCB with a surface finish specified in Board Setup > Board Stackup (e.g., "ENIG")
  2. Export to IPC-2581:
kicad-cli pcb export ipc2581 layout.kicad_pcb -o output.xml
  1. 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:

  1. <Spec> element containing a <SurfaceFinish> specification with the appropriate IPC-6012 finish type
  2. Two <Layer> elements with layerFunction="COATINGCOND" for top and bottom coating
  3. 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
Edited by Akhil Velagapudi