jtalkc 9.5 KB

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