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.
Il progetto viene avviato nel 1998 per poter implementare più facilmente uno stack TCP/IP per “Cambridge z88”. Da allora il progetto si è allargato ad altri modelli e famiglie di CPU, il cui obbiettivo fosse rendere disponibile ai programmatori di queste macchine una toolchain facile da usare e migliorargli la vita. <3
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.
Il software è rilasciato con licenza GNU GPLv3. <3 <3 <3
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
| n° | TARGET | Macchina |
|---|---|---|
| 1 | z88 | Cambridge z88 |
| 2 | ace | Jupiter Ace |
| 3 | lambda | Lambda 8300 |
| 4 | pps | Peters Plus Sprinter |
| 5 | sam | Sam Coupe |
| 6 | zx80 | Sinclair ZX80 |
| 7 | zx81 | Sinclair ZX81 |
| 8 | ts2068 | Timex TS2068 |
| 9 | zx | ZX Spectrum |
| 10 | zxn | ZX Spectrum Next |
MC6847 Derived
| n° | TARGET | Macchina |
|---|---|---|
| 1 | sv8000 | Bandaivision SV-8000 |
| 2 | mc1000 | CCE MC-1000 |
| 3 | pc6001 | PC-6001, PC-6001mk2 |
| 4 | spc1000 | Sumsung SPC-1000 |
| 5 | cd phc25 | Sanyo PHC-25 |
| 6 | Siko MAP-1010 | |
| 7 | vz | VZ-200, VZ-300 |
Japanese Hardware
| n° | TARGET | Macchina |
|---|---|---|
| 1 | rx78 | Bandai RX-78 |
| 2 | x07 | Canon X-07 |
| 3 | fp1100 | Casio FP-1100 |
| 4 | pv1000 | Casio PV-1000 |
| 5 | multi8 | Mitsubishi Multi8 |
| 6 | pc88 | NEC PC-8801 |
| 7 | Sanyo MBC-200, 225, 1200, 1250 | |
| 8 | Sony SMC-70, SMC-777 (native) | |
| 9 | sos | S-OS (The Sentinel) |
| 10 | z80tvgame | Z80 TV Game |
DDR Hardware
| n° | TARGET | Macchina |
|---|---|---|
| 1 | bic | BIC/a5105 |
| 2 | hemc | Hubler/Evert-MC |
| 3 | hgmc | Hubler Grafik-MC |
| 4 | kramermc | Kramer-MC |
| 5 | nanos | NANOS |
| 6 | kc | Robotron HC-900, KC85/2, KC85/3, KC85/4, KC85/5 |
| 7 | z1013 | Robotron Z1013 |
| 8 | z9001 | Robotron Z9001, KC85/1, KC87 |
Other Eastern Bloc
| n° | TARGET | Macchina |
|---|---|---|
| 1 | gal | Galaxija |
| 2 | gal | Galaxija Plus |
| 3 | homelab | Homelab 2 |
| 4 | homelab | Homelab 4 |
| 5 | tim011 | TIM-011 |
| 6 | ondra | Ondra |
| 7 | pmd85 | PMD-85 |
| 8 | primo | Primo |
| 9 | tvc | TVC Videoton |
“Early” hardware
| n° | TARGET | Macchina |
|---|---|---|
| 1 | altair8800 | Altair 8800 |
| 2 | dai | DAI |
| 3 | EACA EG2000 | |
| 4 | excali64 | Excalibur 64 |
| 5 | nascom | Nascom 2 |
| 6 | sol20 | PTC Sol20 |
| 7 | Exidy Sorcerer | |
| 8 | trs80 | TRS80 |
| 9 | kc, m100 | TRS80 Model 100 Olivetti M10 KC85 NEC-PC8201 |
Modern hardware
| n° | TARGET | Macchina |
|---|---|---|
| 1 | agon | Agon Light |
| 2 | aquarius | Aquarius Plus |
| 3 | hbios | HBIOS boards |
| 4 | micro8085 | Micro85 |
| 5 | rc2014 | RC2014 |
| 6 | scz180 | SC Z180 boards |
| 7 | yaz180 | YAZ180 |
TMS99x8 Derived
| n° | TARGET | Macchina |
|---|---|---|
| 1 | bit90 | Bit-90 |
| 2 | pv2000 | Casio PV-2000 |
| 3 | coleco | Colecovision |
| 4 | coleco | Colecovision Adam |
| 5 | pencil2 | Hanimex Pencil II |
| 6 | lm80c | LM80-C |
| 7 | mtx | Memotech MTX |
| 8 | nabu | NabuPC |
| 9 | myvision | Nichibutsu My Vision |
| 10 | msx | MSX1 |
| 11 | msx | MSX2 |
| 12 | sc3000 | Sega SC-3000 / SG-1000 |
| 13 | sms | Sega Master System+ Gamegear |
| 14 | m5 | Sord M5 |
| 15 | SpectraVideo 318 | |
| 16 | einstein | Tatung Einstein |
| 17 | einstein | Tatung Einstein 256 |
Other Home Computer
| n° | TARGET | Macchina |
|---|---|---|
| 1 | abc80 | ABC80 / ABC800 |
| 2 | cpc | Amstrad CPC |
| 3 | nc | Amstrad NC |
| 4 | lynx | Camputers Lynx |
| 5 | c128 | Commodore 128 |
| 6 | super80 | Dick Smith Super-80 |
| 7 | enterprise | Enterprise 64/128 |
| 8 | newbrain | Grundy Newbrain |
| 9 | acquarius | Mattel Acquarius |
| 10 | p2000 | Philips P2000 |
| 11 | vg5k | Philips VG-5000 |
| 12 | laser500 | VTech Laser 350/500/700 |
Sharp Hardware
| n° | TARGET | Macchina |
|---|---|---|
| 1 | mz | Sharp MZ80, MZ700, MZ800 |
| 2 | mz2500 | Sharp MZ2500 |
| 3 | g800 | Sharp PC-G8xx, PCE2xx |
| 4 | oz | Sharp OZ |
| 5 | x1 | Sharp X1 |
Soviet Hardware
| n° | TARGET | Macchina |
|---|---|---|
| 1 | mikro80 | Mikro-80 |
| 2 | special | Specialist |
| 3 | vector06c | Vector06c |
| 4 | krokha | Krokha |
| 5 | lviv | Lviv PK-01 |
| 6 | pk8000 | PK-8000 |
| 7 | radio86 | Radio86-RK |
CP/M Based
| n° | TARGET | Macchina |
|---|---|---|
| 1 | cpm | Vanilla CP/M z80 and 8080 + |
| 2 | pcw | Amstrad PCW |
| 3 | bondwell | Bondwell 12/14 |
| 4 | bondwell2 | Bondwell 2 |
| 5 | px8 | Epson PX-8/HC-80/HC-88 |
| 6 | px4 | Epson PX-4/HC-40 |
| 7 | gemini | Gemini Galaxy |
| 8 | kaypro83, kaypro84 | Kaypro II, Kaypro 4 |
| 9 | aussie | Knight 2000/Aussie Byte |
| 10 | bee, micro8085 | Microbee |
| 11 | mikro80 | MikroBEE |
| 12 | nabu | Nabu PC |
| 13 | osborne1 | Osborne 1 |
| 14 | attache | Otrona Attachè |
| 15 | rc700 | Regnecentralen RC700 |
| 16 | mbc200 | Sanyo MBC-200, 225, 1200, 1250 |
| 17 | smc777 | Sony SMC-70/SMC-777 |
| 18 | tiki100 | Tiki-100 |
| 19 | pasopia7 | Toshiba Pasopia 7 |
| 20 | v1050 | Virtual Technology 1050 |
| 21 | x820 | Xerox 820 |
| 22 | …and many more |
“Unusual” hardware
| n° | TARGET | Macchina |
|---|---|---|
| 1 | gl | Genius Leader Learning Computers |
| 2 | gb | Nintendo Gameboy |
| 3 | pacman | Pacman Hardware |
| 4 | s1mp3 | S1MP3 |
| 5 | ti82 | TI82 |
| 6 | ti83 | TI83 |
| 7 | ti83p | Ti83+ |
| 8 | ti85 | TI85 |
| 9 | ti86 | TI86 |
| 10 | osca | v6z80p OSCA |
| 11 | rex | Xircom Rex 6000 |
Homebrew hardware
(generic support for the following CPUs)
| n° | TARGET | Macchina |
|---|---|---|
| 1 | 8080 | |
| 2 | 8085 | |
| 3 | z80 | Z80 |
| 4 | Z180 | |
| 5 | EZ80 (ADL=0) | |
| 6 | kc | KC160 |
| 7 | Rabbit 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. | Package | Versione | Dipendenza |
|---|---|---|---|
| 1 | gmake | 4.4.1p0 | |
| 2 | gmp | 6.3.0 | |
| 3 | redis | 6.2.20 | ccache | libhiredis |
| 4 | libhiredis | 1.3.0 | ccache |
| 5 | xxhash | 0.8.3p0 | ccache |
| 6 | fmt | 10.2.1 | ccache |
| 7 | ccache | 4.11.3p0 | |
| 8 | boost | 1.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 Operativo | CC | MAKE | INSTALL |
|---|---|---|---|
| SunOS | gcc | gmake | ginstall |
| NetBSD|OpenBSD|FreeBSD | cc|gcc | gmake | install |
| Darwin | gcc | gmake|make | install |
| * | gcc | make | install |
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.sh | Descrizione | Effetto 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) |
| -p | Se 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.sh | Descrizione | Effetto 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.
| flag | descrizione | default value (true->1, false->0) | Parametri per cambiare il defaut value |
|---|---|---|---|
| do_clean | clean (escludendo la bin) | 0 | -c |
| do_clean_bin | clean della sola bin | 0 | -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!