Makefile Reference
This page documents the targets and environment variables provided by the
ruckus backend Makefile fragments: system_vivado.mk (Vivado),
system_vitis_unified_aie.mk (Vitis AIE), system_iverilog.mk (Icarus
Verilog, see How to Simulate Verilog with Icarus Verilog), and system_verilator.mk
(Verilator, see How to Simulate Verilog with Verilator). Include one of these
from your project’s Makefile to access the corresponding build pipeline.
For Vivado build pipeline context see The Vivado Build Pipeline. For the AIE workflow walkthrough see How to Build a Vitis AI Engine (AIE) Graph.
Targets
Target |
Description |
|---|---|
|
Full Vivado batch build: synthesis + implementation + bitstream. |
|
Synthesis only (sets |
|
Synthesis + DCP export (sets |
|
Open the Vivado project in GUI mode. Automatically detects and builds the Rogue TCP/SideBand co-simulation DPI library when present; see How to Run the Rogue Co-Simulation in Vivado XSIM. |
|
Open Vivado in TCL interactive mode. |
|
Run source setup (ruckus.tcl loading) only — no synthesis. Useful for verifying project structure. |
|
Open the Vitis/SDK workspace GUI. |
|
Build MicroBlaze ELF and embed in bitstream. Requires |
|
Run |
|
Run |
|
Generate PyRogue tarball. |
|
Generate CPSW YAML tarball. |
|
Run Vivado XSIM simulation. Automatically detects and builds the Rogue TCP/SideBand co-simulation DPI library when present; see How to Run the Rogue Co-Simulation in Vivado XSIM. |
|
Generate VCS simulation scripts. |
|
Run ModelSim/Questa simulation. |
|
Open Vivado project in batch mode. |
|
Print all environment variable values. Useful for debugging Makefile variable resolution. |
|
Create the build directory structure ( |
|
Delete the entire |
Credential Scoping
GNU Make copies every environment variable into the environment of every recipe it runs. A developer’s shell typically carries several unrelated credentials, so without intervention all of them would be handed to Vivado, Vitis, GHDL, VCS, Genus, Design Compiler, and every project hook script.
ruckus therefore sweeps them out. system_shared.mk removes every environment
variable whose name contains TOKEN from make entirely:
RUCKUS_TOKEN_VARS := $(foreach v,$(.VARIABLES),$(if $(findstring TOKEN,$v),$(if $(filter environment%,$(origin $v)),$v)))
unexport $(RUCKUS_TOKEN_VARS)
$(foreach v,$(RUCKUS_TOKEN_VARS),$(eval undefine $v))
Every backend that includes system_shared.mk inherits this, which covers the Vivado,
GHDL, Genus, Design Compiler, Vitis, Icarus Verilog, and Verilator flows. system_vcs.mk
includes no shared fragment, so the VCS flow is not covered.
Both halves matter, because there are two separate ways a recipe can reach a variable:
Access |
Reads |
Closed by |
|---|---|---|
|
the recipe’s environment |
|
|
make’s variable table |
|
unexport alone would leave $(GITHUB_TOKEN) expanding to the live value, so a
line such as @echo GITHUB_TOKEN: $(GITHUB_TOKEN) in a project’s test target
would print a working credential into the build log. With both directives applied,
$(GITHUB_TOKEN) expands to nothing and $(origin GITHUB_TOKEN) reports
undefined.
undefine accepts only a single name and raises empty variable name if given
none, so it is applied through $(eval) inside $(foreach), which simply does not
iterate when nothing matches.
Three deliberate limits apply:
Matching is case sensitive, so only upper-case
TOKENis swept. Environment variable names are upper case by convention.Only variables whose origin is the environment are swept. A variable a project deliberately defines and exports in its own Makefile is left alone, which is the supported way to opt out.
The credential needed by
releaseis stashed inRUCKUS_GITHUB_AUTH, which is still readable at make level. The sweep prevents accidental exposure through the conventional variable names; it is not a guarantee against a recipe that goes looking for the stash.
This requires GNU Make 3.82 or newer for undefine.
- GITHUB_TOKEN
GitHub personal access token used by
firmwareRelease.pyto create and push a release. It is read from the environment, never from a ruckus file.- Default:
unset
- Required by:
make releaseonly
system_vivado.mkgrants this one credential back to thereleasetarget alone, reading it from the stash thatsystem_shared.mkcaptured before the sweep:ifdef RUCKUS_GITHUB_AUTH release : export GITHUB_TOKEN := $(RUCKUS_GITHUB_AUTH) endif
When no token is set in the calling environment the
ifdefguard does not fire, soGITHUB_TOKENstays unset in the recipe andfirmwareRelease.pyprompts for it interactively, as before. Were the guard omitted, the variable would be exported as an empty string and the script would attempt to authenticate with""instead of prompting.Note
make release_filesgenerates the release archives without contacting GitHub, so it needs no token.Warning
A project that needs a token in a target of its own should re-export it the same way. Prefer a target-specific
exportover an inlineGITHUB_TOKEN=... commandprefix: the inline form places the secret in the shell’s argument list, where other users on a shared build server can read it withps.
Project Identity Variables
These variables define the project’s identity and directory structure. They are set
by system_vivado.mk and system_shared.mk using ifndef VAR / export VAR
— if a variable is already set in the shell environment, the shell value takes precedence.
- PROJECT
Project name. Used for the Vivado project name and output filenames.
- Default:
$(notdir $(PWD))— the name of the project directory
- PROJ_DIR
Absolute path to the top-level firmware project directory (where
Makefilelives).- Default:
$(abspath $(PWD))
- TOP_DIR
Two levels up from
PROJ_DIR. Typically the root of a multi-project tree.- Default:
$(abspath $(PROJ_DIR)/../..)
- MODULES
Root of the submodule tree (where
ruckus,surf, and similar modules live).- Default:
$(TOP_DIR)/submodules
- RUCKUS_DIR
Path to the ruckus installation.
- Default:
$(MODULES)/ruckus
- RELEASE_DIR
Directory where release tarballs are placed by the
releaseandrelease_filestargets.- Default:
$(TOP_DIR)/release
- PRJ_VERSION
Firmware version embedded in output filenames and the build info string.
- Default:
0xFFFFFFFF- Valid values:
Any hex string in the form
0xNNNNNNNN
Build Behaviour Variables
- GIT_BYPASS
Controls whether the build requires a clean git working tree.
- Default:
1(bypass enabled — git checking is skipped)- Valid values:
0(strict: fail if uncommitted files exist),1(permissive: allow dirty trees)
Warning
The default is
1, which means git checking is disabled by default. SetGIT_BYPASS=0to enforce a clean tree before building.GIT_BYPASS=0 make bit
- PARALLEL_SYNTH
Number of parallel jobs used for IP core synthesis by
BuildIpCores().- Default:
CPU count (read from
/proc/cpuinfoviaGetCpuNumber())- Valid values:
Any positive integer
- REMOVE_UNUSED_CODE
When
1, removes auto-disabled source files from the project before synthesis.- Default:
0(disabled)- Valid values:
0,1
- REPORT_QOR
When
1(and Vivado >= 2020.1), writes QoR assessment reports during route.- Default:
0(disabled)- Valid values:
0,1
Output Format Variables
These variables control which output files are copied to the images/ directory
after a successful build.
- GEN_BIT_IMAGE
Copy
.bitbitstream toimages/.- Default:
1(enabled)- Valid values:
0,1
- GEN_BIT_IMAGE_GZIP
Copy gzip-compressed
.bit.gztoimages/.- Default:
0(disabled)- Valid values:
0,1
- GEN_BIN_IMAGE
Copy raw binary
.bintoimages/.- Default:
0(disabled)- Valid values:
0,1
- GEN_BIN_IMAGE_GZIP
Copy gzip-compressed
.bin.gztoimages/.- Default:
0(disabled)- Valid values:
0,1
- GEN_PDI_IMAGE
Copy
.pdi(Versal) toimages/.- Default:
1(enabled)- Valid values:
0,1
- GEN_PDI_IMAGE_GZIP
Copy gzip-compressed
.pdi.gztoimages/.- Default:
0(disabled)- Valid values:
0,1
- GEN_MCS_IMAGE
Generate MCS PROM file. Requires a
vivado/promgen.tclscript in your project. SeeCreatePromMcs().- Default:
1(enabled)- Valid values:
0,1
- GEN_MCS_IMAGE_GZIP
Gzip-compress the MCS output.
- Default:
0(disabled)- Valid values:
0,1
- GEN_XSA_IMAGE
Generate
.xsahardware platform file for Vitis/Yocto. Only useful for projects with embedded processors. SeeCreateXsaFile().- Default:
0(disabled)- Valid values:
0,1
Example — build Versal PDI only:
GEN_BIT_IMAGE=0 GEN_MCS_IMAGE=0 GEN_PDI_IMAGE=1 make bit
Timing Violation Override Variables
These variables override timing failure checks in CheckTiming(). They are
boolean environment variables: ruckus uses [string is true -strict ...]
which recognises true, yes, on, and 1 as truthy.
All timing override variables are unset by default. Leaving a variable unset
is the correct way to keep it disabled. Setting TIG=false does not disable
the override — pass false as a string and TCL may evaluate it as truthy depending
on context; the safe approach is to leave the variable unset.
- TIG
Override all timing failures (setup + hold + pulse-width). Use with extreme caution — this allows a non-timing-clean bitstream to be produced.
- Default:
unset (override disabled)
- Valid values:
true,1(to enable); leave unset to disable
TIG=true make bit
- TIG_SETUP
Override setup timing failures only (WNS < 0, TNS < 0).
- Default:
unset (override disabled)
- Valid values:
true,1
- TIG_HOLD
Override hold timing failures only (WHS < 0, THS < 0).
- Default:
unset (override disabled)
- Valid values:
true,1
- TIG_PULSE
Override pulse-width timing failures only (TPWS < 0).
- Default:
unset (override disabled)
- Valid values:
true,1
- ALLOW_MULTI_DRIVEN
Controls how multi-driven net violations are handled during synthesis.
- Default:
unset (multi-driven nets abort the build with ERROR)
- Valid values:
1ortrue(demote to INFO, allowing the build to continue)
Note
This variable has no
ifndefdefault in any Makefile. It must be passed explicitly as an environment variable. When0or unset,MDRV-1DRC andSynth 8-6859/Synth 8-3352messages are elevated to ERROR. When truthy, they are demoted to INFO.ALLOW_MULTI_DRIVEN=1 make bit
- ALLOW_CDC_VIOLATIONS
Controls how clock-domain-crossing (CDC) violations are handled during implementation.
- Default:
unset (CDC report and CDC check are both skipped)
- Valid values:
0orfalse(a critical CDC violation aborts the build), any other value (no report, no check, build continues)
Note
This variable has no
ifndefdefault in any Makefile. It must be passed explicitly as an environment variable. Unlike the timing overrides above, it is not evaluated with[string is true -strict ...]: only0andfalseenable the check, and every other value bypasses it.While the variable is unset, the post-
opt_designscript skipsreport_cdcand performs no CDC checking at all. This is intentionally optional for now to give existing projects time to clean up their crossings; a future release will makeALLOW_CDC_VIOLATIONSrequired and always run the CDC check.When set to
0orfalse, the post-opt_designscript runsreport_cdc, writes<PROJECT>_cdc_impl.rptinto theimpl_1run directory, and aborts the build if any un-waived violation has aCriticalseverity, dumping the report to the terminal for review. Any other value (1,true, or any non-zero string) skips both the report and the check, and so behaves the same as leaving the variable unset.Violations waived with
create_waiverare always excluded, so a single reviewed crossing can be accepted without disabling the whole check.The check runs after
opt_designrather than after synthesis because out-of-context IP netlists and their XDC constraints are not linked into the design until implementation. Clocks generated inside an IP (such as the GT recovered and transmit clocks) do not exist at the end of synthesis, andreport_cdconly analyzes paths whose clocks are defined on both the source and destination sides, so a synthesis-stage check reports nothing for GT-based designs.The check requires Vivado 2018.1 or later and is skipped on older releases, which lack the
report_cdc -all_checks_per_endpointoption needed to keep the result deterministic.# Enable the CDC check (aborts on a critical violation) ALLOW_CDC_VIOLATIONS=0 make bit # Bypass the CDC check (same as leaving the variable unset) ALLOW_CDC_VIOLATIONS=1 make bit
Simulation Variables
- VIVADO_PROJECT_SIM
Top module name for Vivado simulation. For a batch Rogue co-sim, set this to the demo testbench (e.g.
RogueTcpStreamXsimDemoTb); see How to Run the Rogue Co-Simulation in Vivado XSIM.- Default:
$(PROJECT)
- VIVADO_PROJECT_SIM_TIME
Simulation run length. The default
allfree-runs until the testbench calls$finish/$stopor is interrupted; a testbench with neither (and a free-running clock) never self-terminates, so a batchmake xsimmust be stopped manually. Pass a time value (e.g.1000 ns) to bound the run.allis required for the Rogue co-sim so the external peer can drive the testbench — see How to Run the Rogue Co-Simulation in Vivado XSIM.- Default:
all
- SIM_CARGS_VERILOG
VCS Verilog compile flags.
- Default:
-nc -l +v2k -xlrm -kdb -v2005 +define+SIM_SPEED_UP
- SIM_CARGS_VHDL
VCS VHDL compile flags.
- Default:
-nc -l +v2k -xlrm -kdb
- SIM_VCS_FLAGS
VCS simulation run flags.
- Default:
-debug_acc+pp+dmptf +warn=none -kdb -lca
Icarus Verilog and Verilator Targets
These targets are provided by system_iverilog.mk (Icarus Verilog, see
How to Simulate Verilog with Icarus Verilog) and system_verilator.mk (Verilator,
see How to Simulate Verilog with Verilator). Both backends share the same
target names and dependency chain.
Target |
Description |
|---|---|
|
Print all environment variable values. The first rule in both
Makefile fragments, so a bare |
|
Create |
|
Check the simulator tool/version floor, load the project’s
|
|
Build the Rogue SimLink library when a SimLink leaf is loaded (see
the Rogue Co-Simulation section of either how-to page), then compile
with |
|
Run the compiled simulation: |
|
Set |
|
Delete the entire |
Icarus Verilog and Verilator Variables
These variables are shared by system_iverilog.mk and
system_verilator.mk, with each backend’s own escape-hatch flags listed
separately below. Set overrides in your project Makefile before the
include line, as with GHDLFLAGS. PROJECT and
OUT_DIR (declared above) apply unchanged to both flows.
- SIM_TOP
Top module simulated by
vvp(Icarus Verilog) or built asV$(SIM_TOP)(Verilator).- Default:
$(PROJECT)
- VERILOG_INCDIRS
Whitespace-separated list of extra include directories. Translated to
-I<dir>for Icarus Verilog and+incdir+<dir>for Verilator.- Default:
(empty)
- VERILOG_DEFINES
Whitespace-separated list of
NAMEorNAME=VALwords. Translated to-D<def>for Icarus Verilog and+define+<def>for Verilator. Values containing spaces are not supported.- Default:
(empty)
- SIM_PLUSARGS
Plusargs appended verbatim after the simulation binary on the run command line (
vvp ... $(SIM_PLUSARGS)or./V$(SIM_TOP) $(SIM_PLUSARGS)).- Default:
(empty)
- WAVES
Set to
1to add the waveform-tracing flag to the build/run (-fstfor Icarus Verilog,--trace-fstfor Verilator). The testbench still owns$dumpfile/$dumpvars.- Default:
(empty)
- IVERILOG_FLAGS
Flags passed to
iverilog. Icarus Verilog only.- Default:
-g2012
- VVP_FLAGS
Flags passed to
vvp. Icarus Verilog only.- Default:
-n
- VERILATOR_FLAGS
Flags passed to
verilator. Verilator only.- Default:
--binary --timing -j 0
- RUCKUS_SIM_BACKEND
Backend selector read by
surf/simlink/ruckus.tcl. Set automatically by whichever Makefile fragment is included.- Default:
iverilog(fromsystem_iverilog.mk) orverilator(fromsystem_verilator.mk)
Partial Reconfiguration Variables
- RECONFIG_CHECKPOINT
Path to static DCP for DFX (Dynamic Function eXchange) partial reconfiguration build. Set to a valid DCP path to enable partial reconfiguration mode.
- Default:
0(standard build — partial reconfiguration disabled)
- RECONFIG_ENDPOINT
Partial reconfiguration endpoint name.
- Default:
0(disabled)
- RECONFIG_PBLOCK
Partial reconfiguration pblock name.
- Default:
0(disabled)
Versal Segmented Configuration Variables
- USE_SEGMENTED_CONFIG
Enables Vivado 2025.1+ Segmented Configuration mode on Versal targets. When set to
1, the build emits two PDIs (${IMAGENAME}_static.pdiforBOOT.BINand${IMAGENAME}_dynamic.pdifor runtime PL reload) instead of the single${IMAGENAME}.pdi. Ignored on non-Versal targets (soft-warn at build time). See How to Use Versal Segmented Configuration for the full opt-in workflow.- Default:
0(standard single-PDI Versal build)
Vitis / SDK Variables
- EMBED_PROC
MicroBlaze processor instance name for ELF embedding.
- Default:
microblaze_0
- VITIS_SRC_PATH
Path to the Vitis/SDK application source tree for ELF embedding.
- Default:
unset (ELF embedding disabled)
- SDK_SRC_PATH
Legacy alias for
VITIS_SRC_PATH. Used with Vivado 2019.1 and older.- Default:
unset
Vitis AIE Targets
These targets are provided by system_vitis_unified_aie.mk (Vitis 2025.1+
unified toolchain). For the end-to-end workflow see How to Build a Vitis AI Engine (AIE) Graph.
Target |
Description |
|---|---|
|
Idempotently create the Vitis workspace and AIE component
( |
|
Build the AIE graph for the |
|
Build for the x86 simulator ( |
|
Wrap |
|
Invoke |
|
Invoke |
|
Open the same workspace in the Vitis Unified IDE
( |
|
Drop into a Python REPL with the |
|
Print all AIE environment variable values. |
|
Delete the build directory ( |
Vitis AIE Variables
These variables drive system_vitis_unified_aie.mk. The platform/part,
sources, top-level graph, and XSA-directory variables must be set in the
consuming Makefile before the include line; VIVADO_XSA_DIR is
asserted at recipe time so only package requires it.
- AIE_PLATFORM
Absolute path to the platform
.xpfm. Use this for dev boards with an AMD-shipped xpfm (e.g.xilinx_vek280_base_*). Mutually exclusive withAIE_PART— set exactly one.- Default:
unset (the Makefile errors at parse time if neither
AIE_PLATFORMnorAIE_PARTis defined)
export AIE_PLATFORM := $(firstword $(wildcard \ $(XILINX_VITIS)/base_platforms/xilinx_vek280_base_*/xilinx_vek280_base_*.xpfm))
The wildcard pattern keeps the same Makefile working across Vitis releases — AMD bumps the numeric suffix per release (
202510_1in 2025.1,202520_1in 2025.2, …) so a literal path would pin the project to one Vitis version.
- AIE_PART
Versal device ID (e.g.
xcve2802-vsvh1760-2MP-e-S). Use this for custom AIE boards without a shipped xpfm. The PL clock hint comes from the cfg’spl-freq=line. Mutually exclusive withAIE_PLATFORM.- Default:
unset
- AIE_SOURCES
Whitespace-separated list of
path[:dest_subdir]entries. Thepathhalf is either:a file path → imports just that file, or
a directory path → imports every
.cpp/.cc/.h/.hppfile in that directory (non-recursive — subdirectories are not walked).
Without
:dest_subdir, imports land flat at the component root; with:dest_subdir, they import into<component>/<dest_subdir>/(matches the AMD-canonicalkernels/layout wheregraph.hdoesadf::source(loop) = "kernels/loopback.cc";).include=paths for the component root and everydest_subdirare auto-merged into the generated cfg. Mix local and shared sources freely (including submodule paths).- Default:
unset (parse-time error)
SHARED_AIE := $(TOP_DIR)/submodules/aie-common-kernels export AIE_SOURCES = \ $(CURDIR)/aie \ $(CURDIR)/aie/kernels:kernels \ $(SHARED_AIE)/util.cc
- AIE_TOP_LEVEL_FILE
Top-level graph file basename only (e.g.
graph.cpp). The top-level graph imports at the component root, so this is just the filename — never a path.- Default:
unset (parse-time error)
- VIVADO_XSA_DIR
Directory containing the Vivado-built
.xsaimages, required by thepackagetarget. Set it in the consuming AIE Makefile before theincludeline:export VIVADO_XSA_DIR = $(abspath $(CURDIR)/../../targets/<target>/images)
The
packagestep auto-selects the newest.xsaby theBUILD_TIMEtimestamp encoded in the image filename (<project>-<version>-<YYYYMMDDhhmmss>-<user>-<githash>.xsa) and hard-errors if the directory contains no.xsa.- Default:
unset (recipe-time error from the
packagetarget)
Note
A directory is used instead of an explicit file path because the Vivado-side
IMAGENAMEembedsBUILD_TIMEand is not predictable from inside the AIE archetype.
- AIE_CONF
Optional
partition.confsidecar path, forwarded to$(AIE_PROGRAM_SCRIPT)as the-cflag when set. When unset the default helper auto-derives it from the PDI directory as<pdi-dir>/<name>.partition.conf— which matches theip/pair written by the defaulttargetchain, so most consumers never set it.- Default:
unset (helper auto-derives the path)
- AIE_BOARD_IP
user@hostfor theprogramtarget. Forwarded to$(AIE_PROGRAM_SCRIPT)as the-iflag when set.- Default:
unset (the default
program.sherrors if no-iis passed — most consumers set a project default withAIE_BOARD_IP ?= root@<dev-ip>)
- OUT_DIR
Vitis workspace root. The AIE component is created at
$(OUT_DIR)/$(PROJECT)/.- Default:
$(PROJ_DIR)/build
- AIE_IP_DIR
Final deliverable directory for the dynamic PDI. Mirrors the unified HLS convention of writing artifacts to
$(PROJ_DIR)/ip/.- Default:
$(PROJ_DIR)/ip
- AIE_PDI
Output dynamic PDI path written by
make package. Named$(PROJECT).pdisoip/matches the normalized/boot/aie/<name>pair basename — the deploy helper uploads it verbatim, and still strips a legacy_aie_dynamic/_dynamicsuffix if a consumer overridesAIE_PDIto keep one.- Default:
$(AIE_IP_DIR)/$(PROJECT).pdi
- AIE_PKG_DIR
Scratch directory used by the package step (
v++ --packageworking tree).- Default:
$(OUT_DIR)/aie_package
- VPP_LOG
Log file path for the
v++ --packageinvocation.- Default:
$(OUT_DIR)/vpp_package.log
- USE_BOOTGEN_FALLBACK
Set to
1to package viabootgeninstead ofv++ --package. Both paths produce a functionally equivalent dynamic PDI for the AIE-overlay case.- Default:
0
- AIE_PROGRAM_SCRIPT
Deploy helper invoked by
make program. The default helper is a generic Versal/PetaLinux deploy: scp the PDI +partition.confsidecar to/boot/aie/<name>.{pdi,partition.conf}, ssh-reboot, then verify the startup-app-init boot loop loaded the AIE (journalAIE load:line +fpga_managerdmesg write),aie-partition-init@<name>.serviceis active, and/sys/class/aieexists. Override to point at a project-specific helper when richer verification (application-specific systemd checks,xsdbreadout, etc.) is required.- Default:
$(RUCKUS_DIR)/vitis/aie/program.sh
The helper must accept the following flag contract:
Flag
Meaning
-p <path>Runtime PDI to upload (required)
-i <user@host>Board target (required; forwarded from
AIE_BOARD_IP)-c <path>partition.confsidecar (optional; forwarded fromAIE_CONFwhen set — auto-derived from the PDI directory otherwise)
- AIE_PARTITION_CONF_SCRIPT
partition.confextractor invoked bymake partition_conf. The default helper reads the AIE partition geometry from the Vitis-emittedaie_partition.json(Work/arch/) and writes$(AIE_IP_DIR)/$(PROJECT).partition.confwith two lines —PARTITION_ID=<hex>andUID=<hex>— consumed on-board byaie-partition-init. Driven purely by theOUT_DIR/PROJECT/AIE_IP_DIRenv vars. Override only if a project needs bespoke partition.conf emission.- Default:
$(RUCKUS_DIR)/vitis/aie/emit_partition_conf.sh