|
@@ -0,0 +1,352 @@
|
|
|
|
+#!/bin/bash
|
|
|
|
+#
|
|
|
|
+# This is a "compiler" for Amber code. Run without arguments for help.
|
|
|
|
+
|
|
|
|
+# Get Amber root directory from the location of this script so that
|
|
|
|
+# we can find the st and js directories etc.
|
|
|
|
+
|
|
|
|
+# Earlier we used this but it does not work on Mac
|
|
|
|
+# Amber=$(readlink -f `dirname ${0}`/..)
|
|
|
|
+TARGET=`dirname ${0}`/..
|
|
|
|
+pushd . >/dev/null
|
|
|
|
+cd $TARGET
|
|
|
|
+AMBER="`\pwd -P`"
|
|
|
|
+popd >/dev/null
|
|
|
|
+
|
|
|
|
+function usage {
|
|
|
|
+ cat <<ENDOFHELP
|
|
|
|
+Usage: $0 [-l lib1,lib2...] [-i file] [-m class] [-M file]
|
|
|
|
+ [-o] [-O|-A] [-d] [-s suffix] [-S suffix] [file1 [file2 ...]] [Program]
|
|
|
|
+
|
|
|
|
+ Will compile Amber files - either separately or into a runnable complete
|
|
|
|
+ program. If no .st files are listed only a linking stage is performed.
|
|
|
|
+ Files listed will be handled using these rules:
|
|
|
|
+
|
|
|
|
+ *.js
|
|
|
|
+ Files are linked (concatenated) in listed order.
|
|
|
|
+ If not found we look in $AMBER/js
|
|
|
|
+
|
|
|
|
+ *.st
|
|
|
|
+ Files are compiled into .js files before concatenated.
|
|
|
|
+ If not found we look in $AMBER/st.
|
|
|
|
+
|
|
|
|
+ NOTE: Each file is currently considered to be a fileout of a single class
|
|
|
|
+ category of the same name as the file!
|
|
|
|
+
|
|
|
|
+ If no Program is specified each given .st file will be compiled into
|
|
|
|
+ a .js file. Otherwise a <Program>.js file is linked together based on
|
|
|
|
+ the options:
|
|
|
|
+
|
|
|
|
+ -l library1,library2
|
|
|
|
+ Additionally add listed libraries (no spaces or .js) in listed order.
|
|
|
|
+
|
|
|
|
+ -i file
|
|
|
|
+ Add library initializer <file> instead of default $AMBER/js/init.js
|
|
|
|
+
|
|
|
|
+ -m class
|
|
|
|
+ Add at end a call to #main in class <class>.
|
|
|
|
+
|
|
|
|
+ -M file
|
|
|
|
+ Add at end javascript file <file> acting as main.
|
|
|
|
+
|
|
|
|
+ -o
|
|
|
|
+ Optimize each js file using the Google closure compiler.
|
|
|
|
+ Using Closure compiler found at ~/compiler.jar
|
|
|
|
+
|
|
|
|
+ -O
|
|
|
|
+ Optimize final <Program>.js using the Google closure compiler.
|
|
|
|
+ Using Closure compiler found at ~/compiler.jar
|
|
|
|
+
|
|
|
|
+ -A Same as -O but use --compilation_level ADVANCED_OPTIMIZATIONS
|
|
|
|
+
|
|
|
|
+ -d
|
|
|
|
+ Additionally export code for deploy - stripped from source etc.
|
|
|
|
+ Uses suffix ".deploy.js" in addition to any explicit given suffic using -s.
|
|
|
|
+
|
|
|
|
+ -s suffix
|
|
|
|
+ Add <suffix> to compiled js files so that File.st is compiled into
|
|
|
|
+ File.<suffix>.js.
|
|
|
|
+
|
|
|
|
+ -S suffix
|
|
|
|
+ Use <suffix> for all libraries accessed using -L or -l. This makes it possible
|
|
|
|
+ to have multiple flavors of Amber and libraries in the same place.
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ Example invocations:
|
|
|
|
+
|
|
|
|
+ Just compile Kernel.st to Kernel.js:
|
|
|
|
+
|
|
|
|
+ amberc Kernel.st
|
|
|
|
+
|
|
|
|
+ Compile Hello.st to Hello.js and create complete program called
|
|
|
|
+ Program.js and adding a call to class method #main in class Hello:
|
|
|
|
+
|
|
|
|
+ amberc -m Hello Hello.st Program
|
|
|
|
+
|
|
|
|
+ Compile two .st files into corresponding .js files,
|
|
|
|
+ and link with specific myboot.js, myKernel.js, myinit.js
|
|
|
|
+ and main.js and create complete program called Program.js:
|
|
|
|
+
|
|
|
|
+ amberc -M main.js myinit.js myboot.js myKernel.js Cat1.st Cat2.st Program
|
|
|
|
+
|
|
|
|
+ENDOFHELP
|
|
|
|
+ exit 1;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+# Check we at least got one argument
|
|
|
|
+if [ -z $1 ] ; then
|
|
|
|
+ usage
|
|
|
|
+fi
|
|
|
|
+
|
|
|
|
+# Define our predefined library combinations
|
|
|
|
+KERNEL="boot Kernel"
|
|
|
|
+COMPILER="$KERNEL parser Compiler"
|
|
|
|
+
|
|
|
|
+# Predefined initializer
|
|
|
|
+INITIALIZER="$AMBER/js/init.js"
|
|
|
|
+
|
|
|
|
+# Default values
|
|
|
|
+ENV=
|
|
|
|
+INIT=$INITIALIZER
|
|
|
|
+MAIN=
|
|
|
|
+MAINFILE=
|
|
|
|
+BASE=$KERNEL
|
|
|
|
+LOAD=
|
|
|
|
+CLOSUREOPTS=
|
|
|
|
+# Ok, bad coding practice but hey, who would use such a suffix?
|
|
|
|
+SUFFIX=no-silly-suffix
|
|
|
|
+SUFFIXUSED=
|
|
|
|
+DEPLOY=false
|
|
|
|
+NODECOMPILE=nodecompile
|
|
|
|
+
|
|
|
|
+# Read options and shift them away
|
|
|
|
+while getopts "l:i:m:M:oOAds:S:h?" o; do
|
|
|
|
+case "$o" in
|
|
|
|
+ l) LOAD=$OPTARG;;
|
|
|
|
+ i) INIT=$OPTARG;;
|
|
|
|
+ m) MAIN=$OPTARG;;
|
|
|
|
+ M) MAINFILE=$OPTARG;;
|
|
|
|
+ o) CLOSURE=true
|
|
|
|
+ CLOSUREPARTS=true;;
|
|
|
|
+ O) CLOSURE=true
|
|
|
|
+ CLOSUREFULL=true;;
|
|
|
|
+ A) CLOSURE=true
|
|
|
|
+ CLOSUREOPTS="$CLOSUREOPTS --compilation_level ADVANCED_OPTIMIZATIONS"
|
|
|
|
+ CLOSUREFULL=true;;
|
|
|
|
+ d) DEPLOY=true;;
|
|
|
|
+ s) SUFFIX=$OPTARG
|
|
|
|
+ SUFFIXUSED=$SUFFIX;;
|
|
|
|
+ S) LOADSUFFIX=$OPTARG
|
|
|
|
+ SUFFIXUSED=$SUFFIX;;
|
|
|
|
+ h) usage;;
|
|
|
|
+ [?]) usage;;
|
|
|
|
+ esac
|
|
|
|
+done
|
|
|
|
+shift $(($OPTIND - 1))
|
|
|
|
+
|
|
|
|
+# Check for Closure compiler and Java
|
|
|
|
+if [ ! -z $CLOSURE ]; then
|
|
|
|
+ java > /dev/null
|
|
|
|
+ if [ $? -eq 0 ]; then
|
|
|
|
+ if [ ! -f ~/compiler.jar ]; then
|
|
|
|
+ echo "Can not find Closure compiler at ~/compiler.jar"
|
|
|
|
+ exit 1
|
|
|
|
+ fi
|
|
|
|
+ else
|
|
|
|
+ echo "java is not installed and is needed for -O, -A or -o (Closure compiler)."
|
|
|
|
+ exit 1
|
|
|
|
+ fi
|
|
|
|
+fi
|
|
|
|
+
|
|
|
|
+# Function for looking up listed js files
|
|
|
|
+function resolvejs {
|
|
|
|
+ FNAME="$1$LOADSUFFIX.js"
|
|
|
|
+ if [ -f $FNAME ]; then
|
|
|
|
+ RESOLVED="$FNAME"
|
|
|
|
+ else
|
|
|
|
+ if [ -f $AMBER/js/$FNAME ]; then
|
|
|
|
+ RESOLVED="$AMBER/js/$FNAME"
|
|
|
|
+ else
|
|
|
|
+ echo "Javascript file not found: $FNAME"
|
|
|
|
+ exit 1
|
|
|
|
+ fi
|
|
|
|
+ fi
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+# Resolve listed libraries in $BASE deparated by spaces
|
|
|
|
+for FILE in $BASE
|
|
|
|
+do
|
|
|
|
+ resolvejs $FILE
|
|
|
|
+ TOBASE="$TOBASE $RESOLVED"
|
|
|
|
+done
|
|
|
|
+
|
|
|
|
+# Resolve listed libraries in $LOAD separated by ,
|
|
|
|
+LOAD=${LOAD//,/\ }
|
|
|
|
+for FILE in $LOAD
|
|
|
|
+do
|
|
|
|
+ resolvejs $FILE
|
|
|
|
+ TOLOAD="$TOLOAD $RESOLVED"
|
|
|
|
+done
|
|
|
|
+
|
|
|
|
+# Resolve COMPILER
|
|
|
|
+for FILE in $COMPILER
|
|
|
|
+do
|
|
|
|
+ resolvejs $FILE
|
|
|
|
+ TOCOMPILER="$TOCOMPILER $RESOLVED"
|
|
|
|
+done
|
|
|
|
+
|
|
|
|
+# Add supplied libraries we have not already loaded (they are already resolved)
|
|
|
|
+#for FILE in $EXTRA
|
|
|
|
+#do
|
|
|
|
+# resolvejs $FILE
|
|
|
|
+# TOEXTRA="$TOEXTRA $RESOLVED"
|
|
|
|
+#done
|
|
|
|
+
|
|
|
|
+TOCOMPILER="$TOCOMPILER$TOLOAD"
|
|
|
|
+
|
|
|
|
+# Resolve init and nodecompile
|
|
|
|
+THEREST="init $AMBER/bin/$NODECOMPILE"
|
|
|
|
+for FILE in $THEREST
|
|
|
|
+do
|
|
|
|
+ resolvejs $FILE
|
|
|
|
+ TOCOMPILER="$TOCOMPILER $RESOLVED"
|
|
|
|
+done
|
|
|
|
+
|
|
|
|
+# Add supplied libraries
|
|
|
|
+LIBS="$TOBASE $TOLOAD"
|
|
|
|
+
|
|
|
|
+# Get a unique tempdir and make it get auto removed on exit
|
|
|
|
+TMPDIR=`mktemp -d amberc.XXXXXX`
|
|
|
|
+trap "rm -rf $TMPDIR" EXIT
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+# --------------------------------------------------
|
|
|
|
+# Collect libraries and Smalltalk files looking
|
|
|
|
+# both locally and in $AMBER/js and $AMBER/st
|
|
|
|
+# --------------------------------------------------
|
|
|
|
+PROGRAM=
|
|
|
|
+until [ "$*" = "" ]
|
|
|
|
+do
|
|
|
|
+ case $1 in
|
|
|
|
+ *.st)
|
|
|
|
+ CATEGORY=`basename $1 .st`
|
|
|
|
+ if [ -f "$1" ]; then
|
|
|
|
+ COMPILE="$COMPILE $1 $CATEGORY"
|
|
|
|
+ COMPILED="$COMPILED $CATEGORY$SUFFIXUSED.js"
|
|
|
|
+ else
|
|
|
|
+ if [ -f $AMBER/st/$1 ]; then
|
|
|
|
+ COMPILE="$COMPILE $AMBER/st/$1 $CATEGORY"
|
|
|
|
+ COMPILED="$COMPILED $CATEGORY$SUFFIXUSED.js"
|
|
|
|
+ else
|
|
|
|
+ echo "Amber file not found: $1"
|
|
|
|
+ exit 1
|
|
|
|
+ fi
|
|
|
|
+ fi
|
|
|
|
+ ;;
|
|
|
|
+
|
|
|
|
+ *.js)
|
|
|
|
+ resolvejs $1
|
|
|
|
+ LIBS="$LIBS $RESOLVED"
|
|
|
|
+ ;;
|
|
|
|
+ *)
|
|
|
|
+ # Will end up being the last non js/st argument
|
|
|
|
+ PROGRAM=$1
|
|
|
|
+ ;;
|
|
|
|
+ esac
|
|
|
|
+ shift
|
|
|
|
+done
|
|
|
|
+
|
|
|
|
+# --------------------------------------------------
|
|
|
|
+# Actual compilation phase of collected .st files
|
|
|
|
+# --------------------------------------------------
|
|
|
|
+
|
|
|
|
+# Create compiler dynamically
|
|
|
|
+cat $TOCOMPILER > $TMPDIR/compiler.js
|
|
|
|
+
|
|
|
|
+# Compile all collected .st files to .js
|
|
|
|
+echo "Loading libraries$TOCOMPILER and compiling ..."
|
|
|
|
+node $TMPDIR/compiler.js $DEPLOY $SUFFIX $COMPILE
|
|
|
|
+
|
|
|
|
+# Verify all .js files corresponding to .st files were created, otherwise exit
|
|
|
|
+IFS=" "
|
|
|
|
+for FILE in $COMPILED
|
|
|
|
+do
|
|
|
|
+ if [ ! -f "$FILE" ]; then
|
|
|
|
+ echo "Failed compilation of $FILE, exiting."
|
|
|
|
+ exit 1
|
|
|
|
+ fi
|
|
|
|
+done
|
|
|
|
+
|
|
|
|
+if [ ! -z $CLOSUREPARTS ]; then
|
|
|
|
+ echo "Compiling all js files using Google closure compiler."
|
|
|
|
+
|
|
|
|
+ ALLJSFILES="$COMPILED $LIBS"
|
|
|
|
+ for FILE in $ALLJSFILES
|
|
|
|
+ do
|
|
|
|
+ mv $FILE $FILE.original
|
|
|
|
+ java -jar ~/compiler.jar $CLOSUREOPTS --js $FILE.original --js_output_file $FILE
|
|
|
|
+ rm $FILE.original
|
|
|
|
+ done
|
|
|
|
+fi
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+if [ -z $PROGRAM ]; then
|
|
|
|
+ echo "Done."
|
|
|
|
+ exit 0
|
|
|
|
+fi
|
|
|
|
+
|
|
|
|
+# --------------------------------------------------
|
|
|
|
+# Now we start composing resulting javascript file.
|
|
|
|
+# --------------------------------------------------
|
|
|
|
+
|
|
|
|
+# Add collected libraries to libs.js file.
|
|
|
|
+if [ ! -z "$LIBS" ]; then
|
|
|
|
+ echo "Adding libraries $LIBS ..."
|
|
|
|
+ cat $LIBS > $TMPDIR/libs.js
|
|
|
|
+ LIBS=$TMPDIR/libs.js
|
|
|
|
+fi
|
|
|
|
+
|
|
|
|
+echo "Adding Amber code$COMPILED ..."
|
|
|
|
+
|
|
|
|
+# Check for init file
|
|
|
|
+if [ ! -z "$INIT" ]; then
|
|
|
|
+ if [ -f "$INIT" ]; then
|
|
|
|
+ echo "Adding initializer $INIT ..."
|
|
|
|
+ else
|
|
|
|
+ echo "Can not find init file $INIT, exiting."
|
|
|
|
+ exit 1
|
|
|
|
+ fi
|
|
|
|
+fi
|
|
|
|
+
|
|
|
|
+# Check for adding main
|
|
|
|
+if [ ! -z "$MAIN" ]; then
|
|
|
|
+ echo "Adding call to $MAIN class >> main ..."
|
|
|
|
+ echo "smalltalk.$MAIN._main()" > $TMPDIR/main.js
|
|
|
|
+ MAIN=$TMPDIR/main.js
|
|
|
|
+fi
|
|
|
|
+
|
|
|
|
+# Check for adding main file
|
|
|
|
+if [ ! -z "$MAINFILE" ]; then
|
|
|
|
+ if [ -f "$MAINFILE" ]; then
|
|
|
|
+ echo "Adding main as $MAINFILE ..."
|
|
|
|
+ else
|
|
|
|
+ echo "Can not find main file $MAINFILE, exiting."
|
|
|
|
+ exit 1
|
|
|
|
+ fi
|
|
|
|
+ MAIN=$MAINFILE
|
|
|
|
+fi
|
|
|
|
+
|
|
|
|
+# And finally concatenate Program.js
|
|
|
|
+echo "Writing $PROGRAM.js ..."
|
|
|
|
+cat $LIBS $COMPILED $INIT $MAIN > $PROGRAM.js
|
|
|
|
+echo "Done."
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+if [ ! -z $CLOSUREFULL ]; then
|
|
|
|
+ echo "Compiling $PROGRAM.js file using Google closure compiler."
|
|
|
|
+ mv $PROGRAM.js $PROGRAM.js.original
|
|
|
|
+ java -jar ~/compiler.jar $CLOSUREOPTS --js $PROGRAM.js.original --js_output_file $PROGRAM.js
|
|
|
|
+ rm $PROGRAM.js.original
|
|
|
|
+ echo "Done."
|
|
|
|
+fi
|
|
|
|
+
|