#! /bin/sh
#
# This file is part of Owl.
#
# Copyright © 2019-2021 Sergey Bugaev <bugaevc@gmail.com>
#
# Owl is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published
# by the Free Software Foundation, either version 3 of the License,
# or (at your option) any later version.
#
# Owl is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with Owl.  If not, see <http://www.gnu.org/licenses/>.

# These are the environment variables that
# the user can set to affect this script's
# output.
CC="${CC:-cc}"
CFLAGS="${CFLAGS:-}"
LDFLAGS="${LDFLAGS:-}"
if [ "$(uname)" = Darwin ]; then
    # Use -weak_framework for IOSurface to support macOS 10.5 (Leopard)
    # where IOSurface is not available. The code uses compile-time guards
    # (OWL_HAS_IOSURFACE) to avoid calling IOSurface APIs on older systems.
    # IOKit provides the idle-inhibit power assertions (OWL_HAS_IOPM,
    # 10.6+); CoreServices provides the UpdateSystemActivity() fallback
    # used pre-10.6. Both frameworks exist on every supported OS version,
    # so they're linked normally rather than weakly.
    LIBS=${LIBS:-"-l wayland-server -framework Cocoa -framework OpenGL -weak_framework IOSurface -framework IOKit -framework CoreServices"}
else
    LIBS=${LIBS:-"-l wayland-server -l gnustep-gui -l gnustep-base -l objc"}
fi

# Find the root directory based on where this
# script itself is located. It is expected that
# the current directory is the build directory.
root=$(dirname $0)
echo "Owl root directory detected as $root" >&2

if [ "$root" = . ]; then
    echo "Refusing an in-source build" >&2
    echo "Please create a separate build directory" >&2
    exit 1
fi

# Redirect this script's standard output to Makefile.
# All the following commands inherit it implicitly.
exec > Makefile

echo "# This makefile was generated by running $0 $*"

# Essentially forward-declare the default target.
# Makefile uses the first target in the Makefile
# as the default target to make; but we would like
# to only write out the rule for the default target
# once we visit all the individual targets, if
# only to prepare the list of dependencies of the
# default target. So define a default target named
# "all" that forwards to a target named "app" that
# we will define later near the end.
echo "all: app"
echo

# Find the list of source code directories.
dirs=$(ls "$root/Sources" | grep -Fv .)

includes="-I Protocol/ -I $root/Sources/Protocol/"
headers=""
objs=""
generated=""
resources=""

# Go over the Wayland protocols, generate header and source
# files for them, and build those source files.
mkdir -p Protocol
for xml in $(ls "$root/Sources/Protocol" | grep -F .xml); do
    header="Protocol/${xml%.xml}.h"
    code="Protocol/${xml%.xml}.c"
    obj="Protocol/${xml%.xml}.o"
    headers="$headers $header"
    objs="$objs $obj"
    generated="$generated $header $code"
    echo "$header: $root/Sources/Protocol/$xml"
    echo '	'"wayland-scanner server-header $root/Sources/Protocol/$xml $header"
    echo
    echo "$code: $root/Sources/Protocol/$xml"
    echo '	'"wayland-scanner private-code $root/Sources/Protocol/$xml $code"
    echo
    echo "$obj: $code"
    echo '	'"$CC $code \$(CFLAGS) -c -o $obj"
    echo
done

