OpenBSD | z88dk un cross-CC per z80.

di | Maggio 17, 2026

z88dk è un ambiente di sviluppo C e assembler per UNIX x86|amd64, capace di generare eseguibili per architetture ad 8bit-z80 e sue varianti (8080, 8085, gbz80, z80, z180, ez80_z80, KS160, Rabbit 2000, 3000, 4000, 5000), e questo fa si che possa essere utilizzato per centanaia di modelli di macchine *TARGET* differenti.

Potrò quindi scrivere un codice in linguaggio C ANSI (C98|C99) su moderne macchine a 64bit ed eseguirlo poi –ad esempio– su Sinclair ZX81 o altra macchina ZX.

Di seguito la procedura eseguita per effettuare l’installarlo su un laptop adm64-openbsd, partendo dai sorgenti.

TARGET attualmente supportati.

z88dk supporta una molteplicità di macchine ad 8 bit e configurazioni (denominati TARGET), di seguito una lista completa. Include anche alcuni TARGET non completamente supportati o di cui il supporto non è stato ancora verificato con con l’ultima versione. Questa tabella rimane fondamentale e verrà ripresa in fase di build.

Sinclair Insispired

TARGETMacchina
1z88Cambridge z88
2aceJupiter Ace
3lambdaLambda 8300
4ppsPeters Plus Sprinter
5samSam Coupe
6zx80Sinclair ZX80
7zx81Sinclair ZX81
8ts2068Timex TS2068
9zxZX Spectrum
10zxnZX Spectrum Next

MC6847 Derived

TARGETMacchina
1sv8000Bandaivision SV-8000
2mc1000CCE MC-1000
3pc6001PC-6001, PC-6001mk2
4spc1000Sumsung SPC-1000
5cd phc25Sanyo PHC-25
6Siko MAP-1010
7vzVZ-200, VZ-300

Japanese Hardware

TARGETMacchina
1rx78Bandai RX-78
2x07Canon X-07
3fp1100Casio FP-1100
4pv1000Casio PV-1000
5multi8Mitsubishi Multi8
6pc88NEC PC-8801
7Sanyo MBC-200, 225, 1200, 1250
8Sony SMC-70, SMC-777 (native)
9sosS-OS (The Sentinel)
10z80tvgameZ80 TV Game

DDR Hardware

TARGETMacchina
1bicBIC/a5105
2hemcHubler/Evert-MC
3hgmcHubler Grafik-MC
4kramermcKramer-MC
5nanosNANOS
6kcRobotron HC-900, KC85/2, KC85/3, KC85/4, KC85/5
7z1013Robotron Z1013
8z9001Robotron Z9001, KC85/1, KC87

Other Eastern Bloc

TARGETMacchina
1galGalaxija
2galGalaxija Plus
3homelabHomelab 2
4homelabHomelab 4
5tim011TIM-011
6ondraOndra
7pmd85PMD-85
8primoPrimo
9tvcTVC Videoton

“Early” hardware

TARGETMacchina
1altair8800Altair 8800
2daiDAI
3EACA EG2000
4excali64Excalibur 64
5nascomNascom 2
6sol20PTC Sol20
7Exidy Sorcerer
8trs80TRS80
9kc, m100TRS80 Model 100
Olivetti M10
KC85
NEC-PC8201

Modern hardware

TARGETMacchina
1agonAgon Light
2aquariusAquarius Plus
3hbiosHBIOS boards
4micro8085Micro85
5rc2014RC2014
6scz180SC Z180 boards
7yaz180YAZ180

TMS99x8 Derived

TARGETMacchina
1bit90Bit-90
2pv2000Casio PV-2000
3colecoColecovision
4colecoColecovision Adam
5pencil2Hanimex Pencil II
6lm80cLM80-C
7mtxMemotech MTX
8nabuNabuPC
9myvisionNichibutsu My Vision
10msxMSX1
11msxMSX2
12sc3000Sega SC-3000 / SG-1000
13smsSega Master System+ Gamegear
14m5Sord M5
15SpectraVideo 318
16einsteinTatung Einstein
17einsteinTatung Einstein 256

Other Home Computer

TARGETMacchina
1abc80ABC80 / ABC800
2cpcAmstrad CPC
3ncAmstrad NC
4lynxCamputers Lynx
5c128Commodore 128
6super80Dick Smith Super-80
7enterpriseEnterprise 64/128
8newbrainGrundy Newbrain
9acquariusMattel Acquarius
10p2000Philips P2000
11vg5kPhilips VG-5000
12laser500VTech Laser 350/500/700

Sharp Hardware

TARGETMacchina
1mzSharp MZ80, MZ700, MZ800
2mz2500Sharp MZ2500
3g800Sharp PC-G8xx, PCE2xx
4ozSharp OZ
5x1Sharp X1

