jtalkc 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. #!/bin/bash
  2. #
  3. # This is a "compiler" for JTalk code. Run without arguments for help.
  4. # Get JTalk root directory from the location of this script so that
  5. # we can find the st and js directories etc.
  6. # Earlier we used this but it does not work on Mac
  7. # JTALK=$(readlink -f `dirname ${0}`/..)
  8. TARGET=`dirname ${0}`/..
  9. pushd . >/dev/null
  10. cd $TARGET
  11. JTALK="`\pwd -P`"
  12. popd >/dev/null
  13. function usage {
  14. cat <<ENDOFHELP
  15. Usage: $0 [-L level] [-l lib1,lib2...] [-i file] [-m class] [-M file]
  16. [-o] [-O|-A] [-d] [-s suffix] [-S suffix] [file1 [file2 ...]] [Program]
  17. Will compile Jtalk files - either separately or into a runnable complete
  18. program. If no .st files are listed only a linking stage is performed.
  19. Files listed will be handled using these rules:
  20. *.js
  21. Files are linked (concatenated) in listed order.
  22. If not found we look in $JTALK/js
  23. *.st
  24. Files are compiled into .js files before concatenated.
  25. If not found we look in $JTALK/st.
  26. NOTE: Each file is currently considered to be a fileout of a single class
  27. category of the same name as the file!
  28. If no Program is specified each given .st file will be compiled into
  29. a .js file. Otherwise a <Program>.js file is linked together based on
  30. the options:
  31. -L level
  32. Add libraries to a predefined level (default is KERNEL) of environment
  33. where level is:
  34. KERNEL - a reasonable level for server side programs or libraries.
  35. COMPILER - if you need to compile, import or export Jtalk code.
  36. CANVAS - if you need HTML DOM manipulation, typical for client side.
  37. JQUERY - if you want JQuery stuff on top of Canvas.
  38. IDE - if you are extending the IDE with new tools etc.
  39. -l library1,library2
  40. Additionally add listed libraries (no spaces or .js) in listed order.
  41. -i file
  42. Add library initializer <file> instead of default $JTALK/js/init.js
  43. -m class
  44. Add at end a call to #main in class <class>.
  45. -M file
  46. Add at end javascript file <file> acting as main.
  47. -o
  48. Optimize each js file using the Google closure compiler.
  49. Using Closure compiler found at ~/compiler.jar
  50. -O
  51. Optimize final <Program>.js using the Google closure compiler.
  52. Using Closure compiler found at ~/compiler.jar
  53. -A Same as -O but use --compilation_level ADVANCED_OPTIMIZATIONS
  54. -d
  55. Additionally export code for deploy - stripped from source etc.
  56. Uses suffix ".deploy.js" in addition to any explicit given suffic using -s.
  57. -s suffix
  58. Add <suffix> to compiled js files so that File.st is compiled into
  59. File.<suffix>.js.
  60. -S suffix
  61. Use <suffix> for all libraries accessed using -L or -l. This makes it possible
  62. to have multiple flavors of Jtalk and libraries in the same place.
  63. Example invocations:
  64. Just compile Kernel.st to Kernel.js:
  65. jtalkc Kernel.st
  66. Compile Hello.st to Hello.js and create complete program called
  67. Program.js and adding a call to class method #main in class Hello:
  68. jtalkc -m Hello Hello.st Program
  69. Compile two .st files into corresponding .js files,
  70. and link with specific myboot.js, myKernel.js, myinit.js
  71. and main.js and create complete program called Program.js:
  72. jtalkc -M main.js myinit.js myboot.js myKernel.js Cat1.st Cat2.st Program
  73. ENDOFHELP
  74. exit 1;
  75. }
  76. # Check we at least got one argument
  77. if [ -z $1 ] ; then
  78. usage
  79. fi
  80. # Define our predefined library combinations
  81. BOOT="boot"
  82. KERNEL="$BOOT Kernel"
  83. COMPILER="$KERNEL parser Compiler"
  84. CANVAS="$KERNEL Canvas"
  85. JQUERY="$CANVAS JQuery"
  86. IDE="$JQUERY IDE SUnit Examples"
  87. # Predefined initializer
  88. INITIALIZER="$JTALK/js/init.js"
  89. # Default values
  90. ENV=
  91. INIT=$INITIALIZER
  92. MAIN=
  93. MAINFILE=
  94. BASE=$KERNEL
  95. LOAD=
  96. CLOSUREOPTS=
  97. # Ok, bad coding practice but hey, who would use such a suffix?
  98. SUFFIX=no-silly-suffix
  99. SUFFIXUSED=
  100. DEPLOY=false
  101. NODECOMPILE=nodecompile
  102. # Read options and shift them away
  103. while getopts "L:l:i:m:M:oOAds:S:h?" o; do
  104. case "$o" in
  105. L) BASE=${!OPTARG};; # If OPTARG is "KERNEL" this sets BASE to $KERNEL.
  106. l) LOAD=$OPTARG;;
  107. i) INIT=$OPTARG;;
  108. m) MAIN=$OPTARG;;
  109. M) MAINFILE=$OPTARG;;
  110. o) CLOSURE=true
  111. CLOSUREPARTS=true;;
  112. O) CLOSURE=true
  113. CLOSUREFULL=true;;
  114. A) CLOSURE=true
  115. CLOSUREOPTS="$CLOSUREOPTS --compilation_level ADVANCED_OPTIMIZATIONS"
  116. CLOSUREFULL=true;;
  117. d) DEPLOY=true;;
  118. s) SUFFIX=$OPTARG
  119. SUFFIXUSED=$SUFFIX;;
  120. S) LOADSUFFIX=$OPTARG
  121. SUFFIXUSED=$SUFFIX;;
  122. h) usage;;
  123. [?]) usage;;
  124. esac
  125. done
  126. shift $(($OPTIND - 1))
  127. # Check for Closure compiler and Java
  128. if [ ! -z $CLOSURE ]; then
  129. java > /dev/null
  130. if [ $? -eq 0 ]; then
  131. if [ ! -f ~/compiler.jar ]; then
  132. echo "Can not find Closure compiler at ~/compiler.jar"
  133. exit 1
  134. fi
  135. else
  136. echo "java is not installed and is needed for -O, -A or -o (Closure compiler)."
  137. exit 1
  138. fi
  139. fi
  140. # Function for looking up listed js files
  141. function resolvejs {
  142. FNAME="$1$LOADSUFFIX.js"
  143. if [ -f $FNAME ]; then
  144. RESOLVED="$FNAME"
  145. else
  146. if [ -f $JTALK/js/$FNAME ]; then
  147. RESOLVED="$JTALK/js/$FNAME"
  148. else
  149. echo "Javascript file not found: $FNAME"
  150. exit 1
  151. fi
  152. fi
  153. }
  154. # Resolve listed libraries in $BASE deparated by spaces
  155. for FILE in $BASE
  156. do
  157. resolvejs $FILE
  158. TOBASE="$TOBASE $RESOLVED"
  159. done
  160. # Resolve listed libraries in $LOAD separated by ,
  161. LOAD=${LOAD//,/\ }
  162. for FILE in $LOAD
  163. do
  164. resolvejs $FILE
  165. TOLOAD="$TOLOAD $RESOLVED"
  166. done
  167. # Resolve COMPILER
  168. for FILE in $COMPILER
  169. do
  170. resolvejs $FILE
  171. TOCOMPILER="$TOCOMPILER $RESOLVED"
  172. done
  173. # Add supplied libraries we have not already loaded (they are already resolved)
  174. #for FILE in $EXTRA
  175. #do
  176. # resolvejs $FILE
  177. # TOEXTRA="$TOEXTRA $RESOLVED"
  178. #done
  179. TOCOMPILER="$TOCOMPILER$TOLOAD"
  180. # Resolve init and nodecompile
  181. THEREST="init $JTALK/bin/$NODECOMPILE"
  182. for FILE in $THEREST
  183. do
  184. resolvejs $FILE
  185. TOCOMPILER="$TOCOMPILER $RESOLVED"
  186. done
  187. # Add supplied libraries
  188. LIBS="$TOBASE $TOLOAD"
  189. # Get a unique tempdir and make it get auto removed on exit
  190. TMPDIR=`mktemp -d jtalkc.XXXXXX`
  191. trap "rm -rf $TMPDIR" EXIT
  192. # --------------------------------------------------
  193. # Collect libraries and Smalltalk files looking
  194. # both locally and in $JTALK/js and $JTALK/st
  195. # --------------------------------------------------
  196. PROGRAM=
  197. until [ "$*" = "" ]
  198. do
  199. case $1 in
  200. *.st)
  201. CATEGORY=`basename $1 .st`
  202. if [ -f "$1" ]; then
  203. COMPILE="$COMPILE $1 $CATEGORY"
  204. COMPILED="$COMPILED $CATEGORY$SUFFIXUSED.js"
  205. else
  206. if [ -f $JTALK/st/$1 ]; then
  207. COMPILE="$COMPILE $JTALK/st/$1 $CATEGORY"
  208. COMPILED="$COMPILED $CATEGORY$SUFFIXUSED.js"
  209. else
  210. echo "JTalk file not found: $1"
  211. exit 1
  212. fi
  213. fi
  214. ;;
  215. *.js)
  216. resolvejs $1
  217. LIBS="$LIBS $RESOLVED"
  218. ;;
  219. *)
  220. # Will end up being the last non js/st argument
  221. PROGRAM=$1
  222. ;;
  223. esac
  224. shift
  225. done
  226. # --------------------------------------------------
  227. # Actual compilation phase of collected .st files
  228. # --------------------------------------------------
  229. # Create compiler dynamically
  230. cat $TOCOMPILER > $TMPDIR/compiler.js
  231. # Compile all collected .st files to .js
  232. echo "Loading libraries$TOCOMPILER and compiling ..."
  233. node $TMPDIR/compiler.js $DEPLOY $SUFFIX $COMPILE
  234. # Verify all .js files corresponding to .st files were created, otherwise exit
  235. IFS=" "
  236. for FILE in $COMPILED
  237. do
  238. if [ ! -f "$FILE" ]; then
  239. echo "Failed compilation of $FILE, exiting."
  240. exit 1
  241. fi
  242. done
  243. if [ ! -z $CLOSUREPARTS ]; then
  244. echo "Compiling all js files using Google closure compiler."
  245. ALLJSFILES="$COMPILED $LIBS"
  246. for FILE in $ALLJSFILES
  247. do
  248. mv $FILE $FILE.original
  249. java -jar ~/compiler.jar $CLOSUREOPTS --js $FILE.original --js_output_file $FILE
  250. rm $FILE.original
  251. done
  252. fi
  253. if [ -z $PROGRAM ]; then
  254. echo "Done."
  255. exit 0
  256. fi
  257. # --------------------------------------------------
  258. # Now we start composing resulting javascript file.
  259. # --------------------------------------------------
  260. # Add collected libraries to libs.js file.
  261. if [ ! -z "$LIBS" ]; then
  262. echo "Adding libraries $LIBS ..."
  263. cat $LIBS > $TMPDIR/libs.js
  264. LIBS=$TMPDIR/libs.js
  265. fi
  266. echo "Adding Jtalk code$COMPILED ..."
  267. # Check for init file
  268. if [ ! -z "$INIT" ]; then
  269. if [ -f "$INIT" ]; then
  270. echo "Adding initializer $INIT ..."
  271. else
  272. echo "Can not find init file $INIT, exiting."
  273. exit 1
  274. fi
  275. fi
  276. # Check for adding main
  277. if [ ! -z "$MAIN" ]; then
  278. echo "Adding call to $MAIN class >> main ..."
  279. echo "smalltalk.$MAIN._main()" > $TMPDIR/main.js
  280. MAIN=$TMPDIR/main.js
  281. fi
  282. # Check for adding main file
  283. if [ ! -z "$MAINFILE" ]; then
  284. if [ -f "$MAINFILE" ]; then
  285. echo "Adding main as $MAINFILE ..."
  286. else
  287. echo "Can not find main file $MAINFILE, exiting."
  288. exit 1
  289. fi
  290. MAIN=$MAINFILE
  291. fi
  292. # And finally concatenate Program.js
  293. echo "Writing $PROGRAM.js ..."
  294. cat $LIBS $COMPILED $INIT $MAIN > $PROGRAM.js
  295. echo "Done."
  296. if [ ! -z $CLOSUREFULL ]; then
  297. echo "Compiling $PROGRAM.js file using Google closure compiler."
  298. mv $PROGRAM.js $PROGRAM.js.original
  299. java -jar ~/compiler.jar $CLOSUREOPTS --js $PROGRAM.js.original --js_output_file $PROGRAM.js
  300. rm $PROGRAM.js.original
  301. echo "Done."
  302. fi