#!/bin/bash -Eeux readonly TOP_DIR="$(pwd)" readonly ARCHIVES="${TOP_DIR}/archives" readonly PATCHES="${TOP_DIR}/patches" readonly SOURCES="${TOP_DIR}/sources" readonly BUILD_DIR="${TOP_DIR}/build" readonly HOST_DIR="${TOP_DIR}/host" readonly STAMP="${TOP_DIR}/stamps" readonly MAKE="make -j$(getconf NPROCESSORS_CONF)" function prepare_target { mkdir -p "${STAMP}" "${BUILD_DIR}" "${PREFIX}" [ -f "${STAMP}/prepare-target" ] && return 0 pushd "${PREFIX}" mkdir -p "bin" "etc" "lib" "m68k-amigaos" mkdir -p "os-include/lvo" "os-lib" "vbcc-include" "vbcc-lib" ln -sf "../os-include" "m68k-amigaos/include" ln -sf "../lib" "m68k-amigaos/lib" popd touch "${STAMP}/prepare-target" } function copy_non_diff { find "${PATCHES}/$1" -type f \! -name '*.diff' | while read IN ; do OUT=$(echo "$IN" | sed -e "s,$PATCHES/,$SOURCES/,g") cp "$IN" "$OUT" done } function apply_patches { for file in $(find "${PATCHES}/$1" -type f -iname '*.diff' | sort); do patch -i $file -t -p1 done } function mkdir_empty { rm -rf "$1" mkdir -p "$1" } function unpack_clean { local cmd rm -rf "$1" while (( "$#" > 1 )); do shift if grep "\.tar\.gz$" <<<"$1"; then cmd="tar -xzf" elif grep "\.tar.bz2$" <<<"$1"; then cmd="tar -xjf" elif grep "\.lha$" <<<"$1"; then cmd="lha -xgq" else cmd="false" fi ${cmd} "${ARCHIVES}/$1" done } function compare_version { python - "$1" "$2" "$3" <"${PREFIX}/bin/vasm" < "${PREFIX}/etc/vc.config" touch "${STAMP}/install-vclib" } function build_binutils { [ -f "${STAMP}/build-binutils" ] && return 0 pushd "${BUILD_DIR}" mkdir_empty "${BINUTILS}" cd "${BINUTILS}" CC="${CC} ${ARCH:-}" "${SOURCES}/${BINUTILS}/configure" \ --prefix="${PREFIX}" \ --host="i686-linux-gnu" \ --target="m68k-amigaos" make all make install install-info popd touch "${STAMP}/build-binutils" } function build_gcc { [ -f "${STAMP}/build-gcc" ] && return 0 pushd "${BUILD_DIR}" mkdir_empty "${GCC}" cd "${GCC}" "${SOURCES}/${GCC}/configure" \ --prefix="${PREFIX}" \ --target="m68k-amigaos" \ --enable-languages=c \ --with-headers="${SOURCES}/${IXEMUL}/include" \ ${GCC_CONFIGURE_OPTS[*]} make all ${FLAGS_FOR_TARGET[*]} make install ${FLAGS_FOR_TARGET[*]} popd touch "${STAMP}/build-gcc" } function build_gpp { [ -f "${STAMP}/build-gpp" ] && return 0 local GPP="${GCC/gcc/g++}" pushd "${BUILD_DIR}" mkdir_empty "${GPP}" cd "${GPP}" "${SOURCES}/${GCC}/configure" \ --prefix="${PREFIX}" \ --target="m68k-amigaos" \ --enable-languages=c++ \ --with-headers="${SOURCES}/${IXEMUL}/include" \ ${GCC_CONFIGURE_OPTS[*]} make all ${FLAGS_FOR_TARGET[*]} make install ${FLAGS_FOR_TARGET[*]} popd touch "${STAMP}/build-gpp" } function process_ndk { [ -f "${STAMP}/process-ndk" ] && return 0 pushd "${BUILD_DIR}" rm -rf "${SFDC}" cp -a "${SOURCES}/${SFDC}" "${SFDC}" cd "${SFDC}" ./configure \ --prefix="${PREFIX}" make && make install popd pushd "${PREFIX}/os-include" cp -av "${SOURCES}/${NDK}/Include/include_h/"* . cp -av "${SOURCES}/${NDK}/Include/include_i/"* . for file in ${SOURCES}/${NDK}/Include/sfd/*.sfd; do base=$(basename ${file%_lib.sfd}) sfdc --target=m68k-amigaos --mode=proto \ --output="proto/${base}.h" $file sfdc --target=m68k-amigaos --mode=macros \ --output="inline/${base}.h" $file sfdc --target=m68k-amigaos --mode=lvo \ --output="lvo/${base}.i" $file done popd pushd "${PREFIX}/os-lib" cp -av "${SOURCES}/${NDK}/Include/linker_libs/"* . popd touch "${STAMP}/process-ndk" } function install_libamiga { [ -f "${STAMP}/install-libamiga" ] && return 0 pushd "${PREFIX}" cp -av "${SOURCES}/${LIBAMIGA}/lib" . popd touch "${STAMP}/install-libamiga" } function build_libnix { [ -f "${STAMP}/build-libnix" ] && return 0 pushd "${BUILD_DIR}" mkdir_empty "${LIBNIX}" cd "${LIBNIX}" "${SOURCES}/${LIBNIX}/configure" \ --prefix="${PREFIX}" \ --host="i686-linux-gnu" \ --target="m68k-amigaos" make all \ CC=m68k-amigaos-gcc \ CPP="m68k-amigaos-gcc -E" \ AR=m68k-amigaos-ar \ AS=m68k-amigaos-as \ RANLIB=m68k-amigaos-ranlib \ LD=m68k-amigaos-ld \ MAKEINFO=: [ -f "${PREFIX}/guide" ] && rm -f "${PREFIX}/guide" make install MAKEINFO=: popd touch "${STAMP}/build-libnix" } function build_libm { [ -f "${STAMP}/build-libm" ] && return 0 pushd "${BUILD_DIR}" mkdir_empty "${LIBM}" cd "${LIBM}" CC=m68k-amigaos-gcc \ AR=m68k-amigaos-ar \ CFLAGS="-noixemul" \ RANLIB=m68k-amigaos-ranlib \ "${SOURCES}/${LIBM}/configure" \ --prefix="${PREFIX}" \ --host="i686-linux-gnu" \ --build="m68k-amigaos" make && make install popd touch "${STAMP}/build-libm" } function build_ixemul { [ -f "${STAMP}/build-ixemul" ] && return 0 pushd "${BUILD_DIR}" mkdir_empty "${IXEMUL}" cd "${IXEMUL}" CC=m68k-amigaos-gcc \ CFLAGS="-noixemul -I${PREFIX}/os-include" \ AR=m68k-amigaos-ar \ RANLIB=m68k-amigaos-ranlib \ "${SOURCES}/${IXEMUL}/configure" \ --prefix="${PREFIX}" \ --host="i686-linux-gnu" \ --target="m68k-amigaos" make MAKEINFO=: all make MAKEINFO=: install popd touch "${STAMP}/build-ixemul" } function build { source "${TOP_DIR}/bootstrap.conf" # On 64-bit architecture GNU Assembler crashes writing out an object, due to # (probably) miscalculated structure sizes. There could be some other bugs # lurking there in 64-bit mode, but I have little incentive chasing them. # Just compile everything in 32-bit mode and forget about the issues. if [ "$(uname -m)" == "x86_64" ]; then ARCH="-m32" fi # Make sure we always choose known compiler (from the distro) and not one # in user's path that could shadow the original one. CC="$(which gcc)" CXX="$(which g++)" # Define extra options for gcc's configure script. if [ "${VERSION}" != "4" ]; then # Older gcc compilers (i.e. 2.95.3 and 3.4.6) have to be tricked into # thinking that they're being compiled on IA-32 architecture. CC="${CC} ${ARCH:-}" CXX="${CXX} ${ARCH:-}" GCC_CONFIGURE_OPTS+=("--host=i686-linux-gnu" \ "--build=i686-linux-gnu") else # GCC 4.x requires some extra dependencies to be supplied. GCC_CONFIGURE_OPTS+=("--with-gmp=${HOST_DIR}" \ "--with-mpfr=${HOST_DIR}" \ "--with-mpc=${HOST_DIR}" \ "--disable-shared") fi # Take over the path -- to preserve hermetic build. export PATH="/opt/local/bin:/usr/local/bin:/usr/bin:/bin" export CC CXX readonly FLAGS_FOR_TARGET=( \ "MAKEINFO=makeinfo" \ "CFLAGS_FOR_TARGET=-noixemul" \ "AR_FOR_TARGET=${PREFIX}/bin/m68k-amigaos-ar" \ "AS_FOR_TARGET=${PREFIX}/bin/m68k-amigaos-as" \ "LD_FOR_TARGET=${PREFIX}/bin/m68k-amigaos-ld" \ "NM_FOR_TARGET=${PREFIX}/bin/m68k-amigaos-nm" \ "OBJCOPY_FOR_TARGET=${PREFIX}/bin/m68k-amigaos-objcopy" \ "OBJDUMP_FOR_TARGET=${PREFIX}/bin/m68k-amigaos-objdump" \ "RANLIB_FOR_TARGET=${PREFIX}/bin/m68k-amigaos-ranlib") prepare_target unpack_sources build_tools export PATH="${HOST_DIR}/bin:${PATH}" build_vasm build_vlink build_vbcc install_vclib build_binutils build_gcc export PATH="${PREFIX}/bin:${PATH}" process_ndk install_libamiga build_libnix build_libm build_gpp # TODO: Ixemul is not suited for cross compilation very well. The build # process compiles some tools with cross compiler and tries to run them # locally. #build_ixemul } function main { PREFIX="${TOP_DIR}/target" VERSION="2" local action="build" while [ -n "${1:-}" ]; do case "$1" in --prefix=*) PREFIX=${1#*=} ;; --version=*) VERSION=${1#*=} ;; --*) echo "Unknown option: $1" exit 1 ;; *) break ;; esac shift done if [ -n "${1:-}" ]; then action="$1" fi case "${action}" in "build") build ;; "clean") for dir in ${SOURCES} ${BUILD_DIR} ${HOST_DIR} ${STAMP}; do rm -rf "${dir}" done ;; *) echo "Unknown action '${action}'!" exit 1 ;; esac } main "$@"