The toolchain¶
To build CP/M apps, you need the native DCC tools (dcc, dccmake,
dccpeep, dccrtlstrip, m80c, and l80c), the bundled headers, and
DCCRTL.MAC. Normal builds run entirely on the host. Use
ntvcm to run the resulting
programs, or transfer them to another CP/M emulator or real hardware.
The original m80.com and l80.com are needed only for the optional emulated
assembler/linker path. Source debugging uses the separate
dcc-debug-host.
You build these tools once. After that, use them from any CP/M app project.
Setup flow:
- Install the host prerequisites for Windows, macOS, or Linux.
- Clone the DCC C Compiler (
dcc) andntvcmrepositories. - Build the DCC C Compiler host tools with
pwsh ./scripts/build-dcc.ps1(orsh m-posix.shon Linux platforms without a PowerShell package, e.g. RISC-V64 boards or Raspberry Pi OS). - Build the ntvcm emulator.
- Add the DCC C Compiler and ntvcm directories to your
PATH. - Verify the setup with a sample CP/M program.
Install prerequisites¶
Install the native compiler tools for your host platform before cloning and building DCC C Compiler or ntvcm.
The full PowerShell build requires PowerShell 7 or later (pwsh), CMake,
and a C++17 compiler for dcc-debug-host and its example adapter. The Visual
Studio C++ workload below supplies CMake on Windows. Install it separately with
brew install cmake on macOS or sudo apt install cmake on Ubuntu.
Install the latest stable PowerShell release unless you have a reason to
test a preview. Keep the package manager or installer that installed it as the
owner of upgrades; do not combine a system package, a user-local archive, and
a .NET global-tool installation on the same PATH.
-
Install Visual Studio Build Tools with the C++ workload. Install with
winget:winget install --id Microsoft.VisualStudio.BuildTools -e --override "--add Microsoft.VisualStudio.Workload.VCTools --includeRecommended --quiet --wait --norestart"You can also use the Visual Studio Installer and select Desktop development with C++. The Windows build uses the Microsoft C/C++ compiler tools and CMake from that installation.
-
On Windows 11 or a Windows client with WinGet, install the stable PowerShell package. This is Microsoft's recommended client install path:
winget install --id Microsoft.PowerShell --source winget pwsh --versionWinGet currently selects the MSIX package. That is suitable for this build, but it is per-user and does not support PowerShell remoting or all-users profiles. For Windows Server, managed deployments, remoting, or an all-users installation, use the MSI path in the Microsoft PowerShell install guide instead. Use the architecture-matched package on Windows ARM64.
-
Install the Xcode Command Line Tools:
xcode-select --installThis provides the clang and C++ compiler tools used by the macOS build scripts.
-
Install the architecture-matched, Microsoft-signed PKG from the Microsoft PowerShell install guide. This is Microsoft's preferred path for most macOS users. Choose the
osx-arm64package for Apple Silicon andosx-x64for Intel Macs. Then open a new terminal and verify it:pwsh --versionThe PKG installs
pwshunder/usr/local/bin. A Homebrew cask can be appropriate when Homebrew centrally manages your developer tools, but do not install both variants. Use the archive path only when you need side-by-side versions or a custom install location; it requires manual dependency and update management.
-
Install gcc, g++, make, and the usual build tools:
sudo apt install build-essential -
On a supported Ubuntu LTS release, install PowerShell from Microsoft's package repository. This is the preferred Ubuntu method and lets APT manage upgrades:
sudo apt-get update sudo apt-get install -y wget apt-transport-https software-properties-common . /etc/os-release wget -q "https://packages.microsoft.com/config/ubuntu/${VERSION_ID}/packages-microsoft-prod.deb" sudo dpkg -i packages-microsoft-prod.deb rm packages-microsoft-prod.deb sudo apt-get update sudo apt-get install -y powershell pwsh --versionThe Microsoft repository also carries some .NET packages. If this host uses Ubuntu's .NET packages, review Microsoft's package-source guidance before adding it. Microsoft supports Ubuntu LTS releases; use the manual archive method for interim or unsupported releases.
-
Install gcc, g++, make, and the usual build tools:
sudo apt install build-essential curl -
Use the Ubuntu repository route above if it publishes a package for your release and architecture. Otherwise, use the official
linux-arm64archive. This user-local approach avoids changing system package sources. Setversionto a stable release listed on the PowerShell releases page, and verify the archive against that release's published SHA-256 file before extracting it:version=7.6.6 asset="powershell-${version}-linux-arm64.tar.gz" install_dir="$HOME/.local/share/powershell/$version" release_url="https://github.com/PowerShell/PowerShell/releases/download/v${version}" mkdir -p "$install_dir" "$HOME/.local/bin" curl -fLO "$release_url/$asset" curl -fLO "$release_url/hashes.sha256" grep -F " $asset" hashes.sha256 | sha256sum -c - || exit 1 tar -xzf "$asset" -C "$install_dir" chmod +x "$install_dir/pwsh" ln -sfn "$install_dir/pwsh" "$HOME/.local/bin/pwsh" rm "$asset" hashes.sha256Make sure
~/.local/binis on yourPATH, then verify both the version and architecture:export PATH="$HOME/.local/bin:$PATH" pwsh --version file "$(readlink -f "$HOME/.local/bin/pwsh")"The
fileoutput should reportARM aarch64. Add~/.local/binto your shell startup file if it is not already present. Re-run the checksum step for each upgrade, extract into a new versioned directory, then move only thepwshsymlink.
-
Install Visual Studio Build Tools with the C++ workload and native ARM64 compiler tools. Install with
winget:winget install --id Microsoft.VisualStudio.BuildTools -e --override "--add Microsoft.VisualStudio.Workload.VCTools --add Microsoft.VisualStudio.Component.VC.Tools.ARM64 --includeRecommended --quiet --wait --norestart"You can also use the Visual Studio Installer and select Desktop development with C++, then add the MSVC ARM64/ARM64EC build tools component. The DCC C Compiler Windows build scripts use the native ARM64 MSVC environment (
vcvarsarm64.bat) when they run on Windows ARM64. CMake is included with the recommended components. -
Verify that the ARM64 MSVC tools were installed:
$vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" $installPath = & $vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.ARM64 -property installationPath Test-Path "$installPath\VC\Auxiliary\Build\vcvarsarm64.bat"The final command should print
True. -
Install stable PowerShell 7 with WinGet, which selects the native architecture automatically:
winget install --id Microsoft.PowerShell --source winget pwsh --versionFor server, managed, remoting, or all-users installations, choose the ARM64 MSI package from the Microsoft PowerShell install guide instead of the per-user MSIX package.
Verify PowerShell¶
Run this after any platform-specific installation. It confirms that the shell
on PATH is PowerShell 7+, shows the executable being used, and starts without
loading a profile that might mask a setup problem:
pwsh -NoLogo -NoProfile -Command '$PSVersionTable.PSVersion; $PSVersionTable.PSEdition; $PSVersionTable.OS; (Get-Command pwsh).Source'
Clone the repositories¶
# Clone DCC C Compiler
git clone https://github.com/davidly/dcc.git
# Clone the ntvcm z80 emulator
git clone https://github.com/davidly/ntvcm.git
Build DCC C Compiler¶
The cross-platform PowerShell build script is in the scripts directory. It
builds dcc, dccpeep, dccrtlstrip, dccmake, m80c, l80c,
dcc-debug-host, and its example I/O adapter, using MSVC on Windows, clang on
macOS, and gcc on Linux by default. Run it from the cloned dcc directory:
cd dcc
pwsh ./scripts/build-dcc.ps1
Build ntvcm¶
ntvcm is a C++ project. Build it from its own directory. The commands below
start from the parent directory containing both checkouts; from dcc, first
return to that parent with cd ...
Use the m.bat / mmac.sh / m.sh scripts below, not m.bat / mmac.sh
/ m.sh. The r versions build release configurations of the emulator with
asserts compiled out, so the resulting ntvcm runs faster.
Open a Developer PowerShell or Developer Command Prompt so the Microsoft
C/C++ compiler (cl) is on your PATH, then run the Windows release build
script:
cd ntvcm
.\m.bat
Produces ntvcm.exe.
Open a terminal where the Xcode Command Line Tools are available, then run the macOS release build script:
cd ntvcm
chmod +x mmac.sh
./mmac.sh
Produces the ntvcm executable.
Open a terminal where g++ is available, then run the Linux release build
script:
cd ntvcm
chmod +x m.sh
./m.sh
Produces the ntvcm executable.
Open a terminal where g++ is available, then run the Linux release build
script:
cd ntvcm
chmod +x m.sh
./m.sh
Produces the ntvcm executable.
Open a Developer PowerShell or Developer Command Prompt for ARM64 so the
Microsoft C/C++ compiler (cl) is on your PATH, then run the Windows
release build script:
cd ntvcm
.\m.bat
Produces ntvcm.exe.
Set up your environment¶
Use dccmake to build application projects with the source-built tools.
Use scripts/runall.ps1 to build and verify the test suite.
The tools use an environment variable if you set one; otherwise they look on
your PATH. The relevant tools are:
dcc— compilerdccmake— build pipeline helperdccpeep— peephole optimizerdccrtlstrip— application/runtime stripperntvcm— CP/M emulatorm80c/l80c— native assembler and linker
Recommended setup, especially when building apps in a project outside the DCC C Compiler
repo, is to add the directories containing the built dcc and ntvcm
binaries to your PATH. The DCC C Compiler directory also provides dccpeep,
dccmake, dccrtlstrip, m80c, l80c, the standard headers, and
DCCRTL.MAC. For a dccmake build outside that directory, configure
dcc-runtime and dcc-include-directory as shown in
Building and linking; putting a
directory on PATH alone does not configure header lookup.
-
Add the DCC C Compiler and ntvcm directories to
PATHfor the current PowerShell session:$env:PATH += ";C:\path\to\dcc;C:\path\to\ntvcm" -
To make that permanent for your Windows user account, update the user
PATHand then open a new terminal:$userPath = [Environment]::GetEnvironmentVariable("Path", "User") [Environment]::SetEnvironmentVariable("Path", "$userPath;C:\path\to\dcc;C:\path\to\ntvcm", "User") -
Replace
C:\path\to\dccandC:\path\to\ntvcmwith the actual directories. With this on yourPATH, the scripts finddcc,dccpeep,dccrtlstrip, andntvcmautomatically.
To pin specific binaries instead (for example, when juggling multiple
DCC C Compiler builds), set the environment variables to explicit paths and only
put ntvcm on PATH:
```powershell
$env:PATH += ";C:\path\to\ntvcm"
$env:DCC = "C:\path\to\dcc\dcc.exe"
$env:DCCPEEP = "C:\path\to\dcc\dccpeep.exe"
$env:DCCRTLSTRIP = "C:\path\to\dcc\dccrtlstrip.exe"
```
-
Add the DCC C Compiler and ntvcm directories to
PATHfor the current shell session:export PATH="$PATH:/path/to/dcc:/path/to/ntvcm" -
To make that permanent for the default zsh shell, append the same setting to
~/.zshrc, then open a new terminal or reload the file:printf '\nexport PATH="$PATH:/path/to/dcc:/path/to/ntvcm"\n' >> ~/.zshrc source ~/.zshrc -
Replace
/path/to/dccand/path/to/ntvcmwith the actual directories (e.g.~/GitHub/dccand~/GitHub/ntvcm). With this on yourPATH, the scripts finddcc,dccpeep,dccrtlstrip, andntvcmautomatically.
To pin specific binaries instead (for example, when juggling multiple
DCC C Compiler builds), set the environment variables to explicit paths and only
put ntvcm on PATH:
```bash
export PATH="$PATH:/path/to/ntvcm"
export DCC=/path/to/dcc/dcc
export DCCPEEP=/path/to/dcc/dccpeep
export DCCRTLSTRIP=/path/to/dcc/dccrtlstrip
```
-
Add the DCC C Compiler and ntvcm directories to
PATHfor the current shell session:export PATH="$PATH:/path/to/dcc:/path/to/ntvcm" -
To make that permanent for bash, append the same setting to
~/.bashrc, then open a new terminal or reload the file:printf '\nexport PATH="$PATH:/path/to/dcc:/path/to/ntvcm"\n' >> ~/.bashrc source ~/.bashrc -
Replace
/path/to/dccand/path/to/ntvcmwith the actual directories (e.g.~/GitHub/dccand~/GitHub/ntvcm). With this on yourPATH, the scripts finddcc,dccpeep,dccrtlstrip, andntvcmautomatically.
To pin specific binaries instead (for example, when juggling multiple
DCC C Compiler builds), set the environment variables to explicit paths and only
put ntvcm on PATH:
```bash
export PATH="$PATH:/path/to/ntvcm"
export DCC=/path/to/dcc/dcc
export DCCPEEP=/path/to/dcc/dccpeep
export DCCRTLSTRIP=/path/to/dcc/dccrtlstrip
```
-
Add the DCC C Compiler and ntvcm directories to
PATHfor the current shell session:export PATH="$PATH:/path/to/dcc:/path/to/ntvcm" -
To make that permanent for bash, append the same setting to
~/.bashrc, then open a new terminal or reload the file:printf '\nexport PATH="$PATH:/path/to/dcc:/path/to/ntvcm"\n' >> ~/.bashrc source ~/.bashrc -
Replace
/path/to/dccand/path/to/ntvcmwith the actual directories (e.g.~/GitHub/dccand~/GitHub/ntvcm). With this on yourPATH, the scripts finddcc,dccpeep,dccrtlstrip, andntvcmautomatically.
To pin specific binaries instead (for example, when juggling multiple
DCC C Compiler builds), set the environment variables to explicit paths and only
put ntvcm on PATH:
```bash
export PATH="$PATH:/path/to/ntvcm"
export DCC=/path/to/dcc/dcc
export DCCPEEP=/path/to/dcc/dccpeep
export DCCRTLSTRIP=/path/to/dcc/dccrtlstrip
```
-
Add the DCC C Compiler and ntvcm directories to
PATHfor the current PowerShell session:$env:PATH += ";C:\path\to\dcc;C:\path\to\ntvcm" -
To make that permanent for your Windows user account, update the user
PATHand then open a new terminal:$userPath = [Environment]::GetEnvironmentVariable("Path", "User") [Environment]::SetEnvironmentVariable("Path", "$userPath;C:\path\to\dcc;C:\path\to\ntvcm", "User") -
Replace
C:\path\to\dccandC:\path\to\ntvcmwith the actual directories. With this on yourPATH, the scripts finddcc,dccpeep,dccrtlstrip, andntvcmautomatically.
To pin specific binaries instead (for example, when juggling multiple
DCC C Compiler builds), set the environment variables to explicit paths and only
put ntvcm on PATH:
```powershell
$env:PATH += ";C:\path\to\ntvcm"
$env:DCC = "C:\path\to\dcc\dcc.exe"
$env:DCCPEEP = "C:\path\to\dcc\dccpeep.exe"
$env:DCCRTLSTRIP = "C:\path\to\dcc\dccrtlstrip.exe"
```
Verify the setup¶
With the tools on your PATH, run the full extended unit-test suite. From your
operating-system terminal or the VS Code terminal, first change to your local
DCC checkout directory:
cd C:\path\to\dcc
pwsh ./scripts/runall.ps1 -Mode full -Extended
The suite builds and runs the repository's tests with and without the peephole optimizer. Once it passes, move on to Building and linking for the day-to-day workflow.