This guide covers building everything yourself on Linux, macOS, and Windows:
- the CLI (
arcade-basic) — a native, self-contained executable (NativeAOT), - the IDE (
arcade-basic-ide) — a self-contained single-file terminal app, - a standalone
.basbinary — your program bundled into a runnable executable.
Pre-built binaries for every platform are attached to each tagged release; build from source only if you want to hack on it or target a platform/arch we don't publish.
The repo pins the SDK major version in global.json (9.0.1xx).
Any 9.0.1xx SDK works.
| Platform | Get the SDK |
|---|---|
| All | https://dotnet.microsoft.com/download/dotnet/9.0 |
| Windows | winget install Microsoft.DotNet.SDK.9 |
| Linux | distro packages, or the install script |
| macOS | the official installer above, or Homebrew: brew install dotnet@9 |
Homebrew note (macOS):
dotnet@9is keg-only, so it isn't put on yourPATHautomatically. Either use the official installer (which does), or add the keg yourself:export PATH="$(brew --prefix dotnet@9)/bin:$PATH" export DOTNET_ROOT="$(brew --prefix dotnet@9)/libexec"
Verify:
dotnet --list-sdks # should list a 9.0.1xx SDKNativeAOT invokes the platform's C toolchain to link the final binary. You
don't need this to run from source, run tests, or publish the IDE — only to
build the CLI (arcade-basic) or a standalone .bas binary.
| Platform | Install |
|---|---|
| Linux (Debian/Ubuntu) | sudo apt-get install -y clang zlib1g-dev (plus build-essential) |
| macOS | xcode-select --install (Command Line Tools — provides clang/ld) |
| Windows | Visual Studio 2022 with the Desktop development with C++ workload (MSVC + Windows SDK) |
A RID (Runtime Identifier) names the target a binary is built for — its
operating system and CPU architecture, in the form <os>-<arch>. Publishing is
per-target: every dotnet publish command below takes -r <RID> (long form
--runtime <RID>), and you substitute one concrete value from this table —
the platform you want the binary to run on. There is no "build for all
platforms" option; run the publish once per target.
| Platform | RID | Binary suffix | In tagged releases? |
|---|---|---|---|
| Linux x64 | linux-x64 |
(none) | yes |
| Linux ARM64 | linux-arm64 |
(none) | no — build it yourself |
| macOS Intel | osx-x64 |
(none) | no — build it yourself |
| macOS Apple Silicon | osx-arm64 |
(none) | yes |
| Windows x64 | win-x64 |
.exe |
yes |
So wherever a command shows <RID>, replace it literally — e.g. on an
Apple-Silicon Mac: dotnet publish ... -r osx-arm64.
Cross-compilation: NativeAOT can not cross-compile to a different OS (build Linux binaries on Linux, etc.). For a different architecture on the same OS, build on a matching-arch machine — e.g. the release pipeline builds
osx-arm64on an Apple-Silicon runner. The self-contained IDE publish is more forgiving but is still best built per RID.
osx-x64(Intel Mac) is a valid RID you can still build locally, but it is no longer produced by the release pipeline — download a release only for the platforms marked "yes" above; build the rest from source.
git clone https://github.com/3583Bytes/Arcade-BASIC.git arcade-basic
cd arcade-basic
dotnet build -c Release # warnings are errors in Release
dotnet test -c Release # full test suite
dotnet run --project src/ArcadeBasic.Cli -- run examples/hello.basRun the IDE straight from source:
dotnet run --project src/ArcadeBasic.Ide # empty buffer
dotnet run --project src/ArcadeBasic.Ide -- examples/hello.bas # open a filePublishAot is set in the CLI's .csproj, so do not pass
-p:PublishAot=true on the command line — doing so promotes it to a global
MSBuild property that propagates into the netstandard2.1 builds of the
multi-targeted libraries, which can't be AOT-compiled.
dotnet publish src/ArcadeBasic.Cli -c Release -r <RID> -o publish/cliResult: publish/cli/arcade-basic (arcade-basic.exe on Windows), a ~4 MB
self-contained native binary — no .NET install needed on the target.
Per platform:
# Linux x64
dotnet publish src/ArcadeBasic.Cli -c Release -r linux-x64 -o publish/cli
# macOS Intel
dotnet publish src/ArcadeBasic.Cli -c Release -r osx-x64 -o publish/cli
# macOS Apple Silicon
dotnet publish src/ArcadeBasic.Cli -c Release -r osx-arm64 -o publish/cli
# Windows x64 (PowerShell or cmd — single line)
dotnet publish src/ArcadeBasic.Cli -c Release -r win-x64 -o publish/cliSmoke-test:
./publish/cli/arcade-basic --version
./publish/cli/arcade-basic run examples/hello.bas(Omitting -o puts the binary at
src/ArcadeBasic.Cli/bin/Release/net9.0/<RID>/publish/arcade-basic.)
The IDE is not AOT-compiled (Terminal.Gui relies on reflection), so it ships as a self-contained single-file binary with the .NET runtime bundled inside. No native toolchain required.
Want F7 (Build standalone) to work? Publishing the IDE alone is not enough — see Make standalone builds (F7) work below for the combined recipe.
--runtime <RID> is the target platform (see §2) — replace <RID> with your
own, e.g. win-x64, osx-arm64, or linux-x64. Because the publish is
--self-contained, that RID decides which platform's .NET runtime gets bundled
into the single file, so the result runs on that target with no .NET installed.
dotnet publish src/ArcadeBasic.Ide \
--configuration Release \
--runtime <RID> \
--self-contained \
-p:PublishSingleFile=true \
-p:IncludeNativeLibrariesForSelfExtract=true \
--output publish/ideWindows (single line):
dotnet publish src/ArcadeBasic.Ide --configuration Release --runtime win-x64 --self-contained -p:PublishSingleFile=true -p:IncludeNativeLibrariesForSelfExtract=true --output publish/ideResult: publish/ide/arcade-basic-ide (~64 MB). It's a terminal (TUI) app — run
it inside a terminal:
./publish/ide/arcade-basic-ide examples/startrek.basA published IDE on its own cannot build standalone .bas binaries. The IDE's
Build standalone (F7) shells out to a native arcade-basic (the AOT CLI from
§4) to use as the stub; if it can't find one it reports "Could not find an
arcade-basic AOT binary". F7 looks next to arcade-basic-ide first, then
on your PATH — so the simplest fully-working setup is to publish both into the
same folder:
# 1. native CLI (the F7 stub) — needs the C++ toolchain (§1)
dotnet publish src/ArcadeBasic.Cli -c Release -r <RID> -o publish/ide
# 2. the IDE, into the SAME folder
dotnet publish src/ArcadeBasic.Ide -c Release -r <RID> --self-contained \
-p:PublishSingleFile=true -p:IncludeNativeLibrariesForSelfExtract=true -o publish/ideWindows (single line each):
dotnet publish src/ArcadeBasic.Cli --configuration Release --runtime win-x64 --output publish/ide
dotnet publish src/ArcadeBasic.Ide --configuration Release --runtime win-x64 --self-contained -p:PublishSingleFile=true -p:IncludeNativeLibrariesForSelfExtract=true --output publish/ideResult — both binaries side by side, so F7 works with no further setup
(.exe suffix on Windows only):
publish/ide/arcade-basic # AOT CLI — the F7 build stub
publish/ide/arcade-basic-ide # the IDE
Optionally add the folder to your PATH so you can launch from anywhere (and F7
works regardless of the launch directory). Windows (permanent, user-level — open
a new terminal afterward):
$ideDir = "C:\path\to\arcade-basic\publish\ide"
$userPath = [Environment]::GetEnvironmentVariable("Path", "User")
if ($userPath -notlike "*$ideDir*") { [Environment]::SetEnvironmentVariable("Path", "$userPath;$ideDir", "User") }macOS/Linux: copy arcade-basic to a PATH directory (e.g. /usr/local/bin) or
add publish/ide to PATH in your shell profile. See §6 for the full stub-lookup
details.
See ../src/ArcadeBasic.Ide/README.md for
implementation notes.
arcade-basic build bundles your compiled program onto the end of an AOT CLI
binary, producing one self-contained executable (see
standalone-builds.md for the anatomy).
./publish/cli/arcade-basic build examples/hello.bas -o hello
./helloGraphics programs run standalone too. A §13 graphics program (e.g.
examples/kanban.bas) renders in the terminal when run viaarcade-basic run/vmor as a standalone binary — the CLI draws with a Braille + ANSI backend (the same picture the IDE shows, written straight to the terminal). It activates only on an interactive terminal; piped/redirected output falls back to no rendering (use--svg <file>for headless output). Needs a terminal with Braille-glyph and ANSI/VT support (Windows Terminal, modern macOS/Linux terminals).
The IDE itself isn't AOT'd, so it can't bundle itself. It needs a native
arcade-basic (the AOT CLI from §4) to use as the stub, and looks for it:
- next to the
arcade-basic-idebinary, then - on your
PATH.
If F7 reports "Could not find an arcade-basic AOT binary", build the CLI (§4)
and make it findable — either copy it next to the IDE:
cp publish/cli/arcade-basic publish/ide/ # beside arcade-basic-ideor put it on your PATH once (works for every IDE instance):
cp publish/cli/arcade-basic /usr/local/bin/ # macOS/LinuxWhen you run the IDE via dotnet run, the "IDE binary" is the build apphost
under src/ArcadeBasic.Ide/bin/<Config>/net9.0/, so the PATH approach is the
simplest in that case.
Self-contained and standalone binaries are unsigned and un-notarized. They run fine where you built them, but a Mac that downloads one (browser, email, AirDrop) will quarantine it and refuse to open it. The recipient clears it with:
xattr -dr com.apple.quarantine ./arcade-basic-ideFor real distribution, codesign and notarize the binary.
Use single-line commands (the \ line-continuation above is bash). In
PowerShell you can use a backtick ` to continue lines if you prefer.
If AOT linking fails, the usual cause is a missing clang or zlib dev package
— see the toolchain table in §1.
| Artifact | Command | Output | Native toolchain? |
|---|---|---|---|
| Debug build | dotnet build -c Release |
per-project bin/ |
no |
| Tests | dotnet test -c Release |
— | no |
| CLI (AOT) | dotnet publish src/ArcadeBasic.Cli -c Release -r <RID> -o publish/cli |
publish/cli/arcade-basic |
yes |
| IDE (single file) | dotnet publish src/ArcadeBasic.Ide -c Release -r <RID> --self-contained -p:PublishSingleFile=true -p:IncludeNativeLibrariesForSelfExtract=true -o publish/ide |
publish/ide/arcade-basic-ide |
no |
| Working IDE + F7 | publish the CLI and IDE into the same -o folder (see §5) |
publish/ide/{arcade-basic, arcade-basic-ide} |
yes (CLI step) |
Standalone .bas |
arcade-basic build foo.bas -o foo |
foo |
yes (uses the AOT CLI) |