Mercurial > cgi-bin > hgweb.cgi > JpegWasher
changeset 39:89d7f4d91f67
Got a working, non-bloated Apple Mac bundle!
author | David Barts <n5jrn@me.com> |
---|---|
date | Fri, 01 May 2020 23:06:04 -0700 |
parents | d794ef80f9b0 |
children | a65a8f5a9647 |
files | Building.html Makefile.mac build.xml package-files/osx/DS_Store package-files/osx/Info.plist package-files/osx/JavaApplicationStub package-files/osx/jedit |
diffstat | 7 files changed, 298 insertions(+), 20 deletions(-) [+] |
line wrap: on
line diff
--- a/Building.html Fri May 01 11:52:46 2020 -0700 +++ b/Building.html Fri May 01 23:06:04 2020 -0700 @@ -29,6 +29,7 @@ <li>Exiv2</li> <li>A C++ Compiler</li> <li>Make (Nmake on Windows)</li> + <li>Osdep</li> </ul> <h2>JpegWasher Is Not Pure Java</h2> <p>This means two things: </p>
--- a/Makefile.mac Fri May 01 11:52:46 2020 -0700 +++ b/Makefile.mac Fri May 01 23:06:04 2020 -0700 @@ -6,7 +6,10 @@ .PHONY: all checkenv -all: checkenv $(BDIR)/libjni.dylib $(BDIR)/libexiv2.dylib +all: mkdirs checkenv $(BDIR)/libjni.dylib $(BDIR)/libexiv2.dylib + +mkdirs: + @[ -d "$(BDIR)" ] || mkdir -p "$(BDIR)" checkenv: @if [ -z "$(JRE_HOME)" -o -z "$(EXIV2_HOME)" ]; then \
--- a/build.xml Fri May 01 11:52:46 2020 -0700 +++ b/build.xml Fri May 01 23:06:04 2020 -0700 @@ -1,7 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <project name="JpegWasher" default="help" basedir="." xmlns:contrib="antlib:net.sf.antcontrib" - xmlns:jarbundler="antlib:com.ultramixer.jarbundler" xmlns:launch4j="antlib:net.sf.launch4j.ant"> <!-- import all environment variables as env.* --> <property environment="env"/> @@ -58,7 +57,8 @@ <!-- Define the properties used by the build --> <property name="app.name" value="${ant.project.name}"/> <property name="app.version" value="1.03"/> - <property name="app.entry" value="name.blackcap.exifwasher.MainKt"/> + <property name="app.domain" value="name.blackcap.exifwasher"/> + <property name="app.entry" value="${app.domain}.MainKt"/> <toLowerCase target="lc.app.name" value="${app.name}"/> <property name="jar.name" value="${basedir}/${lc.app.name}.jar"/> <property name="work.jar" value="${basedir}/work.jar"/> @@ -68,8 +68,10 @@ <property name="pf.home" value="${basedir}/package-files"/> <property name="nat.dir" value="${src.home}/name/blackcap/exifwasher/exiv2"/> <property name="bin.dir" value="${src.home}/name/blackcap/exifwasher/binaries"/> + <property name="jvm.version" value="1.8"/> <!-- load the ant-contrib tasks --> + <!-- TODO: see if we need this, remove if not (also see xmlns above) --> <taskdef resource="net/sf/antcontrib/antlib.xml" uri="antlib:net.sf.antcontrib"> <classpath> @@ -77,18 +79,6 @@ </classpath> </taskdef> - <!-- load jarbundler (Mac app bundler) tasks --> - <contrib:if> - <os family="mac"/> - <contrib:then> - <taskdef name="create" - classname="com.ultramixer.jarbundler.JarBundler" - classpath="${lib.home}/jarbundler-core-3.3.0.jar" - uri="antlib:com.ultramixer.jarbundler"> - </taskdef> - </contrib:then> - </contrib:if> - <!-- load launch4j (Windows app bundler) tasks --> <contrib:if> <os family="windows"/> @@ -151,7 +141,7 @@ <!-- remove old cruft --> <target name="clean"> - <delete includeEmptyDirs="true"> + <delete includeEmptyDirs="true" failonerror="false"> <fileset dir="${dist.home}" includes="**/*"/> <fileset dir="${bin.dir}"/> </delete> @@ -159,7 +149,7 @@ <!-- rename files containing OS-dependant code --> <target name="osdep"> - <exec executable="${env.JRE_HOME}/bin/java"> + <exec executable="${env.JRE_HOME}/bin/java" failonerror="true"> <arg value="-jar"/> <arg value="../Osdep/osdep.jar"/> <arg value="${src.home}"/> @@ -175,7 +165,7 @@ description="Compile Java sources to ${work.home}"> <kotlinc src="${src.home}" output="${work.jar}" classpathref="compile.classpath"> - <compilerarg line="-jvm-target 1.8"/> + <compilerarg line="-jvm-target ${jvm.version}"/> </kotlinc> </target> @@ -196,7 +186,73 @@ <!-- the packaging logic here is cribbed from what jEdit does --> <target name="macapp" depends="jar" description="Create MacOS app bundle."> - <!-- not finished --> + <fail message="Macintosh packages can only be built on a Mac."> + <condition> + <not><os family="mac"/></not> + </condition> + </fail> + <sequential> + <property name="mac.disk.image.filename" + value="${lc.app.name}_${app.version}.dmg"/> + <property name="app.bundle" value="${dist.home}/${app.name}.app"/> + <mkdir dir="${app.bundle}/Contents"/> + <copy todir="${app.bundle}/Contents" encoding="UTF-8" overwrite="true"> + <fileset file="${pf.home}/osx/Info.plist"/> + <!-- XXX will break if any tokens contain <, >, or & --> + <filterset> + <filter token="app.domain" value="${app.domain}"/> + <filter token="app.entry" value="${app.entry}"/> + <filter token="app.name" value="${app.name}"/> + <filter token="app.version" value="${app.version}"/> + <filter token="jar.filename" value="${lc.app.name}.jar"/> + <filter token="jvm.version" value="${jvm.version}"/> + <filter token="lc.app.name" value="${lc.app.name}"/> + </filterset> + </copy> + <mkdir dir="${app.bundle}/Contents/MacOS"/> + <copy todir="${app.bundle}/Contents/MacOS" encoding="UTF-8" + overwrite="true"> + <fileset file="${pf.home}/osx/JavaApplicationStub"/> + <filterset> + <filter token="app.domain" value="${app.domain}"/> + <filter token="app.name" value="${app.name}"/> + </filterset> + </copy> + <chmod file="${app.bundle}/Contents/MacOS/JavaApplicationStub" + perm="755"/> + <mkdir dir="${app.bundle}/Contents/Resources"/> + <copy file="${basedir}/${app.name}.icns" + todir="${app.bundle}/Contents/Resources"/> + <mkdir dir="${app.bundle}/Contents/Java"/> + <copy file="${jar.name}" todir="${app.bundle}/Contents/Java"/> + <echo file="${app.bundle}/Contents/PkgInfo" message="APPL????"/> + <exec executable="hdiutil" failonerror="true"> + <arg value="create"/> + <arg value="-volname"/> + <arg value="${app.name}"/> + <arg value="-srcfolder"/> + <arg file="${app.bundle}"/> + <arg file="${dist.home}/orig-${mac.disk.image.filename}"/> + </exec> + <exec executable="hdiutil" failonerror="true"> + <arg value="convert"/> + <arg file="${dist.home}/orig-${mac.disk.image.filename}"/> + <arg value="-format"/> + <arg value="UDRW"/> + <arg value="-o"/> + <arg file="${dist.home}/udrw-${mac.disk.image.filename}"/> + </exec> + <exec executable="hdiutil" failonerror="true"> + <arg value="convert"/> + <arg file="${dist.home}/udrw-${mac.disk.image.filename}"/> + <arg value="-format"/> + <arg value="UDZO"/> + <arg value="-imagekey"/> + <arg value="zlib-level=9"/> + <arg value="-o"/> + <arg file="${dist.home}/${mac.disk.image.filename}"/> + </exec> + </sequential> </target> <target name="winapp" depends="jar" description="Create app bundle."> @@ -204,6 +260,11 @@ </target> <target name="deb" depends="jar" description="Create Debian package."> + <fail message="Linux packages can only be built on Linux."> + <condition> + <not><os family="unix"/></not> + </condition> + </fail> <sequential> <mkdir dir="${dist.home}/data/usr/share/applications"/> <copy file="${pf.home}/linux/deb/jpegwasher.desktop" @@ -246,7 +307,7 @@ <chmod perm="755"> <filelist dir="${dist.home}/control" files="postinst,postrm"/> </chmod> - <exec executable="${basedir}/make-debian-package"> + <exec executable="${basedir}/make-debian-package" failonerror="true"> <arg value="${dist.home}"/> <arg value="${lc.app.name}_${app.version}.deb"/> </exec>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/package-files/osx/Info.plist Fri May 01 23:06:04 2020 -0700 @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<plist version="1.0"> + <!-- see: https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/AboutInformationPropertyListFiles.html --> + <dict> + <!-- Apple says the following are a must --> + <key>CFBundleDevelopmentRegion</key> + <string>English</string> + <key>CFBundleDisplayName</key> + <string>@app.name@</string> + <key>CFBundleExecutable</key> + <string>JavaApplicationStub</string> + <key>CFBundleIconFile</key> + <string>@app.name@.icns</string> + <key>CFBundleIdentifier</key> + <string>@app.domain@</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>@app.name@</string> + <key>CFBundlePackageType</key> + <string>APPL</string> + <key>CFBundleShortVersionString</key> + <string>@app.version@</string> + <key>CFBundleVersion</key> + <string>@app.version@</string> + <key>NSHumanReadableCopyright</key> + <string>Copyright © 2020, David Barts</string> + <!-- most package builders throw the following in --> + <key>CFBundleAllowMixedLocalizations</key> + <string>false</string> + <key>LSApplicationCategoryType</key> + <string>public.app-category.photography</string> + <!-- JavaApplicationStub wants the following stuff --> + <key>JVMMainClassName</key> + <string>@app.entry@</string> + <key>JVMClassPath</key> + <string>Contents/Java/@lc.app.name@.jar</string> + <key>JVMVersion</key> + <string>@jvm.version@+</string> + <key>JVMOptions</key> + <array> + <string>-Dapple.awt.textantialiasing=true</string> + <string>-Dapple.laf.useScreenMenuBar=true</string> + <string>-Dapple.awt.antialiasing=true</string> + </array> + </dict> +</plist>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/package-files/osx/JavaApplicationStub Fri May 01 23:06:04 2020 -0700 @@ -0,0 +1,166 @@ +#!/bin/bash + +# This is based on Tobias Fischer's universalJavaApplicationStub: +# https://github.com/tofi86/universalJavaApplicationStub +# +# Therefore this part of JpegWasher is covered by the same MIT license +# that his code is: +# +# The MIT License (MIT) +# +# Copyright (c) 2014-2020 Tobias Fischer +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# Establish our application names +appname="@app.name@" +appdom="@app.domain@" + +# Make a place for our logs to go +appsupp="$HOME/Library/Application Support/$appdom" +logfile="$appsupp/launcher.log" + +function die { + osascript -e "tell application \"System Events\" to display dialog \"${1}\" with title \"Fatal Error\" buttons {\" OK \"} default button 1" + exit ${2:-1} +} + +# Initialize files and dirs, bail if we can't. +if [ ! -d "$appsupp" ] +then + if ! mkdir -p "$appsupp" + then + die "Unable to create folder '$appsupp'" 2 + fi +fi +> "$logfile" +if [ $? -ne 0 ] +then + die "Unable to create file '$logfile'" 2 +fi + +function stub_logger { + echo "$(date +%c) - $1" >> "$logfile" +} + +# Was originally just for debugging, but I think this could be useful +# for later troubleshooting "in the wild." +stub_logger "execution begins" +{ + echo "****** BEGIN ARGUMENT AND ENVIRONMENT DUMP *******" + echo "Arguments:" "$0" "$@" + echo "Directory:" $(pwd) + env + echo "******* END ARGUMENT AND ENVIRONMENT DUMP ********" +} >> "$logfile" + +# Change to the application root directory, two up from where this script +# (which should contain an absolute path) is. +mydir="${0%/*}" +cd "$mydir/../.." || die "Unable to cd '$mydir/../..'" + +# Determine where Java is, bail if we can't. +if [ -n "$JAVA_HOME" ] +then + if [ ! -d "$JAVA_HOME" ] + then + die "'$JAVA_HOME' does not exist" + fi +else + export JAVA_HOME="$(/usr/libexec/java_home)" + if [ $? -ne 0 -o ! -d "$JAVA_HOME" ] + then + die "Unable to locate Java." + fi +fi + +java="$JAVA_HOME/bin/java" +if [ ! -x "$java" ] +then + die "'$java' not found or not executable" +fi + +# function 'plist_get()' +# +# read a specific Plist key with 'PlistBuddy' utility +# +# @param1 the Plist key with leading colon ':' +# @return the value as String or Array +################################################################################ +function plist_get { + /usr/libexec/PlistBuddy -c "print $1" Contents/Info.plist 2> /dev/null +} +function must_get { + plist_get "$@" || die "Info.plist key '$1' not found." +} + +# Load some parameters from Contents/Info.plist +estat=0 +CFBundleName=$(must_get ':CFBundleName') +CFBundleIconFile=$(must_get ':CFBundleIconFile') +JVMMainClassName=$(must_get ':JVMMainClassName') +JVMClassPath=$(must_get ':JVMClassPath') +JVMVersion=$(must_get ':JVMVersion') + +# Sanity check our JVM version +if [[ "$JVMVersion" == *+ ]] +then + op='>' + JVMVersion="${JVMVersion%+}" +else + op='=' +fi +version=$("$java" -version 2>&1 | awk '/version/{print $3}' | sed -E -e 's/"//g' -e 's/-ea//g') +if [ ! "$version" "$op" "$JVMVersion" ] +then + die "'$java' too old" +fi + +# Load the JVMOptions array (if found) +JVMOptions=() +let i=0 +while true +do + j="$(plist_get :JVMOptions:$i)" + if [ -z "$j" ] + then + break + fi + JVMOptions+=("$j") + let i+=1 +done + +# Fatal error if we cannot change to HOME or HOME not defined +approot="$(pwd)" +if [ -z "$HOME" ] +then + die "HOME not defined!" +fi +cd "$HOME" || die "Unable to cd '$HOME'" + +# And off we go! +jcmd=( "$JAVA_HOME/bin/java" -cp "$approot/$JVMClassPath" + -Xdock:icon="$approot/Contents/Resources/$CFBundleIconFile" + -Xdock:name="$CFBundleName" "${JVMOptions[@]}" "$JVMMainClassName" ) + +stub_logger "Executing: ${jcmd[@]}" +exec "${jcmd[@]}" + +# This shouldn't happen... +die "Could not launch Java."