mirror of
https://github.com/autc04/Retro68.git
synced 2025-01-18 05:33:04 +00:00
Merge pull request #216 from mcayland/feature/docker-build-universal
Retro68: improve Docker support to enable builds with Universal interfaces
This commit is contained in:
commit
a3db211410
16
Dockerfile
16
Dockerfile
@ -7,7 +7,7 @@ RUN apt-get update && \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y \
|
||||
cmake libgmp-dev libmpfr-dev libmpc-dev \
|
||||
libboost-all-dev bison texinfo \
|
||||
ruby flex curl g++ git
|
||||
ruby flex curl g++ git macutils
|
||||
|
||||
# Add toolchain to default PATH
|
||||
ENV PATH=/Retro68-build/toolchain/bin:$PATH
|
||||
@ -19,11 +19,25 @@ FROM base AS build
|
||||
ADD . /Retro68
|
||||
|
||||
RUN mkdir /Retro68-build && \
|
||||
mkdir /Retro68-build/bin && \
|
||||
bash -c "cd /Retro68-build && bash /Retro68/build-toolchain.bash"
|
||||
|
||||
# Release image
|
||||
FROM base AS release
|
||||
|
||||
ENV INTERFACES=multiversal
|
||||
|
||||
COPY --from=build \
|
||||
/Retro68/interfaces-and-libraries.sh \
|
||||
/Retro68/prepare-headers.sh \
|
||||
/Retro68/prepare-rincludes.sh \
|
||||
/Retro68/install-universal-interfaces.sh \
|
||||
/Retro68/docker-entrypoint.sh \
|
||||
/Retro68-build/bin/
|
||||
|
||||
COPY --from=build /Retro68-build/toolchain /Retro68-build/toolchain
|
||||
|
||||
LABEL org.opencontainers.image.source https://github.com/autc04/Retro68
|
||||
|
||||
CMD [ "/bin/bash" ]
|
||||
ENTRYPOINT [ "/Retro68-build/bin/docker-entrypoint.sh" ]
|
||||
|
83
README.md
83
README.md
@ -192,6 +192,89 @@ package contains a very portable library, the command will of course fail. Pleas
|
||||
report bugs, please report successes instead!
|
||||
|
||||
|
||||
Using Retro68 with Docker
|
||||
-------------------------
|
||||
|
||||
Whenever commits are merged into the Retro68 git repository, a build pipeline is triggered to
|
||||
create a container image which is then pushed to the Retro68 package repository as
|
||||
`ghcr.io/autc04/retro68`. This image contains the complete 68K and PPC toolchains ready for
|
||||
use for either local development or as part of CI pipeline. The command line below shows an
|
||||
example invocation of Retro68 to build the `Samples/Raytracer` app:
|
||||
|
||||
```
|
||||
$ git clone --depth 1 https://github.com/autc04/Retro68.git
|
||||
$ cd Retro68
|
||||
$ docker run --rm -v $(pwd):/root -i ghcr.io/autc04/retro68 /bin/bash <<"EOF"
|
||||
cd Samples/Raytracer
|
||||
rm -rf build && mkdir build && cd build
|
||||
cmake .. -DCMAKE_TOOLCHAIN_FILE=/Retro68-build/toolchain/m68k-apple-macos/cmake/retro68.toolchain.cmake
|
||||
make
|
||||
EOF
|
||||
```
|
||||
|
||||
The container image is configured by default to use the multiversal interfaces, but it is
|
||||
possible to use the universal interfaces by passing a path to either a local file or a URL
|
||||
that points to a Macbinary DiskCopy image containing the "Interfaces&Libraries" directory
|
||||
from MPW.
|
||||
|
||||
Using the universal interfaces from a local file:
|
||||
|
||||
```
|
||||
$ docker run --rm -v $(pwd):/root -v $(pwd)/MPW-GM.img.bin:/tmp/MPW-GM.img.bin \
|
||||
-e INTERFACES=universal -e INTERFACESFILE=/tmp/MPW-GM.img.bin \
|
||||
-i ghcr.io/autc04/retro68 /bin/bash <<"EOF"
|
||||
cd Samples/Raytracer
|
||||
rm -rf build && mkdir build && cd build
|
||||
cmake .. -DCMAKE_TOOLCHAIN_FILE=/Retro68-build/toolchain/m68k-apple-macos/cmake/retro68.toolchain.cmake
|
||||
make
|
||||
EOF
|
||||
```
|
||||
|
||||
Using the universal interfaces from a URL:
|
||||
|
||||
```
|
||||
$ docker run --rm -v $(pwd):/root \
|
||||
-e INTERFACES=universal -e INTERFACESFILE=https://mysite.com/MPW-GM.img.bin \
|
||||
-i ghcr.io/autc04/retro68 /bin/bash <<"EOF"
|
||||
cd Samples/Raytracer
|
||||
rm -rf build && mkdir build && cd build
|
||||
cmake .. -DCMAKE_TOOLCHAIN_FILE=/Retro68-build/toolchain/m68k-apple-macos/cmake/retro68.toolchain.cmake
|
||||
make
|
||||
EOF
|
||||
```
|
||||
|
||||
Note that `entrypoint.sh` checks to see if the universal interfaces are installed into
|
||||
`/Retro68/toolchain/universal` first before attempting to access the file or URL specified
|
||||
by INTERFACESFILE. This means that it is possible to use caching or another volume so that
|
||||
the universal interfaces are only processed once to speed up builds e.g.
|
||||
|
||||
```
|
||||
$ docker run --rm -v $(pwd):/root \
|
||||
-v $(pwd)/universal:/Retro68-build/toolchain/universal \
|
||||
-e INTERFACES=universal -e INTERFACESFILE=https://mysite.com/MPW-GM.img.bin \
|
||||
-i ghcr.io/autc04/retro68 /bin/bash <<"EOF"
|
||||
cd Samples/Raytracer
|
||||
rm -rf build && mkdir build && cd build
|
||||
cmake .. -DCMAKE_TOOLCHAIN_FILE=/Retro68-build/toolchain/m68k-apple-macos/cmake/retro68.toolchain.cmake
|
||||
make
|
||||
EOF
|
||||
```
|
||||
|
||||
and then on subsequent runs:
|
||||
|
||||
```
|
||||
$ docker run --rm -v $(pwd):/root \
|
||||
-v $(pwd)/universal:/Retro68-build/toolchain/universal \
|
||||
-e INTERFACES=universal \
|
||||
-i ghcr.io/autc04/retro68 /bin/bash <<"EOF"
|
||||
cd Samples/Raytracer
|
||||
rm -rf build && mkdir build && cd build
|
||||
cmake .. -DCMAKE_TOOLCHAIN_FILE=/Retro68-build/toolchain/m68k-apple-macos/cmake/retro68.toolchain.cmake
|
||||
make
|
||||
EOF
|
||||
```
|
||||
|
||||
|
||||
Sample programs
|
||||
---------------
|
||||
|
||||
|
65
docker-entrypoint.sh
Executable file
65
docker-entrypoint.sh
Executable file
@ -0,0 +1,65 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
TMPDIR=/tmp
|
||||
BUILDDIR=/Retro68-build
|
||||
|
||||
if [[ $INTERFACES == "universal" ]];
|
||||
then
|
||||
# If the universal RIncludes directory is empty, download and install the universal headers
|
||||
if [ ! "$(ls -A $BUILDDIR/toolchain/universal/RIncludes 2> /dev/null)" ]; then
|
||||
# If INTERFACESFILE is empty, exit
|
||||
if [[ -z $INTERFACESFILE ]];
|
||||
then
|
||||
echo -n "Universal interfaces not present, please specify the location of a suitable "
|
||||
echo "MacBinary DiskCopy image using the INTERFACESFILE environment variable."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BASEINTERFACESFILE=`basename $INTERFACESFILE`
|
||||
|
||||
# If INTERFACESFILE is a URL, download it first to TMPDIR. Otherwise assume the file is
|
||||
# already present and copy it to TMPDIR for installation
|
||||
if [[ $INTERFACESFILE == http* ]];
|
||||
then
|
||||
echo "Downloading Universal interfaces from MacBinary DiskCopy image $BASEINTERFACESFILE..."
|
||||
curl -s $INTERFACESFILE -o $TMPDIR/$BASEINTERFACESFILE
|
||||
echo "done"
|
||||
else
|
||||
if [[ -z $INTERFACESFILE ]];
|
||||
then
|
||||
echo "Unable to locate universal interfaces file $INTERFACESFILE"
|
||||
exit 1
|
||||
else
|
||||
echo "Using Universal intefaces from MacBinary Diskcopy image $BASEINTERFACESFILE"
|
||||
cp $INTERFACESFILE $TMPDIR/$BASEINTERFACESFILE
|
||||
fi
|
||||
fi
|
||||
|
||||
# Extract the file
|
||||
$BUILDDIR/bin/install-universal-interfaces.sh $TMPDIR $BASEINTERFACESFILE
|
||||
|
||||
# Switch to universal
|
||||
echo "Linking Universal interfaces..."
|
||||
$BUILDDIR/bin/interfaces-and-libraries.sh $BUILDDIR/toolchain $TMPDIR/InterfacesAndLibraries
|
||||
echo "done"
|
||||
else
|
||||
echo "Linking Universal interfaces..."
|
||||
|
||||
# Link to existing universal interfaces
|
||||
PREFIX=$BUILDDIR/toolchain
|
||||
. "$BUILDDIR/bin/interfaces-and-libraries.sh"
|
||||
BUILD_68K=true
|
||||
BUILD_PPC=true
|
||||
|
||||
unlinkInterfacesAndLibraries
|
||||
linkInterfacesAndLibraries "universal"
|
||||
echo "done"
|
||||
fi
|
||||
else
|
||||
echo "Using multiversal interfaces"
|
||||
fi
|
||||
|
||||
# Execute command
|
||||
exec "$@"
|
101
install-universal-interfaces.sh
Executable file
101
install-universal-interfaces.sh
Executable file
@ -0,0 +1,101 @@
|
||||
#!/bin/bash
|
||||
|
||||
#
|
||||
# install-universal-interfaces.sh
|
||||
#
|
||||
# Optionally download and attempt to install the universal interfaces from
|
||||
# a Macbinary disk image containing the Interfaces&Libraries directory
|
||||
#
|
||||
# Usage:
|
||||
# install-universal-interfaces.sh <tempdir> <filename>
|
||||
#
|
||||
# Decompress the Macbinary image at <tempdir>/<filename> into
|
||||
# <tempdir>/InterfacesAndLibraries in the correct format for
|
||||
# interfaces-and-libraries.sh.
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
TMPDIR=$1
|
||||
FILENAME=$2
|
||||
|
||||
if [[ ! -f $TMPDIR/$FILENAME ]];
|
||||
then
|
||||
echo "$TMPDIR/$FILENAME not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Decompressing $FILENAME..."
|
||||
ConvertDiskImage $TMPDIR/$FILENAME $TMPDIR/$FILENAME.img
|
||||
echo "Decompression complete"
|
||||
|
||||
# Copy over Interfaces&Libraries files
|
||||
echo "Copying Interfaces&Libraries files..."
|
||||
hmount $TMPDIR/$FILENAME.img
|
||||
|
||||
# Find Interfaces&Libraries directory, get recursive directory listing
|
||||
HFSINTERFACESANDLIBSDIR=`hls -R | grep 'Interfaces&Libraries:$'`
|
||||
IFS="$(printf '\n')"
|
||||
echo "Found Interfaces&Libraries at $HFSINTERFACESANDLIBSDIR"
|
||||
FILES=`hls -FR1 $HFSINTERFACESANDLIBSDIR`
|
||||
|
||||
UNIXINTERFACESANDLIBSDIR=$TMPDIR/InterfacesAndLibraries
|
||||
mkdir -p $UNIXINTERFACESANDLIBSDIR
|
||||
|
||||
# Parse results: first line is the HFS path, following lines contain one file
|
||||
# per line terminated by an empty line
|
||||
while IFS= read -r LINE; do
|
||||
if [[ $LINE == :* ]];
|
||||
then
|
||||
# If it starts with : then it is a HFS path
|
||||
HFSPATH=$LINE
|
||||
UNIXRELPATH=$(echo "$HFSPATH" | sed "s#$HFSINTERFACESANDLIBSDIR##g" | sed "s#:#/"#g)
|
||||
UNIXPATH="$UNIXINTERFACESANDLIBSDIR/$UNIXRELPATH"
|
||||
|
||||
# Make UNIX directory
|
||||
mkdir -p $UNIXPATH
|
||||
else
|
||||
# If it ends with : it is a directory so ignore (we will find it during the descent)
|
||||
if [[ ! $LINE == *: ]];
|
||||
then
|
||||
# If it isn't empty, it must be a filename
|
||||
if [[ ! -z $LINE ]];
|
||||
then
|
||||
HFSFULLPATH="$HFSPATH$LINE"
|
||||
UNIXFULLPATH="$UNIXPATH$LINE"
|
||||
|
||||
echo "Copying $HFSFULLPATH to $UNIXFULLPATH"
|
||||
|
||||
# PPC libraries need a resource fork, but the code in
|
||||
# interfaces-and-libraries.sh doesn't correctly detect InterfaceLib in
|
||||
# Macbinary format. Work around this for now by using Basilisk II format
|
||||
# which can be parsed by ResourceFile and still allows the filename
|
||||
# detection logic to work.
|
||||
if [[ $HFSPATH == *SharedLibraries: ]];
|
||||
then
|
||||
if [[ ! -d $UNIXPATH.rsrc ]];
|
||||
then
|
||||
mkdir $UNIXPATH.rsrc
|
||||
fi
|
||||
|
||||
# First copy as Macbinary
|
||||
hcopy -m $HFSFULLPATH $UNIXFULLPATH.bin
|
||||
|
||||
# Extract data fork using normal name
|
||||
bash -c "cd $UNIXPATH && macunpack -d $UNIXFULLPATH.bin && mv $UNIXFULLPATH.data $UNIXFULLPATH"
|
||||
|
||||
# Extract resource fork into .rsrc directory
|
||||
bash -c "cd $UNIXPATH && macunpack -r $UNIXFULLPATH.bin && mv $UNIXFULLPATH.rsrc $UNIXPATH.rsrc/$LINE"
|
||||
|
||||
# Delete original Macbinary
|
||||
rm -rf $UNIXFULLPATH.bin
|
||||
else
|
||||
hcopy -r $HFSFULLPATH $UNIXFULLPATH
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done <<< "$FILES"
|
||||
|
||||
# Unmount image
|
||||
humount
|
Loading…
x
Reference in New Issue
Block a user