Soviet Hardware

TARGETMacchina
1mikro80Mikro-80
2specialSpecialist
3vector06cVector06c
4krokhaKrokha
5lvivLviv PK-01
6pk8000PK-8000
7radio86Radio86-RK

CP/M Based

TARGETMacchina
1cpmVanilla CP/M z80 and 8080 +
2pcwAmstrad PCW
3bondwellBondwell 12/14
4bondwell2Bondwell 2
5px8Epson PX-8/HC-80/HC-88
6px4Epson PX-4/HC-40
7geminiGemini Galaxy
8kaypro83, kaypro84Kaypro II, Kaypro 4
9aussieKnight 2000/Aussie Byte
10bee, micro8085Microbee
11mikro80MikroBEE
12nabuNabu PC
13osborne1Osborne 1
14attacheOtrona Attachè
15rc700Regnecentralen RC700
16mbc200Sanyo MBC-200, 225, 1200, 1250
17smc777Sony SMC-70/SMC-777
18tiki100Tiki-100
19pasopia7Toshiba Pasopia 7
20v1050Virtual Technology 1050
21x820Xerox 820
22…and many more

“Unusual” hardware

TARGETMacchina
1glGenius Leader Learning Computers
2gbNintendo Gameboy
3pacmanPacman Hardware
4s1mp3S1MP3
5ti82TI82
6ti83TI83
7ti83pTi83+
8ti85TI85
9ti86TI86
10oscav6z80p OSCA
11rexXircom Rex 6000

Homebrew hardware

(generic support for the following CPUs)

TARGETMacchina
18080
28085
3z80Z80
4Z180
5EZ80 (ADL=0)
6kcKC160
7Rabbit 2000/3000/4000/5000/6000

Queste tabelle, sono indicative e potrebbero esserci degli errori ed imprecisioni. La documentazione ufficiale non è molto previsa a riguardo ed alcune volte l’associazione TARGET / Macchina è frutto dell’intuito o analizzando l’albero dei sorgenti, quindi ancora in fase di completamento.

Prelevare i sorgenti

z88dk è un software libero, quindi utilizzabile. Purtroppo non è disponibile in binario, già pacchettizzato, nei repository ufficiali di OpneBSD, quindi dovrò prelevarne i sorgenti da github e compilarli con clang o GNU GCC.

arcadia$ git clone --ricorsive https://github.com/z88dk/z88dk.git

Prerequisiti.

z88dk ha una lista di dipendenze, ma il mio approccio è minimalista e da esploratore, non segue alla lettera la documentazione, ma installo solo ciò che mi viene richiesto di volta in volta per andare avanti, anche se ciò comporta –devo dire– talvolta una perdina di tempo. Questo tipo di approccio rispecchia me, ma magari non voi. Per indole ho bisogno di aver il controllo della macchina, conoscere ogni pacchetto installato e del perchè. Alcune volte aiuta l’apprendimento, ed a fissare le informazioni importanti, oltre che a capire come funzionano le cose. Scoprirne i difetti e poi volerli eliminare.

Dopo vari tentativi falliti ed interruzioni varie, son riuscito a portare a termina la compilazione sulla mia macchina OpenBSD, dopo aver installato questi 7 pacchetti :

no.PackageVersioneDipendenza
1gmake4.4.1p0
2gmp6.3.0
3redis6.2.20ccache | libhiredis
4libhiredis1.3.0ccache
5xxhash0.8.3p0ccache
6fmt10.2.1ccache
7ccache4.11.3p0
8boost1.87.0p0v0

Di seguito l’albero delle dipendenze :


     zx88dk-20260515
       \
       '--- gmake (build)
       '--- gmp
       '--- boost
       '--- cchace
              \
              '--- fmt
              '--- xxhash
              '--- libhiredis
                     \
                     '--- redis

Passerò quindi a dettagliare i singolo pacchetto software installato, necessario per il build di z88dk, o vitale al suo funzionamento a runtime.

gmake

gmake è un’alternativa al make, entrambi leggono e processano un Makefile. L’istallazione di gmake l’ho eseguita col solito comando pkg_add senza dar conto troppo alla versione minima suggerità nella documentazione ufficiale. Nel caso specifico il sistema mi ha proposto come unica versione disponibile la 4.4.1p0, e va bene così.

arcadia$ doas pkg_add gmake
quirks-7.147 signed on 2025-10.10T23:15:26Z
gmake-4.4.1p0: ok

gmp

GNU MP è una libreria matemarica, a precisione arbitraria. Opera su interi con segno, numero razionali, numeri a virgola mobile.

arcadia$ doas pkg_add gmp
quirks-7.147 signed on 2025-10.10T23:15:26Z
gmp-6.3.0: ok

