I’m giving you a drop in macOS setup that makes Sublime Text actually work with Verilog and SystemVerilog no guesswork, no rabbit holes. I install the essentials for you (Icarus Verilog and Verilator), I fix the macOS GUI PATH so Sublime sees your Homebrew binaries even when you launch it from the Dock, and I wire up a Sublime project plus build system that can compile, run, and lint right inside the editor. I even include a tiny Verilog module with a testbench so you can prove the whole pipeline in seconds. You clone the folder, you run one setup script to install tools and export PATH for GUI apps, you open the provided Sublime project, and you press ⌘B—I am showing you a passing testbench right away. From there, I let you lint with Verilator, tweak Makefile flags, or drop in your own HDL fi es; I’ve already connected the dots.
Below is a drop in, working project you can clone into a folder on your Mac. It does four things entirely in code:
- Installs the toolchain (Icarus Verilog + Verilator)
- Fixes PATH for GUI apps so Sublime Text can see Homebrew binaries even when launched from the Dock
- Adds Sublime build + project files that compile, run, and lint Verilog from inside Sublime
- Includes a tiny Verilog example with a testbench so you can prove everything works
Folder Layout
sublime-verilog-macos-fix/
├─ setup_macos.sh
├─ launch-agent/ # LaunchAgent that exports PATH to GUI apps (Sublime)
│ └─ com.user.env.path.plist
├─ sublime/
│ ├─ Verilog.sublime-project
│ └─ Verilog.sublime-build
├─ .sublimelinterrc.json # Optional: basic config if you use SublimeLinter + iverilog plugin
├─ src/
│ ├─ adder.v
│ └─ tb_adder.v
├─ Makefile
└─ README.md
Clone And Open
Create a folder (or copy/paste these files) and open it in Sublime Text after you run setup_macos.sh
once.
Install Tools and Fix PATH
File: setup_macos.sh
#!/usr/bin/env bash
set -euo pipefail
# --- 1) Ensure Homebrew exists ---
if ! command -v brew >/dev/null 2>&1; then
echo "Homebrew not found. Installing..."
NONINTERACTIVE=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
fi
# --- 2) Make sure brew is on PATH for this shell (Apple Silicon + Intel support) ---
# Apple Silicon default
if [ -d /opt/homebrew/bin ]; then
eval "$(/opt/homebrew/bin/brew shellenv)"
fi
# Intel default
if [ -d /usr/local/bin ]; then
export PATH="/usr/local/bin:$PATH"
fi
# --- 3) Install HDL toolchain ---
brew update
brew install icarus-verilog verilator
# --- 4) Print versions to prove installs worked ---
echo "iverilog version:"
iverilog -V || true
echo "verilator version:"
verilator --version || true
# --- 5) Export PATH to GUI apps (Sublime Text launched from Dock/Spotlight) ---
# This line makes GUI apps inherit PATH immediately (persists across reboots/logins).
# Includes both typical Apple Silicon and Intel paths to be safe.
launchctl setenv PATH "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
echo "GUI PATH is now:"
launchctl getenv PATH
# --- 6) Offer to install Fix Mac Path (nice-to-have) ---
cat <<'NOTE'
Optional but recommended:
1) Open Sublime Text.
2) Press ⇧⌘P and run: "Package Control: Install Package".
3) Install: Fix Mac Path
This helps keep PATH in sync with your shell.
Finally:
- Open the project file: sublime/Verilog.sublime-project
- Press ⌘B to build (see output).
NOTE
Run it:
chmod +x setup_macos.sh ./setup_macos.sh
Make GUI Apps See Your PATH Even After Reboot
File: launch-agent/com.user.env.path.plist
(Install this if you want a persistent, declarative PATH for GUI apps. It complements the launchctl setenv
you ran above.)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.user.env.path</string>
<key>ProgramArguments</key>
<array>
<string>/bin/launchctl</string>
<string>setenv</string>
<string>PATH</string>
<string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
Load it once and forget it:
mkdir -p ~/Library/LaunchAgents cp launch-agent/com.user.env.path.plist ~/Library/LaunchAgents/ launchctl unload ~/Library/LaunchAgents/com.user.env.path.plist 2>/dev/null || true launchctl load ~/Library/LaunchAgents/com.user.env.path.plist launchctl getenv PATH
Add Sublime Project + Build
File: sublime/Verilog.sublime-project
(Open this file in Sublime to use the project and build commands.)
{
"folders": [
{ "path": "..", "folder_exclude_patterns": [".git", "build"] }
],
"settings": {
// Force SystemVerilog/Verilog syntax when opening .v/.sv
"extensions":
{
"verilog": ["v"],
"systemverilog": ["sv", "svh"]
}
},
"build_systems": [
{
"name": "Icarus: Build & Run",
"cmd": ["make", "-C", "src", "-f", "../Makefile", "run"],
"working_dir": "${project_path}"
},
{
"name": "Verilator: Lint",
"cmd": ["make", "-C", "src", "-f", "../Makefile", "lint"],
"working_dir": "${project_path}"
}
]
}
File: sublime/Verilog.sublime-build
(You can use this build for ad-hoc folders too.)
{
"cmd": ["make", "-C", "src", "-f", "../Makefile", "run"],
"working_dir": "${project_path}",
"selector": "source.verilog, source.systemverilog",
"variants": [
{ "name": "Lint (Verilator)", "cmd": ["make", "-C", "src", "-f", "../Makefile", "lint"] }
]
}
Optional: .sublimelinterrc.json
(Only if you use SublimeLinter + an iverilog linter plugin.)
{
"linters": {
"iverilog": {
"executable": "iverilog",
"args": ["-Wall"],
"selector": "source.verilog, source.systemverilog"
}
}
}
Tiny Verilog Sample to Prove the Pipeline
File: src/adder.v
// Simple 8-bit combinational adder
module adder (
input [7:0] a,
input [7:0] b,
output [7:0] sum
);
assign sum = a + b;
endmodule
File: src/tb_adder.v
`timescale 1ns/1ps
module tb_adder;
reg [7:0] a;
reg [7:0] b;
wire [7:0] sum;
adder dut(.a(a), .b(b), .sum(sum));
initial begin
$display("Starting tb_adder...");
a = 8'd3; b = 8'd4; #1;
$display("3 + 4 = %0d (expect 7) -> %s", sum, (sum == 7) ? "PASS" : "FAIL");
a = 8'd10; b = 8'd20; #1;
$display("10 + 20 = %0d (expect 30) -> %s", sum, (sum == 30) ? "PASS" : "FAIL");
a = 8'd200; b = 8'd100; #1; // overflow wraps at 8 bits
$display("200 + 100 = %0d (expect 44) -> %s", sum, (sum == 44) ? "PASS" : "FAIL");
$finish;
end
endmodule
Makefile That Both Runs and Lints
File: Makefile
# Root Makefile (called from project builds)
# Tools
IVERILOG ?= iverilog
VVP ?= vvp
VERILATOR ?= verilator
# Paths
SRC_DIR := src
BUILD_DIR := build
TOP := tb_adder
# Files
SRCS := $(SRC_DIR)/adder.v $(SRC_DIR)/tb_adder.v
OUT := $(BUILD_DIR)/$(TOP).out
.PHONY: all run lint clean ensure_builddir
all: run
ensure_builddir:
@mkdir -p $(BUILD_DIR)
run: ensure_builddir $(OUT)
@echo "Running simulation..."
@$(VVP) $(OUT)
$(OUT): $(SRCS)
@echo "Compiling with Icarus Verilog..."
@$(IVERILOG) -g2012 -Wall -o $(OUT) $(SRCS)
lint:
@echo "Linting with Verilator..."
@$(VERILATOR) --lint-only -Wall $(SRCS)
clean:
@rm -rf $(BUILD_DIR)
Open, Build, Run (Inside Sublime)
Open the project:
- In Sublime, choose File → Open… and select
sublime/Verilog.sublime-project
. - Open
src/tb_adder.v
. - Press ⌘B to run Icarus: Build & Run.
- You should see output like:
Starting tb_adder...
3 + 4 = 7 (expect 7) -> PASS
10 + 20 = 30 (expect 30) -> PASS
200 + 100 = 44 (expect 44) -> PASS
- Run Tools → Build With… → Lint (Verilator) to get static checks.
Why This Fixes “Package not Working” on macOS
Explained simply: Sublime Text is a GUI app. When you open it from the Dock, it doesn’t automatically inherit your Terminal’s PATH, so it can’t find iverilog
or verilator
. That feels like the Verilog package is “broken.” The project above pushes a proper PATH into the GUI environment (LaunchAgent + launchctl
) and also gives you Sublime build definitions that call Make, which calls the same tools you use in Terminal. That’s the whole trick.
Troubleshooting from Inside this Project
“Build failed: command not found”
Open Sublime’s console (View → Show Console) and check the first error line. If it says iverilog: command not found
, your GUI PATH isn’t set. Re-run:
launchctl setenv PATH "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
launchctl getenv PATH
Then quit and reopen Sublime from the Dock.
“Sublime can’t see Package Control / Install Package is missing”
Open Preferences → Browse Packages… and remove any Package Control
folders and the Installed Packages/Package Control.sublime-package
file, then reinstall via the Command Palette. After that, install Fix Mac Path if you want a plugin to handle PATH for you.
“Verilator warnings everywhere”
That’s good! It means tooling works. Use the Lint (Verilator) build to check code style and common mistakes. Adjust flags in the Makefile
if you want fewer warnings.
README that Explain the Project to Future You
File: README.md
# Sublime Text + Verilog on macOS: Working Example
## Purpose
Fix “Sublime Text Verilog package not working on macOS” by:
- Ensuring Homebrew tools (iverilog, verilator) exist
- Making GUI apps inherit PATH so Sublime can see those tools
- Providing a ready-to-run Sublime project with builds and a testbench
## Quickstart
1) `./setup_macos.sh`
2) Open `sublime/Verilog.sublime-project` in Sublime
3) Press ⌘B to run the simulation; choose "Lint (Verilator)" to lint
## Notes
- If you prefer not to touch LaunchAgents, install the “Fix Mac Path” package in Sublime instead.
- If "Install Package" is missing, reinstall Package Control and then add “SystemVerilog” and “Fix Mac Path”.
Final Thought
I’m fixing the real macOS problem: PATH. Sublime is a GUI app, so it doesn’t inherit your Terminal environment and it can’t find iverilog
or verilator
. I solve that at the root by exporting the right PATH for GUI apps and backing it with a simple LaunchAgent, then I prove it with real builds and a real testbench. I’m aiming for a workflow you can trust after reboots and updates: you open Sublime, you write Verilog, you hit build, you read results done. If you want something lighter, I pair cleanly with “Fix Mac Path.” If you want more power, I’m ready for you to extend the Makefile and project settings for your team. Either way, I’m starting you from a working, reproducible base so you can stop chasing mystery errors and get back to building.