gerberguard

A lightweight Gerber PCB manufacturing file inspection and preflight tool written in MoonBit.

gerber
pcb
eda
manufacturing
preflight
moon add 001-Elsa/gerberguard@0.1.0
Download zip
Author
Version
0.1.0
License
Apache-2.0
Last updated
6 days ago
Downloads
3

Dependencies

README

#GerberGuard-MBT

GerberGuard-MBT is a lightweight Gerber PCB manufacturing file inspection and preflight tool implemented in MoonBit.

It scans Gerber command streams, extracts format, unit and X2 metadata, tracks aperture definitions and graphics state, validates common structural relationships such as undefined apertures, region state, plot state and end-of-file markers, and produces deterministic text or JSON reports.

Version 0.1.0 intentionally implements a limited modern Gerber subset. It does not render PCB geometry or attempt full manufacturing-rule verification. The project focuses on a small, reliable and testable core suitable for command-line use and CI pipelines.

GerberGuard 0.1.0 implements a deliberately limited subset of the Gerber Layer Format.

It is intended for inspection and basic preflight checks.

It is not a complete Gerber conformance checker, renderer, PCB DRC engine, or CAM system.

GerberGuard-MBT 是一个使用 MoonBit 编写的轻量级 PCB Gerber 制造文件检查与预检工具。它读取 Gerber 命令流,提取单位、坐标格式、Aperture 和部分 X2 文件属性,并检查常见结构问题。项目不渲染 PCB 图形,不进行 DRC,也不判断 PCB 是否可以生产。

GerberGuard focuses on a small but useful task: deterministic, offline preflight inspection of Gerber manufacturing files.

Instead of rendering geometry, it checks the command stream and graphics-state relationships, making the implementation compact, testable and suitable for automated CI pipelines.

#Features

  • Gerber UTF-8 file inspection
  • Modern FS format detection
  • Metric and inch unit detection
  • Aperture definition tracking
  • Undefined aperture detection
  • D01/D02/D03 statistics
  • Basic circular plotting checks
  • Region state validation
  • Gerber X2 FileFunction inspection
  • Human-readable reports
  • JSON reports
  • Native command-line interface

#Supported Syntax

#What GerberGuard Does Not Do

GerberGuard does not:

  • render Gerber geometry
  • perform PCB DRC
  • determine manufacturability
  • parse Excellon files
  • parse KiCad or Altium project files
  • validate aperture macro geometry
  • validate region geometry
  • validate arc geometry
  • implement the complete Gerber specification

#Installation

Requires a MoonBit toolchain with Native support.

moon version --all moon update

#Usage

moon run cmd/main --target native -- inspect <FILE> [--json] moon run cmd/main --target native -- check <FILE> [--json] moon run cmd/main --target native -- --help moon run cmd/main --target native -- --version

After moon build --release --target native, the executable can also be invoked as gerberguard depending on your packaging/install path.

#inspect example

moon run cmd/main --target native -- inspect samples/pass/minimal.gbr

GerberGuard 0.1.0 File: samples/pass/minimal.gbr Format: Gerber Layer Format (supported subset) Unit: millimeter Coordinate format: 4.6 File function: Copper,L1,Top File polarity: Positive Generation software: - Statistics ---------- Apertures: 1 Aperture macros: 0 Moves: 1 Draws: 1 Flashes: 0 Regions: 0 Arc draws: 0 Comments: 0 Attributes: 2 Unknown commands: 0 Result: PASS Errors: 0 Warnings: 0

#check example

moon run cmd/main --target native -- check samples/fail/undefined_aperture.gbr

GerberGuard 0.1.0 ERROR G201 line 4 Undefined aperture D15. Result: FAIL Errors: 1 Warnings: 0

#JSON example

moon run cmd/main --target native -- check \ samples/pass/minimal.gbr \ --json

The JSON mode writes one JSON document to stdout without banners or debug logs.

{ "tool": "gerberguard", "version": "0.1.0", "command": "check", "file": "samples/pass/minimal.gbr", "status": "pass", "unit": "mm", "coordinate_format": { "integer_digits": 4, "decimal_digits": 6 }, "file_function": "Copper,L1,Top", "file_polarity": "Positive", "generation_software": null, "statistics": { "apertures": 1, "aperture_macros": 0, "moves": 1, "draws": 1, "flashes": 0, "regions": 0, "arc_draws": 0, "comments": 0, "attributes": 2, "unknown_commands": 0 }, "errors": 0, "warnings": 0, "issues": [] }

#Exit Codes

CodeMeaning
0PASS or PASS WITH WARNINGS
1Report contains one or more Error issues
2CLI usage / argument error
3File IO / UTF-8 decode error

#Error Model

Deterministic issue codes are documented in docs/ERROR_CODES.md.

#Development

Contribution scope and the required local workflow are documented in CONTRIBUTING.md. Security and private-fixture reporting guidance is documented in SECURITY.md. Release and Mooncakes publication steps are documented in docs/RELEASING.md.

moon fmt moon check --target all --deny-warn moon test --target all --deny-warn moon build --release --target native moon info git diff --exit-code

#Testing

Unit tests cover scanner, parser, checker, reporters and CLI parsing. Fixtures live under samples/pass, samples/warn and samples/fail. The complete reproducible acceptance procedure is in ACCEPTANCE.md.

#Project Structure