E’ considerata dai progettisti OpenBSD come componente utente, quindi installata in /usr/local. E’ necessario quindi aggiungere la /usr/local/include e la /usr/local/lib nelle relative variabili di ambiente considerate dal processo di build.

export CPATH="/usr/local/include:$CPATH"
export LIBRARY_PATH="/usr/local/lib:$LIBRARY_PATH"

redis

Database Server chiave valore. Utilizzato per la cache del compilatore zcc, tramite il pacchetto ccache/libhiredis.

arcadia$ doas pkg_add redis
quirks-7.147 signed on 2025-10.10T23:15:26Z
redis-6.2.20: ok

ccache

ccache è un sistema di caching per compilatori C, per evitare di ripetere completamente i medesimi passi durante una ricompilazione di un software. Dipende da : libhiredis, xxhash ed fmt. Il comando pkg_add di default installa preventivamente tutte le dipendenze.

arcadia$ doas pkg_add ccache
quirks-7.147 signed on 2025-10.10T23:15:26Z
ccache-4.11.3p0: libhiredis-1.3.0: ok
ccache-4.11.3p0: xxhash-0.8.3p0: ok
ccache-4.11.3p0: fmt-10.2.1: ok
ccache-4.11.3p0: ok

libhiredis

Hiredis è una libreria client minimalista per database Redis. Probabilmente è funzionale a ccache perchè rappresenta lo strumento per accedere al database in cui memorizza la cache. Questo significa che anche Redis DB è una dipendenza di zccdk, che però risulta già installato.

xxhash

implementa un algoritmo hash non crittografico, molto molto veloce. Anche per questo ne capisco la funzionalità in una gestione della cache, il confronto non di grosse stringhe ma degli hash.

fmt

libreria alternativa ad stdio per la formattazione di stringhe.

boost

libreria in fase di standardizzazione, ed è in fase di inclusione nel C++ standard.

arcadia$ pkg_add boost
quirks-7.147 signed on 2025-10.10T23:15:26Z
boost-1.87.0p0v0: ok

Fase di Compilazione.

La fase di compilazione per ambienti UNIX e unix-like è descritta a questa URL di progetto, e va considerata anche per rimanere aggiornati. Ciò nonostante, ho apportato alcune varianti e correzioni a quando riportato nella documentazione ufficiale, durante la mia lunga esplorazione.

Ad esempio, non ho impostato le variabili di ambiente BUILD_SDCC e BUILD_SDCC_HTTP, che da documentazione andavano valorizzate True (1), permettente una volta avviata la procedura di build di scaricare tramite protocollo HTTP il download (come tarball) dei sorgenti anche di sdcc. Ho capito che tali variabili non venivano realmente utilizzate, quindi le ho escluse.

Così come, sempre per il processo build, non ho impostato la variabile di ambiente ZCCCFG con il valore “lib/config/”. In questa directory son presenti le configurazione da applicare, per ogni macchine z80 supportata, di cui l’elenco completa è in una delle tabelle precedentemente inserite. Questi file di configurazioni, come vedremo sono molto utili (indispensabili) anche a run-time dal compilatore zcc, ma mi son accorto che tale variabile veniva impostata già all’interno della procedura di build, che a breve analizzerò e descriverò.

Ciò che invece va fatto preventivamente, è il settaggio delle directory /usr/local/include ed /usr/local/lib nelle corrispondenti variabili di ambiente CPATH e LIBRARY_PATH, altrimenti il processo di build non riesce a trovare header e librerie del pacchetto gmp, di cui ne è dipendente come visto in precedenza, e se non lo trova si interrompe.

In sintesi, questi sono i passi da eseguire per avviare il build di z88dk, con la configurazione di default. In evidenza i passi documentati ma da me non eseguiti. Se volete un build personalizzato (che ad esempio includa i test post build, gli esempi e altro ancora), andate avanti con la lettura di questo documento, altrimenti aldate oltre.

# Ricordati di controllare le variabili CPATH e LIBRARY_PATH per GMP
export CPATH="/usr/local/include:$CPATH"
export LIBRARY_PATH="/usr/local/lib:$LIBRARY_PATH"

cd z88dk
export BUILD_SDCC=1
export BUILD_SDCC_HTTP=1
chmod +x build.sh
export PATH=${PATH}:`pwd`/bin
export ZCCCFG=`pwd`/lib/config

Analisi dello script ./build.sh

Questa è una sezione di esplorazione dello script ./build.sh, che mi ha permesso di comprendere alcune cose del funzionamento di z88dk. Capisco che non tutti sono esploratori, quindi se non sei interessato a conoscere il contenuto ed il significato di questo script puoi tranquillamente saltare al paragrafo successivo. Si può usare pienamente lo z88dk con il build di default.