# Go over MIG definitions, generate header and source
# files for them, and build those source files.
if [ "$(uname)" = Darwin ]; then
    mig_headers=$(echo "$root"/Sources/Protocol/*.h)
    headers="$headers $mig_headers"
    for defs in $(ls "$root/Sources/Protocol" | grep -F .defs); do
        header="Protocol/${defs%.defs}.h"
        code="Protocol/${defs%.defs}.c"
        obj="Protocol/${defs%.defs}.o"
        headers="$headers $header"
        objs="$objs $obj"
        generated="$generated $header $code"
        echo "$header: $root/Sources/Protocol/$defs"
        echo '	'"mig -sheader $header -server /dev/null -header /dev/null -user /dev/null $root/Sources/Protocol/$defs"
        echo
        echo "$code: $root/Sources/Protocol/$defs"
        echo '	'"mig -server $code -header /dev/null -user /dev/null $root/Sources/Protocol/$defs"
        echo
        echo "$obj: $code $mig_headers"
        echo '	'"$CC $code \$(CFLAGS) -I $root/Sources/Protocol -c -o $obj"
        echo
    done
fi

# Collect the include directories and headers. Also create the
# corresponding directories right now, at configure time.
for dir in "" $dirs; do
    if [ "$dir" = Mach ] && [ "$(uname)" != Darwin ]; then
        continue
    fi
    includes="$includes -I $root/Sources/$dir"
    headers=$(echo "$headers" "$root/Sources/$dir"/*.h)
    if [ ! -z $dir ]; then
        mkdir -p $dir
    fi
done

echo "INCLUDES = $includes"
echo "HEADERS = $headers"
echo
echo "CFLAGS = $CFLAGS"
echo "LDFLAGS = $LDFLAGS $LIBS"
echo


for dir in $dirs; do
    # Skip Mach/ unless running on Darwin.
    if [ "$dir" = Mach ] && [ "$(uname)" != Darwin ]; then
        continue
    fi
    for file in $(ls "$root/Sources/$dir" | grep -F .m); do
        obj=${file%.m}.o
        objs="$objs $dir/$obj"
        echo "$dir/$obj: $root/Sources/$dir/$file \$(HEADERS)"
        echo '	'"$CC $root/Sources/$dir/$file \$(INCLUDES) \$(CFLAGS) -c -o $dir/$obj"
        echo
    done
done

echo "OBJS = $objs"

if [ "$(uname)" != Darwin ]; then
    contents_dir=""
else
    contents_dir="/Contents"
fi

mkdir -p Owl.app$contents_dir/Resources/English.lproj

for res in keymap.xkb Owl.icns; do
    resources="$resources Owl.app$contents_dir/Resources/$res"
    echo "Owl.app$contents_dir/Resources/$res: $root/Resources/$res"
    echo '	'"cp $root/Resources/$res Owl.app$contents_dir/Resources/$res"
    echo
done

if [ "$(uname)" != Darwin ]; then
    # Just copy the xibs over
    for xib in $(ls "$root/Resources/English.lproj" | grep -F .xib); do
        resources="$resources Owl.app/Resources/English.lproj/$xib"
        echo "Owl.app/Resources/English.lproj/$xib: $root/Resources/English.lproj/$xib"
        echo '	'"cp $root/Resources/English.lproj/$xib Owl.app/Resources/English.lproj/$xib"
        echo
    done
else
    for xib in $(ls "$root/Resources/English.lproj" | grep -F .xib); do
        nib="${xib%.xib}.nib"
        resources="$resources Owl.app$contents_dir/Resources/English.lproj/$nib"
        echo "Owl.app$contents_dir/Resources/English.lproj/$nib: $root/Resources/English.lproj/$xib"
        echo '	'"ibtool --compile Owl.app$contents_dir/Resources/English.lproj/$nib $root/Resources/English.lproj/$xib"
        echo
    done
fi

if [ "$(uname)" != Darwin ]; then
    resources="$resources Owl.app/Resources/Info-gnustep.plist"
    echo "Owl.app/Resources/Info-gnustep.plist: $root/Resources/Owl-Info-gnustep.plist"
    echo '	'"cp $root/Resources/Owl-Info-gnustep.plist Owl.app/Resources/Info-gnustep.plist"
    echo
else
    resources="$resources Owl.app$contents_dir/Info.plist"
    echo "Owl.app$contents_dir/Info.plist: $root/Resources/Owl-Info.plist"
    echo '	'"cp $root/Resources/Owl-Info.plist Owl.app$contents_dir/Info.plist"
    echo
fi

if [ "$(uname)" != Darwin ]; then
    platform_dir=""
else
    case "$(sw_vers -productName)" in
        "Mac OS X" | macOS)
            platform_dir="/MacOS"
            ;;
        *)
            platform_dir="/MacOS"
            ;;
    esac
fi

mkdir -p "Owl.app$contents_dir$platform_dir"

echo "Owl.app$contents_dir$platform_dir/Owl: \$(OBJS)"
echo '	'"$CC \$(OBJS) \$(LDFLAGS) -o Owl.app$contents_dir$platform_dir/Owl"
echo
echo "app: Owl.app$contents_dir$platform_dir/Owl $resources"
echo

echo ".PHONY: clean all app"
echo "clean:"
echo '	'"rm -f \$(OBJS) $generated $resources"
