1
0

jtalkc 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  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 [-N|D|E] [-K|C|J] [-o] [-O|-A] [-g] [-p prefix] [-m class] [-M file]
  16. [-i] [-I file] [file1 [file2 ...]] [Program]
  17. Will compile Jtalk files - either separately or into a runnable complete
  18. program. If no files are listed only a linking stage is performed.
  19. Files listed will be handled using these rules:
  20. *.js
  21. Files are 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. -N or -D or -E
  32. Compilation target. Currently Node.js, D8 (V8 shell) or Enyo (webOS 3.0).
  33. All currentl imply "-K -I" so boot.js and Kernel.js are added first and init.js
  34. is added last.
  35. -K
  36. Add libraries to get minimal Jtalk Kernel running.
  37. -C
  38. Add libraries to get minimal Jtalk Compiler running.
  39. -J
  40. Add libraries to get minimal Jtalk IDE running.
  41. -o
  42. Optimize each js file using the Google closure compiler.
  43. Using Closure at ~/compiler.jar
  44. -O
  45. Optimize final <Program>.js using the Google closure compiler.
  46. Using Closure at ~/compiler.jar
  47. -A Same as -O but use --compilation_level ADVANCED_OPTIMIZATIONS
  48. -g
  49. Compile Jtalk code in debug mode - include source and references etc.
  50. -p prefix
  51. Add <prefix> to compiled js files so that File.st is compiled into
  52. <prefix>File.st.
  53. -l library1,library2
  54. Load listed libraries (no spaces) into Compiler before compiling.
  55. -L library1,library2
  56. Load listed libraries (no spaces) into Compiler before compiling and also
  57. into Program.js in listed order.
  58. -i file
  59. Add library initializer <file>.
  60. -I
  61. Add library standard initializer $JTALK/js/init.js
  62. -m class
  63. Add call to #main in class <class>.
  64. -M file
  65. Add javascript file <file> at the end acting as main.
  66. Example invocations:
  67. Just compile Kernel.st to Kernel.js:
  68. jtalkc Kernel.st
  69. Compile Hello.st to Hello.js and create complete program called
  70. Program.js for Node.js and adding a call to class method #main
  71. in class Hello:
  72. jtalkc -N -m Hello Hello.st Program
  73. Compile two .st files into corresponding .js files,
  74. and link with specific myboot.js, myKernel.js, myinit.js
  75. and main.js and create complete program called Program.js:
  76. jtalkc -M main.js -I myinit.js myboot.js myKernel.js Cat1.st Cat2.st Program
  77. ENDOFHELP
  78. exit 1;
  79. }
  80. # Check we at least got one argument
  81. if [ -z $1 ] ; then
  82. usage
  83. fi
  84. # Define our predefined library combinations
  85. BOOT="boot.js"
  86. KERNEL="$BOOT Kernel.js"
  87. COMPILER="$KERNEL Parser.js Compiler.js"
  88. CANVAS="$COMPILER Canvas.js"
  89. IDE="$CANVAS JQuery.js IDE.js SUnit.js Examples.js"
  90. # Predefined initializer
  91. INITIALIZER="$JTALK/js/init.js"
  92. # Default values
  93. ENV=
  94. INIT=
  95. MAIN=
  96. MAINFILE=
  97. BASE=
  98. LOAD=
  99. LOADANDADD=
  100. CLOSUREOPTS=
  101. # Ok, bad coding practice but hey, who would use such a prefix?
  102. PREFIX=no-silly-prefix
  103. PREFIXUSED=
  104. DEBUG=false
  105. NODECOMPILE=nodecompile.js
  106. # Read options and shift them away
  107. while getopts "NDEKCJoOAgp:l:L:i:IM:m:h?" o; do
  108. case "$o" in
  109. N) ENV=NODE
  110. BASE=$KERNEL
  111. INIT=$INITIALIZER;;
  112. D) ENV=D8
  113. BASE=$KERNEL
  114. INIT=$INITIALIZER;;
  115. E) ENV=ENYO
  116. BASE=$KERNEL
  117. INIT=$INITIALIZER;;
  118. K) BASE=$KERNEL;;
  119. C) BASE=$COMPILER;;
  120. J) BASE=$IDE;;
  121. o) CLOSURE=true
  122. CLOSUREPARTS=true;;
  123. O) CLOSURE=true
  124. CLOSUREFULL=true;;
  125. A) CLOSURE=true
  126. CLOSUREOPTS="$CLOSUREOPTS --compilation_level ADVANCED_OPTIMIZATIONS"
  127. CLOSUREFULL=true;;
  128. g) DEBUG=true;;
  129. p) PREFIX=$OPTARG
  130. PREFIXUSED=$PREFIX;;
  131. l) LOAD=$OPTARG;;
  132. L) LOADANDADD=$OPTARG;;
  133. I) INIT=$INITIALIZER;;
  134. i) INIT=$OPTARG;;
  135. M) MAINFILE=$OPTARG;;
  136. m) MAIN=$OPTARG;;
  137. h) usage;;
  138. [?]) usage;;
  139. esac
  140. done
  141. shift $(($OPTIND - 1))
  142. # Check for Closure compiler and Java
  143. if [ ! -z $CLOSURE ]; then
  144. java > /dev/null
  145. if [ $? -eq 0 ]; then
  146. if [ ! -f ~/compiler.jar ]; then
  147. echo "Can not find Closure compiler at ~/compiler.jar"
  148. exit 1
  149. fi
  150. else
  151. echo "java is not installed and is needed for -O, -A or -o (Closure compiler)."
  152. exit 1
  153. fi
  154. fi
  155. # Function for looking up listed js files
  156. function resolvejs {
  157. if [ -f "$1" ]; then
  158. RESOLVED="$1"
  159. else
  160. if [ -f $JTALK/js/$1 ]; then
  161. RESOLVED="$JTALK/js/$1"
  162. else
  163. echo "Javascript file not found: $1"
  164. exit 1
  165. fi
  166. fi
  167. }
  168. # Resolve listed libraries in $BASE separated by spaces
  169. for FILE in $BASE
  170. do
  171. resolvejs $FILE
  172. TOBASE="$TOBASE $RESOLVED"
  173. done
  174. # Resolve listed libraries in $LOAD separated by spaces
  175. LOAD=${LOAD//,/\ }
  176. for FILE in $LOAD
  177. do
  178. resolvejs $FILE
  179. TOLOAD="$TOLOAD $RESOLVED"
  180. done
  181. # Resolve listed libraries in $LOADANDADD separated by spaces
  182. LOADANDADD=${LOADANDADD//,/\ }
  183. for FILE in $LOADANDADD
  184. do
  185. resolvejs $FILE
  186. TOLOAD="$TOLOAD $RESOLVED"
  187. TOADD="$TOADD $RESOLVED"
  188. done
  189. # Define our Compiler loading supplied libraries
  190. OURCOMPILER="$COMPILER $TOLOAD init.js $JTALK/nodejs/$NODECOMPILE"
  191. # Resolve OURCOMPILER
  192. for FILE in $OURCOMPILER
  193. do
  194. resolvejs $FILE
  195. TOOURCOMPILER="$TOOURCOMPILER $RESOLVED"
  196. done
  197. # Add supplied libraries
  198. LIBS="$TOBASE $TOADD"
  199. # Get a unique tempdir and make it get auto removed on exit
  200. TMPDIR=`mktemp -d`
  201. trap "rm -rf $TMPDIR" EXIT
  202. # --------------------------------------------------
  203. # Collect libraries and Smalltalk files looking
  204. # both locally and in $JTALK/js and $JTALK/st
  205. # --------------------------------------------------
  206. PROGRAM=
  207. until [ "$*" = "" ]
  208. do
  209. case $1 in
  210. *.st)
  211. CATEGORY=`basename $1 .st`
  212. if [ -f "$1" ]; then
  213. COMPILE="$COMPILE $1 $CATEGORY"
  214. COMPILED="$COMPILED $PREFIXUSED$CATEGORY.js"
  215. else
  216. if [ -f $JTALK/st/$1 ]; then
  217. COMPILE="$COMPILE $JTALK/st/$1 $CATEGORY"
  218. COMPILED="$COMPILED $PREFIXUSED$CATEGORY.js"
  219. else
  220. echo "JTalk file not found: $1"
  221. exit 1
  222. fi
  223. fi
  224. ;;
  225. *.js)
  226. resolvejs $1
  227. LIBS="$LIBS $RESOLVED"
  228. ;;
  229. *)
  230. # Will end up being the last non js/st argument
  231. PROGRAM=$1
  232. ;;
  233. esac
  234. shift
  235. done
  236. # --------------------------------------------------
  237. # Actual compilation phase of collected .st files
  238. # --------------------------------------------------
  239. # Create compiler dynamically
  240. cat $TOOURCOMPILER > $TMPDIR/compiler.js
  241. # Compile all collected .st files to .js
  242. echo "Loading libraries $TOOURCOMPILER and compiling ..."
  243. node $TMPDIR/compiler.js $DEBUG $PREFIX $COMPILE
  244. # Verify all .js files corresponding to .st files were created, otherwise exit
  245. IFS=" "
  246. for FILE in $COMPILED
  247. do
  248. if [ ! -f "$FILE" ]; then
  249. echo "Failed compilation of $FILE, exiting."
  250. exit 1
  251. fi
  252. done
  253. if [ ! -z $CLOSUREPARTS ]; then
  254. echo "Compiling all js files using Google closure compiler."
  255. ALLJSFILES="$COMPILED $LIBS"
  256. for FILE in $ALLJSFILES
  257. do
  258. mv $FILE $FILE.original
  259. java -jar ~/compiler.jar $CLOSUREOPTS --js $FILE.original --js_output_file $FILE
  260. rm $FILE.original
  261. done
  262. fi
  263. if [ -z $PROGRAM ]; then
  264. echo "Done."
  265. exit 0
  266. fi
  267. # --------------------------------------------------
  268. # Now we start composing resulting javascript file.
  269. # --------------------------------------------------
  270. # Add collected libraries to libs.js file.
  271. if [ ! -z "$LIBS" ]; then
  272. echo "Adding libraries $LIBS ..."
  273. cat $LIBS > $TMPDIR/libs.js
  274. LIBS=$TMPDIR/libs.js
  275. fi
  276. echo "Adding Jtalk code$COMPILED ..."
  277. # Check for init file
  278. if [ ! -z "$INIT" ]; then
  279. if [ -f "$INIT" ]; then
  280. echo "Adding initializer $INIT ..."
  281. else
  282. echo "Can not find init file $INIT, exiting."
  283. exit 1
  284. fi
  285. fi
  286. # Check for adding main
  287. if [ ! -z "$MAIN" ]; then
  288. echo "Adding call to $MAIN class >> main ..."
  289. echo "smalltalk.$MAIN._main()" > $TMPDIR/main.js
  290. MAIN=$TMPDIR/main.js
  291. fi
  292. # Check for adding main file
  293. if [ ! -z "$MAINFILE" ]; then
  294. if [ -f "$MAINFILE" ]; then
  295. echo "Adding main as $MAINFILE ..."
  296. else
  297. echo "Can not find main file $MAINFILE, exiting."
  298. exit 1
  299. fi
  300. MAIN=$MAINFILE
  301. fi
  302. # And finally concatenate Program.js
  303. echo "Writing $PROGRAM.js ..."
  304. cat $LIBS $COMPILED $INIT $MAIN > $PROGRAM.js
  305. echo "Done."
  306. if [ ! -z $CLOSUREFULL ]; then
  307. echo "Compiling $PROGRAM.js file using Google closure compiler."
  308. mv $PROGRAM.js $PROGRAM.js.original
  309. java -jar ~/compiler.jar $CLOSUREOPTS --js $PROGRAM.js.original --js_output_file $PROGRAM.js
  310. rm $PROGRAM.js.original
  311. echo "Done."
  312. fi