model.mbt scanner.mbt parser.mbt checker.mbt report_text.mbt report_json.mbt cli.mbt cmd/main/main.mbt samples/{pass,warn,fail}/ docs/{ARCHITECTURE,SUPPORTED_SYNTAX,ERROR_CODES}.md .github/workflows/ci.yml

#Limitations

GerberGuard v0.1.0 is a Gerber supported-subset preflight checker. It performs structural inspection only.

#Gerber Specification Reference

This project targets a practical modern subset of the Gerber Layer Format (Ucamco), especially common X2 attributes and graphics-state commands used in manufacturing handoff files.

Source, fixture, generated-file, dependency, and AI-assistance disclosures are documented in docs/PROVENANCE.md.

#License

Apache-2.0. See LICENSE.

#
AnalysisStatus

pub(all) enum AnalysisStatus {
Pass
PassWithWarnings
Fail
} derive(Eq,
Debug
)

#
ApertureDefinition

pub(all) struct ApertureDefinition {
code : Int
template : String
parameters_raw : String?
line : Int
} derive(Eq,
Debug
)

#
AttributeScope

pub(all) enum AttributeScope {
File
Aperture
Object
} derive(Eq,
Debug
)

#
CliCommand

pub(all) enum CliCommand {
Inspect
Check
Help
Version
} derive(Eq,
Debug
)

#
CliConfig

pub(all) struct CliConfig {
command : CliCommand
file : String?
json : Bool
} derive(Eq,
Debug
)

#
CliError

pub(all) enum CliError {
Usage(String)
} derive(Eq,
Debug
)

#
CoordinateFields

pub(all) struct CoordinateFields {
x : String?
y : String?
i : String?
j : String?
} derive(Eq,
Debug
)

#
CoordinateFormat

pub(all) struct CoordinateFormat {
integer_digits : Int
decimal_digits : Int
} derive(Eq,
Debug
)

#
GerberAttribute

pub(all) struct GerberAttribute {
scope : AttributeScope
name : String
raw_value : String?
line : Int
} derive(Eq,
Debug
)

#
GerberCommand

pub(all) enum GerberCommand {
Comment(String)
Format(CoordinateFormat)
Unit(GerberUnit)
ApertureMacro(String, String)
ApertureDefinition(ApertureDefinition)
SelectAperture(Int)
SetPlotMode(PlotMode)
MultiQuadrant
Move(CoordinateFields)
Draw(CoordinateFields)
Flash(CoordinateFields)
BeginRegion
EndRegion
SetPolarity(Polarity)
Attribute(GerberAttribute)
DeleteAttribute(String?)
EndFile
UnknownWord(String)
UnknownExtended(String)
Malformed(String)
} derive(Eq,
Debug
)

#
GerberReport

pub(all) struct GerberReport {
status : AnalysisStatus
unit : GerberUnit?
coordinate_format : CoordinateFormat?
file_function : String?
file_polarity : String?
generation_software : String?
statistics : GerberStatistics
issues : Array[Issue]
} derive(Eq,
Debug
)

#
GerberStatistics

pub(all) struct GerberStatistics {
apertures : Int
aperture_macros : Int
moves : Int
draws : Int
flashes : Int
regions : Int
arc_draws : Int
comments : Int
attributes : Int
unknown_commands : Int
} derive(Eq,
Debug
)

#
GerberUnit

pub(all) enum GerberUnit {
Millimeter
Inch
} derive(Eq,
Debug
)

#
Issue

pub(all) struct Issue {
code : String
severity : Severity
message : String
line : Int?
} derive(Eq,
Debug
)

#
LocatedCommand

pub(all) struct LocatedCommand {
command : GerberCommand
line : Int
} derive(Eq,
Debug
)

#
PlotMode

pub(all) enum PlotMode {
Linear
Clockwise
CounterClockwise
} derive(Eq,
Debug
)

#
Polarity

pub(all) enum Polarity {
Dark
Clear
} derive(Eq,
Debug
)

#
RawToken

pub(all) struct RawToken {
kind : RawTokenKind
raw : String
line : Int
} derive(Eq,
Debug
)

#
RawTokenKind

pub(all) enum RawTokenKind {
Word
ExtendedBlock
} derive(Eq,
Debug
)

#
Severity

pub(all) enum Severity {
Error
Warning
} derive(Eq,
Debug
)

#
MAX_EXTENDED_BLOCK_BYTES

let MAX_EXTENDED_BLOCK_BYTES : Int

#
MAX_INPUT_BYTES

let MAX_INPUT_BYTES : Int

#
MAX_TOKEN_COUNT

let MAX_TOKEN_COUNT : Int

#
MAX_WORD_BYTES

let MAX_WORD_BYTES : Int

#
VERSION

let VERSION : String

#
analyze

fn analyze(source : String) -> GerberReport

#
exit_code_for_report

fn exit_code_for_report(report : GerberReport) -> Int

#
input_too_large_report

fn input_too_large_report() -> GerberReport

#
parse_cli

fn parse_cli(args : ArrayView[String]) -> Result[CliConfig, CliError]

#
render_check

fn render_check(report : GerberReport, file_name : String) -> String

#
render_inspect

fn render_inspect(report : GerberReport, file_name : String) -> String

#
render_json

fn render_json(report : GerberReport, file_name : String, command : CliCommand) -> String

#
truncate_for_message

fn truncate_for_message(s : String) -> String

#
usage_text

fn usage_text() -> String

#
version_text

fn version_text() -> String