Browse Source

Merge pull request #700 from mkroehnert/compiler

Compilerflag for specifying js library search directories
Nicolas Petton 11 years ago
parent
commit
29140f5939
4 changed files with 71 additions and 51 deletions
  1. 2 16
      Gruntfile.js
  2. 22 9
      bin/amberc
  3. 31 20
      bin/amberc.js
  4. 16 6
      grunt/tasks/grunt-amberc.js

+ 2 - 16
Gruntfile.js

@@ -53,12 +53,6 @@ module.exports = function(grunt) {
         src: ['st/Kernel-Objects.st', 'st/Kernel-Classes.st', 'st/Kernel-Methods.st', 'st/Kernel-Collections.st',
         src: ['st/Kernel-Objects.st', 'st/Kernel-Classes.st', 'st/Kernel-Methods.st', 'st/Kernel-Collections.st',
               'st/Kernel-Infrastructure.st', 'st/Kernel-Exceptions.st', 'st/Kernel-Transcript.st', 'st/Kernel-Announcements.st']
               'st/Kernel-Infrastructure.st', 'st/Kernel-Exceptions.st', 'st/Kernel-Transcript.st', 'st/Kernel-Announcements.st']
       },
       },
-      amber_compiler: {
-        output_dir : 'js',
-        src: ['st/Importer-Exporter.st', 'st/Compiler-Exceptions.st', 'st/Compiler-Core.st', 'st/Compiler-AST.st',
-              'st/Compiler-IR.st', 'st/Compiler-Inlining.st', 'st/Compiler-Semantic.st', 'st/Compiler-Interpreter.st'],
-        output_name: 'Compiler'
-      },
       amber_canvas: {
       amber_canvas: {
         output_dir : 'js',
         output_dir : 'js',
         src: ['st/Canvas.st', 'st/SUnit.st']
         src: ['st/Canvas.st', 'st/SUnit.st']
@@ -77,25 +71,17 @@ module.exports = function(grunt) {
         src: ['test/Test.st'],
         src: ['test/Test.st'],
         libraries: [
         libraries: [
         'Compiler-Exceptions', 'Compiler-Core', 'Compiler-AST',
         'Compiler-Exceptions', 'Compiler-Core', 'Compiler-AST',
-        'Compiler-IR', 'Compiler-Inlining', 'Compiler-Semantic', 'Compiler-Interpreter', '@parser',
+        'Compiler-IR', 'Compiler-Inlining', 'Compiler-Semantic', 'Compiler-Interpreter', 'parser',
         'SUnit', 'Importer-Exporter',
         'SUnit', 'Importer-Exporter',
         'Kernel-Tests', 'Compiler-Tests', 'SUnit-Tests'],
         'Kernel-Tests', 'Compiler-Tests', 'SUnit-Tests'],
         output_name: 'test/amber_test_runner'
         output_name: 'test/amber_test_runner'
       },
       },
-      amber_dev: {
-        src: [
-              'Compiler-Exceptions.js', 'Compiler-Core.js', 'Compiler-AST.js',
-              'Compiler-IR.js', 'Compiler-Inlining.js', 'Compiler-Semantic.js',
-              'Canvas.js', 'IDE.js', 'SUnit.js',
-              'Kernel-Tests.js', 'Compiler-Tests.js', 'SUnit-Tests.js'],
-        output_name: 'js/amber_dev'
-      },
       amber_cli: {
       amber_cli: {
         output_dir: 'cli/js',
         output_dir: 'cli/js',
         src: ['cli/st/AmberCli.st'],
         src: ['cli/st/AmberCli.st'],
         libraries: [
         libraries: [
             'Compiler-Exceptions', 'Compiler-Core', 'Compiler-AST',
             'Compiler-Exceptions', 'Compiler-Core', 'Compiler-AST',
-            'Compiler-IR', 'Compiler-Inlining', 'Compiler-Semantic', 'Compiler-Interpreter', '@parser'
+            'Compiler-IR', 'Compiler-Inlining', 'Compiler-Semantic', 'Compiler-Interpreter', 'parser'
         ],
         ],
         main_class: 'AmberCli',
         main_class: 'AmberCli',
         output_name: '../../bin/amber-cli',
         output_name: '../../bin/amber-cli',

+ 22 - 9
bin/amberc

@@ -20,7 +20,7 @@ var amber_dir = path.normalize(path.join(path.dirname(process.argv[1]), '..'));
 
 
 var compiler = new amberc.Compiler(amber_dir);
 var compiler = new amberc.Compiler(amber_dir);
 
 
-var configuration = handle_options(parameters, amber_dir);
+var configuration = handle_options(parameters);
 
 
 compiler.main(configuration);
 compiler.main(configuration);
 
 
@@ -29,16 +29,19 @@ compiler.main(configuration);
  * Process given program options and update defaults values.
  * Process given program options and update defaults values.
  * Followed by check_for_closure_compiler() and then collect_files().
  * Followed by check_for_closure_compiler() and then collect_files().
  */
  */
-function handle_options(optionsArray, amber_dir) {
+function handle_options(optionsArray) {
 	var programName = [];
 	var programName = [];
 	var currentItem = optionsArray.shift();
 	var currentItem = optionsArray.shift();
-	var defaults = amberc.createDefaults(amber_dir);
+	var defaults = amberc.createDefaults();
 
 
 	while(undefined !== currentItem) {
 	while(undefined !== currentItem) {
 		switch(currentItem) {
 		switch(currentItem) {
 			case '-l':
 			case '-l':
 				defaults.load.push.apply(defaults.load, optionsArray.shift().split(','));
 				defaults.load.push.apply(defaults.load, optionsArray.shift().split(','));
 				break;
 				break;
+			case '-L':
+				defaults.jsLibraryDirs.push.apply(defaults.jsLibraryDirs, optionsArray.shift().split(','));
+				break;
 			case '-g':
 			case '-g':
 				defaults.jsGlobals.push.apply(defaults.jsGlobals, optionsArray.shift().split(','));
 				defaults.jsGlobals.push.apply(defaults.jsGlobals, optionsArray.shift().split(','));
 				break;
 				break;
@@ -99,8 +102,8 @@ function handle_options(optionsArray, amber_dir) {
 
 
 // print available flags
 // print available flags
 function print_usage() {
 function print_usage() {
-	console.log('Usage: amberc [-l lib1,lib2...] [-i init_file] [-m main_class] [-M main_file]');
-	console.log('          [-o] [-O|-A] [-d] [-s suffix] [-S suffix] [file1 [file2 ...]] [Program]');
+	console.log('Usage: amberc [-l lib1,lib2...] [-g jsGlobal1,jsGlobla2] [-m main_class] [-M main_file]');
+	console.log('          [-n namespace] [-D output_dir] [-v] [-s suffix] [-S suffix] [file1 [file2 ...]] [Program]');
 	console.log('');
 	console.log('');
 	console.log('   amberc compiles Amber files - either separately or into a complete runnable');
 	console.log('   amberc compiles Amber files - either separately or into a complete runnable');
 	console.log('   program. If no .st files are listed only a linking stage is performed.');
 	console.log('   program. If no .st files are listed only a linking stage is performed.');
@@ -120,10 +123,18 @@ function print_usage() {
 	console.log('   If no <Program> is specified each given .st file will be compiled into');
 	console.log('   If no <Program> is specified each given .st file will be compiled into');
 	console.log('   a matching .js file. Otherwise a <Program>.js file is linked together based on');
 	console.log('   a matching .js file. Otherwise a <Program>.js file is linked together based on');
 	console.log('   the given options:');
 	console.log('   the given options:');
+	console.log('');
 	console.log('  -l library1,library2');
 	console.log('  -l library1,library2');
 	console.log('     Add listed JavaScript libraries in listed order.');
 	console.log('     Add listed JavaScript libraries in listed order.');
 	console.log('     Libraries are not separated by spaces or end with .js.');
 	console.log('     Libraries are not separated by spaces or end with .js.');
 	console.log('');
 	console.log('');
+	console.log('  -L directory1,directory2');
+	console.log('     Add listed directories to the library search path.');
+	console.log('     The order of processing is:');
+	console.log('     1. current directory');
+	console.log('     2. directories specified by -L');
+	console.log('     3. $AMBER');
+	console.log('');
 	console.log('  -g jsGlobal1,jsGlobal2');
 	console.log('  -g jsGlobal1,jsGlobal2');
 	console.log('     Comma separated list of JS global variable names.');
 	console.log('     Comma separated list of JS global variable names.');
 	console.log('     The names are added to a list containing "window", "document" and others.');
 	console.log('     The names are added to a list containing "window", "document" and others.');
@@ -138,6 +149,9 @@ function print_usage() {
 	console.log('     Export packages with <amd_namespace> as the require.js namespace.');
 	console.log('     Export packages with <amd_namespace> as the require.js namespace.');
 	console.log('     Default value is "amber_core".');
 	console.log('     Default value is "amber_core".');
 	console.log('');
 	console.log('');
+	console.log('  -v');
+	console.log('     Produce a more verbose output.');
+	console.log('');
 	console.log('  -D');
 	console.log('  -D');
 	console.log('     Specifies the output directory for all generated .js files.');
 	console.log('     Specifies the output directory for all generated .js files.');
 	console.log('     The hierarchy of the input files is not maintaned.');
 	console.log('     The hierarchy of the input files is not maintaned.');
@@ -164,9 +178,8 @@ function print_usage() {
 	console.log('        amberc -m Hello Hello.st Program');
 	console.log('        amberc -m Hello Hello.st Program');
 	console.log('');
 	console.log('');
 	console.log('     Compile Cat1.st and Cat2.st files into corresponding .js files.');
 	console.log('     Compile Cat1.st and Cat2.st files into corresponding .js files.');
-	console.log('     Link them with myboot.js and myKernel.js and add myinit.js as custom');
-	console.log('     initializer file. Add main.js last which contains the startup code');
-	console.log('      and merge everything into a complete program named Program.js:');
+	console.log('     Link them with myboot.js and myKernel.js');
+	console.log('     and merge everything into a complete program named Program.js:');
 	console.log('');
 	console.log('');
-	console.log('        amberc -M main.js -i myinit.js myboot.js myKernel.js Cat1.st Cat2.st Program');
+	console.log('        amberc -M main.js myboot.js myKernel.js Cat1.st Cat2.st Program');
 };
 };

+ 31 - 20
bin/amberc.js

@@ -126,14 +126,17 @@ var path = require('path'),
 /**
 /**
  * AmberC constructor function.
  * AmberC constructor function.
  * amber_dir: points to the location of an amber installation
  * amber_dir: points to the location of an amber installation
- * closure_jar: location of compiler.jar (can be left undefined)
  */
  */
 function AmberC(amber_dir) {
 function AmberC(amber_dir) {
+	if (undefined === amber_dir || !fs.existsSync(amber_dir)) {
+		throw new Error('amber_dir needs to be a valid directory');
+	}
+
 	this.amber_dir = amber_dir;
 	this.amber_dir = amber_dir;
-	this.kernel_libraries = ['@boot', '@smalltalk', '@nil', '@_st', 'Kernel-Objects', 'Kernel-Classes', 'Kernel-Methods',
+	this.kernel_libraries = ['boot', 'smalltalk', 'nil', '_st', 'Kernel-Objects', 'Kernel-Classes', 'Kernel-Methods',
 							'Kernel-Collections', 'Kernel-Infrastructure', 'Kernel-Exceptions', 'Kernel-Transcript',
 							'Kernel-Collections', 'Kernel-Infrastructure', 'Kernel-Exceptions', 'Kernel-Transcript',
 							'Kernel-Announcements'];
 							'Kernel-Announcements'];
-	this.compiler_libraries = this.kernel_libraries.concat(['@parser', 'Importer-Exporter', 'Compiler-Exceptions',
+	this.compiler_libraries = this.kernel_libraries.concat(['parser', 'Importer-Exporter', 'Compiler-Exceptions',
 							'Compiler-Core', 'Compiler-AST', 'Compiler-Exceptions', 'Compiler-IR', 'Compiler-Inlining', 'Compiler-Semantic']);
 							'Compiler-Core', 'Compiler-AST', 'Compiler-Exceptions', 'Compiler-IR', 'Compiler-Inlining', 'Compiler-Semantic']);
 }
 }
 
 
@@ -141,11 +144,7 @@ function AmberC(amber_dir) {
 /**
 /**
  * Default values.
  * Default values.
  */
  */
-var createDefaults = function(amber_dir, finished_callback){
-	if (undefined === amber_dir) {
-		throw new Error('createDefaults() function needs a valid amber_dir parameter');
-	}
-
+var createDefaults = function(finished_callback){
 	return {
 	return {
 		'load': [],
 		'load': [],
 		'main': undefined,
 		'main': undefined,
@@ -158,6 +157,7 @@ var createDefaults = function(amber_dir, finished_callback){
 		'loadsuffix': '',
 		'loadsuffix': '',
 		'suffix_used': '',
 		'suffix_used': '',
 		'libraries': [],
 		'libraries': [],
+		'jsLibraryDirs': [],
 		'compile': [],
 		'compile': [],
 		'compiled': [],
 		'compiled': [],
 		'program': undefined,
 		'program': undefined,
@@ -184,6 +184,11 @@ AmberC.prototype.main = function(configuration, finished_callback) {
 		configuration.amd_namespace = 'amber_core';
 		configuration.amd_namespace = 'amber_core';
 	}
 	}
 
 
+	if (undefined !== configuration.jsLibraryDirs) {
+		configuration.jsLibraryDirs.push(path.join(this.amber_dir, 'js'));
+		configuration.jsLibraryDirs.push(path.join(this.amber_dir, 'support'));
+	}
+
 	console.ambercLog = console.log;
 	console.ambercLog = console.log;
 	if (false === configuration.verbose) {
 	if (false === configuration.verbose) {
 		console.log = function() {};
 		console.log = function() {};
@@ -213,32 +218,38 @@ AmberC.prototype.check_configuration_ok = function(configuration) {
 
 
 
 
 /**
 /**
- * Check if the file given as parameter exists in the local directory or in $AMBER/js/.
- * '.js' is appended first.
+ * Check if the file given as parameter exists in any of the following directories:
+ *  1. current local directory
+ *  2. defauls.jsLibraryDirs
+ *  3. $AMBER/js/
+ *  3. $AMBER/support/
  *
  *
  * @param filename name of a file without '.js' prefix
  * @param filename name of a file without '.js' prefix
  * @param callback gets called on success with path to .js file as parameter
  * @param callback gets called on success with path to .js file as parameter
  */
  */
 AmberC.prototype.resolve_js = function(filename, callback) {
 AmberC.prototype.resolve_js = function(filename, callback) {
-	var special = filename[0] == "@";
-	if (special) {
-		filename = filename.slice(1);
-	}
 	var baseName = path.basename(filename, '.js');
 	var baseName = path.basename(filename, '.js');
 	var jsFile = baseName + this.defaults.loadsuffix + '.js';
 	var jsFile = baseName + this.defaults.loadsuffix + '.js';
-	var amberJsFile = path.join(this.amber_dir, special?'support':'js', jsFile);
+	var defaults = this.defaults;
 	console.log('Resolving: ' + jsFile);
 	console.log('Resolving: ' + jsFile);
 	fs.exists(jsFile, function(exists) {
 	fs.exists(jsFile, function(exists) {
 		if (exists) {
 		if (exists) {
 			callback(jsFile);
 			callback(jsFile);
 		} else {
 		} else {
-			fs.exists(amberJsFile, function(exists) {
-				if (exists) {
-					callback(amberJsFile);
-				} else {
-					throw(new Error('JavaScript file not found: ' + jsFile));
+			var amberJsFile = '';
+			// check for specified .js file in any of the directories from jsLibraryDirs
+			var notFound = defaults.jsLibraryDirs.every(function(directory) {
+				amberJsFile = path.join(directory, jsFile);
+				if (fs.existsSync(amberJsFile)) {
+					return false;
 				}
 				}
+				return true;
 			});
 			});
+			if (notFound) {
+				throw(new Error('JavaScript file not found: ' + jsFile));
+			} else {
+				callback(amberJsFile);
+			}
 		}
 		}
 	});
 	});
 };
 };

+ 16 - 6
grunt/tasks/grunt-amberc.js

@@ -15,11 +15,15 @@ module.exports = function(grunt) {
 
 
      amberc: {
      amberc: {
        options: {
        options: {
-         amber_dir: process.cwd(),     // REQUIRED
-         verbose: true                 // optional
+         amber_dir: process.cwd(),                // REQUIRED
+         library_dirs: ['dir1', '/usr/local/js'], // optional
+         verbose: true                            // optional
        },
        },
        helloWorld: {
        helloWorld: {
-         options: {                             // the 'options' object is optional
+         // this 'options' object is optional as well as all parameters inside it
+         // they can be used to override the global 'options'
+         options: {
+           library_dirs: ['dir1', '/usr/local/js'], // optional
            verbose: true
            verbose: true
          },
          },
          src: ['projects/HelloWorld/st/HelloWorld.st'], // REQUIRED
          src: ['projects/HelloWorld/st/HelloWorld.st'], // REQUIRED
@@ -42,9 +46,11 @@ module.exports = function(grunt) {
 
 
     var options = this.options({
     var options = this.options({
       amber_dir: undefined,
       amber_dir: undefined,
+      library_dirs: [],
       verbose: grunt.option('verbose') || false
       verbose: grunt.option('verbose') || false
     });
     });
     this.data.verbose = options.verbose;
     this.data.verbose = options.verbose;
+    this.data.library_dirs = options.library_dirs;
 
 
     // mark required properties
     // mark required properties
     this.requiresConfig('amberc.options.amber_dir');
     this.requiresConfig('amberc.options.amber_dir');
@@ -57,7 +63,7 @@ module.exports = function(grunt) {
     var compiler = new amberc.Compiler(grunt.config('amberc.options.amber_dir'));
     var compiler = new amberc.Compiler(grunt.config('amberc.options.amber_dir'));
 
 
     // generate the amberc configuration out of the given target properties
     // generate the amberc configuration out of the given target properties
-    var configuration = generateCompilerConfiguration(this.data, this.filesSrc, grunt.config('amberc.options.amber_dir'));
+    var configuration = generateCompilerConfiguration(this.data, this.filesSrc);
 
 
     // run the compiler and call the async callback once finished
     // run the compiler and call the async callback once finished
     var self = this;
     var self = this;
@@ -68,14 +74,18 @@ module.exports = function(grunt) {
   });
   });
 
 
 
 
-  function generateCompilerConfiguration(data, sourceFiles, amber_dir) {
-    var configuration = amberc.createDefaults(amber_dir);
+  function generateCompilerConfiguration(data, sourceFiles) {
+    var configuration = amberc.createDefaults();
     var parameters = [];
     var parameters = [];
 
 
     var libraries = data.libraries;
     var libraries = data.libraries;
     if (undefined !== libraries) {
     if (undefined !== libraries) {
       configuration.load = libraries;
       configuration.load = libraries;
     }
     }
+    var library_dirs = data.library_dirs;
+    if (undefined !== library_dirs) {
+      configuration.jsLibraryDirs = library_dirs;
+    }
     var mainClass = data.main_class;
     var mainClass = data.main_class;
     if (undefined !== mainClass) {
     if (undefined !== mainClass) {
       configuration.main = mainClass;
       configuration.main = mainClass;