Quellcode durchsuchen

WIP android support.

Mark Sibly vor 9 Jahren
Ursprung
Commit
318670eef2

+ 52 - 548
src/mx2cc/builder.monkey2

@@ -12,14 +12,14 @@ Class BuildOpts
 	Field target:String
 	
 	Field config:String
-
+	
 	Field clean:Bool
 	
 	Field verbose:Int
 	
 	Field fast:Bool
-	
-	Field run:Bool
+
+	Field passes:Int	'1=parse, 2=semant, 3=translate, 4=build, 5=run
 	
 End
 
@@ -31,8 +31,8 @@ Class Builder
 
 	Field opts:BuildOpts
 	
-	Field modulesDir:String
-
+	Field product:BuildProduct
+	
 	Field profileName:String
 	
 	Field ppsyms:=New StringMap<String>
@@ -58,94 +58,39 @@ Class Builder
 	Field imported:=New StringMap<Bool>
 	
 	Field currentDir:String
-
-	
-	Field tmpId:Int
 	
-	Field maxObjTime:Long
-
 	Field MX2_SRCS:=New StringStack
+
 	Field MX2_LIBS:=New StringStack
 	
-	Field SRC_FILES:=New StringStack
-	Field OBJ_FILES:=New StringStack
-	Field LD_OPTS:=New StringStack	
-	Field CC_OPTS:=New StringStack
-	Field CPP_OPTS:=New StringStack
-	Field LD_LIBS:=New StringStack
-	Field LD_SYSLIBS:=New StringStack
-	Field DLL_FILES:=New StringStack
-	Field ASSET_FILES:=New StringStack
-	
-	Field AR_CMD:="ar"
-	Field CC_CMD:="gcc"
-	Field CXX_CMD:="g++"
-	Field AS_CMD:="as"
-	Field LD_CMD:="g++"
-	
 	Method New( opts:BuildOpts )
 	
-'		If instance Print "OOPS! There is already a builder instance!"
-		
 		Self.opts=opts
 
 		instance=Self
 		
 		Local copts:=""
 		
-		copts=GetEnv( "MX2_LD_OPTS_"+opts.target.ToUpper() )
-		If copts LD_OPTS.Push( copts )
-
-		copts=GetEnv( "MX2_LD_OPTS_"+opts.target.ToUpper()+"_"+opts.config.ToUpper() )
-		If copts LD_OPTS.Push( copts )
-		
-		copts=GetEnv( "MX2_CC_OPTS_"+opts.target.ToUpper() )
-		If copts CC_OPTS.Push( copts )
-		
-		copts=GetEnv( "MX2_CC_OPTS_"+opts.target.ToUpper()+"_"+opts.config.ToUpper() )
-		If copts CC_OPTS.Push( copts )
-		
-		copts=GetEnv( "MX2_CPP_OPTS_"+opts.target.ToUpper() )
-		If opts CPP_OPTS.Push( copts )
-		
-		copts=GetEnv( "MX2_CPP_OPTS_"+opts.target.ToUpper()+"_"+opts.config.ToUpper() )
-		If copts CPP_OPTS.Push( copts )
+		ppsyms["__HOSTOS__"]="~q"+HostOS+"~q"
+		ppsyms["__TARGET__"]="~q"+opts.target+"~q"
+		ppsyms["__CONFIG__"]="~q"+opts.config+"~q"
 		
 		Select opts.target
 		Case "desktop"
-			AR_CMD= "ar"
-			CC_CMD= "gcc"
-			CXX_CMD="g++"
-			LD_CMD= "g++"
-			AS_CMD= "as"
-		Case "emscripten"
-			AR_CMD= "emar"
-			CC_CMD= "emcc"
-			CXX_CMD="em++"
-			LD_CMD= "em++"
-			AS_CMD= "as"		'as?
-		Case "android"
-			AR_CMD= "arm-linux-androideabi-ar"
-			CC_CMD= "arm-linux-androideabi-clang"
-			CXX_CMD="arm-linux-androideabi-clang++"
-			LD_CMD= "arm-linux-androideabi-clang++"
-			AS_CMD= "arm-linux-androideabi-as"
+			profileName=HostOS+"_"+opts.config
+		Default
+			profileName=opts.target+"_"+opts.config
 		End
 		
-		ppsyms["__HOSTOS__"]="~q"+HostOS+"~q"
-		ppsyms["__TARGET__"]="~q"+opts.target+"~q"
-		ppsyms["__CONFIG__"]="~q"+opts.config+"~q"
-		
-		profileName=opts.target+"_"+opts.config+"_"+HostOS
+		MODULES_DIR=CurrentDir()+"modules/"
 		
-		modulesDir=RealPath( "modules" )+"/"
+		If opts.productType="app" APP_DIR=ExtractDir( opts.mainSource )
 		
 		ClearPrimTypes()
 		
 		rootNamespace=New NamespaceScope( Null,Null )
 		
 		monkeyNamespace=GetNamespace( "monkey" )
-		
 	End
 	
 	Method Parse()
@@ -154,12 +99,20 @@ Class Builder
 		
 		Local name:=StripDir( StripExt( opts.mainSource ) )
 
-		Local module:=New Module( name,opts.mainSource,opts.productType,MX2CC_VERSION )
+		Local module:=New Module( name,opts.mainSource,MX2CC_VERSION,profileName )
 		modulesMap[name]=module
 		modules.Push( module )
 		
+		Select opts.target
+		Case "android"
+			product=New AndroidBuildProduct( module,opts )
+		Default
+			product=New GccBuildProduct( module,opts )
+		End
+		
 		mainModule=module
-		If name="monkey" And module.productType="module" modulesMap["monkey"]=module
+		
+		If name="monkey" And opts.productType="module" modulesMap["monkey"]=module
 		
 		If opts.clean 
 			DeleteDir( module.outputDir,True )
@@ -183,9 +136,9 @@ Class Builder
 				Endif
 				
 				Local name:=MX2_LIBS.Pop()
-				Local srcPath:=modulesDir+name+"/"+name+".monkey2"
+				Local srcPath:=MODULES_DIR+name+"/"+name+".monkey2"
 				
-				module=New Module( name,srcPath,"module",MX2CC_VERSION )
+				module=New Module( name,srcPath,MX2CC_VERSION,profileName )
 				modulesMap[name]=module
 				modules.Push( module )
 				
@@ -264,7 +217,7 @@ Class Builder
 		
 			Local module:=modules[modules.Length-i-1]
 
-			If module<>mainModule LD_LIBS.Push( module.outputDir+module.name+".a" )
+			If module<>mainModule product.LD_LIBS.Push( module.outputDir+module.name+".a" )
 			
 		Next
 		
@@ -430,10 +383,10 @@ Class Builder
 		
 		Local module:=mainModule
 		
-		CreateDir( module.buildDir )
-		CreateDir( module.buildDir+"build_cache" )
-		If Not CreateDir( module.cacheDir ) Print "Failed to create dir:"+module.cacheDir
-		If Not CreateDir( module.outputDir ) Print "Failed to create dir:"+module.outputDir
+		CreateDir( module.outputDir )
+
+		If Not CreateDir( module.hfileDir ) Throw New BuildEx( "Failed to create dir:"+module.hfileDir )
+		If Not CreateDir( module.cfileDir ) Throw New BuildEx( "Failed to create dir:"+module.cfileDir )
 
 		For Local fdecl:=Eachin module.fileDecls
 		
@@ -446,457 +399,8 @@ Class Builder
 			Catch ex:TransEx
 			End
 			
