diff --git a/.gitignore b/.gitignore index 95dacef55d..7dd121f2ae 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ Universal Headers* .*.swp CMakeLists.txt.user .finf +InterfacesAndLibraries \ No newline at end of file diff --git a/PEFTools/CMakeLists.txt b/PEFTools/CMakeLists.txt index 243d7a7073..d628632bb6 100644 --- a/PEFTools/CMakeLists.txt +++ b/PEFTools/CMakeLists.txt @@ -3,9 +3,11 @@ set(CMAKE_CXX_FLAGS "--std=c++11 -Wall -Werror=return-type -Wno-multichar") find_package(Boost COMPONENTS filesystem system REQUIRED) add_executable(MakePEF MakePEF.cc rs6000.h PEF.h) +target_include_directories(MakePEF PRIVATE ${CMAKE_INSTALL_PREFIX}/include) add_executable(MakeImport MakeImport.cc PEF.h) target_link_libraries(MakeImport ResourceFiles ${Boost_LIBRARIES}) target_include_directories(MakeImport PRIVATE ${Boost_INCLUDE_DIR}) +target_include_directories(MakeImport PRIVATE ${CMAKE_INSTALL_PREFIX}/include) install(TARGETS MakePEF MakeImport RUNTIME DESTINATION bin) diff --git a/PEFTools/PEF.h b/PEFTools/PEF.h index f37917ba33..e4fcec35ae 100644 --- a/PEFTools/PEF.h +++ b/PEFTools/PEF.h @@ -40,7 +40,7 @@ typedef void *LogicalAddress; typedef struct {} FSSpec, *FSSpecPtr; /* Definitions for PEF, from Apple's Universal Interfaces */ -#include "../CIncludes/PEFBinaryFormat.h" +#include "PEFBinaryFormat.h" /* Deal with differences between versions of PEFBinaryFormat.h */ #ifndef PEFRelocComposeSetPosition_1st diff --git a/build-toolchain.sh b/build-toolchain.sh old mode 100644 new mode 100755 index adca21b845..2daa5cb2da --- a/build-toolchain.sh +++ b/build-toolchain.sh @@ -1,3 +1,4 @@ +#!/bin/bash # Copyright 2014 Wolfgang Thaller. # # This file is part of Retro68. @@ -22,28 +23,56 @@ SRC=$(cd `dirname $0` && pwd -P) PREFIX=`pwd -P`/toolchain/ BINUTILS=`pwd -P`/binutils-build -CMAKEONLY=false +##################### Command-line Options + +SKIP_THIRDPARTY=false BUILD_68K=true BUILD_PPC=true BUILD_CARBON=true +CLEAN_AFTER_BUILD=false +HOST_CMAKE_FLAGS=() + +function usage() +{ + echo "Usage: $0 [options]" + echo + echo "Options: " + echo " --skip-thirdparty do not rebuild gcc & third party libraries" + echo " --no-68k disable support for 68K Macs" + echo " --no-ppc disable classic PowerPC CFM support" + echo " --no-carbon disable Carbon CFM support" + echo " --clean-after-build remove intermediate build files right after building" + echo " --help show this help message" +} for ARG in $*; do case $ARG in - --cmakeonly) - CMAKEONLY=true + --skip-thirdparty) + SKIP_THIRDPARTY=true ;; --no-68k) - BUILD_68K=false + BUILD_68K=false ;; --no-ppc) - BUILD_PPC=false - BUILD_CARBON=false + BUILD_PPC=false + BUILD_CARBON=false ;; --no-carbon) - BUILD_CARBON=false + BUILD_CARBON=false + ;; + --clean-after-build) + CLEAN_AFTER_BUILD=true + ;; + --host-cxx-compiler=*) + HOST_CMAKE_FLAGS[${#HOST_CMAKE_FLAGS}]="-DCMAKE_CXX_COMPILER=${ARG#*=}" + ;; + --help) + usage + exit 0 ;; *) echo "unknown option $ARG" + usage exit 1 ;; esac @@ -57,148 +86,408 @@ if [ $BUILD_PPC != false ]; then ARCHS="$ARCHS powerpc" fi +##################### Sanity checks -if [ $CMAKEONLY != true ]; then +if [ `pwd -P` == "$SRC" ]; then + echo "Please do not invoke build-toolchain.sh from the source directory." + echo "Instead, create a separate build directory:" + echo " cd .." + echo " mkdir Retro68-build" + echo " ../`basename $SRC`/build-toolchain.sh" + exit 1 +fi -# Remove old install tree -rm -rf toolchain -mkdir -p toolchain -export CPPFLAGS="-I/usr/local/include" -export LDFLAGS="-L/usr/local/lib" - -if [ $BUILD_68K != false ]; then +if [ $SKIP_THIRDPARTY != false ]; then + MISSING=false + if [ ! -d toolchain ]; then MISSING=true; fi + if [ $BUILD_68K != false ]; then + if [ ! -d binutils-build ]; then MISSING=true; fi + if [ ! -d gcc-build ]; then MISSING=true; fi + if [ ! -d elf2flt-build ]; then MISSING=true; fi + fi + if [ $BUILD_PPC != false ]; then + if [ ! -d binutils-build-ppc ]; then MISSING=true; fi + if [ ! -d gcc-build-ppc ]; then MISSING=true; fi + fi + if [ ! -d hfsutils ]; then MISSING=true; fi -export "CFLAGS=-Wno-error" - -# Build binutils for 68K -mkdir -p binutils-build -cd binutils-build -$SRC/binutils/configure --target=m68k-apple-macos --prefix=$PREFIX --disable-doc -make -j8 -make install -cd .. - -# Build gcc for 68K -mkdir -p gcc-build -cd gcc-build -export target_configargs="--disable-nls --enable-libstdcxx-dual-abi=no" -$SRC/gcc/configure --target=m68k-apple-macos --prefix=$PREFIX --enable-languages=c,c++ --with-arch=m68k --with-cpu=m68000 --disable-libssp MAKEINFO=missing -# There seems to be a build failure in parallel builds; ignore any errors and try again without -j8. -make -j8 || make -make install -unset target_configargs -cd .. - -unset CFLAGS - + if [ $MISSING != false ]; then + echo "Not all third-party components have been built yet, ignoring --skip-thirdparty." + SKIP_THIRDPARTY=false + fi fi -if [ $BUILD_PPC != false ]; then +##################### Locate and check Interfaces & Libraries -# Build binutils for PPC -mkdir -p binutils-build-ppc -cd binutils-build-ppc -$SRC/binutils/configure --target=powerpc-apple-macos --prefix=$PREFIX --disable-doc -make -j8 -make install -cd .. +if [ -d "$SRC/CIncludes" -o -d "$SRC/RIncludes" ]; then + echo + echo "### WARNING:" + echo "### Different from previous versions, Retro68 now expects to find" + echo "### header files and libraries inside the InterfacesAndLibraries diretory." + echo +fi -# Build gcc for PPC -mkdir -p gcc-build-ppc -cd gcc-build-ppc -export target_configargs="--disable-nls --enable-libstdcxx-dual-abi=no" -$SRC/gcc/configure --target=powerpc-apple-macos --prefix=$PREFIX --enable-languages=c,c++ --disable-libssp --disable-lto MAKEINFO=missing -make -j8 -make install -unset target_configargs -cd .. +INTERFACES_DIR="$SRC/InterfacesAndLibraries" +function locateInterfaceThing() +{ + local varname=$1 + local name=$2 + printf "Searching for %-25s" "$name..." + local found=`find "$INTERFACES_DIR" -name ".*" -prune -o -name $name -print` + if [ -n "$found" ]; then + eval "$varname=\$found" + echo ${found#$INTERFACES_DIR/} + return 0 # success + else + echo "NOT FOUND" + return 1 # failure + fi +} + +function explainInterfaces() +{ + echo "Please get a copy of Apple's Universal Interfaces & Libraries, " + echo "version 3.x, and place it in the InterfacesAndLibraries directory inside" + echo "the Retro68 source directory." + echo + echo "The exact directory layout does not matter, but there has to be" + echo " - a directory with C header files (usually \"CIncludes\")" + echo " - a directory with Rez header files (usually \"RIncludes\")" + echo " - (for 68K) a directory containing Interface.o (usually \"Libraries\")" + echo " - (for PPC) a directory containing InterfaceLib (usually \"SharedLibraries\")" + echo " - (for Carbon) Carbon.h and CarbonLib, in the same directories" + echo + echo "The Interfaces&Libraries folder from Apple's last MPW release (MPW 3.5 " + echo "aka MPW GM 'Golden Master') is known to work." + exit 1 +} + +echo "Looking for various files in $INTERFACES_DIR/..." + +if locateInterfaceThing CONDITIONALMACROS_H ConditionalMacros.h; then + CINCLUDES=`dirname "$CONDITIONALMACROS_H"` +else + echo "Could not find ConditionalMacros.h anywhere inside InterfaceAndLibraries/" + echo + explainInterfaces +fi + +if locateInterfaceThing CONDITIONALMACROS_R ConditionalMacros.r; then + RINCLUDES=`dirname "$CONDITIONALMACROS_R"` +else + echo "Could not find ConditionalMacros.r anywhere inside InterfaceAndLibraries/" + echo + explainInterfaces fi if [ $BUILD_68K != false ]; then -# Install elf.h (for elf2flt) -mkdir -p $PREFIX/include -cp $SRC/elf.h $PREFIX/include/ + if locateInterfaceThing INTERFACE_O Interface.o; then + true + else + echo "Could not find Interface.o anywhere inside InterfaceAndLibraries/" + echo "(This file is required for 68K support only)" + echo + explainInterfaces + fi -# Build elf2flt -export "CFLAGS=-I${SRC}/binutils/include -I../toolchain/include" -export "CPPFLAGS=$CFLAGS" -mkdir -p elf2flt-build -cd elf2flt-build -$SRC/elf2flt/configure --target=m68k-apple-macos --prefix=$PREFIX --with-binutils-build-dir=$BINUTILS -make -j8 TOOLDIR=$PREFIX/bin -make install -unset CFLAGS -unset CPPFLAGS -cd .. - -fi - -# Build hfsutil -mkdir -p $PREFIX/lib -mkdir -p $PREFIX/man/man1 -rm -rf hfsutils -cp -r $SRC/hfsutils . -cd hfsutils -./configure --prefix=$PREFIX --enable-devlibs -make -make install -cd .. - -# Install Universal Interfaces -for arch in $ARCHS; do - sh "$SRC/prepare-headers.sh" "$SRC/CIncludes" toolchain/${arch}-apple-macos/include - mkdir -p toolchain/${arch}-apple-macos/RIncludes - sh "$SRC/prepare-rincludes.sh" "$SRC/RIncludes" toolchain/${arch}-apple-macos/RIncludes -done - -if [ $BUILD_PPC != false ]; then - cp $SRC/ImportLibraries/*.a toolchain/powerpc-apple-macos/lib/ -fi - -fi # CMAKEONLY - -# Build host-based components -mkdir -p build-host -cd build-host -cmake ${SRC} -DCMAKE_INSTALL_PREFIX=$PREFIX -cd .. -make -C build-host install - - # create an empty libretrocrt.a so that cmake's compiler test doesn't fail -for arch in $ARCHS; do - $PREFIX/bin/${arch}-apple-macos-ar cqs $PREFIX/${arch}-apple-macos/lib/libretrocrt.a -done - # the real libretrocrt.a is built and installed by `make -C build-target install` later - -if [ $BUILD_68K != false ]; then -# Build target-based components for 68K -mkdir -p build-target -cd build-target -cmake ${SRC} -DCMAKE_TOOLCHAIN_FILE=../build-host/cmake/intree.toolchain.cmake \ - -DCMAKE_BUILD_TYPE=Release -cd .. -make -C build-target install fi if [ $BUILD_PPC != false ]; then -# Build target-based components for PPC -mkdir -p build-target-ppc -cd build-target-ppc -cmake ${SRC} -DCMAKE_TOOLCHAIN_FILE=../build-host/cmake/intreeppc.toolchain.cmake \ - -DCMAKE_BUILD_TYPE=Release -cd .. -make -C build-target-ppc install + + if locateInterfaceThing INTERFACELIB InterfaceLib; then + SHAREDLIBRARIES=`dirname "$INTERFACELIB"` + else + echo "Could not find InterfaceLib anywhere inside InterfaceAndLibraries/" + echo "(This file is required for PowerPC support only)" + echo + explainInterfaces + fi + fi if [ $BUILD_CARBON != false ]; then -# Build target-based components for Carbon -mkdir -p build-target-carbon -cd build-target-carbon -cmake ${SRC} -DCMAKE_TOOLCHAIN_FILE=../build-host/cmake/intreecarbon.toolchain.cmake \ - -DCMAKE_BUILD_TYPE=Release -cd .. -make -C build-target-carbon install + if locateInterfaceThing CARBON_H Carbon.h; then + carbondir=`dirname "$CARBON_H"` + if [ "$carbondir" != "$CINCLUDES" ]; then + echo "Carbon.h found, but not in the same directory as ConditionalMacros.h." + echo "This is confusing." + echo + explainInterfaces + fi + else + echo "Could not find Carbon.h anywhere inside InterfaceAndLibraries/" + echo "(This file is required for Carbon support only)" + echo + explainInterfaces + fi + if locateInterfaceThing CARBONLIB CarbonLib; then + carbondir=`dirname "$CARBONLIB"` + if [ "$carbondir" != "$SHAREDLIBRARIES" ]; then + echo "Carbon.h found, but not in the same directory as InterfaceLib." + echo "This is confusing." + echo + explainInterfaces + fi + else + echo "Could not find CarbonLib anywhere inside InterfaceAndLibraries/" + echo "(This file is required for Carbon support only)" + echo + explainInterfaces + fi +fi + +##################### Third-Party components: binutils, gcc, elf2flt, hfsutils + +if [ $SKIP_THIRDPARTY != true ]; then + + # Remove old install tree + rm -rf toolchain + mkdir -p toolchain + + # Components needed for targeting 68K: binutils, gcc, elf2flt + if [ $BUILD_68K != false ]; then + + # present-day Mac users are likely to install dependencies + # in /usr/local via the homebrew package manager + export CPPFLAGS="-I/usr/local/include" + export LDFLAGS="-L/usr/local/lib" + + export "CFLAGS=-Wno-error" + + # Build binutils for 68K + mkdir -p binutils-build + cd binutils-build + $SRC/binutils/configure --target=m68k-apple-macos --prefix=$PREFIX --disable-doc + make -j8 + make install + cd .. + + # Build gcc for 68K + mkdir -p gcc-build + cd gcc-build + export target_configargs="--disable-nls --enable-libstdcxx-dual-abi=no" + $SRC/gcc/configure --target=m68k-apple-macos --prefix=$PREFIX \ + --enable-languages=c,c++ --with-arch=m68k --with-cpu=m68000 \ + --disable-libssp MAKEINFO=missing + # There seems to be a build failure in parallel builds; ignore any errors and try again without -j8. + make -j8 || make + make install + unset target_configargs + cd .. + + unset CPPFLAGS + unset LDFLAGS + unset CFLAGS + + # Install elf.h (for elf2flt) + mkdir -p $PREFIX/include + cp $SRC/elf.h $PREFIX/include/ + + # Build elf2flt + export "CFLAGS=-I${SRC}/binutils/include -I../toolchain/include" + export "CPPFLAGS=$CFLAGS" + mkdir -p elf2flt-build + cd elf2flt-build + $SRC/elf2flt/configure --target=m68k-apple-macos --prefix=$PREFIX \ + --with-binutils-build-dir=$BINUTILS + make -j8 TOOLDIR=$PREFIX/bin + make install + cd .. + + unset CFLAGS + unset CPPFLAGS + + if [ $CLEAN_AFTER_BUILD != false ]; then + rm -rf binutils-build + rm -rf gcc-build + rm -rf elf2flt-build + fi + + fi + + # Components needed for targeting PPC (including Carbon): binutils, gcc + if [ $BUILD_PPC != false ]; then + + # present-day Mac users are likely to install dependencies + # in /usr/local via the homebrew package manager + export CPPFLAGS="-I/usr/local/include" + export LDFLAGS="-L/usr/local/lib" + + export "CFLAGS=-Wno-error" + + # Build binutils for PPC + mkdir -p binutils-build-ppc + cd binutils-build-ppc + $SRC/binutils/configure --target=powerpc-apple-macos --prefix=$PREFIX --disable-doc + make -j8 + make install + cd .. + + # Build gcc for PPC + mkdir -p gcc-build-ppc + cd gcc-build-ppc + export target_configargs="--disable-nls --enable-libstdcxx-dual-abi=no" + $SRC/gcc/configure --target=powerpc-apple-macos --prefix=$PREFIX \ + --enable-languages=c,c++ --disable-libssp --disable-lto MAKEINFO=missing + make -j8 + make install + unset target_configargs + cd .. + + unset CPPFLAGS + unset LDFLAGS + unset CFLAGS + + if [ $CLEAN_AFTER_BUILD != false ]; then + rm -rf binutils-build-ppc + rm -rf gcc-build-ppc + fi + fi + + # Build hfsutil + mkdir -p $PREFIX/lib + mkdir -p $PREFIX/man/man1 + rm -rf hfsutils + cp -r $SRC/hfsutils . + cd hfsutils + ./configure --prefix=$PREFIX --enable-devlibs + make + make install + cd .. + + if [ $CLEAN_AFTER_BUILD != false ]; then + rm -rf hfsutils + fi + +fi # SKIP_THIRDPARTY + +##################### Build host-based components: MakePEF, MakeImport, ConvertObj, Rez, ... + +# Copy PEFBinaryFormat.h from Universal Interfaces, needed by MakePEF & MakeImport +(export LANG=en; sed 's/\r$//' < "$CINCLUDES/PEFBinaryFormat.h" | tr '\r' '\n' > "toolchain/include/PEFBinaryFormat.h") + +mkdir -p build-host +cd build-host +cmake ${SRC} -DCMAKE_INSTALL_PREFIX=$PREFIX -DCMAKE_BUILD_TYPE=Debug "${HOST_CMAKE_FLAGS[@]}" +cd .. +cmake --build build-host --target install + + # make tools (such as MakeImport and the compilers) available for later commands +export PATH=$PREFIX/bin:$PATH + +##################### Setup Interfaces & Libraries + +echo "Preparing CIncludes..." +rm -rf "toolchain/CIncludes" +mkdir "toolchain/CIncludes" +sh "$SRC/prepare-headers.sh" "$CINCLUDES" "toolchain/CIncludes" + +echo "Preparing RIncludes..." +rm -rf "toolchain/RIncludes" +mkdir "toolchain/RIncludes" +sh "$SRC/prepare-rincludes.sh" "$RINCLUDES" "toolchain/RIncludes" + +# remove old symlinks in toolchain/*-apple-macos/include/ +# and link files from toolchain/CIncludes +function linkheaders() +{ + find "$1" -lname "../../CIncludes/*" -delete + (cd "$1" && find "../../CIncludes/" -exec ln -s {} . \;) +} + +echo "Creating Symlinks for CIncludes and RIncludes..." + +if [ $BUILD_68K != false ]; then + ln -sf ../RIncludes toolchain/m68k-apple-macos/RIncludes + linkheaders toolchain/m68k-apple-macos/include +fi + +if [ $BUILD_PPC != false ]; then + ln -sf ../RIncludes toolchain/powerpc-apple-macos/RIncludes + linkheaders toolchain/powerpc-apple-macos/include +fi + + +# if [ $BUILD_PPC != false ]; then +# echo "Copying PowerPC import libraries..." +# cp $SRC/ImportLibraries/*.a toolchain/powerpc-apple-macos/lib/ +#fi + +if [ $BUILD_PPC != false ]; then + echo "Building PowerPC import libraries..." + for shlib in "${SHAREDLIBRARIES}/"*; do + libname=`basename "$shlib"` + implib=lib${libname}.a + printf " %30s => %-30s\n" ${libname} ${implib} + MakeImport "$shlib" "toolchain/powerpc-apple-macos/lib/$implib" + done +fi + + + + # If this is the first build, + # create an empty libretrocrt.a for each platform so that cmake's compiler + # test doesn't fail +for arch in $ARCHS; do + if [ ! -e "$PREFIX/${arch}-apple-macos/lib/libretrocrt.a" ]; then + echo "Creating dummy libretrocrt.a for $arch..." + "$PREFIX/bin/${arch}-apple-macos-ar" cqs "$PREFIX/${arch}-apple-macos/lib/libretrocrt.a" + fi +done + # the real libretrocrt.a is built and installed by + # `cmake --build build-target --target install` later + + ##################### Setup Interfaces & Libraries + +if [ $BUILD_68K != false ]; then + echo "Building target libraries and samples for 68K..." + # Build target-based components for 68K + mkdir -p build-target + cd build-target + + INTERFACE_O=`find "$SRC/InterfacesAndLibraries" -name ".*" -prune -o -name Interface.o -print` + + cmake ${SRC} -DCMAKE_TOOLCHAIN_FILE=../build-host/cmake/intree.toolchain.cmake \ + -DCMAKE_BUILD_TYPE=Release \ + "-DINTERFACE_O=${INTERFACE_O}" + cd .. + cmake --build build-target --target install + +fi + +if [ $BUILD_PPC != false ]; then + echo "Building target libraries and samples for PowerPC..." + # Build target-based components for PPC + mkdir -p build-target-ppc + cd build-target-ppc + cmake ${SRC} -DCMAKE_TOOLCHAIN_FILE=../build-host/cmake/intreeppc.toolchain.cmake \ + -DCMAKE_BUILD_TYPE=Release + cd .. + cmake --build build-target-ppc --target install +fi + +if [ $BUILD_CARBON != false ]; then + echo "Building target libraries and samples for Carbon..." + # Build target-based components for Carbon + mkdir -p build-target-carbon + cd build-target-carbon + cmake ${SRC} -DCMAKE_TOOLCHAIN_FILE=../build-host/cmake/intreecarbon.toolchain.cmake \ + -DCMAKE_BUILD_TYPE=Release + cd .. + cmake --build build-target-carbon --target install +fi + +echo +echo "Done building Retro68." +if [ $BUILD_68K != false ]; then + echo "You will find 68K sample appliations in build-target/Samples/." +fi +if [ $BUILD_PPC != false ]; then + echo "You will find PowerPC sample appliations in build-target-ppc/Samples/." +fi +if [ $BUILD_CARBON != false ]; then + echo "You will find Carbon sample appliations in build-target-carbon/Samples/." fi diff --git a/libretro/CMakeLists.txt b/libretro/CMakeLists.txt index 79ab4f1aa9..c11f8635f0 100644 --- a/libretro/CMakeLists.txt +++ b/libretro/CMakeLists.txt @@ -24,11 +24,19 @@ cmake_minimum_required(VERSION 2.8) if(CMAKE_SYSTEM_NAME MATCHES Retro68) + find_program(CONVERT_OBJ ConvertObj PATH "${CMAKE_INSTALL_PREFIX}/../bin/") + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Interface.s + COMMAND ${CONVERT_OBJ} ${INTERFACE_O} > ${CMAKE_CURRENT_BINARY_DIR}/Interface.s + ) + enable_language(ASM) + set(ARCH_FILES Retro68Runtime.h start.c relocate.c - glue.c + # glue.c + ${CMAKE_CURRENT_BINARY_DIR}/Interface.s qdglobals.c Retro68.r Retro68APPL.r