Initial support for modular JS output
This commit is contained in:
72
include.xml
72
include.xml
@@ -68,6 +68,78 @@
|
||||
<haxedef name="lime-openal" unless="lime-console || static_link || flash || html5" />
|
||||
<haxedef name="lime-openal" if="emscripten" />
|
||||
|
||||
<!-- TODO: Fix inheritance with separate modules -->
|
||||
|
||||
<set name="module-name" value="lime" unless="openfl" />
|
||||
<set name="module-name" value="openfl" if="openfl" />
|
||||
|
||||
<module name="${module-name}" if="html5 modular">
|
||||
|
||||
<source path="${HAXE_STD_PATH}" package="js.html" />
|
||||
<source path="${HAXE_STD_PATH}" package="haxe.ds" />
|
||||
<source path="${HAXE_STD_PATH}" package="haxe.io" />
|
||||
|
||||
<class name="haxe.CallStack" />
|
||||
<class name="haxe.Log" />
|
||||
<class name="haxe.Timer" />
|
||||
<!-- <class name="js.Boot" /> -->
|
||||
<class name="js.Browser" />
|
||||
<class name="js.Cookie" />
|
||||
<class name="js.Error" />
|
||||
<class name="js.Lib" />
|
||||
<class name="js.Promise" />
|
||||
<class name="js.RegExp" />
|
||||
<class name="js.Selection" />
|
||||
<class name="js.XMLSocket" />
|
||||
<class name="EReg" />
|
||||
<class name="HxOverrides" />
|
||||
<class name="List" />
|
||||
<class name="Math" />
|
||||
<class name="Reflect" />
|
||||
<!-- <class name="Std" /> -->
|
||||
<class name="StringBuf" />
|
||||
<class name="StringTools" />
|
||||
<class name="Type" />
|
||||
|
||||
<include type="haxe.ds._StringMap.StringMapIterator" />
|
||||
<include type="haxe.ds.TreeNode" />
|
||||
<include type="haxe.IMap" />
|
||||
<include type="haxe._Int64.___Int64" />
|
||||
<include type="haxe.StackItem" />
|
||||
<include type="js.html._CanvasElement.CanvasUtil" />
|
||||
<!-- <include type="js._Boot.HaxeError" /> -->
|
||||
<include type="_List.ListIterator" />
|
||||
|
||||
</module>
|
||||
|
||||
<module name="${module-name}" if="html5 modular">
|
||||
|
||||
<source path="" package="lime" exclude="lime._backend.*|lime.project.*|lime.tools.*|lime.net.*|lime.graphics.console.*" />
|
||||
<source path="" package="lime" include="lime._backend.html5" />
|
||||
|
||||
<class name="lime.net.HTTPRequest" />
|
||||
|
||||
<include type="lime.app._Future.FutureWork" />
|
||||
<include type="lime.graphics.utils._ImageDataUtil.ImageDataView" />
|
||||
<include type="lime.system._ThreadPool.ThreadPoolMessageType" />
|
||||
<include type="lime.AssetLibrary" />
|
||||
|
||||
<exclude type="lime.graphics.console.IndexBuffer" />
|
||||
<exclude type="lime.graphics.console.PointerUtil" />
|
||||
<exclude type="lime.graphics.console.Primitive" />
|
||||
<exclude type="lime.graphics.console.RenderState" />
|
||||
<exclude type="lime.graphics.console.Shader" />
|
||||
<exclude type="lime.graphics.console.Texture" />
|
||||
<exclude type="lime.graphics.console.TextureAddressMode" />
|
||||
<exclude type="lime.graphics.console.TextureData" />
|
||||
<exclude type="lime.graphics.console.TextureFilter" />
|
||||
<exclude type="lime.graphics.console.TextureFormat" />
|
||||
<exclude type="lime.graphics.console.VertexBuffer" />
|
||||
<exclude type="lime.graphics.console.VertexDecl" />
|
||||
<exclude type="lime.graphics.console.VertexOutput" />
|
||||
|
||||
</module>
|
||||
|
||||
</section>
|
||||
|
||||
<haxelib name="hxcpp" if="setup" />
|
||||
|
||||
@@ -49,6 +49,7 @@ class HXProject {
|
||||
public var libraries:Array <Library>;
|
||||
public var libraryHandlers:Map <String, String>;
|
||||
public var meta:MetaData;
|
||||
public var modules:Map<String, ModuleData>;
|
||||
public var ndlls:Array <NDLL>;
|
||||
public var platformType:PlatformType;
|
||||
public var postBuildCallbacks:Array <CLICommand>;
|
||||
@@ -234,6 +235,7 @@ class HXProject {
|
||||
javaPaths = new Array <String> ();
|
||||
libraries = new Array <Library> ();
|
||||
libraryHandlers = new Map <String, String> ();
|
||||
modules = new Map<String, ModuleData> ();
|
||||
ndlls = new Array <NDLL> ();
|
||||
postBuildCallbacks = new Array <CLICommand> ();
|
||||
preBuildCallbacks = new Array <CLICommand> ();
|
||||
@@ -325,6 +327,12 @@ class HXProject {
|
||||
|
||||
ObjectHelper.copyFields (meta, project.meta);
|
||||
|
||||
for (key in modules.keys ()) {
|
||||
|
||||
project.modules.set (key, modules.get (key).clone ());
|
||||
|
||||
}
|
||||
|
||||
for (ndll in ndlls) {
|
||||
|
||||
project.ndlls.push (ndll.clone ());
|
||||
@@ -370,7 +378,7 @@ class HXProject {
|
||||
}
|
||||
|
||||
|
||||
private function filter (text:String, include:Array <String> = null, exclude:Array <String> = null):Bool {
|
||||
private function filter (text:String, include:Array<String> = null, exclude:Array<String> = null):Bool {
|
||||
|
||||
if (include == null) {
|
||||
|
||||
@@ -744,6 +752,21 @@ class HXProject {
|
||||
icons = ArrayHelper.concatUnique (icons, project.icons);
|
||||
javaPaths = ArrayHelper.concatUnique (javaPaths, project.javaPaths, true);
|
||||
libraries = ArrayHelper.concatUnique (libraries, project.libraries, true);
|
||||
|
||||
for (key in project.modules.keys ()) {
|
||||
|
||||
if (modules.exists (key)) {
|
||||
|
||||
modules.get (key).merge (project.modules.get (key));
|
||||
|
||||
} else {
|
||||
|
||||
modules.set (key, project.modules.get (key));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ndlls = ArrayHelper.concatUnique (ndlls, project.ndlls);
|
||||
postBuildCallbacks = postBuildCallbacks.concat (project.postBuildCallbacks);
|
||||
preBuildCallbacks = preBuildCallbacks.concat (project.preBuildCallbacks);
|
||||
|
||||
57
lime/project/ModuleData.hx
Normal file
57
lime/project/ModuleData.hx
Normal file
@@ -0,0 +1,57 @@
|
||||
package lime.project;
|
||||
|
||||
|
||||
import lime.tools.helpers.ArrayHelper;
|
||||
|
||||
|
||||
class ModuleData {
|
||||
|
||||
|
||||
public var classNames:Array<String>;
|
||||
public var excludeTypes:Array<String>;
|
||||
public var haxeflags:Array<String>;
|
||||
public var includeTypes:Array<String>;
|
||||
public var name:String;
|
||||
|
||||
|
||||
public function new (name:String) {
|
||||
|
||||
this.name = name;
|
||||
classNames = [];
|
||||
excludeTypes = [];
|
||||
haxeflags = [];
|
||||
includeTypes = [];
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function clone ():ModuleData {
|
||||
|
||||
var copy = new ModuleData (name);
|
||||
copy.classNames = classNames.copy ();
|
||||
copy.excludeTypes = excludeTypes.copy ();
|
||||
copy.haxeflags = haxeflags.copy ();
|
||||
copy.includeTypes = includeTypes.copy ();
|
||||
return copy;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function merge (other:ModuleData):Bool {
|
||||
|
||||
if (other.name == name) {
|
||||
|
||||
classNames = ArrayHelper.concatUnique (classNames, other.classNames);
|
||||
excludeTypes = ArrayHelper.concatUnique (excludeTypes, other.excludeTypes);
|
||||
haxeflags = ArrayHelper.concatUnique (haxeflags, other.haxeflags);
|
||||
includeTypes = ArrayHelper.concatUnique (includeTypes, other.includeTypes);
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -133,6 +133,10 @@ class ProjectXMLParser extends HXProject {
|
||||
|
||||
defines.set ("debug", "1");
|
||||
|
||||
} else if (targetFlags.exists ("final")) {
|
||||
|
||||
defines.set ("final", "1");
|
||||
|
||||
} else {
|
||||
|
||||
defines.set ("release", "1");
|
||||
@@ -754,6 +758,191 @@ class ProjectXMLParser extends HXProject {
|
||||
}
|
||||
|
||||
|
||||
private function parseModuleElement (element:Fast, basePath:String = "", moduleData:ModuleData = null):Void {
|
||||
|
||||
var topLevel = (moduleData == null);
|
||||
|
||||
var exclude = "";
|
||||
var include = "*";
|
||||
|
||||
if (element.has.include) {
|
||||
|
||||
include = substitute (element.att.include);
|
||||
|
||||
}
|
||||
|
||||
if (element.has.exclude) {
|
||||
|
||||
exclude = substitute (element.att.exclude);
|
||||
|
||||
}
|
||||
|
||||
if (moduleData == null) {
|
||||
|
||||
var name = substitute (element.att.name);
|
||||
|
||||
if (modules.exists (name)) {
|
||||
|
||||
moduleData = modules.get (name);
|
||||
|
||||
} else {
|
||||
|
||||
moduleData = new ModuleData (name);
|
||||
modules.set (name, moduleData);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
switch (element.name) {
|
||||
|
||||
case "module":
|
||||
|
||||
if (element.has.source) {
|
||||
|
||||
var source = PathHelper.combine (basePath, substitute (element.att.source));
|
||||
|
||||
if (!FileSystem.exists (source)) {
|
||||
|
||||
LogHelper.error ("Could not find module source \"" + source + "\"");
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
moduleData.haxeflags.push ("-cp " + source);
|
||||
|
||||
var path = source;
|
||||
|
||||
if (element.has.resolve ("package")) {
|
||||
|
||||
path = PathHelper.combine (source, StringTools.replace (substitute (element.att.resolve ("package")), ".", "/"));
|
||||
|
||||
}
|
||||
|
||||
parseModuleElementSource (source, moduleData, include.split ("|"), exclude.split ("|"), path);
|
||||
|
||||
}
|
||||
|
||||
case "source":
|
||||
|
||||
if (element.has.path) {
|
||||
|
||||
var source = PathHelper.combine (basePath, substitute (element.att.path));
|
||||
|
||||
if (!FileSystem.exists (source)) {
|
||||
|
||||
LogHelper.error ("Could not find module source \"" + source + "\"");
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
moduleData.haxeflags.push ("-cp " + source);
|
||||
|
||||
var path = source;
|
||||
|
||||
if (element.has.resolve ("package")) {
|
||||
|
||||
path = PathHelper.combine (source, StringTools.replace (substitute (element.att.resolve ("package")), ".", "/"));
|
||||
|
||||
}
|
||||
|
||||
parseModuleElementSource (source, moduleData, include.split ("|"), exclude.split ("|"), path);
|
||||
|
||||
}
|
||||
|
||||
case "class":
|
||||
|
||||
moduleData.classNames.push (substitute (element.att.name));
|
||||
|
||||
case "haxedef":
|
||||
|
||||
var value = substitute (element.att.name);
|
||||
|
||||
if (element.has.value) {
|
||||
|
||||
value += "=" + substitute (element.att.value);
|
||||
|
||||
}
|
||||
|
||||
moduleData.haxeflags.push ("-D " + value);
|
||||
|
||||
case "haxeflag":
|
||||
|
||||
var flag = substitute (element.att.name);
|
||||
|
||||
if (element.has.value) {
|
||||
|
||||
flag += " " + substitute (element.att.value);
|
||||
|
||||
}
|
||||
|
||||
moduleData.haxeflags.push (substitute (flag));
|
||||
|
||||
case "include":
|
||||
|
||||
moduleData.includeTypes.push (substitute (element.att.type));
|
||||
|
||||
case "exclude":
|
||||
|
||||
moduleData.excludeTypes.push (substitute (element.att.type));
|
||||
|
||||
}
|
||||
|
||||
if (topLevel) {
|
||||
|
||||
for (childElement in element.elements) {
|
||||
|
||||
if (isValidElement (childElement, "")) {
|
||||
|
||||
parseModuleElement (childElement, basePath, moduleData);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private function parseModuleElementSource (source:String, moduleData:ModuleData, include:Array<String>, exclude:Array<String>, currentPath:String):Void {
|
||||
|
||||
var files = FileSystem.readDirectory (currentPath);
|
||||
var filePath, className;
|
||||
|
||||
for (file in files) {
|
||||
|
||||
filePath = PathHelper.combine (currentPath, file);
|
||||
|
||||
if (FileSystem.isDirectory (filePath)) {
|
||||
|
||||
parseModuleElementSource (source, moduleData, include, exclude, filePath);
|
||||
|
||||
} else {
|
||||
|
||||
if (Path.extension (file) != "hx") continue;
|
||||
|
||||
className = StringTools.replace (filePath, source, "");
|
||||
className = StringTools.replace (className, "\\", "/");
|
||||
|
||||
while (StringTools.startsWith (className, "/")) className = className.substr (1);
|
||||
|
||||
className = StringTools.replace (className, "/", ".");
|
||||
className = StringTools.replace (className, ".hx", "");
|
||||
|
||||
if (filter (className, include, exclude)) {
|
||||
|
||||
moduleData.classNames.push (className);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private function parseOutputElement (element:Fast):Void {
|
||||
|
||||
if (element.has.name) {
|
||||
@@ -1367,6 +1556,10 @@ class ProjectXMLParser extends HXProject {
|
||||
|
||||
}
|
||||
|
||||
case "module":
|
||||
|
||||
parseModuleElement (element, extensionPath);
|
||||
|
||||
case "ssl":
|
||||
|
||||
//if (wantSslCertificate())
|
||||
|
||||
@@ -111,4 +111,53 @@ class ArrayHelper {
|
||||
}
|
||||
|
||||
|
||||
public static function getUnique<T> (a:Array<T>, b:Array<T>, key:String = null):Array<T> {
|
||||
|
||||
if (a == null && b == null) {
|
||||
|
||||
return new Array<T> ();
|
||||
|
||||
} else if (a == null && b != null) {
|
||||
|
||||
return b;
|
||||
|
||||
}
|
||||
|
||||
var concat = [];
|
||||
|
||||
for (bValue in b) {
|
||||
|
||||
var hasValue = false;
|
||||
|
||||
for (aValue in a) {
|
||||
|
||||
if (key != null) {
|
||||
|
||||
if (Reflect.field (aValue, key) == Reflect.field (bValue, key)) {
|
||||
|
||||
hasValue = true;
|
||||
|
||||
}
|
||||
|
||||
} else if (aValue == bValue) {
|
||||
|
||||
hasValue = true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!hasValue) {
|
||||
|
||||
concat.push (bValue);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return concat;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
179
lime/tools/helpers/ModuleHelper.hx
Normal file
179
lime/tools/helpers/ModuleHelper.hx
Normal file
@@ -0,0 +1,179 @@
|
||||
package lime.tools.helpers; #if !macro
|
||||
|
||||
|
||||
import lime.project.Dependency;
|
||||
import lime.project.Haxelib;
|
||||
import lime.project.HXProject;
|
||||
import sys.io.File;
|
||||
|
||||
|
||||
class ModuleHelper {
|
||||
|
||||
|
||||
public static function buildModules (project:HXProject, tempDirectory:String, outputDirectory:String):Void {
|
||||
|
||||
tempDirectory = PathHelper.combine (tempDirectory, "lib");
|
||||
outputDirectory = PathHelper.combine (outputDirectory, "lib");
|
||||
|
||||
PathHelper.mkdir (tempDirectory);
|
||||
PathHelper.mkdir (outputDirectory);
|
||||
|
||||
var importName, hxmlPath, importPath, outputPath, moduleImport, hxml;
|
||||
|
||||
for (module in project.modules) {
|
||||
|
||||
if (module.classNames.length > 0) {
|
||||
|
||||
importName = "Module" + module.name.charAt (0).toUpperCase () + module.name.substr (1);
|
||||
|
||||
hxmlPath = PathHelper.combine (tempDirectory, module.name + ".hxml");
|
||||
importPath = PathHelper.combine (tempDirectory, importName + ".hx");
|
||||
|
||||
if (project.targetFlags.exists ("final")) {
|
||||
|
||||
outputPath = PathHelper.combine (outputDirectory, module.name + ".min.js");
|
||||
|
||||
} else {
|
||||
|
||||
outputPath = PathHelper.combine (outputDirectory, module.name + ".js");
|
||||
|
||||
}
|
||||
|
||||
moduleImport = "package;\n\nimport " + module.classNames.join (";\nimport ") + ";";
|
||||
|
||||
hxml = "-cp " + tempDirectory;
|
||||
|
||||
hxml += "\n" + module.haxeflags.join ("\n");
|
||||
hxml += "\n-cp " + PathHelper.getHaxelib (new Haxelib ("lime"));
|
||||
|
||||
for (key in project.haxedefs.keys ()) {
|
||||
|
||||
if (key != "no-compilation") {
|
||||
|
||||
var value = project.haxedefs.get (key);
|
||||
|
||||
if (value == null || value == "") {
|
||||
|
||||
hxml += "\n-D " + key;
|
||||
|
||||
} else {
|
||||
|
||||
hxml += "\n-D " + key + "=" + value;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
hxml += "\n-D html5";
|
||||
hxml += "\n-D html";
|
||||
hxml += "\n--no-inline";
|
||||
hxml += "\n-dce no";
|
||||
hxml += "\n-js " + outputPath;
|
||||
|
||||
var includeTypes = module.classNames.concat (module.includeTypes);
|
||||
var excludeTypes = module.excludeTypes;
|
||||
|
||||
for (otherModule in project.modules) {
|
||||
|
||||
if (otherModule != module) {
|
||||
|
||||
excludeTypes = excludeTypes.concat (ArrayHelper.getUnique (includeTypes, otherModule.classNames));
|
||||
excludeTypes = excludeTypes.concat (ArrayHelper.getUnique (includeTypes, otherModule.includeTypes));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (excludeTypes.length > 0) {
|
||||
|
||||
hxml += "\n--macro lime.tools.helpers.ModuleHelper.exclude(['" + excludeTypes.join ("','") + "'])";
|
||||
|
||||
}
|
||||
|
||||
hxml += "\n--macro lime.tools.helpers.ModuleHelper.expose(['" + includeTypes.join ("','") + "'])";
|
||||
|
||||
hxml += "\n" + importName;
|
||||
|
||||
File.saveContent (importPath, moduleImport);
|
||||
File.saveContent (hxmlPath, hxml);
|
||||
|
||||
ProcessHelper.runCommand ("", "haxe", [ hxmlPath ]);
|
||||
|
||||
if (project.targetFlags.exists ("final")) {
|
||||
|
||||
HTML5Helper.minify (project, outputPath);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static function updateProject (project:HXProject):Void {
|
||||
|
||||
var excludeTypes = [];
|
||||
var suffix = (project.targetFlags.exists ("final") ? ".min" : "") + ".js";
|
||||
|
||||
for (module in project.modules) {
|
||||
|
||||
project.dependencies.push (new Dependency ("./lib/" + module.name + suffix, null));
|
||||
|
||||
excludeTypes = ArrayHelper.concatUnique (excludeTypes, module.classNames);
|
||||
excludeTypes = ArrayHelper.concatUnique (excludeTypes, module.excludeTypes);
|
||||
excludeTypes = ArrayHelper.concatUnique (excludeTypes, module.includeTypes);
|
||||
|
||||
}
|
||||
|
||||
if (excludeTypes.length > 0) {
|
||||
|
||||
project.haxeflags.push ("--macro lime.tools.helpers.ModuleHelper.exclude(['" + excludeTypes.join ("','") + "'])");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
|
||||
import haxe.macro.Compiler;
|
||||
|
||||
|
||||
class ModuleHelper {
|
||||
|
||||
|
||||
public static function exclude (types:Array<String>):Void {
|
||||
|
||||
for (type in types) {
|
||||
|
||||
Compiler.exclude (type);
|
||||
Compiler.addMetadata ("@:native(\"$hx_exports." + type + "\")", type);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static function expose (classNames:Array<String>):Void {
|
||||
|
||||
for (className in classNames) {
|
||||
|
||||
Compiler.addMetadata ("@:expose('" + className + "')", className);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#end
|
||||
@@ -9,6 +9,7 @@ import lime.tools.helpers.FileHelper;
|
||||
import lime.tools.helpers.HTML5Helper;
|
||||
import lime.tools.helpers.IconHelper;
|
||||
import lime.tools.helpers.LogHelper;
|
||||
import lime.tools.helpers.ModuleHelper;
|
||||
import lime.tools.helpers.PathHelper;
|
||||
import lime.tools.helpers.ProcessHelper;
|
||||
import lime.project.AssetType;
|
||||
@@ -36,6 +37,8 @@ class HTML5Platform extends PlatformTarget {
|
||||
|
||||
public override function build ():Void {
|
||||
|
||||
ModuleHelper.buildModules (project, targetDirectory + "/obj", targetDirectory + "/bin");
|
||||
|
||||
if (project.app.main != null) {
|
||||
|
||||
var type = "release";
|
||||
@@ -169,6 +172,8 @@ class HTML5Platform extends PlatformTarget {
|
||||
|
||||
}
|
||||
|
||||
ModuleHelper.updateProject (project);
|
||||
|
||||
var context = project.templateContext;
|
||||
|
||||
context.WIN_FLASHBACKGROUND = project.window.background != null ? StringTools.hex (project.window.background, 6) : "";
|
||||
|
||||
@@ -1395,6 +1395,26 @@ class CommandLineTools {
|
||||
|
||||
}
|
||||
|
||||
if (Sys.getEnv ("HAXEPATH") == null) {
|
||||
|
||||
if (PlatformHelper.hostPlatform == Platform.WINDOWS) {
|
||||
|
||||
Sys.putEnv ("HAXEPATH", "C:\\HaxeToolkit\\haxe\\");
|
||||
|
||||
} else {
|
||||
|
||||
Sys.putEnv ("HAXEPATH", "/usr/lib/haxe");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (Sys.getEnv ("HAXE_STD_PATH") == null) {
|
||||
|
||||
Sys.putEnv ("HAXE_STD_PATH", PathHelper.combine (Sys.getEnv ("HAXEPATH"), "std"));
|
||||
|
||||
}
|
||||
|
||||
if (project == null) {
|
||||
|
||||
HXProject._command = command;
|
||||
|
||||
Reference in New Issue
Block a user