diff --git a/Jakefile b/Jakefile index 1f5f22be4..d6e0210a5 100644 --- a/Jakefile +++ b/Jakefile @@ -38,11 +38,7 @@ filedir ($BUILD_CJS_CAPPUCCINO_DEBUG_FRAMEWORKS, ["debug", "release"], function( cp_r(FILE.join($BUILD_DIR, "Debug", "BlendKit"), FILE.join($BUILD_CJS_CAPPUCCINO_DEBUG_FRAMEWORKS, "BlendKit")); }); -task ("CommonJS", [$BUILD_CJS_OBJECTIVE_J_DEBUG_FRAMEWORKS, $BUILD_CJS_CAPPUCCINO_DEBUG_FRAMEWORKS, "debug", "release"], function() -{ - // We have a complete CommonJS, so redo this. - setupEnvironment(); -}); +task ("CommonJS", [$BUILD_CJS_OBJECTIVE_J_DEBUG_FRAMEWORKS, $BUILD_CJS_CAPPUCCINO_DEBUG_FRAMEWORKS, "debug", "release"]); task ("install", ["CommonJS"], function() { diff --git a/bootstrap.sh b/bootstrap.sh index 124c2dbdc..7a19b51a2 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -24,6 +24,7 @@ function ask_remove_dir () { if [ -d "$dir" ]; then echo "================================================================================" echo "Found an existing Narwhal/Cappuccino installation, $dir. Remove it automatically now?" + echo "WARNING: custom modifications and installed packages in this installation WILL BE DELETED." if prompt; then rm -rf "$dir" fi @@ -76,40 +77,57 @@ PATH_SAVED="$PATH" ask_remove_dir "/usr/local/share/objj" ask_remove_dir "/usr/local/share/narwhal" ask_remove_dir "/usr/local/narwhal" +if which "narwhal" > /dev/null; then + dir=$(dirname -- $(dirname -- $(which "narwhal"))) + ask_remove_dir "$dir" +fi -if ! which "narwhal" > /dev/null; then +install_narwhal="" +if which "narwhal" > /dev/null; then + dir=$(dirname -- $(dirname -- $(which "narwhal"))) + echo "Using Narwhal installation at \"$dir\". Is this correct?" + if ! prompt; then + echo "================================================================================" + echo "Narwhal JavaScript platform is required. Install it automatically now?" + if prompt; then + install_narwhal="yes" + fi + fi +else echo "================================================================================" echo "Narwhal JavaScript platform is required. Install it automatically now?" if prompt; then - echo "================================================================================" - echo "To use the default location, \"$install_directory\", just hit enter/return, or enter another path:" - read input - if [ "$input" ]; then - install_directory="$input" - fi - - if [ "$git_clone" ]; then - git_repo="git://github.com/$github_path.git" - echo "Cloning Narwhal from \"$git_repo\"..." - git clone "$git_repo" "$install_directory" - else - zip_ball="http://github.com/$github_path/zipball/master" - echo "Downloading Narwhal from \"$zip_ball\"..." - curl -L -o "$tmp_zip" "$zip_ball" - echo "Installing Narwhal..." - unzip "$tmp_zip" -d "$install_directory" - rm "$tmp_zip" - - mv $install_directory/$github_project-*/* $install_directory/. - rm -rf $install_directory/$github_project-* - fi - - if ! which "narwhal" > /dev/null; then - export PATH="$install_directory/bin:$PATH" - fi + install_narwhal="yes" fi fi +if [ "$install_narwhal" ]; then + echo "================================================================================" + echo "To use the default location, \"$install_directory\", just hit enter/return, or enter another path:" + read input + if [ "$input" ]; then + install_directory="$input" + fi + + if [ "$git_clone" ]; then + git_repo="git://github.com/$github_path.git" + echo "Cloning Narwhal from \"$git_repo\"..." + git clone "$git_repo" "$install_directory" + else + zip_ball="http://github.com/$github_path/zipball/master" + echo "Downloading Narwhal from \"$zip_ball\"..." + curl -L -o "$tmp_zip" "$zip_ball" + echo "Installing Narwhal..." + unzip "$tmp_zip" -d "$install_directory" + rm "$tmp_zip" + + mv $install_directory/$github_project-*/* $install_directory/. + rm -rf $install_directory/$github_project-* + fi + + export PATH="$install_directory/bin:$PATH" +fi + if ! which "narwhal" > /dev/null; then echo "Problem installing Narwhal. To install Narwhal manually follow the instructions at http://narwhaljs.org/" exit 1 diff --git a/common.jake b/common.jake index bd1ec004d..2fb851ace 100644 --- a/common.jake +++ b/common.jake @@ -1,72 +1,97 @@ +var SYSTEM = require("system"); +var FILE = require("file"); +var OS = require("os"); +var UTIL = require("util"); -function ensurePackageUpToDate(packageName, requiredVersion) +function ensurePackageUpToDate(packageName, requiredVersion, options) { + options = options || {}; + var packageInfo = require("packages").catalog[packageName]; if (!packageInfo) { print("You are missing package \"" + packageName + "\", version " + requiredVersion + " or later. Please install using \"tusk install "+packageName+"\" and re-run jake"); - require("os").exit(1); + OS.exit(1); } - // newer versions of packages provide already split versions - var version = typeof packageInfo.version === "string" ? packageInfo.version.split(".") : packageInfo; - + var version = packageInfo.version; + if (typeof version === "string") + version = version.split("."); + if (typeof requiredVersion === "string") requiredVersion = requiredVersion.split("."); - if (version && require("util").compare(version, requiredVersion) !== -1) + if (version && UTIL.compare(version, requiredVersion) !== -1) return; - print("Your copy of " + packageName + " is out of date (version " + version + "). Update? yes or no:"); + print("Your copy of " + packageName + " is out of date (" + (version||["0"]).join(".") + " installed, " + requiredVersion.join(".") + " required)."); - var response = system.stdin.readLine(); - - if (response !== "yes\n") + if (!options.noupdate) { - print("Jake aborted."); - require("os").exit(1); + print("Update? yes or no:"); + if (system.stdin.readLine() !== "yes\n") + { + print("Jake aborted."); + OS.exit(1); + } + OS.system(["tusk", "install", "--force", packageName]); + } + + if (options.message) + { + print(options.message) + OS.exit(1); } - - require("os").system("NARWHAL_ENGINE_HOME='' NARWHAL_ENGINE=rhino tusk install --force " + packageName); } // UPDATE THESE TO PICK UP CORRESPONDING CHANGES IN DEPENDENCIES -ensurePackageUpToDate("jake", "0.1.2"); -ensurePackageUpToDate("browserjs", "0.1.1"); +ensurePackageUpToDate("jake", "0.1.2"); +ensurePackageUpToDate("browserjs", "0.1.1"); +ensurePackageUpToDate("narwhal", "0.2.1", { + noupdate : true, + message : "Update Narwhal to 0.2.1 by running bootstrap.sh, or pulling the latest from git (see: http://github.com/280north/narwhal)." +}); +ensurePackageUpToDate("narwhal-jsc", "0.1.1", { + message : "Rebuild narwhal-jsc by changing to the narwhal-jsc package directory and running \"make webkit\"." +}); -var Jake = require("jake"); +var JAKE = require("jake"); -global.ENV = require("system").env; -global.ARGV = require("system").args -global.FILE = require("file"); -global.OS = require("os"); +// Set up development environment variables. -global.task = Jake.task; -global.directory = Jake.directory; -//global.file = Jake.file; -global.filedir = Jake.filedir; -global.FileList = Jake.FileList; +// record the initial SYSTEM.env so we know which need to be serialized later +var envInitial = Object.freeze(UTIL.copy(SYSTEM.env)); + +SYSTEM.env["BUILD_PATH"] = FILE.absolute( + SYSTEM.env["BUILD_PATH"] || + SYSTEM.env["CAPP_BUILD"] || // Global Cappuccino build directory. + SYSTEM.env["STEAM_BUILD"] || // Maintain backwards compatibility with steam. + FILE.join(FILE.dirname(module.path), "Build") // Just build here. +); + +if (!SYSTEM.env["CAPP_BUILD"] && SYSTEM.env["STEAM_BUILD"]) + system.stderr.print("STEAM_BUILD environment variable is deprecated; Please use CAPP_BUILD instead."); + +if (!SYSTEM.env["CONFIG"]) + SYSTEM.env["CONFIG"] = "Release"; + +// TODO: deprecate these globals +global.ENV = SYSTEM.env; +global.ARGV = SYSTEM.args +global.FILE = FILE; +global.OS = OS; + +global.task = JAKE.task; +global.directory = JAKE.directory; +//global.file = JAKE.file; +global.filedir = JAKE.filedir; +global.FileList = JAKE.FileList; global.CLEAN = require("jake/clean").CLEAN; global.CLOBBER = require("jake/clean").CLOBBER; - -// Read in and set up development environment variables. - -ENV["BUILD_PATH"] = FILE.absolute( - ENV["BUILD_PATH"] || - ENV["CAPP_BUILD"] || // Global Cappuccino build directory. - ENV["STEAM_BUILD"] || // Maintain backwards compatibility with steam. - FILE.join(FILE.dirname(module.path), "Build") // Just build here. -); - -if (!ENV["CAPP_BUILD"] && ENV["STEAM_BUILD"]) - system.stderr.print("STEAM_BUILD is deprecated, please use CAPP_BUILD instead"); - -ENV["CONFIG"] = ENV["CONFIG"] || "Release"; - -global.$CONFIGURATION = ENV['CONFIG']; -global.$BUILD_DIR = ENV['BUILD_PATH']; +global.$CONFIGURATION = SYSTEM.env['CONFIG']; +global.$BUILD_DIR = SYSTEM.env['BUILD_PATH']; global.$BUILD_CONFIGURATION_DIR = FILE.join($BUILD_DIR, $CONFIGURATION); global.$BUILD_CJS_OBJECTIVE_J = FILE.join($BUILD_CONFIGURATION_DIR, "CommonJS", "objective-j"); @@ -79,75 +104,107 @@ global.$BUILD_CJS_CAPPUCCINO_FRAMEWORKS = FILE.join($BUILD_CJS_CAPPUCCINO, "Fram global.$HOME_DIR = FILE.absolute(FILE.dirname(module.path)); global.$LICENSE_FILE = FILE.absolute(FILE.join(FILE.dirname(module.path), 'LICENSE')); -function partial_require(path, exports) + +// logic to determine which packages should be loaded but are not. +// used in serializedENV() +function additionalPackages() { - var lib = FILE.join(path, "lib"); - - if (!FILE.exists(lib)) - return false; - - require.paths.unshift(lib); - - if (FILE.exists(FILE.join(path, "package.json"))) - { - var catalog = require("json").parse(FILE.read(FILE.join(path, "package.json"), { charset:"UTF8" })); - - if (catalog.preload) - { - if (!Array.isArray(catalog.preload)) - catalog.preload = [catalog.preload]; - - catalog.preload.forEach(function(preload) - { - require(preload); - }); - } + var unbuiltObjectiveJPackage = FILE.path($HOME_DIR).join("Objective-J", "CommonJS", ""); + var builtObjectiveJPackage = FILE.path($BUILD_CONFIGURATION_DIR).join("CommonJS", "objective-j", ""); + var builtCappuccinoPackage = FILE.path($BUILD_CONFIGURATION_DIR).join("CommonJS", "cappuccino", ""); + + var packages = []; + + // load built objective-j if exists, otherwise unbuilt + // FIXME: this isn't quite correct. sometimes we want the unbuilt one to have priority. + if (builtObjectiveJPackage.join("package.json").exists()) { + if (!packageInCatalog(builtObjectiveJPackage)) + packages.push(builtObjectiveJPackage); + } else { + if (!packageInCatalog(unbuiltObjectiveJPackage)) + packages.push(unbuiltObjectiveJPackage); } - - var bin = FILE.join(path, "bin"), - system = OS.system; - - // FIXME: is there a better way to do this??? - OS.system = function(aCommand) - { - if (Array.isArray(aCommand)) - aCommand = aCommand.map(OS.enquote).join(" "); - - return system("PATH=" + OS.enquote(bin) + ":$PATH " + aCommand); + + // load built cappuccino if it exists + if (builtCappuccinoPackage.join("package.json").exists()) { + if (!packageInCatalog(builtCappuccinoPackage)) + packages.push(builtCappuccinoPackage); } - - return true; + + return packages; } -global.setupEnvironment = function() +// checks to see if a path is in the package catalog +function packageInCatalog(path) { - if (partial_require(FILE.join($BUILD_CONFIGURATION_DIR, "CommonJS", "objective-j")) || - partial_require(FILE.join($HOME_DIR, "Objective-J", "CommonJS"))) - { - var OBJECTIVE_J_JAKE = require("objective-j/jake"); + var catalog = require("packages").catalog; + for (var name in catalog) + if (String(catalog[name].directory) === String(path)) + return true; + return false; +} +function serializedENV() +{ + var envNew = {}; + + // add changed keys to the new ENV + Object.keys(SYSTEM.env).forEach(function(key) { + if (SYSTEM.env[key] !== envInitial[key]) + envNew[key] = SYSTEM.env[key]; + }); + + // pseudo-HACK: add NARWHALOPT with packages we should ensure are loaded + var packages = additionalPackages(); + if (packages.length) + envNew["NARWHALOPT"] = packages.map(function(p) { return "-p " + p; }).join(" "); + + return Object.keys(envNew).map(function(key) { + return key + "=" + OS.enquote(envNew[key]); + }).join(" "); +} + +function reforkWithPackages() +{ + if (additionalPackages().length > 0) { + var cmd = serializedENV() + " " + system.args.map(OS.enquote).join(" "); + //print("REFORKING: " + cmd); + OS.exit(OS.system(cmd)); + } +} + +reforkWithPackages(); + +function setupEnvironment() +{ + // TODO: deprecate these globals + try { + var OBJECTIVE_J_JAKE = require("objective-j/jake"); + global.app = OBJECTIVE_J_JAKE.app; global.bundle = OBJECTIVE_J_JAKE.bundle; global.framework = OBJECTIVE_J_JAKE.framework; global.BundleTask = OBJECTIVE_J_JAKE.BundleTask; + } catch (e) { + //print("setupEnvironment (app, bundle, framework, BundleTask): " + e); } - - if (partial_require(FILE.join($BUILD_CONFIGURATION_DIR, "CommonJS", "cappuccino"))) - { - require("objective-j"); - require("browser/window").OBJJ_INCLUDE_PATHS.push(FILE.join($BUILD_CONFIGURATION_DIR, "CommonJS", "cappuccino", "Frameworks")); - - try - { - var CAPPUCCINO_JAKE = require("cappuccino/jake"); - - if (CAPPUCCINO_JAKE.blend) - global.blend = CAPPUCCINO_JAKE.blend; - } - catch (anException) - { - } + + try { + require("objective-j").OBJJ_INCLUDE_PATHS.push(FILE.join($BUILD_CONFIGURATION_DIR, "CommonJS", "cappuccino", "Frameworks")); + } catch (e) { + //print("setupEnvironment (OBJJ_INCLUDE_PATHS): " + e); + } + + try { + var CAPPUCCINO_JAKE = require("cappuccino/jake"); + if (CAPPUCCINO_JAKE.blend) + global.blend = CAPPUCCINO_JAKE.blend; + //else + // print("no blend!") + } + catch (e) { + //print("setupEnvironment (blend): " + e); } } @@ -181,19 +238,6 @@ global.mv = function(/*String*/ from, /*String*/ to) FILE.move(from, to); } -function serializedENV() -{ - var serialized = ""; - - if (ENV["CONFIG"]) - serialized += "CONFIG=\"" + ENV["CONFIG"] + "\""; - - if (ENV["BUILD_DIR"]) - serialized += "BUILD_DIR=\"" + ENV["BUILD_DIR"] + "\""; - - return serialized; -} - global.subjake = function(/*Array*/ directories, /*String*/ aTaskName) { if (!Array.isArray(directories)) @@ -203,7 +247,7 @@ global.subjake = function(/*Array*/ directories, /*String*/ aTaskName) { if (FILE.isDirectory(aDirectory) && FILE.isFile(FILE.join(aDirectory, "Jakefile"))) { - var returnCode = OS.system("cd " + aDirectory + " && " + serializedENV() + " " + ARGV[0] + " " + aTaskName); + var returnCode = OS.system("cd " + aDirectory + " && " + serializedENV() + " " + SYSTEM.args[0] + " " + aTaskName); if (returnCode) OS.exit(returnCode); } @@ -214,13 +258,13 @@ global.subjake = function(/*Array*/ directories, /*String*/ aTaskName) global.executableExists = function(/*String*/ aFileName) { - return ENV["PATH"].split(':').some(function(/*String*/ aPath) + return SYSTEM.env["PATH"].split(':').some(function(/*String*/ aPath) { return FILE.exists(FILE.join(aPath, aFileName)); }); } -$OBJJ_TEMPLATE_EXECUTABLE = FILE.join($HOME_DIR, "Objective-J", "CommonJS", "objj-executable"); +$OBJJ_TEMPLATE_EXECUTABLE = FILE.join($HOME_DIR, "Objective-J", "CommonJS", "objj-executable"); global.make_objj_executable = function(aPath) { @@ -235,67 +279,6 @@ global.symlink_executable = function(source) FILE.symlink(relative, destination); } -task ("build"); -task ("default", "build"); - -task ("release", function() -{ - ENV["CONFIG"] = "Release"; - spawnJake("build"); -}); - -task ("debug", function() -{ - ENV["CONFIG"] = "Debug"; - spawnJake("build"); -}); - -task ("all", ["debug", "release"]); - -task ("clean-debug", function() -{ - ENV['CONFIG'] = 'Debug' - spawnJake("clean"); -}); - -task ("cleandebug", ["clean-debug"]); - -task ("clean-release", function() -{ - ENV["CONFIG"] = "Release"; - spawnJake("clean"); -}); - -task ("cleanrelease", ["clean-release"]); - -task ("clean-all", ["clean-debug", "clean-release"]); -task ("cleanall", ["clean-all"]); - -task ("clobber-debug", function() -{ - ENV["CONFIG"] = "Debug"; - spawnJake("clobber"); -}); - -task ("clobberdebug", ["clobber-debug"]); - -task ("clobber-release", function() -{ - ENV["CONFIG"] = "Release"; - spawnJake("clobber"); -}); - -task ("clobberrelease", ['clobber-release']); - -task ("clobber-all", ["clobber-debug", "clobber-release"]); -task ("clobberall", ["clobber-all"]); - -function spawnJake(/*String*/ aTaskName) -{ - if (OS.system(serializedENV() + " " + ARGV[0] + " " + aTaskName)) - OS.exit(1);//rake abort if ($? != 0) -} - global.subtasks = function(subprojects, taskNames) { taskNames.forEach(function(aTaskName) @@ -310,3 +293,66 @@ global.subtasks = function(subprojects, taskNames) }); }); } + +function spawnJake(/*String*/ aTaskName) +{ + if (OS.system(serializedENV() + " " + SYSTEM.args[0] + " " + aTaskName)) + OS.exit(1);//rake abort if ($? != 0) +} + +// built in tasks + +task ("build"); +task ("default", "build"); + +task ("release", function() +{ + SYSTEM.env["CONFIG"] = "Release"; + spawnJake("build"); +}); + +task ("debug", function() +{ + SYSTEM.env["CONFIG"] = "Debug"; + spawnJake("build"); +}); + +task ("all", ["debug", "release"]); + +task ("clean-debug", function() +{ + SYSTEM.env['CONFIG'] = 'Debug' + spawnJake("clean"); +}); + +task ("cleandebug", ["clean-debug"]); + +task ("clean-release", function() +{ + SYSTEM.env["CONFIG"] = "Release"; + spawnJake("clean"); +}); + +task ("cleanrelease", ["clean-release"]); + +task ("clean-all", ["clean-debug", "clean-release"]); +task ("cleanall", ["clean-all"]); + +task ("clobber-debug", function() +{ + SYSTEM.env["CONFIG"] = "Debug"; + spawnJake("clobber"); +}); + +task ("clobberdebug", ["clobber-debug"]); + +task ("clobber-release", function() +{ + SYSTEM.env["CONFIG"] = "Release"; + spawnJake("clobber"); +}); + +task ("clobberrelease", ['clobber-release']); + +task ("clobber-all", ["clobber-debug", "clobber-release"]); +task ("clobberall", ["clobber-all"]);