Eseguendo lo script col parametro -h, si ottiene la lista dei parametri previsti.

arcadia$ ./build.sh -h

Usage: ./build.sh [-b][-c][-C][-e][-h][-k][-l][-p][-t][-z]

  -b   Don't build binaries
  -c   Clean build environment
  -C   Clean build environment and binaries (including bin/*)
       Chosing this option makes a manual rebuild of zsdcc
       necessary in the win32 environment
  -e   Build examples
  -h   This help information
  -k   Keep building ignoring errors
  -l   Don't build libraries
  -p   TARGET Build specified targets
  -i   PATH Final installation directory
  -t   Run tests
  -z   Skip the z80asm tests
  -v   Be verbose

A seguito dell’analisi di ./build.sh, seguiranno alcune questioni.

DOMANDA 1: Quali Sistemi Operativi UNIX e UNIX-Like son supportati ?

Sembrerebbe che la famiglia BSD (almeno FreeBSD, OpenBSD e NetBSD) venga gestita dal processo di compilazione, così come SunOS e Darwin, mentre altri sistemi operativi (ad esempio sistemi GNU/Linux) ricadono nella gestione di default. Quindi *non* sappiamo con certezza se uno specifico UNIX venga supportato o meno, è necessario provare, e prima di tutto continuare a leggere questo documento

Lo script build.sh, si chiede sin da subito il sistema operativo che sta utilizzando l’utente, al fine di valorizzare le seguenti 3 variabili : CC, MAKE ed INSTALL, ossia il compilatore e comando make da utilizzare. L’uso della terza variabile (INSTALL) non è ben chiaro, e di fatto tale variabile non viene utilizzata.

Di seguito il frammento di build.sh che valorizza le suddette 3 variabili

case `uname -s` in                      # Insert default values for MAKE and INSTALL following used OS
  SunOS)
    MAKE="gmake"
    INSTALL="ginstall"
    export INSTALL
    ;;
  OpenBSD|NetBSD|FreeBSD)
    MAKE="gmake"
    INSTALL="install"
    export INSTALL
    if [ -z "$CC" ]; then                   # Insert default value for CC if CC is empty
      CC="cc"
      export CC
    fi
    ;;
  Darwin)
    if ! command -v gmake &> /dev/null
    then
        MAKE="make"
        echo "Using gmake is recommended on MacOS"
    else
        MAKE="gmake"
    fi
    INSTALL="install"
    export INSTALL
    ;;
  *)
    MAKE="make"
    INSTALL="install"
    export INSTALL
    ;;
esac

Potremmo schematizzare il tutto con una tabella :

Sistema OperativoCCMAKEINSTALL
SunOSgccgmakeginstall
NetBSD|OpenBSD|FreeBSDcc|gccgmakeinstall
Darwingccgmake|makeinstall
*gccmakeinstall

DOMANDA 2: Z88DK è progettato a componenti ?

Si. A guardare il processo di build ne ha almeno 3 : core, librerie ed esempi.

Le core è essenziale è va installato sempre.

Le librerie, sono un estensione per supportare lo specifico TARGET, dove per TARGET si può intendere una macchina, una famiglia di macchine, o una speciale configurazione di una macchina. Questa componente è essenziale ma possiamo decidere noi quali TARGET includere e quali escludere dal processo di build. Il default include tutti i TARGET supportati.

Gli esempi sono una collezione di piccoli programmi per ogni singolo TARGET supportato, utili allo sviluppatore di software per macchine z80, una volta disponibili tutti gli strumenti inclusi in Z88DK. Includere nel build questa componente, che di default niene esclusa, quindi considerata opzionale, vuol dire effettuare il build di tutti gli esempi resi disponibili dalla comunità (sviluppatori, tester, utenti). La compilazione in questo caso avviene già col cross-compiler zcc, quindi è anche un modo per verificare il processo stesso di bild delle prime 2 componenti (core e librerie)

Scendendo nel dettaglio, quindi tornando allo script build.sh, la sezione successiva definisce quali parti compilare e quali no, tramite la definizione di una serie di flag interni, impostati con una valore di default :

do_build=1
do_clean=0
do_clean_bin=0
do_examples=0
do_libbuild=1
do_tests=0
skip_z80asm_tests=0

Per cambiare tali impostazioni di default è necessario modificare i valori di tali variabili, direttamente nello script ./build.sh, oppure *consigliato* impostando sulla linea di comando i parametri a questi collegati (ad esempio -e imposta ad 1 il flag do_examples, che permetterà di includere nel processo di build anche la terza componente esempi). Se siamo al primo build, il default sembra assai sensato sensato. Direi.

Per quanto riguarda le librerie per includere solamente alcuni TARGET, di nostro interesse, è necessario impostare sulla linea di comando il parametro -p, seguito dal TARGET o dall’elenco dei TARGET che desideriamo includere nel processo di build, e qui bisogna far riferimento alla tabella dei target inclusa precedentemente. Di DEFAULT vengono inclusi nel processo di build tutti i TARGET previsti, anche quelli non ancora verificati.

Riepilogo dei parametri trattati :

Paramentro di ./build.shDescrizioneEffetto interno a ./build.sh
-b*esclude* la componente core dal build (inclusa di default)do_build = 0
(da true a false)
-l*esclude* la componente libreria dal build (inclusa di default)do_libbuild = 0
(da true a false)
-e*include* la componente esempi nel build (esclusa di default)do_examples = 1
(da false a true)
-pSe la componente libreria è stata inclusa, il parametro permettere di definire quali librerie TARGET includere nel build. Potrei ad esempio essere interessato al solo TARGET zx81, e quindi includere di tutte le librerie esclusivamente quella che fa riferimento a tale macchina. Questo riduce notevolmente i tempi di build, che dovrà compilare una sola libreria anzichè per le centinaia previste, una per ogni TARGET supportato.
Al momento non so, se è possibile specificare piu’ di un TARGET, ad esempio potrei essere interezzaro a 3 target, ma non a tutti (es zx80, zx81 e zxn)
TARGET=zx81
(da NULL a zx81)

Il questo primo frammento di codice, evidenzia il setting dei flag interni per l’inserimento di una dei parametri elenecato precedentemente :

set -e      # -e: exit on error; -u: exit on undefined variable
            # -e can be overidden by -k option

DESTDIR=/usr/local

builddir=$(pwd)
ZCCCFG=$builddir/lib/config
PATH="$builddir/bin:$PATH"
export ZCCCFG
export PATH


while getopts "bcCehkltzp:i:v" arg; do       # Handle all given arguments
  case "$arg" in
    b)     do_build=0              ;;   # Don't build
    c)     do_clean=1              ;;   # clean except bin/*
    C)     do_clean_bin=1          ;;   # Clean including bin/*
    e)     do_examples=1           ;;   # Build examples as well
    k)     set +e                  ;;   # keep building ignoring errors
    l)     do_libbuild=0           ;;   # Don't build libraries
    p)     TARGETS=$OPTARG  ;;
    i)     DESTDIR=$OPTARG  ;;
    t)     do_tests=1              ;;   # Run tests as well
    z)     skip_z80asm_tests=1     ;;   # Skip z80asm tests
    v)     export Q=               ;;   # verbose makefiles
    h | *) show_help_and_exit 0    ;;   # Show help on demand
  esac
done

Nel frammento successivo, l’effetto che questi hanno in termini di istruzioni di build eseguite

if [ $do_build = 1 ]; then              # Build binaries or not...
  $MAKE DESTDIR=$DESTDIR
fi

if [ $do_libbuild = 1 ]; then           # Build libraries or not...
  if [ $TARGETS ]; then
	  MAKEARG="TARGETS=$TARGETS"
  else
	  MAKEARG=""
  fi
  $MAKE -C libsrc $MAKE_CONCURRENCY $MAKEARG
  $MAKE -C libsrc install
  $MAKE -C libsrc/newlib $TARGETS $MAKE_CONCURRENCY
  $MAKE -C include/_DEVELOPMENT
fi

if [ $do_examples = 1 ]; then           # Build examples or not...
  $MAKE -C examples
fi

Della variabile DESTDIR ne parleremo successivamente, successivamente alla fase di build quando potremo andare ad eseguire l’installazione di z88dk, ossia effettuare la copia dei binari dall’albero di build a quello definitivo, di default il prodotto viene installato al di sotto della /usr/local.

Tornando invece all’argomento di questo paragrafo, di seguito questo è quel che esegue ./build.sh quando viene impostati il parametro -e (per includere nel build anche la componente opzionale esempi) ed il paramentro -p zx81 (per includere nel buil delle librerie, esclusivamente lo specifico target).

# definisce l'ambiente
set -e
export CC=cc
export CFLAGS="-g -O2"
export MAKE=gmake
export INSTALL=install 
export DESTDIR=/usr/local
export TARGET=zx81
export builddir=~/z88dk
export ZCCCFG=~/z88dk/lib/config/
export PATH=~/z88dk/bin:$PATH

cd ~/z88dk
mkdir ~/z88dk/bin
#mkdir ~/z88dk/lib
#mkdir ~/z88dk/lib/config

#--- build componente core
gmake DESTDIR=/usr/local

#--- build componente librerie
gmake -C libsrc TARGETS=zx81
gmake -C libsrc install
gmake -C libsrc/newlib TARGETS=zx81 
gmake -C include/_DEVELOPMENT

#--- build componente esempi 
gmake -C examples

DOMANDA 4: Sono previsti test post-build per verificare che z88dk sia completamente funzionante?

Si. Successivamente alla compilazione, si può abilitare l’esecuzione di una serie di test rilasciati dagli sviluppatori per verificare che l’ambiente sia perfettamente funzionante. Questa fase di test, è regolata dai flag: do_tests e skip_z80asm_tests.

do_build=1
do_clean=0
do_clean_bin=0
do_examples=0
do_libbuild=1
do_tests=0
skip_z80asm_tests=0

Per cambiare le impostazioni default è necessario modificare i valori di tali flag, direttamente nello script ./build.sh, oppure eseguire il build impostando sulla linea di comando il parametro: -t (per includere i test), se poi da questi si vogliono escludere i test relativi all’assembler va importato inserito anche il parametro -z. Pertanto se si vogliono eseguire *tutti* i test va inserito esclusivamente il primo parametro. Se siamo al primo build, aggiungere i test, quindi cambiare il default, mi sembra sensato. Non so perchè rimangono di default disabilitati, probabilmente per ridurre i tempi complessivi del build, abbastanza lunghi. E’ possibile eseguire i test anche successivamente, e probabilmente questa è anche la scelta piu’ saggia. Eseguirli si, ma solo sucessivamente

Paramentro di ./build.shDescrizioneEffetto interno a ./build.sh
-t*abilita* l’esecuzione dei test post build, per verificare che z88dk sia perfettamente funzionante do_tests = 1
(da false a true)
-z*esclude* dai test post istallazione (se ne è abilitata la loro esecuzione) quella parte di test legati all’assembler. Se non è abilitata l’esecuzione dei test, l’impostazione di questo parametro è inunflente. Di default è l’inclusione dei test relativi all’assembler.skips_z80asm_tests = 1
(da false a true)

Il frammento di codice determina la valorizzazione dei corrispondenti flag interni è già stata riportata precedentemente, quindi evito di replicarla anche qui. Invece, quello relativo ai comandi eseguiti da ./build.sh a fronte dei due paramentri -t e -z è riportata di seguito :

if [ $do_tests = 1 ]; then              # Build tests or not...
  $MAKE -C testsuite
  if [ $skip_z80asm_tests = 1 ]; then
      $MAKE -C test suites feature
  else
      $MAKE -C test
  fi
fi

Questo è quel che esegue ./build.sh quando viene impostato il parametro -t (per abiulitare l’esecuzione del test post build) ed il paramentro -z (per escludere dai test quelli riferiti all’assembler z80).

casistica 1. esecuzione test (parametro -t)

# definisce l'ambiente
set -e
export CC=cc
export CFLAGS="-g -O2"
export MAKE=gmake
export INSTALL=install 
export DESTDIR=/usr/local
export TARGET=zx81
export builddir=~/z88dk
export ZCCCFG=~/z88dk/lib/config/
export PATH=~/z88dk/bin:$PATH

# ...

#--- esecuzione di test (paramentro -t)
gmake -C testsuite
gmake -C test

casistica 2. esecuzione test, escludendo quelli assembler z80 (parametri -t -z)

# definisce l'ambiente
set -e
export CC=cc
export CFLAGS="-g -O2"
export MAKE=gmake
export INSTALL=install 
export DESTDIR=/usr/local
export TARGET=zx81
export builddir=~/z88dk
export ZCCCFG=~/z88dk/lib/config/
export PATH=~/z88dk/bin:$PATH

# ...

#--- esecuzione di test (paramentro -t)
gmake -C testsuite
gmake -C test suites feature

DOMANDA 5: Posso ripulire l’albero dei sorgenti ad esempio per ripetere il BUILD, da eseguire con parametri differenti ?

Si. Ci sono alcuni casi che è necessario ripetere o riavvia un processo di build interrotto, ad esempio per un errore. Nel caso in cui è necessario ripartire da un’ambiente pulito, è possibile lo script di ./build.sh impostando i parametri -c (ripulisce l’intero albero tranne la directory bin) e/o -C (ripulisce la sola directory bin). Per ripristinare l’albero dei sorgenti, a come era prima della build è necessario inserire entrambi i parametri.

L’operazione di clean è regolata internamente dai flag do_clean e do_clean_bin, che di default sono impostati a false (0)

do_build=1
do_clean=0
do_clean_bin=0
do_examples=0
do_libbuild=1
do_tests=0
skip_z80asm_tests=0

I suddetti parametri (-c e -C) riportano il valore dei due flag a true.

flagdescrizionedefault value (true->1,
false->0)
Parametri per cambiare il defaut value
do_cleanclean (escludendo la bin)0-c
do_clean_binclean della sola bin0-C

Bisogna notare un dettaglio che potrebbe sfuggire. L’attivazione della fase di clean non è un’alternativa al build (compilazione dei sorgenti). Se si esegue il clean, senza disattivare il build, esegue entrambe le cose, vale a dire che esegue il build dopo un’operazione di clean, e questo ha un suo significato ed una sua utilità, ma se necessitassimo del solo clean, allora dovremmo aggiungere sulla linea di comando anche i parametri di disabilitazione delle build : -b (core) e -l (lib)

./build -c -C -b -l

Il frammento di codice determina la valorizzazione dei corrispondenti flag interni è sempre il medesimo visto in precedenza. Quello relativo ai comandi eseguiti da ./build.sh a fronte dei due paramentri -c e -C è quello riportato di seguito :

if [ $do_clean = 1 -o $do_clean_bin = 1 ]; then              # Dont remove bin, as zsdcc must be built by hand in win32
  $MAKE clean
fi

if [ $do_clean_bin = 1 ]; then          # Remove bin => zsdcc must be built again by hand in win32
  echo "rm -rf bin"
  rm -rf bin
fi

Quindi i comandi che eseguirebbe sono :

  • Per il parametro -c (do_clean = true), ossia per l’eliminazione di zcc
gmake clean
  • Per il parametro -C (do_clean_bin = true), per l’eliminazione dei binari
echo "rm -rf bin"
rm -rf bin

DOMANDA 6: Il processo di build prevede altri parametri oltre a quelli : selezione delle componenti da includere, i test post compilazione e l’operazione di clean ?

si, ci sono altri 2 parametri : -k (per ignorare gli errori) e -v (per avere maggiori dettagli durante il build)

arcadia$ ./build.sh -h

Usage: ./build.sh [-b][-c][-C][-e][-h][-k][-l][-p][-t][-z]

  -b   Don't build binaries
  -c   Clean build environment
  -C   Clean build environment and binaries (including bin/*)
       Chosing this option makes a manual rebuild of zsdcc
       necessary in the win32 environment
  -e   Build examples
  -h   This help information
  -k   Keep building ignoring errors
  -l   Don't build libraries
  -p   TARGET Build specified targets
  -i   PATH Final installation directory
  -t   Run tests
  -z   Skip the z80asm tests
  -v   Be verbose

Questi ultimi 2 parametri non vengono gestiti tramite i soliti flag interni allo script di ./build. Nel caso del primo (-k) viene eseguita una “set +e” che annulla la precedente “set -e” posizionata in testa allo script. Dai commenti sembra previsto anche il parametro -u che svolge la funzione inversa, ma poi non viene implementato essendo questo il comportamento di default. Nel secondo caso (-v) viene definita la variabile Q, che rimane vuota.

set -e      # -e: exit on error; -u: exit on undefined variable
            # -e can be overidden by -k option

DESTDIR=/usr/local

builddir=$(pwd)
ZCCCFG=$builddir/lib/config
PATH="$builddir/bin:$PATH"
export ZCCCFG
export PATH


while getopts "bcCehkltzp:i:v" arg; do       # Handle all given arguments
  case "$arg" in
    b)     do_build=0              ;;   # Don't build
    c)     do_clean=1              ;;   # clean except bin/*
    C)     do_clean_bin=1          ;;   # Clean including bin/*
    e)     do_examples=1           ;;   # Build examples as well
    k)     set +e                  ;;   # keep building ignoring errors
    l)     do_libbuild=0           ;;   # Don't build libraries
    p)     TARGETS=$OPTARG  ;;
    i)     DESTDIR=$OPTARG  ;;
    t)     do_tests=1              ;;   # Run tests as well
    z)     skip_z80asm_tests=1     ;;   # Skip z80asm tests
    v)     export Q=               ;;   # verbose makefiles
    h | *) show_help_and_exit 0    ;;   # Show help on demand
  esac
done

DOMANDA 7: Terminato la compilazione, custom ed essenziale come piace a me, come faccio ad effettuare l’installazione di tutta la mia toolchain di sviluppo, ossia la copia dei soli file che mi servono per iniziare ad usarla?

La toolchain la li può già utilizzare senza fare nessuna installazione. Nell’albero di build sono apparse delle nuove directory (bin, lib, example). Se invece vuoi rendere disponibile la toolchain a tutti gli utenti della macchina, e quindi vuoi spostarla dalla tua home directory ad una directory di sistema (in questo caso la posizione appropriata sul filesystem secondo gli standard unix, è la /usr/local/) allora devo eseguire il comando

gmake install

o se sei su un sistema GNULinux

make install

Finite le possibili domande.

Esempi di Build.

# Ricordati di controllare le variabili CPATH e LIBRARY_PATH per GMP
export CPATH="/usr/local/include:$CPATH"
export LIBRARY_PATH="/usr/local/lib:$LIBRARY_PATH"

Esempio 1. Compilazione di default : core e librerie (includento tutte le macchine supportate), senza effettuare il clean preventivo perchè si tratta di prima compilazione. Esclusione degli esempi

./build.sh

Esempio 2. Compilazione di core e librerie (includendo tutte le macchine supportate), effettuando preventivamente il clean preventivo completo

./build.sh -c -C

Esempio 3. Compilazione di core, librerie (includendo tutte le macchine supportate) ed esempi, effettuando preventivamente il clean preventivo completo

./build.sh -c -C -e

Esempio 4. Esecuzione *esclusivamente* del clean salvando solamente i binari di di z88dk

./build.sh -c -b -l

Esempio 5. Esecuzione *esclusivamente* del clean totale dell’albero di build com’era inizialmente, appena dopo il git clone.

./build.sh -c -C -b -l

Esempio 6. Ho fatto il build di default, ma adesso voglio compilare anche gli esempi, senza dover ricompilare di nuovo core e librerie, e senza effettuare alcuna clear.

./build.sh -b -l -e

Esempio 7. Build con aggiunta degli esempi, clean totale preventivo e test post compilazione

./build.sh -c -C -e -t 

Esempio 8. Mi son dimenticato di eseguire i test post installazione. Voglio eseguire solamente quelli.

./build.sh -b -l -t 

Esempio 9. Voglio eseguire il build, con clean totale preventivo e includere nelle librerie esclusivamente il supporto per la macchina “sinclaird zx81”. Inoltre compilare anche gli esempi.

./build.sh -c -C -e -p zx81 

Esempio 10. Ho terminato compilazione ed eseguito i test, ora voglio effettuare l’installazione di z88dk nelle directory di sistema della macchine, per renderlo fruibile agli altri utenti del server.

# OpenBSD|FreeBSD|NetBSD
./gmake install
# GNU/Linux
./make install

helloWorld in C per Sinclair ZX81.

Proviamo a scrivere un primo programma di esempio in ANSI C (C98/C99), il classico helloWorld, che ribattezzerò helloClive, per omaggiare uno degli zii di tutti i nerd della z80-generazion.

Questo è il listato. Semplice.

/*
 
    Primo esempio di programma in ANSI C (C98/C99)
    per Sinclair ZX81

    name    : helloClive.c
    author  : jack0e AT gnu.org
    date    : 17/05/2026

    memo build :
  |
  | arcadia$ export PATH=~/z88dk/bin:$PATH 
  | arcadia$ export ZCCCFG=~/z88dk/lib/config
  | arcadia$ zcc +zx81 \
  |             -create-app \
  |             ~/z88dk/myprg/helloClive/helloClive.c \
  |               -o myprg/helloClive/helloClive.p
  |    

    happy haching!

*/       
  
#include <stdio.h>  

void main(void) 
{
   printf("helloClive!\n");
}

Va compilato, che è un’operazione banale. E’ come farla su UNIX con gnu-gcc o clang, solo che va specificato il target, ossia la macchina che dovrà eseguirlo, in maniera tale che zcc sappia come produrre il corrispondente linguaggio macchina e le giuste locazioni di memoria, ramtop e altre variabili di ambiente, previste dal sistema operativo previsto su questa macchina. Noi non ci dobbiamo preoccupare di nulla. Fantastico!!!!!!!!

arcadia$ export PATH=~/z88dk/bin:$PATH 
arcadia$ export ZCCCFG=~/z88dk/lib/config
arcadia$ zcc \
             +zx81 \
              -create-app \
              ~/z88dk/myprg/helloClive/helloClive.c \
                -o myprg/helloClive/helloClive.p
arcadia$

…e in un attimo ha creato il file eseguibile helloClive.P

arcadia@ ls -ltr /myprg/helloClive/
-rw-r--r--  1 jack0e  jack0e   552 May 17 22:03 myprg/helloClive/helloClive.c
-rw-r--r--  1 jack0e  jack0e  2480 May 17 22:06 myprg/helloClive/helloClive.p
-rw-r--r--  1 jack0e  jack0e  3411 May 17 22:06 myprg/helloClive/helloClive.P

l’eseguibile impacchetto e pronto per Sinclair zx81 è helloClive.P. Questo file –prossimamente– proverò ad eseguirlo su OpenBSD, tramite l’emulazione di ZEsaUX (di cui ho scritto giorni fa un appunto sul come compilarlo ed installarso su macchine unix), dopodichè girerà su macchina reale.

La cosa stupefacente di z88dk è, che il medesimo listato C potrei compilarlo per “Commodore 128” (o per uno degli oltre 100 ed altri target supportati) semplicemente sostituendo nel comando di compilazione “+zx81” con “+c128”, o altro target.

Divertentissimo.

Happy Hacking!