-			SRC_FILES.Push( fdecl.cfile )
-		Next
-	
-	End
-	
-	Method Compile()
-	
-		If opts.verbose=0 Print "Compiling...."
-		
-		Local module:=mainModule
-	
-		For Local src:=Eachin SRC_FILES
-		
-			Local obj:=module.cacheDir+MungPath( MakeRelativePath( src,module.cacheDir ) )+".o"
-			
-			Local ext:=ExtractExt( src ).ToLower()
-						
-			Local cmd:="",isasm:=False
-			
-			Select ext
-			Case ".c",".m"
-			
-				cmd=CC_CMD+" "+CC_OPTS.Join( " " )
-				cmd+=" -I~q"+modulesDir+"monkey/native~q"
-				
-			Case ".cc",".cxx",".cpp",".mm"
-
-				cmd=CXX_CMD+" "+CPP_OPTS.Join( " " )
-				cmd+=" -I~q"+modulesDir+"monkey/native~q"
-
-			Case ".asm",".s"
-			
-				cmd=AS_CMD
-				isasm=True
-			End
-			
-			'Check dependancies
-			'			
-			Local objTime:=GetFileTime( obj )
-			
-			Local deps:=StripExt( obj )+".deps"
-			
-			If opts.fast And objTime>=GetFileTime( src )	'source file up to date?
-			
-				Local uptodate:=True
-			
-				If Not isasm
-			
-					If GetFileType( deps )=FILETYPE_NONE
-					
-						If opts.verbose>0 Print "Scanning "+src
-				
-						Exec( cmd+" -MM ~q"+src+"~q >~q"+deps+"~q" ) 
-						
-					Endif
-					
-					Local srcs:=LoadString( deps ).Split( " \" )
-					
-					For Local i:=1 Until srcs.Length
-					
-						Local src:=srcs[i].Trim().Replace( "\ "," " )
-					
-						If GetFileTime( src )>objTime
-							uptodate=False
-							Exit
-						Endif
-						
-					Next
-				
-				Endif
-				
-				If uptodate
-					maxObjTime=Max( maxObjTime,objTime )
-					OBJ_FILES.Push( obj )
-					Continue
-				Endif
-				
-			Else
-			
-				DeleteFile( deps )
-
-			Endif
-			
-			If opts.verbose>0 Print "Compiling "+src
-			
-			If Not isasm cmd+=" -c"
-			
-			cmd+=" -o ~q"+obj+"~q ~q"+src+"~q"
-			
-			Exec( cmd )
-			
-			maxObjTime=Max( maxObjTime,GetFileTime( obj ) )
-			
-			OBJ_FILES.Push( obj )
-			
-		Next
-	
-	End
-	
-	Method Link:String()
-	
-		Select opts.productType
-		Case "app"
-			Return CreateApp()
-		Case "module"
-			Return CreateArchive()
-		End
-		
-		Return ""
-	End
-	
-	Method CreateApp:String()
-	
-		Local module:=mainModule
-		
-		Local outputFile:="",assetsDir:="",dllsDir:=""
-		
-		Local cmd:=LD_CMD
-		cmd+=" "+LD_OPTS.Join( " " )
-		
-		If opts.target="emscripten"
-		
-			outputFile=module.outputDir+module.name+".html"
-			assetsDir=module.buildDir+"assets/"
-			dllsDir=ExtractDir( outputFile )
-			
-'			Note: mserver can't handle --emrun as it tries to POST stdout
-'			cmd="em++ --emrun --preload-file ~q"+assetsDir+"@/assets~q"
-
-			cmd+=" --preload-file ~q"+assetsDir+"@/assets~q"
-			
-		Else If opts.target="desktop" And HostOS="windows"
-		
-			If opts.appType="gui" cmd+=" -mwindows"
-		
-			outputFile=module.outputDir+module.name+".exe"
-			assetsDir=module.outputDir+"assets/"
-			dllsDir=ExtractDir( outputFile )
-			
-		Else If opts.target="desktop" And HostOS="macos"
-		
-			If opts.appType="gui"
-			
-				Local productName:=module.name
-	
-				Local outputDir:=module.outputDir+module.name+".app/"
-				
-				outputFile=outputDir+"Contents/MacOS/"+module.name
-				assetsDir=outputDir+"Contents/Resources/"
-				dllsDir=ExtractDir( outputFile )
-				
-				CreateDir( outputDir )
-				CreateDir( outputDir+"Contents" )
-				CreateDir( outputDir+"Contents/MacOS" )
-				CreateDir( outputDir+"Contents/Resources" )
-				
-				Local plist:=""
-				plist+="<?xml version=~q1.0~q encoding=~qUTF-8~q?>~n"
-				plist+="<!DOCTYPE plist PUBLIC ~q-//Apple Computer//DTD PLIST 1.0//EN~q ~qhttp://www.apple.com/DTDs/PropertyList-1.0.dtd~q>~n"
-				plist+="<plist version=~q1.0~q>~n"
-				plist+="<dict>~n"
-				plist+="~t<key>CFBundleExecutable</key>~n"
-				plist+="~t<string>"+productName+"</string>~n"
-				plist+="~t<key>CFBundleIconFile</key>~n"
-				plist+="~t<string>"+productName+"</string>~n"
-				plist+="~t<key>CFBundlePackageType</key>~n"
-				plist+="~t<string>APPL</string>~n"
-				plist+="</dict>~n"
-				plist+="</plist>~n"
-				
-				SaveString( plist,outputDir+"Contents/Info.plist" )
-				
-			Else
-			
-				outputFile=module.outputDir+module.name
-				assetsDir=module.outputDir+"assets/"
-				dllsDir=ExtractDir( outputFile )
-			
-			Endif
-			
-		Else If opts.target="desktop" And HostOS="linux"
-		
-			outputFile=module.outputDir+module.name
-			assetsDir=module.outputDir+"assets/"
-			dllsDir=ExtractDir( outputFile )
-			
-		Else If opts.target="android"
-		
-			outputFile=module.outputDir+"lib"+module.name+".so"
-			assetsDir=module.outputDir+"assets/"
-			dllsDir=ExtractDir( outputFile )
-			
-		Endif
-		
-		If opts.verbose>=0 Print "Linking "+outputFile
-		
-		DeleteDir( assetsDir,True )
-
-		CreateDir( assetsDir )
-		
-		Local assetFiles:=New StringMap<String>
-		
-		For Local src:=Eachin ASSET_FILES
-		
-			Local dst:=assetsDir
-		
-			Local i:=src.Find( "@/" )
-			If i<>-1
-				dst+=src.Slice( i+2 )
-				src=src.Slice( 0,i )
-				If Not dst.EndsWith( "/" ) dst+="/"
-			Endif
-			
-			Select GetFileType( src )
-			
-			Case FileType.File
-			
-				dst+=StripDir( src )
-				EnumAssetFiles( src,dst,assetFiles )
-				
-			Case FileType.Directory
-			
-				EnumAssetFiles( src,dst,assetFiles )
-			End
-			
-		Next
-		
-		CopyAssetFiles( assetFiles )
-	
-		#rem
-		For Local src:=Eachin ASSET_FILES.Backwards()
-		
-			Local dst:=assetsDir
-			
-			Local i:=src.Find( "@/" )
-			If i<>-1
-				dst+=src.Slice( i+2 )
-				src=src.Slice( 0,i )
-				If Not dst.EndsWith( "/" ) dst+="/"
-			Endif
-			
-			Select GetFileType( src )
-			
-			Case FileType.File
-			
-				CreateDir( dst )
-				dst+=StripDir( src )
-				If Not CopyFile( src,dst ) New BuildEx( "Error copying asset '"+src+"'" )
-				
-			Case FileType.Directory
-			
-				If Not CopyAll( src,dst ) New BuildEx( "Error copying asset '"+src+"'" )
-			End
-			#rem		
-			Local i:=ass.Find( "@/" )
-			If i=-1
-				CopyFile( ass,assetsDir+StripDir( ass ) )
-				Continue
-			Endif
-			
-			Local dst:=assetsDir+ass.Slice( i+2 )
-			If Not dst.EndsWith( "/" ) dst+="/"
-			CreateDir( dst )
-			
-			ass=ass.Slice( 0,i )
-			
-			CopyFile( ass,dst+StripDir( ass ) )
-			#end
+			product.SRC_FILES.Push( fdecl.cfile )
 		Next
-		#end
-		
-		cmd+=" -o ~q"+outputFile+"~q"
-		
-		Local lnkFiles:=""
-		
-		For Local obj:=Eachin OBJ_FILES
-			lnkFiles+=" ~q"+obj+"~q"
-		Next
-		
-		If opts.target="android"
-			lnkFiles+=" -Wl,--whole-archive"
-		Endif
-		
-		For Local lib:=Eachin LD_LIBS
-			lnkFiles+=" ~q"+lib+"~q"
-		Next
-	
-		If opts.target="android"	
-			lnkFiles+=" -Wl,--no-whole-archive"
-		Endif
-		
-		lnkFiles+=" "+LD_SYSLIBS.Join( " " )
-		
-		If opts.target="android"
-			lnkFiles+=" -lstdc++"
-		Endif
-		
-		If HostOS="windows" And opts.target<>"android"
-			Local tmp:=AllocTmpFile( "lnkFiles" )
-			SaveString( lnkFiles,tmp )
-			cmd+=" -Wl,@"+tmp
-		Else
-			cmd+=lnkFiles
-		Endif
-
-		Exec( cmd )
-		
-		For Local src:=Eachin DLL_FILES
-		
-			Local dir:=dllsDir
-			
-			Local ext:=ExtractExt( src )
-			If ext
-				Local rdir:=GetEnv( "MX2_APP_DIR_"+ext.Slice( 1 ).ToUpper() )
-				If rdir dir=RealPath( dir+rdir )
-			Endif
-			
-			If Not dir.EndsWith( "/" ) dir+="/"
-			
-			Local dst:=dir+StripDir( src )
-			
-			'FIXME! Hack for copying frameworks on macos!
-			'		
-#If __HOSTOS__="macos"
-			If ExtractExt( src ).ToLower()=".framework"
-				CreateDir( ExtractDir( dst ) )
-				If Not Exec( "rm -f -R "+dst ) Throw New BuildEx( "rm failed" )
-				If Not Exec( "cp -f -R "+src+" "+dst ) Throw New BuildEx( "cp failed" )
-				Continue
-			Endif
-#Endif
-			
-			If Not CopyAll( src,dst ) Throw New BuildEx( "Failed to copy '"+src+"' to '"+dst+"'" )
-			
-		Next
-		
-		If Not opts.run Return outputFile
-	
-		Local run:=""
-		If opts.target="emscripten"
-			Local mserver:=GetEnv( "MX2_MSERVER" )
-			run=mserver+" ~q"+outputFile+"~q"
-		Else
-			run="~q"+outputFile+"~q"
-		Endif
-		
-		If opts.verbose>=0 Print "Running "+outputFile
-		Exec( run )
-		
-		Return outputFile
-	End
-	
-	Method CopyAssetFiles( files:StringMap<String> )
-	
-		For Local it:=Eachin files
-		
-			Local src:=it.Value
-			Local dst:=it.Key
-			
-			If CreateDir( ExtractDir( dst ) )
-			
-				If GetFileTime( dst )>=GetFileTime( src ) Continue
-				
-				If CopyFile( src,dst ) Continue
-
-			Endif
-			
-			Throw New BuildEx( "Error copying asset file '"+src+"' to '"+dst+"'" )
-		Next
-	End
-	
-	Method EnumAssetFiles( src:String,dst:String,files:StringMap<String> )
-
-		Select GetFileType( src )
-
-		Case FILETYPE_FILE
-		
-			If Not files.Contains( dst ) files[dst]=src
-			
-		Case FILETYPE_DIR
-		
-			For Local f:=Eachin LoadDir( src )
-			
-				EnumAssetFiles( src+"/"+f,dst+"/"+f,files )
-
-			Next
-		
-		End
-		
-	End
-	
-	Method CopyAll:Bool( src:String,dst:String )
-		
-		Select GetFileType( src )
-
-		Case FILETYPE_FILE
-		
-			If Not CreateDir( ExtractDir( dst ) ) Return False
-		
-'			If GetFileTime( src )>GetFileTime( dst )
-				If Not CopyFile( src,dst ) Return False
-'			Endif
-			
-			Return True
-			
-		Case FILETYPE_DIR
-		
-			If Not CreateDir( dst ) Return False
-			
-			For Local file:=Eachin LoadDir( src )
-				If Not CopyAll( src+"/"+file,dst+"/"+file ) Return False
-			Next
-			
-			Return True
-		
-		End
-		
-		Return False
-		
-	End
-	
-	Method CreateArchive:String()
-
-		Local module:=mainModule
-		
-		Local outputFile:=module.outputDir+module.name+".a"
-		
-		'AR is slow! This is probably not quite right, but it'll do for now...
-		If GetFileTime( outputFile )>maxObjTime Return outputFile
-		
-		If opts.verbose>=0 Print "Archiving "+outputFile
-		
-		DeleteFile( outputFile )
-		
-		Local objs:=""
-		
-		For Local i:=0 Until OBJ_FILES.Length
-			
-			objs+=" ~q"+OBJ_FILES.Get( i )+"~q"
-			
-			If objs.Length<1000 And i<OBJ_FILES.Length-1 Continue
-
-			Local cmd:=AR_CMD+" q ~q"+outputFile+"~q"+objs
-
-			Exec( cmd )
-			
-			objs=""
-			
-		Next
-		
-		Return outputFile
 		
 	End
 	
@@ -1044,15 +548,15 @@ Class Builder
 		Case ".a"
 
 			If name.StartsWith( "lib" ) name=name.Slice( 3 ) Else name=path
-			LD_SYSLIBS.Push( "-l"+name )
+			product.LD_SYSLIBS.Push( "-l"+name )
 			
 		Case ".lib",".dylib"
 		
-			LD_SYSLIBS.Push( "-l"+name )
+			product.LD_SYSLIBS.Push( "-l"+name )
 			
 		Case ".framework"
 		
-			LD_SYSLIBS.Push( "-framework "+name )
+			product.LD_SYSLIBS.Push( "-framework "+name )
 			
 		Case ".h",".hh",".hpp"
 		
@@ -1084,7 +588,7 @@ Class Builder
 				Return
 			Endif
 			
-			ASSET_FILES.Push( path )
+			product.ASSET_FILES.Push( path )
 			Return
 		Endif
 		
@@ -1106,20 +610,20 @@ Class Builder
 			Select ext
 			Case ".h"
 			
-				CC_OPTS.Push( "-I"+qdir )
-				CPP_OPTS.Push( "-I"+qdir )
+				product.CC_OPTS.Push( "-I"+qdir )
+				product.CPP_OPTS.Push( "-I"+qdir )
 				
 			Case ".hh",".hpp"
 			
-				CPP_OPTS.Push( "-I"+qdir )
+				product.CPP_OPTS.Push( "-I"+qdir )
 				
 			Case ".a",".lib",".dylib"
 			
-				LD_OPTS.Push( "-L"+qdir )
+				product.LD_OPTS.Push( "-L"+qdir )
 				
 			Case ".framework"
 			
-				LD_OPTS.Push( "-F"+qdir )
+				product.LD_OPTS.Push( "-F"+qdir )
 				
 			Default
 			
@@ -1144,7 +648,7 @@ Class Builder
 			Select GetFileType( path )
 			Case FileType.Directory
 			
-				ASSET_FILES.Push( path )
+				product.ASSET_FILES.Push( path )
 				Return
 				
 			Case FileType.None
@@ -1166,7 +670,7 @@ Class Builder
 			
 		Case ".c",".cc",".cxx",".cpp",".m",".mm",".asm",".s"
 		
-			If parsingModule=mainModule SRC_FILES.Push( path )
+			If parsingModule=mainModule product.SRC_FILES.Push( path )
 		
 '			If modules.Length=1
 '				SRC_FILES.Push( path )
@@ -1174,31 +678,31 @@ Class Builder
 			
 		Case ".o"
 		
-			OBJ_FILES.Push( path )
+			product.OBJ_FILES.Push( path )
 			
 		Case ".a",".lib"
 		
-			LD_SYSLIBS.Push( qpath )
+			product.LD_SYSLIBS.Push( qpath )
 			
 		Case ".so"
 		
 			If opts.target="android"		'probably all non-windows targets
 			
-				LD_SYSLIBS.Push( qpath )
+				product.LD_SYSLIBS.Push( qpath )
 			
 			Endif
 			
-			DLL_FILES.Push( path )
+			product.DLL_FILES.Push( path )
 			
 		Case ".dll",".exe"
 		
-			DLL_FILES.Push( path )
+			product.DLL_FILES.Push( path )
 			
 		Case ".dylib"
 		
-			LD_SYSLIBS.Push( qpath )
+			product.LD_SYSLIBS.Push( qpath )
 			
-			DLL_FILES.Push( path )
+			product.DLL_FILES.Push( path )
 			
 		Case ".framework"
 		
@@ -1208,11 +712,11 @@ Class Builder
 			
 			ImportSystemFile( StripDir( path ) )
 			
-			DLL_FILES.Push( path )
+			product.DLL_FILES.Push( path )
 		
 		Default
 		
-			ASSET_FILES.Push( path )
+			product.ASSET_FILES.Push( path )
 		End
 	
 	End

+ 640 - 0
src/mx2cc/buildproduct.monkey2

@@ -0,0 +1,640 @@
+
+Namespace mx2
+
+Class BuildProduct
+
+	Field module:Module
+	Field opts:BuildOpts
+	
+	Field outputFile:String
+
+	Field LD_OPTS:=New StringStack	
+	Field CC_OPTS:=New StringStack
+	Field CPP_OPTS:=New StringStack
+
+	Field SRC_FILES:=New StringStack
+	Field OBJ_FILES:=New StringStack
+	Field LD_LIBS:=New StringStack
+	Field LD_SYSLIBS:=New StringStack
+	Field DLL_FILES:=New StringStack
+	Field ASSET_FILES:=New StringStack
+	
+	Method New( module:Module,opts:BuildOpts )
+		Self.module=module
+		Self.opts=opts
+		
+		Local copts:=""
+		
+		copts=GetEnv( "MX2_LD_OPTS_"+opts.target.ToUpper() )
+		If copts LD_OPTS.Push( copts )
+
+		copts=GetEnv( "MX2_LD_OPTS_"+opts.target.ToUpper()+"_"+opts.config.ToUpper() )
+		If copts LD_OPTS.Push( copts )
+		
+		copts=GetEnv( "MX2_CC_OPTS_"+opts.target.ToUpper() )
+		If copts CC_OPTS.Push( copts )
+		
+		copts=GetEnv( "MX2_CC_OPTS_"+opts.target.ToUpper()+"_"+opts.config.ToUpper() )
+		If copts CC_OPTS.Push( copts )
+		
+		copts=GetEnv( "MX2_CPP_OPTS_"+opts.target.ToUpper() )
+		If opts CPP_OPTS.Push( copts )
+		
+		copts=GetEnv( "MX2_CPP_OPTS_"+opts.target.ToUpper()+"_"+opts.config.ToUpper() )
+		If copts CPP_OPTS.Push( copts )
+		
+	End
+
+	Method Build() Virtual
+	End
+	
+	Method Run() Virtual
+	End
+
+	Protected
+	
+	Method AllocTmpFile:String( kind:String )
+	
+		CreateDir( "tmp" )
+
+		For Local i:=1 Until 10
+			Local file:="tmp/"+kind+i+".txt"
+			DeleteFile( file )
+			If GetFileType( file )=FileType.None Return file
+		Next
+		
+		Throw New BuildEx( "Can't allocate tmp file" )
+		
+		Return ""
+	End
+	
+	Method Exec:Bool( cmd:String )
+	
+		If opts.verbose>2 Print cmd
+	
+		Local errs:=AllocTmpFile( "stderr" )
+			
+		If Not system( cmd+" 2>"+errs ) Return True
+		
+		Local terrs:=LoadString( errs )
+		
+		Throw New BuildEx( "System command '"+cmd+"' failed.~n~n"+cmd+"~n~n"+terrs )
+		
+		Return False
+	End
+	
+	Method CopyAssets( assetsDir:String )
+	
+		DeleteDir( assetsDir,True )
+		
+		CreateDir( assetsDir )
+		
+		Local assetFiles:=New StringMap<String>
+		
+		For Local src:=Eachin ASSET_FILES
+		
+			Local dst:=assetsDir
+		
+			Local i:=src.Find( "@/" )
+			If i<>-1
+				dst+=src.Slice( i+2 )
+				src=src.Slice( 0,i )
+				If Not dst.EndsWith( "/" ) dst+="/"
+			Endif
+			
+			Select GetFileType( src )
+			
+			Case FileType.File
+			
+				dst+=StripDir( src )
+				EnumAssetFiles( src,dst,assetFiles )
+				
+			Case FileType.Directory
+			
+				EnumAssetFiles( src,dst,assetFiles )
+			End
+			
+		Next
+		
+		CopyAssetFiles( assetFiles )
+	End
+
+	Private
+		
+	Method CopyAll:Bool( src:String,dst:String )
+		
+		Select GetFileType( src )
+
+		Case FILETYPE_FILE
+		
+			If Not CreateDir( ExtractDir( dst ) ) Return False
+		
+'			If GetFileTime( src )>GetFileTime( dst )
+				If Not CopyFile( src,dst ) Return False
+'			Endif
+			
+			Return True
+			
+		Case FILETYPE_DIR
+		
+			If Not CreateDir( dst ) Return False
+			
+			For Local file:=Eachin LoadDir( src )
+				If Not CopyAll( src+"/"+file,dst+"/"+file ) Return False
+			Next
+			
+			Return True
+		
+		End
+		
+		Return False
+		
+	End
+	
+	Method CopyAssetFiles( files:StringMap<String> )
+	
+		For Local it:=Eachin files
+		
+			Local src:=it.Value
+			Local dst:=it.Key
+			
+			If CreateDir( ExtractDir( dst ) )
+			
+				If GetFileTime( dst )>=GetFileTime( src ) Continue
+				
+				If CopyFile( src,dst ) Continue
+
+			Endif
+			
+			Throw New BuildEx( "Error copying asset file '"+src+"' to '"+dst+"'" )
+		Next
+	End
+	
+	Method EnumAssetFiles( src:String,dst:String,files:StringMap<String> )
+
+		Select GetFileType( src )
+
+		Case FILETYPE_FILE
+		
+			If Not files.Contains( dst ) files[dst]=src
+			
+		Case FILETYPE_DIR
+		
+			For Local f:=Eachin LoadDir( src )
+			
+				EnumAssetFiles( src+"/"+f,dst+"/"+f,files )
+
+			Next
+		
+		End
+		
+	End
+		
+End
+
+Class GccBuildProduct Extends BuildProduct
+
+	Field AR_CMD:="ar"
+	Field CC_CMD:="gcc"
+	Field CXX_CMD:="g++"
+	Field AS_CMD:="as"
+	Field LD_CMD:="g++"
+	
+	Field maxObjTime:Long
+
+	Method New( module:Module,opts:BuildOpts )
+		Super.New( module,opts )
+		
+		Select opts.target
+		Case "emscripten"
+			AR_CMD= "emar"
+			CC_CMD= "emcc"
+			CXX_CMD="em++"
+			LD_CMD= "em++"
+			AS_CMD= ""
+		Default
+			AR_CMD= "ar"
+			CC_CMD= "gcc"
+			CXX_CMD="g++"
+			LD_CMD= "g++"
+			AS_CMD= "as"
+		End
+		
+	End
+	
+	Method Build() Override
+
+		If opts.verbose=0 Print "Compiling...."
+		
+		If Not CreateDir( module.cacheDir ) Throw New BuildEx( "Error create dir '"+module.cacheDir+"'" )
+		
+		For Local src:=Eachin SRC_FILES
+		
+			Local obj:=module.cacheDir+MungPath( MakeRelativePath( src,module.cacheDir ) )+".o"
+			
+			Local ext:=ExtractExt( src ).ToLower()
+						
+			Local cmd:="",isasm:=False
+			
+			Select ext
+			Case ".c",".m"
+			
+				cmd=CC_CMD+" "+CC_OPTS.Join( " " )
+				cmd+=" -I~q"+MODULES_DIR+"monkey/native~q"
+				cmd+=" -I~q"+MODULES_DIR+"~q"
+				If APP_DIR cmd+=" -I~q"+APP_DIR+"~q"
+				
+			Case ".cc",".cxx",".cpp",".mm"
+
+				cmd=CXX_CMD+" "+CPP_OPTS.Join( " " )
+				cmd+=" -I~q"+MODULES_DIR+"monkey/native~q"
+				cmd+=" -I~q"+MODULES_DIR+"~q"
+				If APP_DIR cmd+=" -I~q"+APP_DIR+"~q"
+
+			Case ".asm",".s"
+			
+				cmd=AS_CMD
+				isasm=True
+			End
+			
+			'Check dependancies
+			'			
+			Local objTime:=GetFileTime( obj )
+			
+			Local deps:=StripExt( obj )+".deps"
+			
+			If opts.fast And objTime>=GetFileTime( src )	'source file up to date?
+			
+				Local uptodate:=True
+			
+				If Not isasm
+			
+					If GetFileType( deps )=FILETYPE_NONE
+					
+						If opts.verbose>0 Print "Scanning "+src
+				
+						Exec( cmd+" -MM ~q"+src+"~q >~q"+deps+"~q" ) 
+						
+					Endif
+					
+					Local srcs:=LoadString( deps ).Split( " \" )
+					
+					For Local i:=1 Until srcs.Length
+					
+						Local src:=srcs[i].Trim().Replace( "\ "," " )
+					
+						If GetFileTime( src )>objTime
+							uptodate=False
+							Exit
+						Endif
+						
+					Next
+				
+				Endif
+				
+				If uptodate
+					maxObjTime=Max( maxObjTime,objTime )
+					OBJ_FILES.Push( obj )
+					Continue
+				Endif
+				
+			Else
+			
+				DeleteFile( deps )
+
+			Endif
+			
+			If opts.verbose>0 Print "Compiling "+src
+			
+			If Not isasm cmd+=" -c"
+			
+			cmd+=" -o ~q"+obj+"~q ~q"+src+"~q"
+			
+			Exec( cmd )
+			
+			maxObjTime=Max( maxObjTime,GetFileTime( obj ) )
+			
+			OBJ_FILES.Push( obj )
+			
+		Next
+	
+		Select opts.productType
+		Case "app"
+			CreateApp()
+		Case "module"
+			CreateArchive()
+		End
+	
+	End
+	
+	Method CreateApp()
+	
+		Local assetsDir:="",dllsDir:=""
+		
+		Local cmd:=LD_CMD
+		cmd+=" "+LD_OPTS.Join( " " )
+		
+		If opts.target="desktop" And HostOS="windows"
+		
+			If opts.appType="gui" cmd+=" -mwindows"
+		
+			outputFile=module.outputDir+module.name+".exe"
+			assetsDir=module.outputDir+"assets/"
+			dllsDir=ExtractDir( outputFile )
+			
+		Else If opts.target="desktop" And HostOS="macos"
+		
+			If opts.appType="gui"
+			
+				Local productName:=module.name
+	
+				Local outputDir:=module.outputDir+module.name+".app/"
+				
+				outputFile=outputDir+"Contents/MacOS/"+module.name
+				assetsDir=outputDir+"Contents/Resources/"
+				dllsDir=ExtractDir( outputFile )
+				
+				CreateDir( outputDir )
+				CreateDir( outputDir+"Contents" )
+				CreateDir( outputDir+"Contents/MacOS" )
+				CreateDir( outputDir+"Contents/Resources" )
+				
+				Local plist:=""
+				plist+="<?xml version=~q1.0~q encoding=~qUTF-8~q?>~n"
+				plist+="<!DOCTYPE plist PUBLIC ~q-//Apple Computer//DTD PLIST 1.0//EN~q ~qhttp://www.apple.com/DTDs/PropertyList-1.0.dtd~q>~n"
+				plist+="<plist version=~q1.0~q>~n"
+				plist+="<dict>~n"
+				plist+="~t<key>CFBundleExecutable</key>~n"
+				plist+="~t<string>"+productName+"</string>~n"
+				plist+="~t<key>CFBundleIconFile</key>~n"
+				plist+="~t<string>"+productName+"</string>~n"
+				plist+="~t<key>CFBundlePackageType</key>~n"
+				plist+="~t<string>APPL</string>~n"
+				plist+="</dict>~n"
+				plist+="</plist>~n"
+				
+				SaveString( plist,outputDir+"Contents/Info.plist" )
+				
+			Else
+			
+				outputFile=module.outputDir+module.name
+				assetsDir=module.outputDir+"assets/"
+				dllsDir=ExtractDir( outputFile )
+			
+			Endif
+			
+		Else If opts.target="desktop" And HostOS="linux"
+		
+			outputFile=module.outputDir+module.name
+			assetsDir=module.outputDir+"assets/"
+			dllsDir=ExtractDir( outputFile )
+			
+		Else If opts.target="emscripten"
+		
+			outputFile=module.outputDir+module.name+".html"
+			assetsDir=module.outputDir+"assets/"
+			dllsDir=ExtractDir( outputFile )
+			
+'			Note: mserver can't handle --emrun as it tries to POST stdout
+'			cmd="em++ --emrun --preload-file ~q"+assetsDir+"@/assets~q"
+
+			cmd+=" --preload-file ~q"+assetsDir+"@/assets~q"
+			
+		Endif
+		
+		If opts.verbose>=0 Print "Linking "+outputFile
+		
+		CopyAssets( assetsDir )
+		
+		cmd+=" -o ~q"+outputFile+"~q"
+		
+		Local lnkFiles:=""
+		
+		For Local obj:=Eachin OBJ_FILES
+			lnkFiles+=" ~q"+obj+"~q"
+		Next
+		
+		For Local lib:=Eachin LD_LIBS
+			lnkFiles+=" ~q"+lib+"~q"
+		Next
+	
+		lnkFiles+=" "+LD_SYSLIBS.Join( " " )
+		
+		If HostOS="windows" And opts.target="desktop"
+			Local tmp:=AllocTmpFile( "lnkFiles" )
+			SaveString( lnkFiles,tmp )
+			cmd+=" -Wl,@"+tmp
+		Else
+			cmd+=lnkFiles
+		Endif
+
+		Exec( cmd )
+		
+		For Local src:=Eachin DLL_FILES
+		
+			Local dir:=dllsDir
+			
+			Local ext:=ExtractExt( src )
+			If ext
+				Local rdir:=GetEnv( "MX2_APP_DIR_"+ext.Slice( 1 ).ToUpper() )
+				If rdir dir=RealPath( dir+rdir )
+			Endif
+			
+			If Not dir.EndsWith( "/" ) dir+="/"
+			
+			Local dst:=dir+StripDir( src )
+			
+			'FIXME! Hack for copying frameworks on macos!
+			'		
+#If __HOSTOS__="macos"
+			If ExtractExt( src ).ToLower()=".framework"
+				CreateDir( ExtractDir( dst ) )
+				If Not Exec( "rm -f -R "+dst ) Throw New BuildEx( "rm failed" )
+				If Not Exec( "cp -f -R "+src+" "+dst ) Throw New BuildEx( "cp failed" )
+				Continue
+			Endif
+#Endif
+			
+			If Not CopyAll( src,dst ) Throw New BuildEx( "Failed to copy '"+src+"' to '"+dst+"'" )
+			
+		Next
+		
+	End
+	
+	Method CreateArchive:String()
+
+		Local outputFile:=module.outputDir+module.name+".a"
+		
+		'AR is slow! This is probably not quite right, but it'll do for now...
+		If GetFileTime( outputFile )>maxObjTime Return outputFile
+		
+		If opts.verbose>=0 Print "Archiving "+outputFile
+		
+		DeleteFile( outputFile )
+		
+		Local objs:=""
+		
+		For Local i:=0 Until OBJ_FILES.Length
+			
+			objs+=" ~q"+OBJ_FILES.Get( i )+"~q"
+			
+			If objs.Length<1000 And i<OBJ_FILES.Length-1 Continue
+
+			Local cmd:=AR_CMD+" q ~q"+outputFile+"~q"+objs
+
+			Exec( cmd )
+			
+			objs=""
+			
+		Next
+		
+		Return outputFile
+		
+	End
+
+	Method Run() Override
+	
+		Local run:=""
+		If opts.target="emscripten"
+			Local mserver:=GetEnv( "MX2_MSERVER" )
+			run=mserver+" ~q"+outputFile+"~q"
+		Else
+			run="~q"+outputFile+"~q"
+		Endif
+		
+		If opts.verbose>=0 Print "Running "+outputFile
+		Exec( run )
+	End
+	
+End
+	
+Class AndroidBuildProduct Extends BuildProduct
+
+	Method New( module:Module,opts:BuildOpts )
+		Super.New( module,opts )
+	End
+	
+	Method Build() Override
+	
+		Local jniDir:=module.outputDir+"jni/"
+		
+		If Not CreateDir( jniDir ) Throw New BuildEx( "Failed to create dir '"+jniDir+"'" )
+	
+		Local buf:=New StringStack
+		
+		buf.Push( "APP_OPTIM := "+opts.config )
+		
+		buf.Push( "APP_ABI := armeabi-v7a" )
+'		buf.Push( "APP_ABI := armeabi armeabi-v7a x86" )
+'		buf.Push( "APP_ABI := armeabi-v7a x86" )
+'		buf.Push( "APP_ABI := all" )
+
+		buf.Push( "APP_PLATFORM := 10" )
+		
+		buf.Push( "APP_CFLAGS += -std=gnu99" )
+		buf.Push( "APP_CPPFLAGS += -std=c++11" )
+		buf.Push( "APP_CPPFLAGS += -frtti" )
+		buf.Push( "APP_CPPFLAGS += -fexceptions" )
+		buf.Push( "APP_STL := c++_static" )
+		
+		CSaveString( buf.Join( "~n" ),jniDir+"Application.mk" )
+		buf.Clear()
+
+		buf.Push( "LOCAL_PATH := $(call my-dir)" )
+		
+		If opts.productType="app"
+		
+			For Local extmod:=Eachin Builder.instance.modules
+				If extmod=module continue
+			
+				Local src:=extmod.outputDir+"obj/local/$(TARGET_ARCH_ABI)/libmx2_"+extmod.name+".a"
+					
+				buf.Push( "include $(CLEAR_VARS)" )
+				buf.Push( "LOCAL_MODULE := mx2_"+extmod.name )
+				buf.Push( "LOCAL_SRC_FILES := "+src )
+				buf.Push( "include $(PREBUILT_STATIC_LIBRARY)" )
+			Next
+			
+			For Local dll:=Eachin DLL_FILES
+			
+				buf.Push( "include $(CLEAR_VARS)" )
+				buf.Push( "LOCAL_MODULE := "+StripDir( dll ) )
+				buf.Push( "LOCAL_SRC_FILES := "+dll )
+				buf.Push( "include $(PREBUILT_SHARED_LIBRARY)" )
+			
+			Next
+			
+		Endif
+		
+		buf.Push( "include $(CLEAR_VARS)" )
+		
+		If opts.productType="app"
+			buf.Push( "LOCAL_MODULE := mx2_main" )
+		Else
+			buf.Push( "LOCAL_MODULE := mx2_"+module.name )
+		Endif
+		
+		buf.Push( "LOCAL_CFLAGS += -I~q"+MODULES_DIR+"monkey/native~q" )
+		buf.Push( "LOCAL_CFLAGS += -I~q"+MODULES_DIR+"~q" )
+		If APP_DIR buf.Push( "LOCAL_CFLAGS += -I~q"+APP_DIR+"~q" )
+		
+		For Local opt:=Eachin CC_OPTS
+			If opt.StartsWith( "-I" ) buf.Push( "LOCAL_CFLAGS += "+opt )
+		Next
+		
+		buf.Push( "LOCAL_SRC_FILES := \" )
+		For Local src:=Eachin SRC_FILES
+			buf.Push( MakeRelativePath( src,jniDir )+" \" )
+		Next
+		buf.Push( "" )
+		
+		If opts.productType="app"
+		
+			buf.Push( "LOCAL_STATIC_LIBRARIES := \" )
+			For Local extmod:=Eachin Builder.instance.modules.Backwards()
+				If extmod=module Continue
+				
+				buf.Push( "mx2_"+extmod.name+" \" )
+			Next
+			buf.Push( "" )
+			
+			buf.Push( "LOCAL_SHARED_LIBRARIES := \" )
+			For Local dll:=Eachin DLL_FILES
+				buf.Push( StripDir( dll )+" \" )
+			Next
+			buf.Push( "" )
+			
+			For Local lib:=Eachin LD_SYSLIBS
+				If lib.StartsWith( "-l" ) buf.Push( "LOCAL_LDLIBS += "+lib )
+			Next
+			
+			'This keeps the JNI functions in sdl2 alive, or it gets optimized out of the build as its unused...
+			'
+			buf.Push( "LOCAL_WHOLE_STATIC_LIBRARIES := mx2_sdl2" )
+
+			buf.Push( "include $(BUILD_SHARED_LIBRARY)" )
+		Else
+
+			buf.Push( "include $(BUILD_STATIC_LIBRARY)" )
+		Endif
+		
+		CSaveString( buf.Join( "~n" ),jniDir+"Android.mk" )
+		buf.Clear()
+		
+		Local cd:=CurrentDir()
+		
+		ChangeDir( module.outputDir )
+		
+		Exec( "ndk-build" )
+		
+		ChangeDir( cd )
+		
+		If opts.productType="app"
+		
+			CopyAssets( module.outputDir+"assets/" )
+		
+		Endif
+		
+	End
+	
+End

+ 0 - 207
src/mx2cc/dox_matrix.txt

@@ -1,207 +0,0 @@
-
-The DOX MATRIX!
-
-module{
-
-	'strings...
-	name
-	shortDesc
-	longDesc
-	author
-	version
-	license
-	docs	
-	
-	namespaces
-}
-
-namespaces[]{
-
-	ident
-
-	namespaces
-	aliases
-	enums
-	structs
-	classes
-	interfaces
-	consts
-	globals
-	functions
-}
-
-aliases[]{
-
-	ident
-	docs
-	flags
-	type
-}
-
-enums[]{
-
-	ident
-	docs
-	flags
-	
-	consts
-}
-
-structs[]{
-
-	ident
-	docs
-	flags
-	genArgs
-	superType
-	ifaceTypes
-	where
-
-	aliases
-	enums
-	classes
-	structs
-	interfaces	
-	consts
-	globals
-	functions
-	
-	fields
-	methods
-	properties
-}
-
-classes[]{
-
-	ident
-	docs
-	flags
-	genArgs
-	superType
-	ifaceTypes
-	where
-
-	aliases
-	enums
-	classes
-	structs
-	interfaces	
-	consts
-	globals
-	functions
-	
-	fields
-	methods
-	properties
-}
-
-interfaces[]{
-
-	ident
-	docs
-	flags
-	genArgs
-	superType
-	ifaceTypes
-	where
-
-	aliases
-	enums
-	classes
-	structs
-	interfaces	
-	consts
-	globals
-	functions
-	
-	methods
-	properties
-}
-
-consts[]{
-
-	ident
-	docs
-	flags
-	type
-}
-
-globals[]{
-
-	ident
-	docs
-	flags
-	type
-}
-
-fields[]{
-
-	ident
-	docs
-	flags
-	type
-}
-
-properties[]{
-
-	ident
-	docs
-	flags
-	type
-}
-
-functions[]{
-
-	ident
-	docs
-	overloads
-}
-
-methods[]{
-
-	ident
-	docs
-	overloads 
-}
-
-overloads[]{
-
-	genArgs
-	flags
-	return
-	params
-	where
-}
-
-return{
-
-	type
-	docs
-}
-
-params[]{
-
-	ident
-	docs
-	flags
-	type
-	default
-}
-
-ident=string
-
-docs=string (html)
-
-flags=int bitmask (public, private, abstract, extern etc)
-
-type, superType = string (namespace path to type + optional genArgs, eg: "std.List<Int>" )
-
-ifaceTypes = string[] (array of type paths)
-
-genArgs=string (generic args for generic types/funcs, eg: "<T>" )
-
-default=string (default param value expression)
-
-Notes:
-
-* Multiple modules can currently add stuff to the same namespace, so to find a 'type path' you may have search multiple modules.

+ 24 - 10
src/mx2cc/module.monkey2

@@ -1,17 +1,29 @@
 
 Namespace mx2
 
+#rem
+
+Module directory structure:
+
+baseDir:	mojo/
+buildDir:	mojo/mojo.buildv1.0.3/
+outputDir:	mojo/mojo.buildv1.0.3/desktop_windows_debug/
+cacheDir:	mojo/mojo.buildv1.0.3/desktop_windows_debug/build
+hfileDir:	mojo/mojo.buildv1.0.3/desktop_windows_debug/include
+cfileDir:	mojo/mojo.buildv1.0.3/desktop_windows_debug/src
+
+#end
+
 Class Module
 
 	Field name:String
 	Field srcPath:String
-	Field productType:String
 	
 	Field ident:String
 	Field baseDir:String
 	Field buildDir:String
-	Field cacheDir:String
 	Field outputDir:String
+	Field cacheDir:String
 	Field hfileDir:String
 	Field cfileDir:String
 
@@ -24,21 +36,23 @@ Class Module
 	
 	Field moduleDeps:=New StringMap<Bool>
 	
-	Method New( name:String,srcPath:String,productType:String,version:String )
+	Method New( name:String,srcPath:String,version:String,profile:String )
 		Self.name=name
 		Self.srcPath=srcPath
-		Self.productType=productType
-		
-		Local builder:=Builder.instance
 		
 		ident=MungPath( name )
+		
 		baseDir=ExtractDir( srcPath )
+		
 		buildDir=baseDir+name+".buildv"+version+"/"
-		outputDir=buildDir+builder.profileName+"/"
-		cacheDir=buildDir+"build_cache/"+builder.profileName+"/"
 		
-		cfileDir=cacheDir
-		If productType="module" hfileDir=outputDir Else hfileDir=cacheDir
+		outputDir=buildDir+profile+"/"
+		
+		cacheDir=outputDir+"build/"
+
+		hfileDir=outputDir+"include/"
+		
+		cfileDir=outputDir+"src/"
 	End
 End
 

+ 2 - 1
src/mx2cc/mx2.monkey2

@@ -33,6 +33,7 @@ Namespace mx2
 #Import "mung.monkey2"
 
 #Import "builder.monkey2"
+#Import "buildproduct.monkey2"
 
 Using std
 Using std.stringio
@@ -48,4 +49,4 @@ Using lib.c
 ' 3) edit .sh and .bat files to use new version (common.sh, common.bat)
 ' 4) ./rebuildall
 '
-Const MX2CC_VERSION:="1.0.3"
+Const MX2CC_VERSION:="1.0.4"

+ 33 - 18
src/mx2cc/mx2cc.monkey2

@@ -19,11 +19,13 @@ Using mx2..
 
 Global StartDir:String
 
-Const TestArgs:="mx2cc makedocs mojox"
+Const TestArgs:="mx2cc makemods -clean"	' -target=android"
 
-'Const TestArgs:="mx2cc makemods -clean std"' -target=android"
+'Const TestArgs:="mx2cc makeapp -clean -target=android src/mx2cc/test.monkey2"
+
+'Const TestArgs:="mx2cc makeapp -clean -target=android bananas/gridshooter/gridshooter.monkey2"
 
-'Const TestArgs:="mx2cc makeapp -clean src/mx2cc/test.monkey2"
+'Const TestArgs:="mx2cc makemods -clean std"' -target=android"
 
 'Const TestArgs:="mx2cc makeapp src/ted2/ted2.monkey2"
 
@@ -47,7 +49,7 @@ Function Main()
 	Wend
 	
 	If GetFileType( env )<>FILETYPE_FILE Fail( "Unable to locate mx2cc 'bin' directory" )
-	
+
 	LoadEnv( env )
 	
 	Local args:=AppArgs()
@@ -100,8 +102,8 @@ Function MakeApp:Bool( args:String[] )
 	opts.config="debug"
 	opts.clean=False
 	opts.fast=True
-	opts.run=true
 	opts.verbose=0
+	opts.passes=5
 	
 	args=ParseOpts( opts,args )
 	
@@ -122,21 +124,24 @@ Function MakeApp:Bool( args:String[] )
 	
 	builder.Parse()
 	If builder.errors.Length Return False
+	If opts.passes=1 Return True
 	
 	builder.Semant()
 	If builder.errors.Length Return False
+	If opts.passes=2 Return True
 	
 	builder.Translate()
 	If builder.errors.Length Return False
-
-	builder.Compile()
-	If builder.errors.Length Return False
-
-	Local app:=builder.Link()
-	If builder.errors.Length Return False
+	If opts.passes=3 Return True
 	
-	If Not opts.run Print "Application built:"+app
+	builder.product.Build()
+	If builder.errors.Length Return False
+	If opts.passes=4
+		Print "Application built:"+builder.product.outputFile
+		Return True
+	Endif
 	
+	builder.product.Run()
 	Return True
 End
 
@@ -149,6 +154,7 @@ Function MakeMods:Bool( args:String[] )
 	opts.clean=False
 	opts.fast=True
 	opts.verbose=0
+	opts.passes=4
 	
 	args=ParseOpts( opts,args )
 
@@ -171,18 +177,18 @@ Function MakeMods:Bool( args:String[] )
 		
 		builder.Parse()
 		If builder.errors.Length errs+=1;Continue
+		If opts.passes=1 Continue
 
 		builder.Semant()
 		If builder.errors.Length errs+=1;Continue
+		If opts.passes=2 Continue
 		
 		builder.Translate()
 		If builder.errors.Length errs+=1;Continue
+		If opts.passes=3 Continue
 		
-		builder.Compile()
+		builder.product.Build()
 		If builder.errors.Length errs+=1;Continue
-
-		builder.Link()
-		If builder.errors.Length errs+=1
 	Next
 	
 	Return errs=0
@@ -197,8 +203,10 @@ Function MakeDocs:Bool( args:String[] )
 	opts.clean=False
 	opts.fast=True
 	opts.verbose=0
+	opts.passes=2
 	
 	args=ParseOpts( opts,args )
+	
 	opts.clean=False
 	
 	If Not args args=EnumModules()
@@ -265,9 +273,15 @@ Function ParseOpts:String[]( opts:BuildOpts,args:String[] )
 		If j=-1 
 			Select arg
 			Case "-run"
-				opts.run=True
+				opts.passes=5
 			Case "-build"
-				opts.run=False
+				opts.passes=4
+			Case "-translate"
+				opts.passes=3
+			Case "-semant"
+				opts.passes=2
+			Case "-parse"
+				opts.passes=1
 			Case "-clean"
 				opts.clean=True
 			Case "-verbose"
@@ -373,6 +387,7 @@ End
 Function LoadEnv:Bool( path:String )
 
 	SetEnv( "MX2_HOME",CurrentDir() )
+	SetEnv( "MX2_MODULES",CurrentDir()+"modules" )
 
 	Local lineid:=0
 	

+ 131 - 10
src/mx2cc/test.monkey2

@@ -1,24 +1,145 @@
 
-#Import "docs@/mojox/filebrowser_filetypes"
+Namespace myapp
 
-Namespace test
+#Import "<std>"
+#Import "<mojo>"
+
+Using std..
+Using mojo..
+
+Class MyWindow Extends Window
+
+	Method New()
+	
+		ClearColor=Color.Magenta
+	
+		Local stream:=Stream.Open( "asset::fonts/DejaVuSans.ttf","r" )
+		
+		If stream
+			Print "Stream opened!"
+			Print "Length="+stream.Length
+			stream.Close()
+			If Font.Open( "asset::fonts/DejaVuSans.ttf",16 )
+				Print "Font opened!"
+			Else
+				Print "Font failed!"
+			Endif
+		Else
+			Print "Failed to open stream"
+		Endif
+		
+	End
+
+	Method OnRender( canvas:Canvas ) Override
+	
+		Print "Render!"
+		
+		RequestRender()
+	
+	#rem
+		canvas.Clear( Color.Blue )
+		
+		canvas.Color=Color.Red
+		
+		canvas.DrawRect( 16,16,64,64 )
+		
+		canvas.Color=Color.Yellow
+		
+		canvas.DrawText( "Fuck yeah!",Width/2,Height/2,.5,.5 )
+	#end
+	
+	End
+	
+End
 
 Function Main()
 
-	Local t:=1
+	Print "HELLO WORLD!"
+
+	New AppInstance
 	
-	Local x:=Lambda()
+	New MyWindow
 	
-		Local y:=Lambda()
+	App.Run()
+End
+
+#rem
+
+#import "<libc>"
+#import "<sdl2>"
+#import "<gles20>"
+
+Namespace sdl2test
+
+Using libc..
+Using sdl2..
+Using gles20..
+
+Class SdlWindow
+
+	Field sdlWindow:SDL_Window Ptr
+	Field sdlGLContext:SDL_GLContext
+	
+	Method New()
+	
+		SDL_Init( SDL_INIT_EVERYTHING )
+		
+		sdlWindow=SDL_CreateWindow( "SDL2 OpenGL Window",SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,640,480,SDL_WINDOW_OPENGL )
+		
+		sdlGLContext=SDL_GL_CreateContext( sdlWindow )
+		
+		SDL_GL_MakeCurrent( sdlWindow,sdlGLContext )
+	End
+	
+	Method Run()
+	
+		Repeat
 		
-			Print t
+			Local event:SDL_Event
+			
+			While( SDL_PollEvent( Varptr event ) )
 		
-		End
+				Select event.type
+					
+				Case SDL_WINDOWEVENT
 		
-		Local t:=10
+					Local wevent:=Cast<SDL_WindowEvent Ptr>( Varptr event )
+			
+					Select wevent->event
+					
+					Case SDL_WINDOWEVENT_CLOSE
+					
+						exit_( 0 )
+					
+					End
+					
+				End
+
+			Wend
+			
+			OnRender()
+			
+			SDL_GL_SwapWindow( sdlWindow )
+		Forever
+		
+	End
 	
+	Method OnRender()
+	
+		glClearColor( 1,1,0,1 )
+		
+		glClear( GL_COLOR_BUFFER_BIT )
 	End
 	
-	x()
+End
+
+
+Function Main()
+
+	Local window:=New SdlWindow
+	
+	window.Run()
+
+End
 
-End
+#end

+ 2 - 2
src/mx2cc/translator.monkey2

@@ -375,8 +375,8 @@ Class Translator
 	Method EmitInclude( fdecl:FileDecl,baseDir:String )
 	
 		If _incs.Contains( fdecl.ident ) Return
-		
-		Emit( "#include ~q"+MakeRelativePath( fdecl.hfile,baseDir )+"~q" )
+
+		Emit( "#include ~q"+MakeIncludePath( fdecl.hfile,baseDir )+"~q" )
 		
 		_incs[fdecl.ident]=fdecl
 	End

+ 4 - 4
src/mx2cc/translator_cpp.monkey2

@@ -20,7 +20,7 @@ Class Translator_CPP Extends Translator
 		Emit( "#include <bbmonkey.h>" )
 		
 		If fdecl.exhfile
-			Emit( "#include ~q"+MakeRelativePath( fdecl.exhfile,ExtractDir( fdecl.hfile ) )+"~q" )
+			Emit( "#include ~q"+MakeIncludePath( fdecl.exhfile,ExtractDir( fdecl.hfile ) )+"~q" )
 		End
 		
 		For Local ipath:=Eachin fdecl.imports
@@ -31,7 +31,7 @@ Class Translator_CPP Extends Translator
 			
 			If imp.EndsWith( ".h" ) Or imp.EndsWith( ".hh" ) Or imp.EndsWith( ".hpp" )
 				Local path:=ExtractDir( fdecl.path )+ipath
-				Emit( "#include ~q"+MakeRelativePath( path,ExtractDir( fdecl.hfile ) )+"~q" )
+				Emit( "#include ~q"+MakeIncludePath( path,ExtractDir( fdecl.hfile ) )+"~q" )
 				Continue
 			Endif
 			
@@ -934,8 +934,8 @@ Class Translator_CPP Extends Translator
 	End
 	
 	Method EmitStmt( stmt:PrintStmt )
-	
-		Emit( "puts("+Trans( stmt.value )+".c_str());fflush( stdout );" )
+
+		Emit( "bb_print("+Trans( stmt.value )+");" )
 	End
 	
 	Method EmitStmt( stmt:ExitStmt )

+ 15 - 0
src/mx2cc/util.monkey2

@@ -44,6 +44,21 @@ Global STRING_MX2EOL:=STRING_TILDE+"n"
 Global STRING_MX2RETURN:=STRING_TILDE+"r"
 Global STRING_MX2TAB:=STRING_TILDE+"t"
 
+Global APP_DIR:String
+Global MODULES_DIR:String
+
+Function MakeIncludePath:String( path:String,baseDir:String )
+
+'	Return MakeRelativePath( path,baseDir )
+'	Return path
+
+	If path.StartsWith( MODULES_DIR ) Return path.Slice( MODULES_DIR.Length )
+	
+	If APP_DIR And path.StartsWith( APP_DIR ) Return path.Slice( APP_DIR.Length )
+	
+	Return path
+End
+
 Function MungPath:String( path:String )
 	Local id:=path
 	id=id.Replace( "_","_0" )