forked from LeenkxTeam/LNXSDK
Update Files
This commit is contained in:
158
Kha/Backends/Kinc-hxcpp/khacpp/tools/azure-pipelines/build.yml
Normal file
158
Kha/Backends/Kinc-hxcpp/khacpp/tools/azure-pipelines/build.yml
Normal file
@ -0,0 +1,158 @@
|
||||
parameters:
|
||||
name: ''
|
||||
vmImage: ''
|
||||
arch: '' # hxcpp's target arch (HXCPP_Mxx), can be '32' or '64'
|
||||
platform: '' # can be linux64, mac, windows, or windows64
|
||||
listPlatform32: ['linux32', 'windows']
|
||||
listPlatform64: ['linux64', 'mac', 'windows64']
|
||||
|
||||
jobs:
|
||||
- job: ${{ parameters.name }}
|
||||
pool:
|
||||
vmImage: ${{ parameters.vmImage }}
|
||||
variables:
|
||||
${{ if startsWith(parameters.vmImage, 'ubuntu-') }}:
|
||||
libExt: .dso
|
||||
sep: '/'
|
||||
${{ if contains(parameters.vmImage, 'mac') }}:
|
||||
libExt: .dylib
|
||||
sep: '/'
|
||||
${{ if contains(parameters.vmImage, 'win') }}:
|
||||
libExt: .dll
|
||||
sep: '\'
|
||||
steps:
|
||||
- ${{ if startsWith(parameters.vmImage, 'ubuntu-') }}:
|
||||
- script: |
|
||||
set -ex
|
||||
sudo rm -R /var/lib/mysql/
|
||||
# mariadb
|
||||
curl -sS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup > mariadb_repo_setup
|
||||
curl -sS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup.sha256 > mariadb_repo_setup.sha256
|
||||
sha256sum --check mariadb_repo_setup.sha256
|
||||
sudo bash mariadb_repo_setup
|
||||
sudo apt-get update -qqy
|
||||
sudo apt-get remove -qqy mysql-common
|
||||
sudo apt-get autoremove -qqy
|
||||
sudo apt-get install -qqy mariadb-server
|
||||
# remaining packages
|
||||
sudo apt-get install -qqy gcc-multilib g++-multilib
|
||||
displayName: Install dependencies
|
||||
- script: |
|
||||
set -ex
|
||||
sudo systemctl start mysql
|
||||
sudo mysql -u root -e "create database hxcpp; grant all privileges on hxcpp.* to hxcpp@localhost identified by 'hxcpp'; flush privileges;"
|
||||
displayName: Configure MariaDB
|
||||
- template: install-neko-snapshot.yaml
|
||||
parameters:
|
||||
platform: ${{ parameters.platform }}
|
||||
- template: install-haxe-snapshot.yaml
|
||||
parameters:
|
||||
platform: ${{ parameters.platform }}
|
||||
- script: |
|
||||
set -ex
|
||||
mkdir -p ~/haxelib
|
||||
haxelib setup ~/haxelib
|
||||
haxelib install utest
|
||||
haxelib dev hxcpp $(Build.SourcesDirectory)
|
||||
haxelib list
|
||||
displayName: Install Haxe libraries
|
||||
- script: haxe compile.hxml
|
||||
workingDirectory: tools/run
|
||||
displayName: Build run.n
|
||||
- script: haxe compile.hxml
|
||||
workingDirectory: tools/hxcpp
|
||||
displayName: Build hxcpp
|
||||
- script: haxe compile-cppia.hxml
|
||||
workingDirectory: project
|
||||
displayName: Build cppia
|
||||
|
||||
# cffi
|
||||
- script: haxelib run hxcpp build.xml -debug -DHXCPP_M${{parameters.arch}}
|
||||
workingDirectory: test/cffi/project
|
||||
displayName: Build cffi project
|
||||
- bash: |
|
||||
set -ex
|
||||
haxe compile.hxml -debug -D HXCPP_M${{parameters.arch}}
|
||||
haxe compile-utf8.hxml -debug -D HXCPP_M${{parameters.arch}}
|
||||
haxe compile-neko.hxml -debug -D HXCPP_M${{parameters.arch}}
|
||||
workingDirectory: test/cffi
|
||||
displayName: cffi test - Compile
|
||||
- script: bin$(sep)cpp$(sep)TestMain-debug
|
||||
workingDirectory: test/cffi
|
||||
displayName: cffi test - Run
|
||||
- script: bin$(sep)cpp-utf8$(sep)TestMain-debug
|
||||
workingDirectory: test/cffi
|
||||
displayName: cffi-utf8 test - Run
|
||||
- ${{ if or(and(containsValue(parameters.listPlatform32, parameters.platform), eq(parameters.arch, '32')), and(containsValue(parameters.listPlatform64, parameters.platform), eq(parameters.arch, '64'))) }}:
|
||||
- bash: cp test/cffi/project/ndll/*/prime$(libExt) test/cffi/bin/neko/prime.ndll
|
||||
displayName: Copy prime.ndll
|
||||
- script: neko TestMain.n
|
||||
workingDirectory: test/cffi/bin/neko
|
||||
displayName: cffi-neko test - Run
|
||||
|
||||
# haxe
|
||||
- script: haxe compile.hxml -debug -D HXCPP_M${{parameters.arch}}
|
||||
workingDirectory: test/haxe
|
||||
displayName: haxe test - Compile
|
||||
- script: bin$(sep)TestMain-debug
|
||||
workingDirectory: test/haxe
|
||||
displayName: haxe test - Run
|
||||
|
||||
# telemetry, should work in debug and non-debug modes
|
||||
- script: haxe compile.hxml -debug -D HXCPP_M${{parameters.arch}}
|
||||
workingDirectory: test/telemetry
|
||||
displayName: telemetry test (debug) - Compile
|
||||
- script: bin$(sep)TestMain-debug
|
||||
workingDirectory: test/telemetry
|
||||
displayName: telemetry test (debug) - Run
|
||||
- script: haxe compile.hxml -D HXCPP_M${{parameters.arch}}
|
||||
workingDirectory: test/telemetry
|
||||
displayName: telemetry test - Compile
|
||||
- script: bin$(sep)TestMain
|
||||
workingDirectory: test/telemetry
|
||||
displayName: telemetry test - Run
|
||||
|
||||
# std
|
||||
- script: haxe compile${{parameters.arch}}.hxml
|
||||
workingDirectory: test/std
|
||||
displayName: std test - Compile
|
||||
- script: cpp${{parameters.arch}}$(sep)Test
|
||||
workingDirectory: test/std
|
||||
displayName: std test - Run
|
||||
|
||||
# debugger
|
||||
- script: haxe compile.hxml -D HXCPP_M${{parameters.arch}}
|
||||
workingDirectory: test/debugger
|
||||
displayName: debugger test - Compile
|
||||
- script: bin$(sep)App-debug
|
||||
workingDirectory: test/debugger
|
||||
displayName: debugger test - Run
|
||||
|
||||
# native
|
||||
- script: haxe compile.hxml -D HXCPP_M${{parameters.arch}}
|
||||
workingDirectory: test/native
|
||||
displayName: native test - Compile
|
||||
- script: bin$(sep)Native
|
||||
workingDirectory: test/native
|
||||
displayName: native test - Run
|
||||
|
||||
# haxe unit test
|
||||
- bash: |
|
||||
set -ex
|
||||
HAXE_VERSION=`haxe -version`
|
||||
HAXE_HASH=`[[ "$HAXE_VERSION" =~ ^.+\+(.+) ]] && echo ${BASH_REMATCH[1]}`
|
||||
git clone -q https://github.com/HaxeFoundation/haxe.git
|
||||
pushd haxe
|
||||
git reset --hard "$HAXE_HASH"
|
||||
git clean -fdx
|
||||
popd
|
||||
displayName: haxe unit test - Clone haxe repo
|
||||
- script: haxelib install compile-cpp.hxml --always
|
||||
workingDirectory: haxe/tests/unit
|
||||
displayName: haxe unit test - Install haxelibs
|
||||
- script: haxe compile-cpp.hxml -D HXCPP_M${{parameters.arch}} -D no_http
|
||||
workingDirectory: haxe/tests/unit
|
||||
displayName: haxe unit test - Compile
|
||||
- script: bin$(sep)cpp$(sep)TestMain-debug
|
||||
workingDirectory: haxe/tests/unit
|
||||
displayName: haxe unit test - Run
|
@ -0,0 +1,31 @@
|
||||
parameters:
|
||||
platform: '' # can be linux64, mac, windows, or windows64
|
||||
|
||||
steps:
|
||||
- ${{ if startsWith(parameters.platform, 'windows') }}:
|
||||
- powershell: |
|
||||
Invoke-WebRequest https://build.haxe.org/builds/haxe/${{parameters.platform}}/haxe_latest.zip -OutFile $(Agent.TempDirectory)/haxe_latest.zip
|
||||
Expand-Archive $(Agent.TempDirectory)/haxe_latest.zip -DestinationPath $(Agent.TempDirectory)
|
||||
Remove-Item $(Agent.TempDirectory)/haxe_latest.zip
|
||||
$HAXEPATH = Get-Item $(Agent.TempDirectory)/haxe_*
|
||||
$HAXE_STD_PATH = "$HAXEPATH\std"
|
||||
Write-Host "##vso[task.prependpath]$HAXEPATH"
|
||||
Write-Host "##vso[task.setvariable variable=HAXE_STD_PATH]$HAXE_STD_PATH"
|
||||
displayName: Install Haxe using snapshot from S3
|
||||
- ${{ if not(startsWith(parameters.platform, 'windows')) }}:
|
||||
- bash: |
|
||||
set -ex
|
||||
DOWNLOADDIR=$(Agent.TempDirectory)
|
||||
curl -sSL https://build.haxe.org/builds/haxe/${{parameters.platform}}/haxe_latest.tar.gz -o $(Agent.TempDirectory)/haxe_latest.tar.gz
|
||||
tar -xf $(Agent.TempDirectory)/haxe_latest.tar.gz -C $(Agent.TempDirectory)
|
||||
rm $(Agent.TempDirectory)/haxe_latest.tar.gz
|
||||
HAXEPATH=`echo $(Agent.TempDirectory)/haxe_*`
|
||||
sudo mkdir -p /usr/local/bin
|
||||
sudo mkdir -p /usr/local/share/haxe
|
||||
sudo ln -s $HAXEPATH/{haxe,haxelib} /usr/local/bin/
|
||||
sudo ln -s $HAXEPATH/std /usr/local/share/haxe/std
|
||||
set +x
|
||||
echo "##vso[task.setvariable variable=HAXE_STD_PATH]/usr/local/share/haxe/std"
|
||||
displayName: Install Haxe using snapshot from S3
|
||||
- script: haxe -version
|
||||
displayName: Print Haxe version
|
@ -0,0 +1,33 @@
|
||||
parameters:
|
||||
platform: '' # can be linux64, mac, windows, or windows64
|
||||
|
||||
steps:
|
||||
- ${{ if startsWith(parameters.platform, 'windows') }}:
|
||||
- powershell: |
|
||||
Invoke-WebRequest https://build.haxe.org/builds/neko/${{parameters.platform}}/neko_latest.zip -OutFile $(Agent.TempDirectory)/neko_latest.zip
|
||||
Expand-Archive $(Agent.TempDirectory)/neko_latest.zip -DestinationPath $(Agent.TempDirectory)
|
||||
$NEKOPATH = Get-ChildItem $(Agent.TempDirectory)/neko-*-win
|
||||
Write-Host "##vso[task.prependpath]$NEKOPATH"
|
||||
Write-Host "##vso[task.setvariable variable=NEKOPATH]$NEKOPATH"
|
||||
displayName: Install Neko using snapshot from S3
|
||||
- ${{ if not(startsWith(parameters.platform, 'windows')) }}:
|
||||
- bash: |
|
||||
set -ex
|
||||
DOWNLOADDIR=$(Agent.TempDirectory)
|
||||
curl -sSL https://build.haxe.org/builds/neko/${{parameters.platform}}/neko_latest.tar.gz -o $(Agent.TempDirectory)/neko_latest.tar.gz
|
||||
tar -xf $(Agent.TempDirectory)/neko_latest.tar.gz -C $(Agent.TempDirectory)
|
||||
NEKOPATH=`echo $(Agent.TempDirectory)/neko-*-*`
|
||||
sudo mkdir -p /usr/local/bin
|
||||
sudo mkdir -p /usr/local/lib/neko
|
||||
sudo ln -s $NEKOPATH/{neko,nekoc,nekoml,nekotools} /usr/local/bin/
|
||||
sudo ln -s $NEKOPATH/libneko.* /usr/local/lib/
|
||||
sudo ln -s $NEKOPATH/*.ndll /usr/local/lib/neko/
|
||||
set +x
|
||||
echo "##vso[task.prependpath]$NEKOPATH"
|
||||
echo "##vso[task.setvariable variable=NEKOPATH]$NEKOPATH"
|
||||
displayName: Install Neko using snapshot from S3
|
||||
- ${{ if eq(parameters.platform, 'linux64') }}:
|
||||
- bash: sudo ldconfig
|
||||
displayName: ldconfig
|
||||
- script: neko -version 2>&1
|
||||
displayName: Print Neko version
|
39
Kha/Backends/Kinc-hxcpp/khacpp/tools/build/Build.hx
Normal file
39
Kha/Backends/Kinc-hxcpp/khacpp/tools/build/Build.hx
Normal file
@ -0,0 +1,39 @@
|
||||
class Build extends hxcpp.Builder
|
||||
{
|
||||
// Create a build in 'bin' directory, with the "stdlibc++" flags for compatibility
|
||||
// This flasg should not make a difference because hxcpp does not use stdlibc++
|
||||
override public function wantLegacyIosBuild() { return true; }
|
||||
|
||||
override public function wantWindows64() { return true; }
|
||||
|
||||
|
||||
// Override to ensure this version if hxcpp is used, even if haxelib says otherwise
|
||||
override public function runBuild(target:String, isStatic:Bool, arch:String, inFlags:Array<String>)
|
||||
{
|
||||
var args = ["run.n", "Build.xml"].concat(inFlags);
|
||||
var here = Sys.getCwd().split("\\").join("/");
|
||||
|
||||
var parts = here.split("/");
|
||||
if (parts.length>0 && parts[parts.length-1]=="")
|
||||
parts.pop();
|
||||
if (parts.length>0)
|
||||
parts.pop();
|
||||
var hxcppDir = parts.join("/");
|
||||
|
||||
// This is how haxelib calls a 'run.n' script...
|
||||
Sys.setCwd(hxcppDir);
|
||||
args.push(here);
|
||||
Sys.println("neko " + args.join(" "));
|
||||
if (Sys.command("neko",args)!=0)
|
||||
{
|
||||
Sys.println("#### Error building neko " + inFlags.join(" "));
|
||||
Sys.exit(-1);
|
||||
}
|
||||
Sys.setCwd(here);
|
||||
}
|
||||
|
||||
public static function main()
|
||||
{
|
||||
new Build( Sys.args() );
|
||||
}
|
||||
}
|
5
Kha/Backends/Kinc-hxcpp/khacpp/tools/build/compile.hxml
Normal file
5
Kha/Backends/Kinc-hxcpp/khacpp/tools/build/compile.hxml
Normal file
@ -0,0 +1,5 @@
|
||||
-neko ../../project/build.n
|
||||
-main Build
|
||||
-D neko_v1
|
||||
-lib hxcpp
|
||||
-debug
|
32
Kha/Backends/Kinc-hxcpp/khacpp/tools/haxe/build_linux.sh
Normal file
32
Kha/Backends/Kinc-hxcpp/khacpp/tools/haxe/build_linux.sh
Normal file
@ -0,0 +1,32 @@
|
||||
#!/bin/bash
|
||||
set -ev
|
||||
|
||||
git clone --recursive https://github.com/HaxeFoundation/haxe.git ~/haxe --depth 1
|
||||
|
||||
sudo add-apt-repository ppa:avsm/ppa -y
|
||||
sudo add-apt-repository ppa:haxe/snapshots -y
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y \
|
||||
neko \
|
||||
ocaml-nox \
|
||||
camlp4-extra \
|
||||
opam \
|
||||
libpcre3-dev \
|
||||
zlib1g-dev \
|
||||
awscli
|
||||
|
||||
export OPAMYES=1
|
||||
opam init
|
||||
eval `opam config env`
|
||||
opam pin add haxe ~/haxe --no-action
|
||||
opam install haxe --deps-only
|
||||
|
||||
# Build haxe
|
||||
pushd ~/haxe
|
||||
make ADD_REVISION=1 && sudo make install INSTALL_DIR=/usr/local
|
||||
popd
|
||||
haxe -version
|
||||
# setup haxelib
|
||||
mkdir ~/haxelib && haxelib setup ~/haxelib
|
||||
haxelib dev hxcpp $TRAVIS_BUILD_DIR
|
||||
haxelib install record-macros
|
28
Kha/Backends/Kinc-hxcpp/khacpp/tools/haxe/build_osx.sh
Normal file
28
Kha/Backends/Kinc-hxcpp/khacpp/tools/haxe/build_osx.sh
Normal file
@ -0,0 +1,28 @@
|
||||
#!/bin/bash
|
||||
set -ev
|
||||
|
||||
git clone --recursive https://github.com/HaxeFoundation/haxe.git ~/haxe --depth 1
|
||||
|
||||
brew update
|
||||
brew tap Homebrew/bundle
|
||||
brew bundle --file=~/haxe/tests/Brewfile --no-upgrade
|
||||
|
||||
brew install neko --HEAD;
|
||||
|
||||
export OPAMYES=1
|
||||
opam init
|
||||
eval `opam config env`
|
||||
opam update
|
||||
opam pin add haxe ~/haxe --no-action
|
||||
opam install haxe --deps-only
|
||||
|
||||
# Build haxe
|
||||
pushd ~/haxe
|
||||
make ADD_REVISION=1 && sudo make install INSTALL_DIR=/usr/local
|
||||
popd
|
||||
haxe -version
|
||||
# setup haxelib
|
||||
mkdir ~/haxelib && haxelib setup ~/haxelib
|
||||
haxelib dev hxcpp $TRAVIS_BUILD_DIR
|
||||
haxelib install record-macros
|
||||
|
2552
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/BuildTool.hx
Normal file
2552
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/BuildTool.hx
Normal file
File diff suppressed because it is too large
Load Diff
304
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/CompileCache.hx
Normal file
304
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/CompileCache.hx
Normal file
@ -0,0 +1,304 @@
|
||||
import sys.FileSystem;
|
||||
|
||||
class CompileCache
|
||||
{
|
||||
public static var hasCache = false;
|
||||
public static var compileCache:String;
|
||||
|
||||
|
||||
public static function init(inDefines:Map<String, String>) : Bool
|
||||
{
|
||||
compileCache = "";
|
||||
hasCache = false;
|
||||
|
||||
if (inDefines.exists("HXCPP_COMPILE_CACHE"))
|
||||
{
|
||||
compileCache = inDefines.get("HXCPP_COMPILE_CACHE");
|
||||
compileCache = compileCache.split("\\").join("/");
|
||||
// Don't get upset by trailing slash
|
||||
while(compileCache.length>1)
|
||||
{
|
||||
var l = compileCache.length;
|
||||
var last = compileCache.substr(l-1);
|
||||
if (last=="/")
|
||||
compileCache = compileCache.substr(0,l-1);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (!FileSystem.exists(compileCache))
|
||||
{
|
||||
try{
|
||||
PathManager.mkdir(compileCache);
|
||||
}
|
||||
catch(e:Dynamic)
|
||||
{
|
||||
Log.error("Could not create compiler cache directory \"" + compileCache + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
if (FileSystem.exists(compileCache) && FileSystem.isDirectory(compileCache))
|
||||
{
|
||||
hasCache = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.error("Could not find compiler cache \"" + compileCache + "\"");
|
||||
//throw "Could not find compiler cache: " + compileCache;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (hasCache)
|
||||
{
|
||||
Log.info("", "\x1b[33;1mUsing compiler cache: " + compileCache + "\x1b[0m");
|
||||
}
|
||||
|
||||
return hasCache;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
public static function getPchCacheName(inProject:String,hash:String,header:String, inExt:String)
|
||||
{
|
||||
var dir = compileCache + "/" + inProject + "/pch" + hash.substr(0,8);
|
||||
try
|
||||
{
|
||||
if (!FileSystem.exists(dir))
|
||||
PathManager.mkdir(dir);
|
||||
} catch(e:Dynamic) { }
|
||||
return dir + "/" + header + inExt;
|
||||
}
|
||||
*/
|
||||
|
||||
public static function getPchDir(inProject:String,hash:String)
|
||||
{
|
||||
var dir = compileCache + "/" + inProject + "/pch" + hash.substr(0,8);
|
||||
try
|
||||
{
|
||||
if (!FileSystem.exists(dir))
|
||||
PathManager.mkdir(dir);
|
||||
} catch(e:Dynamic) { }
|
||||
return dir;
|
||||
}
|
||||
|
||||
public static function getCacheName(inProject:String,hash:String,inExt:String)
|
||||
{
|
||||
var dir = compileCache + "/" + inProject + "/" + hash.substr(0,2);
|
||||
try
|
||||
{
|
||||
if (!FileSystem.exists(dir))
|
||||
PathManager.mkdir(dir);
|
||||
} catch(e:Dynamic) { }
|
||||
return dir + "/" + hash.substr(2) + inExt;
|
||||
}
|
||||
|
||||
public static function clear(inDays:Int,inMB:Int,inLogInfo:Bool,inProject:String)
|
||||
{
|
||||
try
|
||||
{
|
||||
var projects = FileSystem.readDirectory(compileCache);
|
||||
var deleted = 0;
|
||||
var total = 0;
|
||||
var t0 = haxe.Timer.stamp();
|
||||
var tooOld = Date.now().getTime() - inDays * 24 * 3600 * 1000.0;
|
||||
var sizeKB:Float = 0;
|
||||
var fileInfo = [];
|
||||
|
||||
for(project in projects)
|
||||
{
|
||||
if (inProject!=null && inProject!=project)
|
||||
continue;
|
||||
var projectHasDirs = false;
|
||||
var projDir = compileCache + "/" + project;
|
||||
if(!FileSystem.isDirectory(projDir))
|
||||
continue;
|
||||
var dirs = FileSystem.readDirectory(projDir);
|
||||
for(dir in dirs)
|
||||
{
|
||||
var path = projDir + "/" + dir;
|
||||
if(!FileSystem.isDirectory(path)) {
|
||||
FileSystem.deleteFile(path);
|
||||
continue;
|
||||
}
|
||||
if (dir.length!=2 && dir!="lib" && dir.substr(0,3)!="pch" )
|
||||
{
|
||||
Log.warn('bad cache name "$dir" found - try manually clearing');
|
||||
continue;
|
||||
}
|
||||
var dirFiles = FileSystem.readDirectory(path);
|
||||
var allDeleted = true;
|
||||
for(file in dirFiles)
|
||||
{
|
||||
total++;
|
||||
var filename = path + "/" + file;
|
||||
var doDelete = true;
|
||||
if (inDays>0)
|
||||
{
|
||||
var info = FileSystem.stat(filename);
|
||||
var atime = info.atime;
|
||||
var time = atime==null ? info.mtime.getTime() :
|
||||
Math.max(info.atime.getTime(),info.mtime.getTime() );
|
||||
if (time>=tooOld)
|
||||
doDelete = false;
|
||||
}
|
||||
else if (inMB>0)
|
||||
{
|
||||
var info = FileSystem.stat(filename);
|
||||
var atime = info.atime;
|
||||
var time = atime==null ? info.mtime.getTime() :
|
||||
Math.max(info.atime.getTime(),info.mtime.getTime() );
|
||||
fileInfo.push( {filename:filename, time:time, size:info.size } );
|
||||
sizeKB += info.size/1024;
|
||||
doDelete = false;
|
||||
}
|
||||
|
||||
if (doDelete)
|
||||
{
|
||||
try
|
||||
{
|
||||
FileSystem.deleteFile(filename);
|
||||
deleted++;
|
||||
}
|
||||
catch(e:Dynamic)
|
||||
{
|
||||
Log.warn('Could not delete $filename');
|
||||
}
|
||||
}
|
||||
else
|
||||
allDeleted = false;
|
||||
}
|
||||
if (allDeleted)
|
||||
{
|
||||
try
|
||||
{
|
||||
FileSystem.deleteDirectory(path);
|
||||
}
|
||||
catch(e:Dynamic)
|
||||
{
|
||||
Log.warn('Could not delete directory $path');
|
||||
}
|
||||
}
|
||||
else
|
||||
projectHasDirs = true;
|
||||
}
|
||||
if (!projectHasDirs)
|
||||
{
|
||||
try
|
||||
{
|
||||
FileSystem.deleteDirectory(projDir);
|
||||
}
|
||||
catch(e:Dynamic)
|
||||
{
|
||||
Log.warn('Could not delete directory $projDir');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (inMB*1024<sizeKB)
|
||||
{
|
||||
// newest first
|
||||
fileInfo.sort( function(a,b) return a.time > b.time ? -1 : 1 );
|
||||
var keepKB:Float = inMB*1024;
|
||||
for(info in fileInfo)
|
||||
{
|
||||
if (keepKB>0)
|
||||
{
|
||||
sizeKB -= info.size/1024;
|
||||
keepKB -= info.size/1024;
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
FileSystem.deleteFile(info.filename);
|
||||
deleted++;
|
||||
}
|
||||
catch(e:Dynamic)
|
||||
{
|
||||
Log.warn('Could not delete ${info.filename}');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var t = haxe.Timer.stamp()-t0;
|
||||
var projString = inProject==null ? "" : ' from project $inProject';
|
||||
var message = inMB > 0 ?
|
||||
'Cache: removed $deleted/$total files$projString, leaving ' + Std.int(sizeKB/1024) + 'MB, in $t seconds' :
|
||||
'Cache: removed $deleted/$total files$projString in $t seconds';
|
||||
if (inLogInfo)
|
||||
Log.info(message);
|
||||
else
|
||||
Log.v(message);
|
||||
}
|
||||
catch(error:Dynamic)
|
||||
{
|
||||
Log.warn("Error cleaning cache: " + error);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static function list(inDetails:Bool,inProject:String)
|
||||
{
|
||||
try
|
||||
{
|
||||
Sys.println('Cache Directory: $compileCache');
|
||||
var t0 = haxe.Timer.stamp();
|
||||
var files = new Array<String>();
|
||||
var projects = FileSystem.readDirectory(compileCache);
|
||||
var size = 0.0;
|
||||
var count = 0;
|
||||
|
||||
for(project in projects)
|
||||
{
|
||||
if (inProject!=null && inProject!=project)
|
||||
continue;
|
||||
var projSize = size;
|
||||
var projCount = count;
|
||||
var projDir = compileCache + "/" + project;
|
||||
if(!FileSystem.isDirectory(projDir))
|
||||
continue;
|
||||
var dirs = FileSystem.readDirectory(projDir);
|
||||
for(dir in dirs)
|
||||
{
|
||||
var path = projDir + "/" + dir;
|
||||
if(!FileSystem.isDirectory(path))
|
||||
continue;
|
||||
var dirFiles = FileSystem.readDirectory(path);
|
||||
for(file in dirFiles)
|
||||
{
|
||||
var filename = path + "/" + file;
|
||||
var info = FileSystem.stat(filename);
|
||||
if (inDetails)
|
||||
{
|
||||
var atime = info.atime;
|
||||
if (atime==null || atime.getTime()<info.mtime.getTime())
|
||||
atime = info.mtime;
|
||||
Sys.println('$filename : ${info.size} bytes, $atime');
|
||||
}
|
||||
count++;
|
||||
size += info.size;
|
||||
}
|
||||
//files = files.concat(dirFiles);
|
||||
}
|
||||
projSize = Std.int( (size - projSize)/1024 );
|
||||
projCount = count - projCount;
|
||||
Sys.println('Project $project\t: ${projSize}k in $projCount files');
|
||||
}
|
||||
|
||||
var k = Std.int(size/1024);
|
||||
var t = haxe.Timer.stamp()-t0;
|
||||
var projString = inProject==null ? "" : ' in project $inProject';
|
||||
Sys.println('Found: ${k}k in $count files$projString in $t seconds');
|
||||
}
|
||||
catch(error:Dynamic)
|
||||
{
|
||||
Log.warn("Error accessing cache: " + error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
642
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/Compiler.hx
Normal file
642
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/Compiler.hx
Normal file
@ -0,0 +1,642 @@
|
||||
import haxe.crypto.Md5;
|
||||
import haxe.io.Path;
|
||||
import sys.FileSystem;
|
||||
|
||||
private class FlagInfo
|
||||
{
|
||||
var flag:String;
|
||||
var tag:String;
|
||||
public function new(inFlag:String, inTag:String)
|
||||
{
|
||||
flag = inFlag;
|
||||
tag = inTag;
|
||||
}
|
||||
public function add(args:Array<String>, inFilter:Array<String>)
|
||||
{
|
||||
var allowSpace = inFilter.indexOf("nvcc")<0;
|
||||
if ((tag==""&&allowSpace) || inFilter.indexOf(tag)>=0)
|
||||
args.push(flag);
|
||||
}
|
||||
public function toString():String
|
||||
{
|
||||
if (tag=="")
|
||||
return flag;
|
||||
else
|
||||
return '$flag($tag)';
|
||||
}
|
||||
}
|
||||
|
||||
class Compiler
|
||||
{
|
||||
private var mFlags:Array<FlagInfo>;
|
||||
public var mCFlags:Array<String>;
|
||||
public var mNvccFlags:Array<String>;
|
||||
public var mMMFlags:Array<String>;
|
||||
public var mCPPFlags:Array<String>;
|
||||
public var mOBJCFlags:Array<String>;
|
||||
public var mPCHFlags:Array<String>;
|
||||
public var mAddGCCIdentity:Bool;
|
||||
public var mExe:String;
|
||||
public var mOutFlag:String;
|
||||
public var mObjDir:String;
|
||||
public var mRelObjDir:String;
|
||||
public var mExt:String;
|
||||
|
||||
public var mPCHExt:String;
|
||||
public var mPCHCreate:String;
|
||||
public var mPCHUse:String;
|
||||
public var mPCHFilename:String;
|
||||
public var mPCH:String;
|
||||
|
||||
public var mRcExe:String;
|
||||
public var mRcExt:String;
|
||||
public var mRcFlags:Array<String>;
|
||||
|
||||
public var mGetCompilerVersion:String;
|
||||
public var mCompilerVersion:String;
|
||||
public var mCompilerVersionString:String;
|
||||
public var mCached:Bool;
|
||||
|
||||
public var mID:String;
|
||||
|
||||
//testing...
|
||||
public var useCacheInPlace = true;
|
||||
//public var useCacheInPlace = false;
|
||||
|
||||
public function new(inID,inExe:String)
|
||||
{
|
||||
mFlags = [];
|
||||
mCFlags = [];
|
||||
mNvccFlags = [];
|
||||
mCPPFlags = [];
|
||||
mOBJCFlags = [];
|
||||
mMMFlags = [];
|
||||
mPCHFlags = [];
|
||||
mAddGCCIdentity = false;
|
||||
mCompilerVersion = null;
|
||||
mRcExt = ".res";
|
||||
mObjDir = "obj";
|
||||
mOutFlag = "-o";
|
||||
mExe = inExe;
|
||||
mID = inID;
|
||||
mExt = ".o";
|
||||
mPCHExt = ".pch";
|
||||
mPCHCreate = "-Yc";
|
||||
mPCHUse = "-Yu";
|
||||
mPCHFilename = "/Fp";
|
||||
mCached = false;
|
||||
mRcFlags = [];
|
||||
}
|
||||
|
||||
public function getFlagStrings()
|
||||
{
|
||||
var result = new Array<String>();
|
||||
for(f in mFlags)
|
||||
result.push( f.toString() );
|
||||
return result;
|
||||
}
|
||||
|
||||
public function addFlag(inFlag:String, inTag:String)
|
||||
{
|
||||
mFlags.push( new FlagInfo(inFlag, inTag) );
|
||||
}
|
||||
|
||||
|
||||
public function objToAbsolute()
|
||||
{
|
||||
if (mRelObjDir==null)
|
||||
mRelObjDir = mObjDir;
|
||||
mObjDir = Path.normalize( PathManager.combine( Sys.getCwd(), mRelObjDir ) );
|
||||
}
|
||||
|
||||
public function getTargetPrefix()
|
||||
{
|
||||
var dir = mRelObjDir!=null ? mRelObjDir : mObjDir;
|
||||
dir = dir.split("\\").join("/");
|
||||
var parts = dir.split("/");
|
||||
// Trailing slash?
|
||||
var prefix = parts.pop();
|
||||
if (prefix=="")
|
||||
prefix = parts.pop();
|
||||
if (prefix==null)
|
||||
prefix = "";
|
||||
prefix = prefix.split("-").join("_");
|
||||
return prefix;
|
||||
}
|
||||
|
||||
function addIdentity(ext:String,ioArgs:Array<String>)
|
||||
{
|
||||
if (mAddGCCIdentity)
|
||||
{
|
||||
var identity = switch(ext)
|
||||
{
|
||||
case "c" : "c";
|
||||
case "m" : "objective-c";
|
||||
case "mm" : "objective-c++";
|
||||
case "cpp" : "c++";
|
||||
case "c++" : "c++";
|
||||
default:"";
|
||||
}
|
||||
if (identity!="")
|
||||
{
|
||||
ioArgs.push("-x");
|
||||
ioArgs.push(identity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addOptimTags(tagFilter:Array<String>)
|
||||
{
|
||||
var optimFlags = (tagFilter.indexOf("debug") >= 0 ? 1 : 0) +
|
||||
(tagFilter.indexOf("release") >= 0 ? 1 : 0) +
|
||||
(tagFilter.indexOf("optim-std") >= 0 ? 1 : 0) +
|
||||
(tagFilter.indexOf("optim-none") >= 0 ? 1 : 0) +
|
||||
(tagFilter.indexOf("optim-size") >= 0 ? 1 : 0);
|
||||
if (optimFlags==0)
|
||||
tagFilter.push("optim-std");
|
||||
else if (optimFlags>1)
|
||||
Log.error("More than one optimization tag has been set:" + tagFilter);
|
||||
}
|
||||
|
||||
|
||||
public function getCompilerDefines(inTags:String)
|
||||
{
|
||||
var args = new Array<String>();
|
||||
var tagFilter = inTags.split(",");
|
||||
addOptimTags(tagFilter);
|
||||
for(flag in mFlags)
|
||||
flag.add(args,tagFilter);
|
||||
return args;
|
||||
}
|
||||
|
||||
function getArgs(inFile:File)
|
||||
{
|
||||
var nvcc = inFile.isNvcc();
|
||||
var isRc = mRcExe!=null && inFile.isResource();
|
||||
var args = nvcc ? inFile.mGroup.mCompilerFlags.concat( BuildTool.getNvccFlags() ) :
|
||||
inFile.mCompilerFlags.concat(inFile.mGroup.mCompilerFlags);
|
||||
var tagFilter = inFile.getTags().split(",");
|
||||
addOptimTags(tagFilter);
|
||||
if (!isRc)
|
||||
for(flag in mFlags)
|
||||
flag.add(args,tagFilter);
|
||||
var ext = mExt.toLowerCase();
|
||||
var ext = new Path(inFile.mName).ext;
|
||||
if (ext!=null)
|
||||
ext = ext.toLowerCase();
|
||||
else
|
||||
Log.error("Unkown extension for " + inFile.mName);
|
||||
|
||||
|
||||
addIdentity(ext,args);
|
||||
|
||||
var allowPch = false;
|
||||
if (nvcc)
|
||||
args = args.concat(mNvccFlags);
|
||||
else if (isRc)
|
||||
args = args.concat(mRcFlags);
|
||||
else if (ext=="c")
|
||||
args = args.concat(mCFlags);
|
||||
else if (ext=="m")
|
||||
args = args.concat(mOBJCFlags);
|
||||
else if (ext=="mm")
|
||||
args = args.concat(mMMFlags);
|
||||
else if (ext=="cpp" || ext=="c++" || ext=="cc")
|
||||
{
|
||||
allowPch = true;
|
||||
args = args.concat(mCPPFlags);
|
||||
}
|
||||
|
||||
if (isRc || inFile.getTags()!=inFile.mGroup.getTags())
|
||||
allowPch = false;
|
||||
|
||||
if (inFile.mGroup.isPrecompiled() && allowPch)
|
||||
{
|
||||
var pchDir = getPchDir(inFile.mGroup);
|
||||
if (mPCHUse!="")
|
||||
{
|
||||
args.push(mPCHUse + inFile.mGroup.mPrecompiledHeader + ".h");
|
||||
args.push(mPCHFilename + pchDir + "/" + inFile.mGroup.getPchName() + mPCHExt);
|
||||
}
|
||||
else
|
||||
args.unshift("-I"+pchDir);
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
public function createEmbedFile(srcName:String, destName:String, embedName:String, scramble:String)
|
||||
{
|
||||
try
|
||||
{
|
||||
var content = sys.io.File.getContent(srcName);
|
||||
var output = new Array<String>();
|
||||
|
||||
if (scramble==null)
|
||||
{
|
||||
output.push( 'const char *$embedName = ' );
|
||||
content = content.split("\r").join("");
|
||||
content = content.split("\\").join( String.fromCharCode(1) );
|
||||
content = content.split('"').join('\\"');
|
||||
content = content.split(String.fromCharCode(1)).join("\\\\" );
|
||||
var lines = content.split("\n");
|
||||
for(line in lines)
|
||||
output.push( '"$line\\n"' );
|
||||
output.push(";\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
var bytes = haxe.io.Bytes.ofString(content);
|
||||
var byteLen = bytes.length;
|
||||
var key = haxe.io.Bytes.ofString(scramble);
|
||||
var keyLen = key.length;
|
||||
var state = 0;
|
||||
var line = "";
|
||||
|
||||
output.push( 'int ${embedName}_len = $byteLen;' );
|
||||
output.push( 'static const unsigned char data[] = {' );
|
||||
for(i in 0...byteLen)
|
||||
{
|
||||
var ch = bytes.get(i);
|
||||
state = (((state + key.get(i%keyLen)) ^ ch) & 0xff);
|
||||
line += state + ",";
|
||||
if ( (i%10)==9 )
|
||||
{
|
||||
output.push(line);
|
||||
line = "";
|
||||
}
|
||||
}
|
||||
if (line!="")
|
||||
output.push(line);
|
||||
output.push( '};' );
|
||||
output.push( 'const unsigned char * $embedName = data;' );
|
||||
}
|
||||
sys.io.File.saveContent(destName, output.join("\n") );
|
||||
}
|
||||
catch(e:Dynamic)
|
||||
{
|
||||
Log.warn('Error creating $destName from $srcName: $e');
|
||||
}
|
||||
}
|
||||
|
||||
public function cleanTmp(file:String)
|
||||
{
|
||||
if (BuildTool.keepTemp())
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
if (file!=null && FileSystem.exists(file))
|
||||
FileSystem.deleteFile(file);
|
||||
}
|
||||
catch(e:Dynamic) { }
|
||||
}
|
||||
|
||||
public function compile(inFile:File,inTid:Int,headerFunc:Void->Void,pchTimeStamp:Null<Float>)
|
||||
{
|
||||
var obj_name = getObjName(inFile);
|
||||
var args = getArgs(inFile);
|
||||
var nvcc = inFile.isNvcc();
|
||||
var exe = nvcc ? BuildTool.getNvcc() : mExe;
|
||||
var isRc = mRcExe!=null && inFile.isResource();
|
||||
if (isRc)
|
||||
exe = mRcExe;
|
||||
|
||||
var found = false;
|
||||
var cacheName:String = null;
|
||||
if (mCompilerVersion!=null && inFile.mGroup.isCached())
|
||||
{
|
||||
cacheName = getHashedName(inFile, args);
|
||||
if (useCacheInPlace)
|
||||
{
|
||||
//Log.info(""," link cache for " + obj_name );
|
||||
obj_name = cacheName;
|
||||
}
|
||||
|
||||
if (FileSystem.exists(cacheName))
|
||||
{
|
||||
var newer = true;
|
||||
if (pchTimeStamp!=null || inFile.mGroup.mRespectTimestamp)
|
||||
{
|
||||
var time = FileSystem.stat(cacheName).mtime.getTime();
|
||||
|
||||
if (pchTimeStamp!=null)
|
||||
newer = time>=pchTimeStamp;
|
||||
if (inFile.mGroup.mRespectTimestamp)
|
||||
newer = newer && time>= FileSystem.stat(inFile.mDir + "/" + inFile.mName).mtime.getTime();
|
||||
}
|
||||
if (newer)
|
||||
{
|
||||
//Log.info(""," copy cache for " + obj_name );
|
||||
if (!useCacheInPlace)
|
||||
sys.io.File.copy(cacheName, obj_name);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
if (headerFunc!=null)
|
||||
headerFunc();
|
||||
|
||||
var tmpFile:String = null;
|
||||
var delayedFilename:String = null;
|
||||
|
||||
if (inFile.mEmbedName!=null)
|
||||
{
|
||||
var srcDir = Path.directory( inFile.mDir + "/" + inFile.mName);
|
||||
tmpFile = new Path( srcDir + "/" + inFile.mEmbedName + ".cpp").toString();
|
||||
Log.v("Creating temp file " + tmpFile);
|
||||
createEmbedFile( inFile.mDir + "/" + inFile.mName, tmpFile, inFile.mEmbedName, inFile.mScramble );
|
||||
args.push( tmpFile );
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isRc)
|
||||
delayedFilename = (new Path( inFile.mDir + inFile.mName)).toString();
|
||||
else
|
||||
args.push( (new Path( inFile.mDir + inFile.mName)).toString() );
|
||||
}
|
||||
|
||||
var out = nvcc ? "-o " : mOutFlag;
|
||||
if (out.substr(-1)==" ")
|
||||
{
|
||||
args.push(out.substr(0,out.length-1));
|
||||
out = "";
|
||||
}
|
||||
|
||||
args.push(out + obj_name);
|
||||
|
||||
if (delayedFilename!=null)
|
||||
args.push(delayedFilename);
|
||||
|
||||
var tagInfo = inFile.mTags==null ? "" : " " + inFile.mTags.split(",");
|
||||
|
||||
var fileName = inFile.mName;
|
||||
var split = fileName.split ("/");
|
||||
if (split.length > 1)
|
||||
{
|
||||
fileName = " \x1b[2m-\x1b[0m \x1b[33m" + split.slice(0, split.length - 1).join("/") + "/\x1b[33;1m" + split[split.length - 1] + "\x1b[0m";
|
||||
}
|
||||
else
|
||||
{
|
||||
fileName = " \x1b[2m-\x1b[0m \x1b[33;1m" + fileName + "\x1b[0m";
|
||||
}
|
||||
fileName += " \x1b[3m" + tagInfo + "\x1b[0m";
|
||||
|
||||
|
||||
if (inTid >= 0)
|
||||
{
|
||||
if (BuildTool.threadExitCode == 0)
|
||||
{
|
||||
if (!Log.verbose)
|
||||
{
|
||||
Log.info(fileName);
|
||||
}
|
||||
var err = ProcessManager.runProcessThreaded(exe, args, null);
|
||||
cleanTmp(tmpFile);
|
||||
if (err!=0)
|
||||
{
|
||||
if (FileSystem.exists(obj_name))
|
||||
FileSystem.deleteFile(obj_name);
|
||||
BuildTool.setThreadError(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Log.verbose)
|
||||
{
|
||||
Log.info(fileName);
|
||||
}
|
||||
var result = ProcessManager.runProcessThreaded(exe, args, null);
|
||||
cleanTmp(tmpFile);
|
||||
if (result!=0)
|
||||
{
|
||||
if (FileSystem.exists(obj_name))
|
||||
FileSystem.deleteFile(obj_name);
|
||||
Tools.exit (result);
|
||||
//throw "Error : " + result + " - build cancelled";
|
||||
}
|
||||
}
|
||||
|
||||
if (cacheName!=null && !useCacheInPlace)
|
||||
{
|
||||
Log.info("", " caching " + cacheName);
|
||||
sys.io.File.copy(obj_name, cacheName);
|
||||
}
|
||||
}
|
||||
|
||||
return obj_name;
|
||||
}
|
||||
|
||||
public function createCompilerVersion(inGroup:FileGroup)
|
||||
{
|
||||
if ( mCompilerVersion==null)
|
||||
{
|
||||
var versionString = "";
|
||||
var command = "";
|
||||
|
||||
if (mGetCompilerVersion==null)
|
||||
{
|
||||
command = mExe + " --version";
|
||||
versionString = ProcessManager.readStdout(mExe,["--version"]).join(" ");
|
||||
}
|
||||
else
|
||||
{
|
||||
command = mGetCompilerVersion;
|
||||
versionString = ProcessManager.readStderr(mGetCompilerVersion,[]).join(" ");
|
||||
}
|
||||
|
||||
if (versionString=="" || versionString==null)
|
||||
Log.error("Could not deduce compiler version with " + command);
|
||||
|
||||
Log.info("", "Compiler version: " + versionString);
|
||||
|
||||
mCompilerVersionString = versionString;
|
||||
mCompilerVersion = Md5.encode(versionString);
|
||||
mCached = true;
|
||||
}
|
||||
|
||||
return mCached;
|
||||
}
|
||||
|
||||
function getObjName(inFile:File)
|
||||
{
|
||||
var isRc = mRcExe!=null && inFile.isResource();
|
||||
|
||||
var path = new Path(inFile.mName);
|
||||
var dirId = Md5.encode(BuildTool.targetKey + path.dir + inFile.mGroup.mId).substr(0,8) + "_";
|
||||
|
||||
return PathManager.combine(mObjDir, inFile.mGroup.mObjPrefix + dirId + path.file + (isRc ? mRcExt : mExt) );
|
||||
}
|
||||
|
||||
function getHashedName(inFile:File, args:Array<String>)
|
||||
{
|
||||
var sourceName = inFile.mDir + inFile.mName;
|
||||
var contents = sys.io.File.getContent(sourceName);
|
||||
if (contents!="")
|
||||
{
|
||||
var md5 = Md5.encode(contents + args.join(" ") +
|
||||
inFile.mGroup.mDependHash + mCompilerVersion + inFile.mDependHash );
|
||||
return CompileCache.getCacheName(inFile.getCacheProject(),md5,mExt);
|
||||
}
|
||||
else
|
||||
throw "Unkown source contents " + sourceName;
|
||||
return "";
|
||||
}
|
||||
|
||||
public function getCacheString(inFile:File)
|
||||
{
|
||||
var args = getArgs(inFile);
|
||||
return ("<contents>" + args.join(" ") + " " + inFile.mGroup.getDependString() + " " + mCompilerVersionString + " " + inFile.getDependString() );
|
||||
}
|
||||
|
||||
public function getCachedObjName(inFile:File)
|
||||
{
|
||||
if (mCompilerVersion!=null && useCacheInPlace && inFile.mGroup.isCached())
|
||||
{
|
||||
//trace(inFile.mName + " " + inFile.getTags().split(",") + " " + getFlagStrings() + " " + getArgs(inFile));
|
||||
return getHashedName(inFile, getArgs(inFile));
|
||||
}
|
||||
else
|
||||
return getObjName(inFile);
|
||||
}
|
||||
|
||||
public function needsPchObj()
|
||||
{
|
||||
return mPCH!="gcc";
|
||||
}
|
||||
|
||||
/*
|
||||
public function getPchObjName(group:FileGroup)
|
||||
{
|
||||
var pchDir = getPchDir(group);
|
||||
if (pchDir != "")
|
||||
return pchDir + "/" + group.getPchName() + mExt;
|
||||
throw "Missing precompiled directory name";
|
||||
}
|
||||
*/
|
||||
public function getPchCompileFlags(inGroup:FileGroup)
|
||||
{
|
||||
var args = inGroup.mCompilerFlags.copy();
|
||||
var tags = inGroup.mTags.split(",");
|
||||
addOptimTags(tags);
|
||||
for(flag in mFlags)
|
||||
flag.add(args,tags);
|
||||
|
||||
return args.concat( mCPPFlags );
|
||||
}
|
||||
|
||||
public function getPchDir(inGroup:FileGroup)
|
||||
{
|
||||
if (!inGroup.isCached())
|
||||
return inGroup.getPchDir(mObjDir);
|
||||
|
||||
var args = getPchCompileFlags(inGroup);
|
||||
var md5 = Md5.encode(args.join(" ") + inGroup.mPrecompiledHeader +
|
||||
inGroup.mDependHash + mCompilerVersion );
|
||||
return CompileCache.getPchDir(inGroup.getCacheProject(),md5);
|
||||
}
|
||||
|
||||
public function precompile(inGroup:FileGroup, inReuseIfPossible:Bool)
|
||||
{
|
||||
// header will be like "hxcpp" or "wx/wx"
|
||||
var header = inGroup.mPrecompiledHeader;
|
||||
// file will be like "hxcpp" or "wx"
|
||||
var file = inGroup.getPchName();
|
||||
|
||||
var args = getPchCompileFlags(inGroup);
|
||||
|
||||
// Local output dir
|
||||
var dir = getPchDir(inGroup);
|
||||
|
||||
// Like objs/hxcpp.pch or objs/wx.gch
|
||||
var pch_name = dir + "/" + file + mPCHExt;
|
||||
if (inGroup.isCached() || inReuseIfPossible)
|
||||
{
|
||||
// No obj needed for gcc
|
||||
var obj = mPCH=="gcc" ? null : PathManager.combine(dir, file + mExt);
|
||||
if (FileSystem.exists(pch_name) && (obj==null || FileSystem.exists(obj)) )
|
||||
return obj;
|
||||
}
|
||||
|
||||
args = args.concat( mPCHFlags );
|
||||
|
||||
|
||||
//Log.info("", "Make pch dir " + dir );
|
||||
PathManager.mkdir(dir);
|
||||
|
||||
if (mPCH!="gcc")
|
||||
{
|
||||
args.push( mPCHCreate + header + ".h" );
|
||||
var symbol = "link" + Md5.encode( PathManager.combine(dir, file + mExt) );
|
||||
args.push( "-Yl" + symbol );
|
||||
|
||||
// Create a temp file for including ...
|
||||
var tmp_cpp = dir + "/" + file + ".cpp";
|
||||
var outFile = sys.io.File.write(tmp_cpp,false);
|
||||
outFile.writeString("#include <" + header + ".h>\n");
|
||||
outFile.close();
|
||||
|
||||
args.push( tmp_cpp );
|
||||
args.push(mPCHFilename + pch_name);
|
||||
args.push(mOutFlag + PathManager.combine(dir, file + mExt));
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.info("", 'Creating PCH directory "$dir"');
|
||||
PathManager.mkdir(dir);
|
||||
args.push( "-o" );
|
||||
args.push(pch_name);
|
||||
args.push( inGroup.mPrecompiledHeaderDir + "/" + inGroup.mPrecompiledHeader + ".h" );
|
||||
}
|
||||
|
||||
Log.info("Creating " + pch_name + "...", " - Precompile " + pch_name );
|
||||
var result = ProcessManager.runCommand("", mExe, args);
|
||||
if (result!=0)
|
||||
{
|
||||
var goes = 10;
|
||||
for(attempt in 0...goes)
|
||||
{
|
||||
try {
|
||||
if (FileSystem.exists(pch_name))
|
||||
FileSystem.deleteFile(pch_name);
|
||||
break;
|
||||
}
|
||||
catch(error:Dynamic)
|
||||
{
|
||||
Log.warn('Error cleaning PCH file $pch_name: $error');
|
||||
if (attempt<goes-1)
|
||||
Sys.sleep(0.25);
|
||||
}
|
||||
}
|
||||
Log.error("Could not create PCH");
|
||||
//throw "Error creating pch: " + result + " - build cancelled";
|
||||
}
|
||||
|
||||
if (mPCH!="gcc")
|
||||
return PathManager.combine(dir, file + mExt);
|
||||
return null;
|
||||
}
|
||||
|
||||
public function setPCH(inPCH:String)
|
||||
{
|
||||
mPCH = inPCH;
|
||||
if (mPCH=="gcc")
|
||||
{
|
||||
mPCHExt = ".h.gch";
|
||||
mPCHUse = "";
|
||||
mPCHFilename = "";
|
||||
}
|
||||
}
|
||||
|
||||
public function initPrecompile(inDefault:String)
|
||||
{
|
||||
if (mPCH==null)
|
||||
setPCH(inDefault);
|
||||
return mPCH!=null;
|
||||
}
|
||||
|
||||
}
|
97
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/CopyFile.hx
Normal file
97
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/CopyFile.hx
Normal file
@ -0,0 +1,97 @@
|
||||
import sys.FileSystem;
|
||||
|
||||
class CopyFile
|
||||
{
|
||||
public var name:String;
|
||||
public var from:String;
|
||||
public var toolId:String;
|
||||
public var allowMissing:Bool;
|
||||
public var overwrite:Overwrite;
|
||||
|
||||
public function new(inName:String, inFrom:String, inAlowMissing:Bool, inOverwrite:Overwrite, ?inToolId:String)
|
||||
{
|
||||
name = inName;
|
||||
from = inFrom;
|
||||
toolId = inToolId;
|
||||
allowMissing = inAlowMissing;
|
||||
overwrite = inOverwrite;
|
||||
}
|
||||
|
||||
public function copy(inTo:String)
|
||||
{
|
||||
var fromFile = from + "/" + name;
|
||||
var toFile = inTo + name;
|
||||
copyFile(fromFile, toFile, allowMissing, overwrite);
|
||||
}
|
||||
|
||||
|
||||
public static function copyFile(fromFile:String, toFile:String, allowMissing = false, overwrite:Overwrite = Overwrite.ALWAYS, addExePermission=false)
|
||||
{
|
||||
if (!FileSystem.exists(fromFile))
|
||||
{
|
||||
if (allowMissing)
|
||||
{
|
||||
Log.v('Missing "$fromFile" - ignore');
|
||||
return;
|
||||
}
|
||||
Log.error("Error - source file does not exist " + fromFile);
|
||||
}
|
||||
try
|
||||
{
|
||||
Log.v('Copy "$fromFile" to "$toFile"');
|
||||
|
||||
var applyCopy = true;
|
||||
switch(overwrite)
|
||||
{
|
||||
case Overwrite.IF_NEWER:
|
||||
if(FileSystem.exists(toFile)
|
||||
&& (FileSystem.stat(fromFile).mtime.getTime() - FileSystem.stat(toFile).mtime.getTime()) <= 0)
|
||||
{
|
||||
Log.v('The "$fromFile" is older or it hasn\'t changes. Skip copy');
|
||||
applyCopy = false;
|
||||
}
|
||||
|
||||
case Overwrite.NEVER:
|
||||
if(FileSystem.exists(toFile))
|
||||
{
|
||||
Log.v('The "$toFile" file exists. Skip copy');
|
||||
applyCopy = false;
|
||||
}
|
||||
|
||||
case Overwrite.ALWAYS:
|
||||
|
||||
default:
|
||||
Log.v('The Overwrite option "$overwrite" is not supported. ' +
|
||||
'Possible values: {${Overwrite.ALWAYS}, ${Overwrite.IF_NEWER}, ${Overwrite.NEVER}}. ' +
|
||||
'Applying "${Overwrite.ALWAYS}" by default');
|
||||
}
|
||||
|
||||
if(applyCopy)
|
||||
{
|
||||
sys.io.File.copy( fromFile, toFile );
|
||||
if (addExePermission)
|
||||
{
|
||||
Log.v("chmod 755 " + toFile );
|
||||
Sys.command("chmod", ["755", toFile]);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(e:Dynamic)
|
||||
{
|
||||
if (allowMissing)
|
||||
{
|
||||
Log.v('Could not copy to "$toFile" - ignore');
|
||||
return;
|
||||
}
|
||||
Log.error('Error $e - could not copy to "$toFile"');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@:enum
|
||||
abstract Overwrite(String) from String to String
|
||||
{
|
||||
var ALWAYS = "always";
|
||||
var IF_NEWER = "ifNewer";
|
||||
var NEVER = "never";
|
||||
}
|
159
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/File.hx
Normal file
159
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/File.hx
Normal file
@ -0,0 +1,159 @@
|
||||
import sys.FileSystem;
|
||||
using StringTools;
|
||||
|
||||
#if haxe4
|
||||
import sys.thread.Mutex;
|
||||
#elseif cpp
|
||||
import cpp.vm.Mutex;
|
||||
#else
|
||||
import neko.vm.Mutex;
|
||||
#end
|
||||
|
||||
class File
|
||||
{
|
||||
static var mFileHashes = new Map<String,String>();
|
||||
public var mName:String;
|
||||
public var mDir:String;
|
||||
public var mDependHash:String;
|
||||
public var mDepends:Array<String>;
|
||||
public var mCompilerFlags:Array<String>;
|
||||
public var mGroup:FileGroup;
|
||||
public var mTags:String;
|
||||
public var mFilterOut:String;
|
||||
public var mEmbedName:String;
|
||||
public var mScramble:String;
|
||||
static public var mDependMutex = new Mutex();
|
||||
|
||||
public function new(inName:String, inGroup:FileGroup)
|
||||
{
|
||||
mName = inName;
|
||||
mDir = "";
|
||||
if (inGroup.mDir != "" && !PathManager.isAbsolute(mName))
|
||||
mDir = inGroup.mDir;
|
||||
if (mDir!="") mDir += "/";
|
||||
// Do not take copy - use reference so it can be updated
|
||||
mGroup = inGroup;
|
||||
mDepends = [];
|
||||
mCompilerFlags = [];
|
||||
mEmbedName = null;
|
||||
mScramble = null;
|
||||
mTags = null;
|
||||
}
|
||||
|
||||
inline public function getCacheProject() return mGroup.getCacheProject();
|
||||
|
||||
public function isNvcc() return mGroup.mNvcc;
|
||||
|
||||
public function isResource() return mName.endsWith(".rc");
|
||||
|
||||
public function keep(inDefines:Map<String,String>)
|
||||
{
|
||||
return mFilterOut==null || !inDefines.exists(mFilterOut);
|
||||
}
|
||||
|
||||
public function getTags()
|
||||
{
|
||||
return mTags==null ? mGroup.mTags : mTags;
|
||||
}
|
||||
|
||||
public function setTags(inTags:String)
|
||||
{
|
||||
return mTags=inTags;
|
||||
}
|
||||
|
||||
public function computeDependHash(localCache:Map<String,String>)
|
||||
{
|
||||
mDependHash = "";
|
||||
for(depend in mDepends)
|
||||
mDependHash += getFileHash(depend,localCache);
|
||||
mDependHash = haxe.crypto.Md5.encode(mDependHash);
|
||||
}
|
||||
|
||||
public function getDependString()
|
||||
{
|
||||
return "FILES(" + mDepends.join(",") + ")";
|
||||
}
|
||||
|
||||
public static function getFileHash(inName:String,localCache:Map<String,String>)
|
||||
{
|
||||
if (localCache==null)
|
||||
{
|
||||
var result = mFileHashes.get(inName);
|
||||
if (result==null)
|
||||
{
|
||||
var content = sys.io.File.getContent(inName);
|
||||
result = haxe.crypto.Md5.encode(content);
|
||||
mFileHashes.set(inName,result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = localCache.get(inName);
|
||||
if (result!=null)
|
||||
return result;
|
||||
|
||||
mDependMutex.acquire();
|
||||
result = mFileHashes.get(inName);
|
||||
mDependMutex.release();
|
||||
|
||||
if (result==null)
|
||||
{
|
||||
var content = sys.io.File.getContent(inName);
|
||||
result = haxe.crypto.Md5.encode(content);
|
||||
mDependMutex.acquire();
|
||||
mFileHashes.set(inName,result);
|
||||
mDependMutex.release();
|
||||
}
|
||||
|
||||
localCache.set(inName,result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public function isOutOfDate(inObj:String, ?dependDebug:String->Void)
|
||||
{
|
||||
if (!FileSystem.exists(inObj))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var obj_stamp = FileSystem.stat(inObj).mtime.getTime();
|
||||
if (mGroup.isOutOfDate(obj_stamp))
|
||||
{
|
||||
if (dependDebug!=null)
|
||||
dependDebug(mName + " - whole group is out of date " + mGroup.getNewestFile() + " " + obj_stamp + " < " + mGroup.mNewest);
|
||||
return true;
|
||||
}
|
||||
|
||||
var source_name = mDir+mName;
|
||||
if (!FileSystem.exists(source_name))
|
||||
{
|
||||
Log.error("Could not find source file \"" + source_name + "\"");
|
||||
//throw "Could not find source '" + source_name + "'";
|
||||
}
|
||||
var source_stamp = FileSystem.stat(source_name).mtime.getTime();
|
||||
if (obj_stamp < source_stamp)
|
||||
{
|
||||
if (dependDebug!=null)
|
||||
dependDebug(mName + ' - stamped $obj_stamp < $source_stamp');
|
||||
return true;
|
||||
}
|
||||
for(depend in mDepends)
|
||||
{
|
||||
if (!FileSystem.exists(depend))
|
||||
{
|
||||
Log.error("Could not find dependency \"" + depend + "\" for \"" + mName + "\"");
|
||||
//throw "Could not find dependency '" + depend + "' for '" + mName + "'";
|
||||
}
|
||||
var dependTime = FileSystem.stat(depend).mtime.getTime();
|
||||
if (dependTime > obj_stamp )
|
||||
{
|
||||
if (dependDebug!=null)
|
||||
dependDebug(mName + ' - depend $obj_stamp < $dependTime');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
292
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/FileGroup.hx
Normal file
292
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/FileGroup.hx
Normal file
@ -0,0 +1,292 @@
|
||||
import haxe.io.Path;
|
||||
import sys.FileSystem;
|
||||
|
||||
class FileGroup
|
||||
{
|
||||
public var mNewest:Float;
|
||||
public var mNewestFile:String;
|
||||
public var mCompilerFlags:Array<String>;
|
||||
public var mMissingDepends:Array<String>;
|
||||
public var mOptions:Array<String>;
|
||||
public var mPrecompiledHeader:String;
|
||||
public var mPrecompiledHeaderDir:String;
|
||||
public var mFiles:Map<String, File>;
|
||||
public var mHLSLs:Array<HLSL>;
|
||||
public var mDir:String;
|
||||
public var mId:String;
|
||||
public var mConfig:String;
|
||||
public var mCacheDepends:Array<String>;
|
||||
public var mDependHash:String;
|
||||
public var mAsLibrary:Bool;
|
||||
public var mAddTwice:Bool;
|
||||
public var mSetImportDir:Bool;
|
||||
public var mUseCache:Bool;
|
||||
public var mRespectTimestamp:Bool;
|
||||
public var mCacheProject:String;
|
||||
public var mTags:String;
|
||||
public var mNvcc:Bool;
|
||||
public var mObjPrefix:String;
|
||||
|
||||
public function new(inDir:String,inId:String,inSetImportDir = false)
|
||||
{
|
||||
mId = inId;
|
||||
replace(inDir, inSetImportDir);
|
||||
}
|
||||
|
||||
public function toString() return 'FileGroup($mId)';
|
||||
|
||||
public function replace(inDir:String,inSetImportDir)
|
||||
{
|
||||
mNewest = 0;
|
||||
mFiles = new Map<String, File>();
|
||||
mCompilerFlags = [];
|
||||
mPrecompiledHeader = "";
|
||||
mCacheDepends = [];
|
||||
mMissingDepends = [];
|
||||
mOptions = [];
|
||||
mHLSLs = [];
|
||||
mDir = inDir;
|
||||
mConfig = "";
|
||||
mAsLibrary = false;
|
||||
mAddTwice = false;
|
||||
mSetImportDir = inSetImportDir;
|
||||
mUseCache = false;
|
||||
mRespectTimestamp = false;
|
||||
mCacheProject = "";
|
||||
mNvcc = false;
|
||||
mTags = "haxe,static";
|
||||
mObjPrefix = "";
|
||||
return this;
|
||||
}
|
||||
|
||||
public function find(name:String)
|
||||
{
|
||||
return mFiles.get(name);
|
||||
}
|
||||
|
||||
public function addFile(file:File)
|
||||
{
|
||||
mFiles.set(file.mName, file);
|
||||
}
|
||||
|
||||
public function hasFiles():Bool {
|
||||
return Lambda.exists(mFiles, function(file:File) { return true; } );
|
||||
}
|
||||
|
||||
public function filter(defines:Map<String,String>)
|
||||
{
|
||||
var newFiles = new Map<String, File>();
|
||||
for(file in mFiles)
|
||||
if (file.keep(defines))
|
||||
newFiles.set(file.mName, file);
|
||||
mFiles = newFiles;
|
||||
}
|
||||
|
||||
public function getTags()
|
||||
{
|
||||
return mTags;
|
||||
}
|
||||
|
||||
public function addTag(inTag:String)
|
||||
{
|
||||
if (inTag!=null && inTag!="")
|
||||
{
|
||||
var have = mTags.split(",");
|
||||
if (have.indexOf(inTag)<0)
|
||||
{
|
||||
have.push(inTag);
|
||||
mTags = have.join(",");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function isPrecompiled() return mPrecompiledHeader!="";
|
||||
|
||||
public function dontPrecompile()
|
||||
{
|
||||
mPrecompiledHeader = "";
|
||||
}
|
||||
|
||||
public function addCompilerFlag(inFlag:String)
|
||||
{
|
||||
mCompilerFlags.push(inFlag);
|
||||
}
|
||||
|
||||
public function getCacheProject()
|
||||
{
|
||||
if (mCacheProject=="")
|
||||
mCacheProject = mId;
|
||||
return mCacheProject;
|
||||
}
|
||||
|
||||
|
||||
public function addDepend(inFile:String, inDateOnly:Bool)
|
||||
{
|
||||
if (mSetImportDir && !Path.isAbsolute(inFile) )
|
||||
inFile = PathManager.combine(mDir, inFile);
|
||||
if (!FileSystem.exists(inFile))
|
||||
{
|
||||
mMissingDepends.push(inFile);
|
||||
return;
|
||||
}
|
||||
var stamp = FileSystem.stat(inFile).mtime.getTime();
|
||||
if (stamp>mNewest)
|
||||
{
|
||||
mNewest = stamp;
|
||||
mNewestFile = inFile;
|
||||
}
|
||||
|
||||
if (!inDateOnly)
|
||||
mCacheDepends.push(inFile);
|
||||
}
|
||||
|
||||
public function getNewestFile()
|
||||
{
|
||||
return '$mId($mNewestFile)';
|
||||
}
|
||||
|
||||
public function addDependFiles(inGroup:FileGroup)
|
||||
{
|
||||
if (inGroup.mNewest>mNewest)
|
||||
{
|
||||
mNewestFile = inGroup.getNewestFile();
|
||||
mNewest = inGroup.mNewest;
|
||||
}
|
||||
|
||||
for(depend in inGroup.mCacheDepends)
|
||||
mCacheDepends.push(depend);
|
||||
|
||||
for(missing in inGroup.mMissingDepends)
|
||||
mMissingDepends.push(missing);
|
||||
}
|
||||
|
||||
|
||||
public function addHLSL(inFile:String,inProfile:String,inVariable:String,inTarget:String)
|
||||
{
|
||||
addDepend(inFile, true );
|
||||
|
||||
mHLSLs.push( new HLSL(inFile,inProfile,inVariable,inTarget) );
|
||||
}
|
||||
|
||||
public function addOptions(inFile:String)
|
||||
{
|
||||
mOptions.push(inFile);
|
||||
}
|
||||
|
||||
public function checkDependsExist()
|
||||
{
|
||||
if (mMissingDepends.length>0)
|
||||
{
|
||||
Log.error("Could not find dependencies for " + mId + " : [ " + mMissingDepends.join (", ") + " ]");
|
||||
//throw "Could not find dependencies: " + mMissingDepends.join(",");
|
||||
}
|
||||
}
|
||||
|
||||
public function filterOptions(contents:String)
|
||||
{
|
||||
// Old-style
|
||||
if (contents.substr(0,1)==" ")
|
||||
return contents;
|
||||
|
||||
var result = new Array<String>();
|
||||
for(def in contents.split("\n"))
|
||||
{
|
||||
var name = def.split("=")[0];//.toLowerCase();
|
||||
if (name.indexOf("hxcpp_link")>=0)
|
||||
{
|
||||
// Only effects linking, not compiling
|
||||
}
|
||||
else if (name=="hxcpp_verbose" || name=="hxcpp_silent" || name=="hxcpp_quiet" || name=="hxcpp_times" || name=="hxcpp_neko_buildtool" || name=="hxcpp_link_no_tool_depends" )
|
||||
{
|
||||
// Does not affect build
|
||||
}
|
||||
else if (name.indexOf("hxcpp")>=0 || name=="scriptable" || name.indexOf("dll")>=0 || name=="no_console" ||
|
||||
name.substr(0,8)=="android-" || name.substr(0,4)=="ndkv" || name=="toolchain" || name=="platform" ||
|
||||
name=="toolchain_version" || name=="android_ndk_root" )
|
||||
result.push(def);
|
||||
}
|
||||
|
||||
return result.join("\n");
|
||||
}
|
||||
|
||||
public function checkOptions(inObjDir:String)
|
||||
{
|
||||
var changed = false;
|
||||
for(option in mOptions)
|
||||
{
|
||||
if (!FileSystem.exists(option))
|
||||
{
|
||||
mMissingDepends.push(option);
|
||||
}
|
||||
else
|
||||
{
|
||||
var contents = filterOptions(sys.io.File.getContent(option));
|
||||
|
||||
var dest = inObjDir + "/" + Path.withoutDirectory(option);
|
||||
var skip = false;
|
||||
|
||||
if (FileSystem.exists(dest))
|
||||
{
|
||||
var dest_content = filterOptions(sys.io.File.getContent(dest));
|
||||
if (dest_content==contents)
|
||||
skip = true;
|
||||
}
|
||||
|
||||
if (!skip)
|
||||
{
|
||||
PathManager.mkdir(inObjDir);
|
||||
var stream = sys.io.File.write(dest,true);
|
||||
stream.writeString(contents);
|
||||
stream.close();
|
||||
changed = true;
|
||||
}
|
||||
addDepend(dest,true);
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
public function getPchDir(inObjDir:String)
|
||||
{
|
||||
var result = inObjDir + "/__pch/" + mId ;
|
||||
PathManager.mkdir(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public function getPchName()
|
||||
{
|
||||
return Path.withoutDirectory(mPrecompiledHeader);
|
||||
}
|
||||
|
||||
public function isOutOfDate(inStamp:Float)
|
||||
{
|
||||
return inStamp<mNewest;
|
||||
}
|
||||
|
||||
public function isCached() return CompileCache.hasCache && mUseCache;
|
||||
|
||||
public function preBuild()
|
||||
{
|
||||
for(hlsl in mHLSLs)
|
||||
hlsl.build();
|
||||
|
||||
if (CompileCache.hasCache && mUseCache)
|
||||
{
|
||||
mDependHash = "";
|
||||
for(depend in mCacheDepends)
|
||||
mDependHash += File.getFileHash(depend,null);
|
||||
mDependHash = haxe.crypto.Md5.encode(mDependHash);
|
||||
}
|
||||
}
|
||||
|
||||
public function getDependString()
|
||||
{
|
||||
return "Group(" + mCacheDepends.join(",") + ")";
|
||||
}
|
||||
|
||||
public function setPrecompiled(inFile:String, inDir:String)
|
||||
{
|
||||
mPrecompiledHeader = inFile;
|
||||
mPrecompiledHeaderDir = inDir;
|
||||
}
|
||||
}
|
42
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/HLSL.hx
Normal file
42
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/HLSL.hx
Normal file
@ -0,0 +1,42 @@
|
||||
import haxe.io.Path;
|
||||
import sys.FileSystem;
|
||||
|
||||
class HLSL
|
||||
{
|
||||
var file:String;
|
||||
var profile:String;
|
||||
var target:String;
|
||||
var variable:String;
|
||||
|
||||
public function new(inFile:String, inProfile:String, inVariable:String, inTarget:String)
|
||||
{
|
||||
file = inFile;
|
||||
profile = inProfile;
|
||||
variable = inVariable;
|
||||
target = inTarget;
|
||||
}
|
||||
|
||||
public function build()
|
||||
{
|
||||
if (!FileSystem.exists(Path.directory (target)))
|
||||
{
|
||||
PathManager.mkdir(Path.directory (target));
|
||||
}
|
||||
|
||||
//DirManager.makeFileDir(target);
|
||||
|
||||
var srcStamp = FileSystem.stat(file).mtime.getTime();
|
||||
if (!FileSystem.exists(target) || FileSystem.stat(target).mtime.getTime() < srcStamp)
|
||||
{
|
||||
var exe = "fxc.exe";
|
||||
var args = [ "/nologo", "/T", profile, file, "/Vn", variable, "/Fh", target ];
|
||||
|
||||
var result = ProcessManager.runCommand("", exe, args);
|
||||
if (result!=0)
|
||||
{
|
||||
Log.error("Could not compile shader \"" + file + "\"");
|
||||
//throw "Error : Could not compile shader " + file + " - build cancelled";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
324
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/Linker.hx
Normal file
324
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/Linker.hx
Normal file
@ -0,0 +1,324 @@
|
||||
import haxe.io.Path;
|
||||
import sys.FileSystem;
|
||||
import haxe.crypto.Md5;
|
||||
|
||||
using StringTools;
|
||||
|
||||
class Linker
|
||||
{
|
||||
public var mExe:String;
|
||||
public var mFlags:Array<String>;
|
||||
public var mOutFlag:String;
|
||||
public var mExt:String;
|
||||
public var mNamePrefix:String;
|
||||
public var mLibDir:String;
|
||||
public var mRanLib:String;
|
||||
public var mFromFile:String;
|
||||
public var mFromFileNeedsQuotes:Bool;
|
||||
public var mLibs:Array<String>;
|
||||
public var mExpandArchives:Bool;
|
||||
public var mRecreate:Bool;
|
||||
public var mLastOutName:String;
|
||||
public var mAddLibPath:String;
|
||||
|
||||
public function new(inExe:String)
|
||||
{
|
||||
mFlags = [];
|
||||
mOutFlag = "-o";
|
||||
mAddLibPath = "-L";
|
||||
mExe = inExe;
|
||||
mNamePrefix = "";
|
||||
mLibDir = "";
|
||||
mRanLib = "";
|
||||
mExpandArchives = false;
|
||||
// Default to on...
|
||||
mFromFile = "@";
|
||||
mFromFileNeedsQuotes = true;
|
||||
mLibs = [];
|
||||
mRecreate = false;
|
||||
}
|
||||
|
||||
function isOutOfDate(inName:String, inObjs:Array<String>)
|
||||
{
|
||||
if (!FileSystem.exists(inName))
|
||||
return true;
|
||||
var stamp = FileSystem.stat(inName).mtime.getTime();
|
||||
for(obj in inObjs)
|
||||
{
|
||||
if (!FileSystem.exists(obj))
|
||||
{
|
||||
Log.error("Could not find \"" + obj + "\" required by \"" + inName + "\"");
|
||||
//throw "Could not find " + obj + " required by " + inName;
|
||||
}
|
||||
var obj_stamp = FileSystem.stat(obj).mtime.getTime();
|
||||
if (obj_stamp > stamp)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getSimpleFilename(inTarget:Target)
|
||||
{
|
||||
var ext = inTarget.getExt(mExt);
|
||||
// Remove arch from ext ...
|
||||
var idx = ext.indexOf('.');
|
||||
if (idx>0)
|
||||
ext = ext.substr(idx);
|
||||
|
||||
return mNamePrefix + inTarget.mOutput + ext;
|
||||
}
|
||||
public function getUnstrippedFilename(inObjDir, inTarget:Target)
|
||||
{
|
||||
if (inTarget.mFullUnstrippedName!=null)
|
||||
{
|
||||
PathManager.mkdir( inTarget.mFullUnstrippedName, true );
|
||||
return inTarget.mFullUnstrippedName;
|
||||
}
|
||||
return inObjDir + "/" + getSimpleFilename(inTarget);
|
||||
}
|
||||
|
||||
public function link(inTarget:Target,inObjs:Array<String>,inCompiler:Compiler,extraDeps:Array<String> )
|
||||
{
|
||||
var ext = inTarget.getExt(mExt);
|
||||
var file_name = mNamePrefix + inTarget.mOutput + ext;
|
||||
|
||||
var tmpDir = inCompiler.mObjDir;
|
||||
|
||||
try
|
||||
{
|
||||
PathManager.mkdir(inTarget.mOutputDir);
|
||||
}
|
||||
catch (e:Dynamic)
|
||||
{
|
||||
Log.error("Unable to create output directory \"" + inTarget.mOutputDir + "\"");
|
||||
//throw "Unable to create output directory " + inTarget.mOutputDir;
|
||||
}
|
||||
|
||||
var out_name = Path.normalize(PathManager.combine( inTarget.mBuildDir, inTarget.mOutputDir + file_name));
|
||||
var hashFile = out_name + ".hash";
|
||||
if (inTarget.mFullOutputName!=null)
|
||||
{
|
||||
PathManager.mkdir( inTarget.mFullOutputName, true );
|
||||
out_name = inTarget.mFullOutputName;
|
||||
}
|
||||
|
||||
mLastOutName = out_name;
|
||||
|
||||
|
||||
var lastLib = "";
|
||||
var libs = new Array<String>();
|
||||
for(l in inTarget.mAutoLibs)
|
||||
if (l!=lastLib)
|
||||
{
|
||||
libs.push(l);
|
||||
lastLib = l;
|
||||
}
|
||||
|
||||
for(l in inTarget.mLibs)
|
||||
if (l!=lastLib)
|
||||
{
|
||||
libs.push(l);
|
||||
lastLib = l;
|
||||
}
|
||||
|
||||
for(l in mLibs)
|
||||
if (l!=lastLib)
|
||||
{
|
||||
libs.push(l);
|
||||
lastLib = l;
|
||||
}
|
||||
|
||||
var v18Added = false;
|
||||
var isOutOfDateLibs = false;
|
||||
|
||||
var md5 = Md5.encode(inObjs.join(";"));
|
||||
if (!FileSystem.exists(hashFile) || sys.io.File.getContent(hashFile)!=md5)
|
||||
isOutOfDateLibs = true;
|
||||
|
||||
for(i in 0...libs.length)
|
||||
{
|
||||
var lib = libs[i];
|
||||
var parts = lib.split("{MSVC_VER}");
|
||||
if (parts.length==2)
|
||||
{
|
||||
var ver = "";
|
||||
if (BuildTool.isMsvc())
|
||||
{
|
||||
var current = parts[0] + "-" + BuildTool.getMsvcVer() + parts[1];
|
||||
if (FileSystem.exists(current))
|
||||
{
|
||||
Log.info("", " - \x1b[1mUsing current compiler library:\x1b[0m " + current);
|
||||
libs[i]=current;
|
||||
}
|
||||
else
|
||||
{
|
||||
var v18 = parts[0] + "-18" + parts[1];
|
||||
if (FileSystem.exists(v18))
|
||||
{
|
||||
Log.info("", " - \x1b[1mUsing MSVC18 compatible library:\x1b[0m " + v18);
|
||||
libs[i]=v18;
|
||||
if (!v18Added)
|
||||
{
|
||||
v18Added=true;
|
||||
libs.push( BuildTool.HXCPP + "/lib/Windows/libmsvccompat-18.lib");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.error("Could not find compatible library for " + lib + ", " + v18 + " does not exist");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
libs[i] = parts[0] + parts[1];
|
||||
}
|
||||
|
||||
if (!isOutOfDateLibs)
|
||||
{
|
||||
var lib = libs[i];
|
||||
if (FileSystem.exists(lib))
|
||||
isOutOfDateLibs = isOutOfDate(out_name,[lib]);
|
||||
}
|
||||
|
||||
if (BuildTool.isMingw())
|
||||
{
|
||||
var libMatch = ~/^([a-zA-Z0-9_]+).lib$/;
|
||||
if (libMatch.match(libs[i]))
|
||||
libs[i] = "-l" + libMatch.matched(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (isOutOfDateLibs || isOutOfDate(out_name,inObjs) || isOutOfDate(out_name,inTarget.mDepends) || isOutOfDate(out_name,extraDeps) )
|
||||
{
|
||||
var args = new Array<String>();
|
||||
var out = mOutFlag;
|
||||
if (out.substr(-1)==" ")
|
||||
{
|
||||
args.push(out.substr(0,out.length-1));
|
||||
out = "";
|
||||
}
|
||||
// Build in temp dir, and then move out so all the crap windows
|
||||
// creates stays out of the way
|
||||
if (mLibDir!="")
|
||||
{
|
||||
PathManager.mkdir(mLibDir);
|
||||
args.push(out + mLibDir + "/" + file_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mRecreate && FileSystem.exists(out_name))
|
||||
{
|
||||
Log.info("\x1b[1mClean: \x1b[0m" + out_name);
|
||||
FileSystem.deleteFile(out_name);
|
||||
}
|
||||
args.push(out + out_name);
|
||||
}
|
||||
|
||||
args = args.concat(mFlags).concat(inTarget.mFlags);
|
||||
|
||||
var objs = inObjs.copy();
|
||||
|
||||
if (mExpandArchives)
|
||||
{
|
||||
var isArchive = ~/\.a$/;
|
||||
var libArgs = new Array<String>();
|
||||
for(lib in libs)
|
||||
{
|
||||
if (isArchive.match(lib))
|
||||
{
|
||||
var libName = Path.withoutDirectory(lib);
|
||||
var libObjs = ProcessManager.readStdout(mExe, ["t", lib ]);
|
||||
var objDir = tmpDir + "/" + libName + ".unpack";
|
||||
PathManager.mkdir(objDir);
|
||||
ProcessManager.runCommand (objDir, mExe, ["x", lib], true, true, false, " - Unpack : " + lib);
|
||||
for(obj in libObjs)
|
||||
objs.push( objDir+"/"+obj );
|
||||
}
|
||||
else
|
||||
libArgs.push(lib);
|
||||
}
|
||||
libs = libArgs;
|
||||
}
|
||||
|
||||
var here = Path.normalize(Sys.getCwd()) + "/";
|
||||
var hereLen = here.length;
|
||||
for(oid in 0...objs.length)
|
||||
{
|
||||
var obj = Path.normalize( objs[oid] );
|
||||
if (obj.startsWith(here))
|
||||
objs[oid] = obj.substr(hereLen);
|
||||
}
|
||||
|
||||
// Place list of obj files in a file called "all_objs"
|
||||
if (mFromFile!="")
|
||||
{
|
||||
PathManager.mkdir(tmpDir);
|
||||
var fname = tmpDir + "/all_objs";
|
||||
|
||||
var local = Path.normalize(fname);
|
||||
if (local.startsWith(here))
|
||||
fname = local.substr(hereLen);
|
||||
|
||||
var fout = sys.io.File.write(fname,false);
|
||||
if (mFromFileNeedsQuotes)
|
||||
{
|
||||
for(obj in objs)
|
||||
fout.writeString('"' + obj + '"\n');
|
||||
}
|
||||
else
|
||||
{
|
||||
for(obj in objs)
|
||||
fout.writeString(obj + '\n');
|
||||
}
|
||||
fout.close();
|
||||
var parts = mFromFile.split(" ");
|
||||
var last = parts.pop();
|
||||
args = args.concat(parts);
|
||||
args.push(last + fname );
|
||||
}
|
||||
else
|
||||
args = args.concat(objs);
|
||||
|
||||
for(libpath in inTarget.mLibPaths)
|
||||
{
|
||||
var path = Path.normalize(libpath);
|
||||
if (path.startsWith(here))
|
||||
path = path.substr(hereLen);
|
||||
args.push( mAddLibPath + path );
|
||||
}
|
||||
|
||||
args = args.concat(libs);
|
||||
|
||||
var result = ProcessManager.runCommand("", mExe, args, true, true, false,
|
||||
"\x1b[1mLink: \x1b[0m" + out_name);
|
||||
if (result!=0)
|
||||
{
|
||||
Tools.exit(result);
|
||||
//throw "Error : " + result + " - build cancelled";
|
||||
}
|
||||
|
||||
if (mRanLib!="")
|
||||
{
|
||||
args = [out_name];
|
||||
var result = ProcessManager.runCommand("", mRanLib, args, true, true, false, "\x1b[1mRanlib:\x1b[0m " + out_name);
|
||||
if (result!=0)
|
||||
{
|
||||
Tools.exit(result);
|
||||
//throw "Error : " + result + " - build cancelled";
|
||||
}
|
||||
}
|
||||
|
||||
if (mLibDir!="")
|
||||
{
|
||||
sys.io.File.copy( mLibDir+"/"+file_name, out_name );
|
||||
FileSystem.deleteFile( mLibDir+"/"+file_name );
|
||||
}
|
||||
|
||||
sys.io.File.saveContent(hashFile,md5);
|
||||
return out_name;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
}
|
189
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/Log.hx
Normal file
189
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/Log.hx
Normal file
@ -0,0 +1,189 @@
|
||||
import haxe.io.Bytes;
|
||||
import sys.io.Process;
|
||||
|
||||
#if haxe4
|
||||
import sys.thread.Mutex;
|
||||
#elseif neko
|
||||
import neko.vm.Mutex;
|
||||
#else
|
||||
import cpp.vm.Mutex;
|
||||
#end
|
||||
|
||||
#if neko
|
||||
import neko.Lib;
|
||||
#else
|
||||
import cpp.Lib;
|
||||
#end
|
||||
|
||||
class Log
|
||||
{
|
||||
public static var mute:Bool= false;
|
||||
public static var quiet:Bool = false;
|
||||
public static var verbose:Bool = false;
|
||||
|
||||
public static var colorSupported:Null<Bool> = null;
|
||||
private static var sentWarnings = new Map<String,Bool>();
|
||||
|
||||
public static var printMutex:Mutex;
|
||||
|
||||
public static inline var RED = "\x1b[31m";
|
||||
public static inline var YELLOW = "\x1b[33m";
|
||||
public static inline var WHITE = "\x1b[37m";
|
||||
public static inline var NORMAL = "\x1b[0m";
|
||||
public static inline var BOLD = "\x1b[1m";
|
||||
public static inline var ITALIC = "\x1b[3m";
|
||||
|
||||
public static function initMultiThreaded()
|
||||
{
|
||||
if (printMutex==null)
|
||||
printMutex = new Mutex();
|
||||
}
|
||||
|
||||
public static function e(message:String):Void
|
||||
{
|
||||
error(message);
|
||||
}
|
||||
public static function error(message:String, verboseMessage:String = "", e:Dynamic = null, terminate:Bool = true):Void
|
||||
{
|
||||
var output;
|
||||
if (verbose && verboseMessage != "")
|
||||
{
|
||||
output = "\x1b[31;1mError:\x1b[0m\x1b[1m " + verboseMessage + "\x1b[0m\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (message=="")
|
||||
output = "\x1b[31;1mError\x1b[0m\n";
|
||||
else
|
||||
output = "\x1b[31;1mError:\x1b[0m \x1b[1m" + message + "\x1b[0m\n";
|
||||
}
|
||||
if (printMutex!=null)
|
||||
printMutex.acquire();
|
||||
Sys.stderr().write(Bytes.ofString(stripColor(output)));
|
||||
if (printMutex!=null)
|
||||
printMutex.release();
|
||||
|
||||
if ((verbose || !terminate) && e != null)
|
||||
Lib.rethrow(e);
|
||||
|
||||
if (terminate)
|
||||
Tools.exit(1);
|
||||
}
|
||||
|
||||
public static function info(message:String, verboseMessage:String = ""):Void
|
||||
{
|
||||
if (!mute)
|
||||
{
|
||||
if (printMutex!=null)
|
||||
printMutex.acquire();
|
||||
if (verbose && verboseMessage != "")
|
||||
{
|
||||
println(verboseMessage);
|
||||
}
|
||||
else if (message != "")
|
||||
{
|
||||
println(message);
|
||||
}
|
||||
if (printMutex!=null)
|
||||
printMutex.release();
|
||||
}
|
||||
}
|
||||
inline public static function v(verboseMessage:String):Void
|
||||
{
|
||||
Log.info("",verboseMessage);
|
||||
}
|
||||
|
||||
public static function lock():Void
|
||||
{
|
||||
if (printMutex!=null)
|
||||
printMutex.acquire();
|
||||
}
|
||||
|
||||
public static function unlock():Void
|
||||
{
|
||||
if (printMutex!=null)
|
||||
printMutex.release();
|
||||
}
|
||||
|
||||
|
||||
public static function print(message:String):Void
|
||||
{
|
||||
if (printMutex!=null)
|
||||
printMutex.acquire();
|
||||
Sys.print(stripColor(message));
|
||||
if (printMutex!=null)
|
||||
printMutex.release();
|
||||
}
|
||||
|
||||
public static function println(message:String):Void
|
||||
{
|
||||
if (printMutex!=null)
|
||||
printMutex.acquire();
|
||||
Sys.println(stripColor(message));
|
||||
if (printMutex!=null)
|
||||
printMutex.release();
|
||||
}
|
||||
|
||||
private static function stripColor(output:String):String
|
||||
{
|
||||
if (colorSupported == null)
|
||||
{
|
||||
if (!BuildTool.isWindows)
|
||||
{
|
||||
var result = -1;
|
||||
try
|
||||
{
|
||||
var process = new Process ("tput", [ "colors" ]);
|
||||
result = process.exitCode ();
|
||||
process.close ();
|
||||
}
|
||||
catch (e:Dynamic) {};
|
||||
|
||||
colorSupported = (result == 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
colorSupported = (Sys.getEnv("TERM") == "xterm" || Sys.getEnv("ANSICON") != null);
|
||||
}
|
||||
}
|
||||
|
||||
if (colorSupported)
|
||||
{
|
||||
return output;
|
||||
}
|
||||
else
|
||||
{
|
||||
var colorCodes:EReg = ~/\x1b\[[^m]+m/g;
|
||||
return colorCodes.replace(output, "");
|
||||
}
|
||||
}
|
||||
|
||||
public static function warn(message:String, verboseMessage:String = "", allowRepeat:Bool = false):Void
|
||||
{
|
||||
if (!mute)
|
||||
{
|
||||
var output = "";
|
||||
if (verbose && verboseMessage != "")
|
||||
{
|
||||
output = "\x1b[33;1mWarning:\x1b[0m \x1b[1m" + verboseMessage + "\x1b[0m";
|
||||
}
|
||||
else if (message != "")
|
||||
{
|
||||
output = "\x1b[33;1mWarning:\x1b[0m \x1b[1m" + message + "\x1b[0m";
|
||||
}
|
||||
|
||||
if (!allowRepeat && sentWarnings.exists (output))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
sentWarnings.set(output, true);
|
||||
|
||||
if (printMutex!=null)
|
||||
printMutex.acquire();
|
||||
println(output);
|
||||
if (printMutex!=null)
|
||||
printMutex.release();
|
||||
}
|
||||
}
|
||||
}
|
32
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/Manifester.hx
Normal file
32
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/Manifester.hx
Normal file
@ -0,0 +1,32 @@
|
||||
class Manifester
|
||||
{
|
||||
public var mExe:String;
|
||||
public var mFlags:Array<String>;
|
||||
public var mOutPre:String;
|
||||
public var mOutPost:String;
|
||||
|
||||
public function new(inExe:String)
|
||||
{
|
||||
mFlags = [];
|
||||
mExe = inExe;
|
||||
mOutPre = "";
|
||||
mOutPost = "";
|
||||
}
|
||||
|
||||
public function add(binName:String,manifestName:String, isExe:Bool)
|
||||
{
|
||||
var args = new Array<String>();
|
||||
args = args.concat(mFlags);
|
||||
|
||||
//only windows for now
|
||||
mOutPost = isExe ? ";1" : ";2";
|
||||
|
||||
var result = ProcessManager.runCommand("", mExe, args.concat([manifestName,mOutPre + binName + mOutPost]) );
|
||||
if (result!=0)
|
||||
{
|
||||
Tools.exit(result);
|
||||
//throw "Error : " + result + " - build cancelled";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
365
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/PathManager.hx
Normal file
365
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/PathManager.hx
Normal file
@ -0,0 +1,365 @@
|
||||
import sys.FileSystem;
|
||||
|
||||
class PathManager
|
||||
{
|
||||
private static var directoryCache = new Map<String,Bool>();
|
||||
private static var haxelibPaths = new Map<String,String>();
|
||||
|
||||
public static function combine(firstPath:String, secondPath:String):String
|
||||
{
|
||||
if (firstPath == null || firstPath == "")
|
||||
{
|
||||
return secondPath;
|
||||
}
|
||||
else if (secondPath != null && secondPath != "" && secondPath!=".")
|
||||
{
|
||||
if (BuildTool.isWindows)
|
||||
{
|
||||
if (secondPath.indexOf (":") == 1)
|
||||
{
|
||||
return secondPath;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (secondPath.substr (0, 1) == "/")
|
||||
{
|
||||
return secondPath;
|
||||
}
|
||||
}
|
||||
|
||||
var firstSlash = (firstPath.substr(-1) == "/" || firstPath.substr(-1) == "\\");
|
||||
var secondSlash = (secondPath.substr(0, 1) == "/" || secondPath.substr(0, 1) == "\\");
|
||||
|
||||
if (firstSlash && secondSlash)
|
||||
{
|
||||
return firstPath + secondPath.substr(1);
|
||||
}
|
||||
else if (!firstSlash && !secondSlash)
|
||||
{
|
||||
return firstPath + "/" + secondPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
return firstPath + secondPath;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return firstPath;
|
||||
}
|
||||
}
|
||||
|
||||
public static function escape(path:String):String
|
||||
{
|
||||
if (!BuildTool.isWindows)
|
||||
{
|
||||
path = StringTools.replace(path, "\\ ", " ");
|
||||
path = StringTools.replace(path, " ", "\\ ");
|
||||
path = StringTools.replace(path, "\\'", "'");
|
||||
path = StringTools.replace(path, "'", "\\'");
|
||||
}
|
||||
else
|
||||
{
|
||||
path = StringTools.replace(path, "^,", ",");
|
||||
path = StringTools.replace(path, ",", "^,");
|
||||
}
|
||||
return expand(path);
|
||||
}
|
||||
|
||||
public static function expand(path:String):String
|
||||
{
|
||||
if (path == null)
|
||||
{
|
||||
path = "";
|
||||
}
|
||||
|
||||
if (!BuildTool.isWindows)
|
||||
{
|
||||
if (StringTools.startsWith(path, "~/"))
|
||||
{
|
||||
path = Sys.getEnv("HOME") + "/" + path.substr(2);
|
||||
}
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
public static function getHaxelib (haxelib:String, version:String = "", validate:Bool = true, clearCache:Bool = false):String
|
||||
{
|
||||
var name = haxelib;
|
||||
if (version != "")
|
||||
{
|
||||
name += ":" + version;
|
||||
}
|
||||
|
||||
if (clearCache)
|
||||
{
|
||||
haxelibPaths.remove(name);
|
||||
}
|
||||
|
||||
if (!haxelibPaths.exists(name))
|
||||
{
|
||||
var cache = Log.verbose;
|
||||
Log.verbose = false;
|
||||
var output = "";
|
||||
|
||||
try
|
||||
{
|
||||
output = ProcessManager.runProcess(Sys.getEnv ("HAXEPATH"), "haxelib", [ "path", name ], true, false);
|
||||
}
|
||||
catch (e:Dynamic) {}
|
||||
|
||||
Log.verbose = cache;
|
||||
|
||||
var lines = output.split("\n");
|
||||
var result = "";
|
||||
var re = new EReg("^-D " + haxelib + "(=.*)?$", ""); //matches "-D hxcpp=3.1.0" or "-D hxcpp", but not "-D hxcpp-extras"
|
||||
for (i in 1...lines.length)
|
||||
{
|
||||
if (re.match(StringTools.trim(lines[i])))
|
||||
{
|
||||
result = StringTools.trim(lines[i - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
if (result == "")
|
||||
{
|
||||
for (line in lines)
|
||||
{
|
||||
if (line != "" && line.substr(0, 1) != "-")
|
||||
{
|
||||
try
|
||||
{
|
||||
if (FileSystem.exists(line))
|
||||
{
|
||||
result = line;
|
||||
}
|
||||
}
|
||||
catch (e:Dynamic) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (validate)
|
||||
{
|
||||
if (result == "")
|
||||
{
|
||||
if (output.indexOf("does not have") > -1)
|
||||
{
|
||||
var directoryName = "";
|
||||
if (BuildTool.isWindows)
|
||||
{
|
||||
directoryName = "Windows";
|
||||
}
|
||||
else if (BuildTool.isMac)
|
||||
{
|
||||
directoryName = BuildTool.is64 ? "Mac64" : "Mac";
|
||||
}
|
||||
else
|
||||
{
|
||||
directoryName = BuildTool.is64 ? "Linux64" : "Linux";
|
||||
}
|
||||
|
||||
Log.error ("haxelib \"" + haxelib + "\" does not have an \"ndll/" + directoryName + "\" directory");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (version != "")
|
||||
{
|
||||
Log.error("Could not find haxelib \"" + haxelib + "\" version \"" + version + "\", does it need to be installed?");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.error("Could not find haxelib \"" + haxelib + "\", does it need to be installed?");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( result!="" )
|
||||
{
|
||||
var rootPath = result;
|
||||
var depth = 0;
|
||||
while( FileSystem.exists(rootPath) && FileSystem.isDirectory(rootPath) && depth<10 )
|
||||
{
|
||||
if (FileSystem.exists(rootPath + "/haxelib.json"))
|
||||
{
|
||||
result = rootPath;
|
||||
break;
|
||||
}
|
||||
depth++;
|
||||
rootPath = haxe.io.Path.directory(rootPath);
|
||||
}
|
||||
}
|
||||
haxelibPaths.set(name,result);
|
||||
}
|
||||
|
||||
return haxelibPaths.get(name);
|
||||
}
|
||||
|
||||
public static function isAbsolute(path:String):Bool
|
||||
{
|
||||
if (BuildTool.isWindows)
|
||||
{
|
||||
if (path != null && path.length > 2 && path.charAt(1) == ":" && (path.charAt(2) == "\\" || path.charAt(2) == "/"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (StringTools.startsWith(path, "/") || StringTools.startsWith(path, "\\"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function mkdir(directory:String, skipFilePart=false):Void
|
||||
{
|
||||
directory = StringTools.replace(directory, "\\", "/");
|
||||
var total = "";
|
||||
|
||||
if (directory.substr(0, 1) == "/")
|
||||
{
|
||||
total = "/";
|
||||
}
|
||||
|
||||
var parts = directory.split("/");
|
||||
if (skipFilePart && parts.length>0)
|
||||
parts.pop();
|
||||
|
||||
if (parts.length > 0 && parts[0].indexOf(":") > -1)
|
||||
{
|
||||
total = parts.shift();
|
||||
}
|
||||
|
||||
for (part in parts)
|
||||
{
|
||||
if (part != "." && part != "")
|
||||
{
|
||||
if (total != "" && total != "/")
|
||||
{
|
||||
total += "/";
|
||||
}
|
||||
|
||||
total += part;
|
||||
|
||||
if (!directoryCache.exists (total))
|
||||
{
|
||||
//directoryCache.set(total, true);
|
||||
if (!FileSystem.exists(total))
|
||||
{
|
||||
Log.info("", " - \x1b[1mCreating directory:\x1b[0m " + total);
|
||||
FileSystem.createDirectory(total);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static function removeDirectory(directory:String):Void
|
||||
{
|
||||
if (FileSystem.exists(directory))
|
||||
{
|
||||
var files;
|
||||
try
|
||||
{
|
||||
files = FileSystem.readDirectory(directory);
|
||||
}
|
||||
catch (e:Dynamic)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (file in FileSystem.readDirectory(directory))
|
||||
{
|
||||
var path = directory + "/" + file;
|
||||
try
|
||||
{
|
||||
if (FileSystem.isDirectory(path))
|
||||
{
|
||||
removeDirectory(path);
|
||||
}
|
||||
else
|
||||
{
|
||||
FileSystem.deleteFile(path);
|
||||
}
|
||||
}
|
||||
catch (e:Dynamic) {}
|
||||
}
|
||||
|
||||
Log.info("", " - \x1b[1mRemoving directory:\x1b[0m " + directory);
|
||||
|
||||
try
|
||||
{
|
||||
FileSystem.deleteDirectory(directory);
|
||||
}
|
||||
catch (e:Dynamic) {}
|
||||
}
|
||||
}
|
||||
|
||||
static public function removeFile(file:String)
|
||||
{
|
||||
if (FileSystem.exists(file))
|
||||
{
|
||||
Log.info("", " - \x1b[1mRemoving file:\x1b[0m " + file);
|
||||
FileSystem.deleteFile(file);
|
||||
}
|
||||
}
|
||||
|
||||
static public function removeFilesWithExtension(inExt:String)
|
||||
{
|
||||
var contents = FileSystem.readDirectory(".");
|
||||
for(item in contents)
|
||||
{
|
||||
if (item.length > inExt.length && item.substr(item.length-inExt.length)==inExt)
|
||||
removeFile(item);
|
||||
}
|
||||
}
|
||||
|
||||
public static function resetDirectoryCache():Void
|
||||
{
|
||||
directoryCache = new Map<String,Bool>();
|
||||
}
|
||||
|
||||
public static function standardize(path:String, trailingSlash:Bool = false):String
|
||||
{
|
||||
path = StringTools.replace (path, "\\", "/");
|
||||
path = StringTools.replace (path, "//", "/");
|
||||
path = StringTools.replace (path, "//", "/");
|
||||
|
||||
if (!trailingSlash && StringTools.endsWith(path, "/"))
|
||||
{
|
||||
path = path.substr(0, path.length - 1);
|
||||
}
|
||||
else if (trailingSlash && !StringTools.endsWith(path, "/"))
|
||||
{
|
||||
path += "/";
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
public static function clean(path:String)
|
||||
{
|
||||
var result = new Array<String>();
|
||||
for(part in standardize(path).split("/"))
|
||||
{
|
||||
if (part!=".")
|
||||
{
|
||||
if (part=="..")
|
||||
{
|
||||
if (result.length==0)
|
||||
Log.error("Bad relative path " + path);
|
||||
result.pop();
|
||||
}
|
||||
else
|
||||
result.push(part);
|
||||
}
|
||||
}
|
||||
return result.join("/");
|
||||
}
|
||||
}
|
122
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/Prelinker.hx
Normal file
122
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/Prelinker.hx
Normal file
@ -0,0 +1,122 @@
|
||||
import haxe.io.Path;
|
||||
import sys.FileSystem;
|
||||
|
||||
class Prelinker
|
||||
{
|
||||
public var mExe:String;
|
||||
public var mFlags:Array<String>;
|
||||
public var mOutFlag:String;
|
||||
public var mFromFile:String;
|
||||
public var mExpandArchives:Bool;
|
||||
|
||||
public function new(inExe:String)
|
||||
{
|
||||
mFlags = [];
|
||||
mOutFlag = "-o";
|
||||
mExe = inExe;
|
||||
mExpandArchives = false;
|
||||
// Default to on...
|
||||
mFromFile = "@";
|
||||
}
|
||||
|
||||
function isOutOfDate(inName:String, inObjs:Array<String>)
|
||||
{
|
||||
if (!FileSystem.exists(inName))
|
||||
return true;
|
||||
var stamp = FileSystem.stat(inName).mtime.getTime();
|
||||
for(obj in inObjs)
|
||||
{
|
||||
if (!FileSystem.exists(obj))
|
||||
{
|
||||
Log.error("Could not find \"" + obj + "\" required by \"" + inName + "\"");
|
||||
//throw "Could not find " + obj + " required by " + inName;
|
||||
}
|
||||
var obj_stamp = FileSystem.stat(obj).mtime.getTime();
|
||||
if (obj_stamp > stamp)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function prelink(inTarget:Target,inObjs:Array<String>,inCompiler:Compiler)
|
||||
{
|
||||
var file_name = "prelink.o";
|
||||
|
||||
try
|
||||
{
|
||||
PathManager.mkdir(inTarget.mOutputDir);
|
||||
}
|
||||
catch (e:Dynamic)
|
||||
{
|
||||
Log.error("Unable to create output directory \"" + inTarget.mOutputDir + "\"");
|
||||
//throw "Unable to create output directory " + inTarget.mOutputDir;
|
||||
}
|
||||
|
||||
var out_name = inCompiler.mObjDir + "/" + file_name;
|
||||
|
||||
if (isOutOfDate(out_name,inObjs) || isOutOfDate(out_name,inTarget.mDepends))
|
||||
{
|
||||
var args = new Array<String>();
|
||||
var out = mOutFlag;
|
||||
if (out.substr(-1)==" ")
|
||||
{
|
||||
args.push(out.substr(0,out.length-1));
|
||||
out = "";
|
||||
}
|
||||
|
||||
args.push(out + out_name);
|
||||
//args = args.concat(mFlags).concat(inTarget.mFlags);
|
||||
args = args.concat(mFlags);
|
||||
|
||||
var objs = inObjs.copy();
|
||||
|
||||
/*if (mExpandArchives)
|
||||
{
|
||||
var isArchive = ~/\.a$/;
|
||||
var libArgs = new Array<String>();
|
||||
for(lib in libs)
|
||||
{
|
||||
if (isArchive.match(lib))
|
||||
{
|
||||
var libName = Path.withoutDirectory(lib);
|
||||
var libObjs = Setup.readStdout(mExe, ["t", lib ]);
|
||||
var objDir = inCompiler.mObjDir + "/" + libName;
|
||||
PathManager.mkdir(objDir);
|
||||
ProcessManager.runCommand (objDir, mExe, ["x", lib]);
|
||||
for(obj in libObjs)
|
||||
objs.push( objDir+"/"+obj );
|
||||
}
|
||||
else
|
||||
libArgs.push(lib);
|
||||
}
|
||||
libs = libArgs;
|
||||
}*/
|
||||
|
||||
// Place list of obj files in a file called "all_objs"
|
||||
if (mFromFile=="@")
|
||||
{
|
||||
var fname = inCompiler.mObjDir + "/all_objs";
|
||||
var fout = sys.io.File.write(fname,false);
|
||||
for(obj in objs)
|
||||
fout.writeString(obj + "\n");
|
||||
fout.close();
|
||||
args.push("@" + fname );
|
||||
}
|
||||
else
|
||||
args = args.concat(objs);
|
||||
|
||||
//args = args.concat(libs);
|
||||
|
||||
var result = ProcessManager.runCommand("", mExe, args);
|
||||
if (result!=0)
|
||||
{
|
||||
Tools.exit(result);
|
||||
//throw "Error : " + result + " - build cancelled";
|
||||
}
|
||||
|
||||
return out_name;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
}
|
509
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/ProcessManager.hx
Normal file
509
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/ProcessManager.hx
Normal file
@ -0,0 +1,509 @@
|
||||
import haxe.io.BytesOutput;
|
||||
import haxe.io.Eof;
|
||||
import haxe.io.Path;
|
||||
import sys.io.Process;
|
||||
import sys.FileSystem;
|
||||
#if haxe4
|
||||
import sys.thread.Thread;
|
||||
#elseif neko
|
||||
import neko.vm.Thread;
|
||||
#else
|
||||
import cpp.vm.Thread;
|
||||
#end
|
||||
|
||||
class ProcessManager
|
||||
{
|
||||
static function dup(inArgs:Array<String>)
|
||||
{
|
||||
if (inArgs==null)
|
||||
return [];
|
||||
return inArgs.copy();
|
||||
}
|
||||
|
||||
// Command may be a pseudo command, like "xcrun --sdk abc", or 'python "some script"'
|
||||
// Here we split the first word into command and move the rest into args, being careful
|
||||
// to preserve quoted words
|
||||
static function combineCommand(command:String, args:Array<String>)
|
||||
{
|
||||
var parts = new Array<String>();
|
||||
var c = command;
|
||||
var quoted = ~/^\s*"([^"]+)"(.*)/;
|
||||
var word = ~/^\s*(\S+)(.*)/;
|
||||
while(c.length>0)
|
||||
{
|
||||
if (quoted.match(c))
|
||||
{
|
||||
parts.push( quoted.matched(1) );
|
||||
c = quoted.matched(2);
|
||||
}
|
||||
else if (word.match(c))
|
||||
{
|
||||
parts.push( word.matched(1) );
|
||||
c = word.matched(2);
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (parts.length>1)
|
||||
{
|
||||
command = parts.shift();
|
||||
while(parts.length>0)
|
||||
args.unshift( parts.pop() );
|
||||
}
|
||||
return PathManager.escape(command);
|
||||
}
|
||||
|
||||
private static function formatMessage(command:String, args:Array<String>, colorize:Bool = true):String
|
||||
{
|
||||
var message = "";
|
||||
|
||||
if (colorize)
|
||||
{
|
||||
message = "\x1b[33;1m" + command + "\x1b[0m";
|
||||
}
|
||||
else
|
||||
{
|
||||
message = command;
|
||||
}
|
||||
|
||||
for (arg in args)
|
||||
{
|
||||
if (colorize)
|
||||
{
|
||||
var ext = Path.extension(arg);
|
||||
if (ext == "cpp" || ext == "c" || ext == "h" || ext == "hpp" || ext == "m" || ext == "mm")
|
||||
{
|
||||
var split = arg.split ("/");
|
||||
if (split.length > 1)
|
||||
{
|
||||
arg = "\x1b[33m" + split.slice(0, split.length - 1).join("/") + "/\x1b[33;1m" + split[split.length - 1] + "\x1b[0m";
|
||||
}
|
||||
else
|
||||
{
|
||||
arg = "\x1b[1m" + arg + "\x1b[0m";
|
||||
}
|
||||
}
|
||||
else if (StringTools.startsWith(arg, "-D"))
|
||||
{
|
||||
arg = "\x1b[1m" + arg + "\x1b[0m";
|
||||
}
|
||||
else
|
||||
{
|
||||
arg = "\x1b[0m" + arg + "\x1b[0m";
|
||||
}
|
||||
}
|
||||
|
||||
if (arg.indexOf(" ") > -1)
|
||||
{
|
||||
message += " \"" + arg + "\"";
|
||||
}
|
||||
else
|
||||
{
|
||||
message += " " + arg;
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
public static function runCommand(path:String, command:String, args:Array<String>, print:Bool = true, safeExecute:Bool = true, ignoreErrors:Bool = false,?inText:String):Int
|
||||
{
|
||||
args = dup(args);
|
||||
command = combineCommand(command,args);
|
||||
|
||||
|
||||
if (print && !Log.verbose && !Log.quiet)
|
||||
{
|
||||
Log.info(inText==null ? "" : inText,formatMessage(command, args));
|
||||
}
|
||||
|
||||
if (safeExecute)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (path != null && path != "" && !FileSystem.exists(FileSystem.fullPath(path)) && !FileSystem.exists(FileSystem.fullPath(new Path(path).dir)))
|
||||
{
|
||||
Log.error("The specified target path \"" + path + "\" does not exist");
|
||||
return 1;
|
||||
}
|
||||
return _runCommand(path, command, args, inText);
|
||||
}
|
||||
catch (e:Dynamic)
|
||||
{
|
||||
if (!ignoreErrors)
|
||||
{
|
||||
//var text = formatMessage(command, args);
|
||||
//Log.error("Error while running command\n" + text , e);
|
||||
if (Log.verbose)
|
||||
{
|
||||
Log.error ("", e);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return _runCommand(path, command, args, inText);
|
||||
}
|
||||
}
|
||||
|
||||
public static function readStderr(inCommand:String,inArgs:Array<String>)
|
||||
{
|
||||
inArgs = dup(inArgs);
|
||||
inCommand = combineCommand(inCommand,inArgs);
|
||||
|
||||
var result = new Array<String>();
|
||||
var proc = new Process(inCommand,inArgs);
|
||||
try
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
var out = proc.stderr.readLine();
|
||||
result.push(out);
|
||||
}
|
||||
} catch(e:Dynamic){}
|
||||
proc.close();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static function readStdout(command:String,args:Array<String>)
|
||||
{
|
||||
args = dup(args);
|
||||
command = combineCommand(command,args);
|
||||
|
||||
|
||||
var result = new Array<String>();
|
||||
var proc = new Process(command,args);
|
||||
try
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
var out = proc.stdout.readLine();
|
||||
result.push(out);
|
||||
}
|
||||
} catch(e:Dynamic){}
|
||||
proc.close();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static function runProcess(path:String, command:String, args:Array<String>, waitForOutput:Bool = true, print:Bool = true, safeExecute:Bool = true, ignoreErrors:Bool = false, ?text:String):String
|
||||
{
|
||||
args = dup(args);
|
||||
command = combineCommand(command,args);
|
||||
|
||||
if (print && !Log.verbose)
|
||||
{
|
||||
Log.info(formatMessage(command, args));
|
||||
}
|
||||
|
||||
|
||||
if (safeExecute)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (path != null && path != "" && !FileSystem.exists(FileSystem.fullPath(path)) && !FileSystem.exists(FileSystem.fullPath(new Path(path).dir)))
|
||||
{
|
||||
Log.error("The specified target path \"" + path + "\" does not exist");
|
||||
}
|
||||
return _runProcess(path, command, args, waitForOutput, ignoreErrors, text);
|
||||
}
|
||||
catch (e:Dynamic)
|
||||
{
|
||||
if (!ignoreErrors)
|
||||
{
|
||||
//Log.error("Error while running command\n" + formatMessage(command,args), e);
|
||||
if (Log.verbose)
|
||||
{
|
||||
Log.error ("", e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return _runProcess(path, command, args, waitForOutput, ignoreErrors, text);
|
||||
}
|
||||
}
|
||||
public static function runProcessLine(path:String, command:String, args:Array<String>, waitForOutput:Bool = true, print:Bool = true, safeExecute:Bool = true, ignoreErrors:Bool = false):String
|
||||
{
|
||||
var result = runProcess(path, command, args, waitForOutput, print, safeExecute, ignoreErrors);
|
||||
if (result!=null)
|
||||
return result.split("\n")[0];
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private static function _runCommand(path:String, command:String, args:Array<String>, inText:String):Int
|
||||
{
|
||||
var oldPath:String = "";
|
||||
|
||||
if (path != null && path != "")
|
||||
{
|
||||
Log.info("", " - \x1b[1mChanging directory:\x1b[0m " + path + "");
|
||||
|
||||
oldPath = Sys.getCwd();
|
||||
Sys.setCwd(path);
|
||||
}
|
||||
|
||||
if (Log.quiet && inText!=null)
|
||||
{
|
||||
Log.info(inText);
|
||||
}
|
||||
else
|
||||
{
|
||||
var text = inText==null ? "Running command" : inText;
|
||||
Log.info("", " - \x1b[1m" + text + ":\x1b[0m " + formatMessage(command, args));
|
||||
}
|
||||
|
||||
var result = 0;
|
||||
|
||||
if (args != null && args.length > 0)
|
||||
{
|
||||
result = Sys.command(command, args);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = Sys.command(command);
|
||||
}
|
||||
|
||||
if (oldPath != "")
|
||||
{
|
||||
Sys.setCwd(oldPath);
|
||||
}
|
||||
|
||||
if (result != 0)
|
||||
{
|
||||
throw ("Error while running command\n" + formatMessage(command, args) + (path != "" ? " [" + path + "]" : ""));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static function _runProcess(path:String, command:String, args:Array<String>, waitForOutput:Bool, ignoreErrors:Bool, inText:String):String
|
||||
{
|
||||
var oldPath:String = "";
|
||||
|
||||
if (path != null && path != "")
|
||||
{
|
||||
Log.info("", " - \x1b[1m - Changing directory:\x1b[0m " + path + "");
|
||||
|
||||
oldPath = Sys.getCwd();
|
||||
Sys.setCwd(path);
|
||||
}
|
||||
|
||||
if ( !Log.quiet)
|
||||
{
|
||||
var text = inText==null ? "Running process" : inText;
|
||||
Log.info("", " - \x1b[1m" + text + ":\x1b[0m " + formatMessage(command, args));
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.info("",inText);
|
||||
}
|
||||
|
||||
var output = "";
|
||||
var result = 0;
|
||||
|
||||
var process:Process = null;
|
||||
try
|
||||
{
|
||||
process = new Process(command, args);
|
||||
}
|
||||
catch(e:Dynamic)
|
||||
{
|
||||
if (ignoreErrors)
|
||||
return null;
|
||||
Log.error(e+"");
|
||||
}
|
||||
|
||||
var buffer = new BytesOutput();
|
||||
|
||||
if (waitForOutput)
|
||||
{
|
||||
var waiting = true;
|
||||
while (waiting)
|
||||
{
|
||||
try
|
||||
{
|
||||
var current = process.stdout.readAll(1024);
|
||||
buffer.write(current);
|
||||
if (current.length == 0)
|
||||
{
|
||||
waiting = false;
|
||||
}
|
||||
}
|
||||
catch (e:Eof)
|
||||
{
|
||||
waiting = false;
|
||||
}
|
||||
}
|
||||
|
||||
result = process.exitCode();
|
||||
process.close();
|
||||
|
||||
//if (result == 0)
|
||||
//{
|
||||
output = buffer.getBytes().toString();
|
||||
if (output == "")
|
||||
{
|
||||
var error = process.stderr.readAll().toString();
|
||||
if (ignoreErrors)
|
||||
{
|
||||
output = error;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (error==null || error=="")
|
||||
error = "Error while running command\n" + formatMessage(command, args);
|
||||
Log.error(error);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
if (oldPath != "")
|
||||
{
|
||||
Sys.setCwd(oldPath);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
// This function will return 0 on success, or non-zero error code
|
||||
public static function runProcessThreaded(command:String, args:Array<String>, inText:String = null):Int
|
||||
{
|
||||
args = dup(args);
|
||||
command = combineCommand(command,args);
|
||||
|
||||
Log.lock();
|
||||
|
||||
// Other thread may have already thrown an error
|
||||
if (BuildTool.threadExitCode!=0)
|
||||
{
|
||||
Log.unlock();
|
||||
return BuildTool.threadExitCode;
|
||||
}
|
||||
|
||||
if (inText != null)
|
||||
Log.info(inText,"");
|
||||
|
||||
if (!Log.quiet)
|
||||
Log.v(" - \x1b[1mRunning command:\x1b[0m " + formatMessage(command, args));
|
||||
Log.unlock();
|
||||
|
||||
var output = new Array<String>();
|
||||
var process:Process = null;
|
||||
try
|
||||
{
|
||||
process = new Process(command, args);
|
||||
}
|
||||
catch(e:Dynamic)
|
||||
{
|
||||
Log.lock();
|
||||
if (BuildTool.threadExitCode == 0)
|
||||
{
|
||||
Log.info('${Log.RED}${Log.BOLD}$e${Log.NORMAL}\n');
|
||||
BuildTool.setThreadError(-1);
|
||||
}
|
||||
Log.unlock();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
var err = process.stderr;
|
||||
var out = process.stdout;
|
||||
var reader = BuildTool.helperThread.value;
|
||||
|
||||
// Read stderr in separate thread to avoid blocking
|
||||
if (reader==null)
|
||||
{
|
||||
var controller = Thread.current();
|
||||
BuildTool.helperThread.value = reader = Thread.create(function()
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
var stream = Thread.readMessage(true);
|
||||
var output:Array<String> = null;
|
||||
try
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
var line = stream.readLine();
|
||||
if (output==null)
|
||||
output = [ line ];
|
||||
else
|
||||
output.push(line);
|
||||
}
|
||||
}
|
||||
catch(e:Dynamic){ }
|
||||
controller.sendMessage(output);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Start-up the error reader
|
||||
reader.sendMessage(err);
|
||||
|
||||
try
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
var line = out.readLine();
|
||||
output.push(line);
|
||||
}
|
||||
}
|
||||
catch(e:Dynamic){ }
|
||||
|
||||
if (output.length==1 && ~/^\S+\.(cpp|c|cc)$/.match(output[0]))
|
||||
{
|
||||
// Microsoft prints the name of the cpp file for some reason
|
||||
output = [];
|
||||
}
|
||||
|
||||
var errOut:Array<String> = Thread.readMessage(true);
|
||||
|
||||
var code = process.exitCode();
|
||||
process.close();
|
||||
|
||||
if (code != 0)
|
||||
{
|
||||
if (BuildTool.threadExitCode == 0)
|
||||
{
|
||||
Log.lock();
|
||||
var message = "";
|
||||
if (Log.verbose)
|
||||
{
|
||||
Log.println("");
|
||||
message += "Error while running command\n";
|
||||
message += formatMessage(command,args) + "\n\n";
|
||||
}
|
||||
if (output.length > 0)
|
||||
{
|
||||
message += output.join("\n") + "\n";
|
||||
}
|
||||
if (errOut != null)
|
||||
{
|
||||
message += errOut.join("\n") + '${Log.NORMAL}';
|
||||
}
|
||||
Log.error(message,"",null,false);
|
||||
Log.unlock();
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
if (errOut!=null && errOut.length>0)
|
||||
output = output.concat(errOut);
|
||||
|
||||
if (output.length>0)
|
||||
{
|
||||
Log.info(output.join("\n"));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
140
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/Profile.hx
Executable file
140
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/Profile.hx
Executable file
@ -0,0 +1,140 @@
|
||||
|
||||
class Entry
|
||||
{
|
||||
public var name:String;
|
||||
public var entry:Float;
|
||||
public var total:Float;
|
||||
public var running:Bool;
|
||||
public var children:Array<Entry>;
|
||||
public var current:Entry;
|
||||
|
||||
public function new(inName:String)
|
||||
{
|
||||
name = inName;
|
||||
total = 0.0;
|
||||
children = [];
|
||||
entry = haxe.Timer.stamp();
|
||||
running = true;
|
||||
current = null;
|
||||
}
|
||||
|
||||
public function start()
|
||||
{
|
||||
if (running)
|
||||
trace("===== Restarted " + name);
|
||||
entry = haxe.Timer.stamp();
|
||||
running = true;
|
||||
}
|
||||
|
||||
public function stop()
|
||||
{
|
||||
if (running)
|
||||
{
|
||||
total += haxe.Timer.stamp() - entry;
|
||||
running = false;
|
||||
}
|
||||
}
|
||||
|
||||
public function find(inName:String)
|
||||
{
|
||||
for(c in children)
|
||||
if (c.name==inName)
|
||||
{
|
||||
current = c;
|
||||
current.start();
|
||||
return current;
|
||||
}
|
||||
var result = new Entry(inName);
|
||||
children.push(result);
|
||||
current = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static function timeString(t:Float)
|
||||
{
|
||||
return Std.int(t*1000.0) + "ms";
|
||||
}
|
||||
|
||||
public function dump(indent = "")
|
||||
{
|
||||
if (running)
|
||||
trace("========== running?");
|
||||
Sys.println(indent + name + " : " + timeString(total) );
|
||||
for(c in children)
|
||||
c.dump( indent + " " );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
class Profile
|
||||
{
|
||||
static var valid = false;
|
||||
static var t0:Float;
|
||||
static var root:Entry;
|
||||
static var current:Entry;
|
||||
static var currentParent:Entry;
|
||||
static var stack:Array<Entry>;
|
||||
|
||||
|
||||
public static function start()
|
||||
{
|
||||
t0 = now();
|
||||
root = new Entry("Program");
|
||||
currentParent = root;
|
||||
current = null;
|
||||
stack = [];
|
||||
}
|
||||
|
||||
public static function enable()
|
||||
{
|
||||
valid = true;
|
||||
Tools.addOnExitHook( dump );
|
||||
}
|
||||
|
||||
public static function setEntry(inName:String)
|
||||
{
|
||||
if (!valid) return;
|
||||
|
||||
if (current!=null)
|
||||
current.stop();
|
||||
current = currentParent.find(inName);
|
||||
}
|
||||
|
||||
public static function push(inName:String)
|
||||
{
|
||||
if (!valid) return;
|
||||
|
||||
stack.push(currentParent);
|
||||
currentParent = current;
|
||||
current = currentParent.find(inName);
|
||||
}
|
||||
public static function pop()
|
||||
{
|
||||
if (!valid) return;
|
||||
|
||||
current.stop();
|
||||
currentParent = stack.pop();
|
||||
current = currentParent.current;
|
||||
}
|
||||
|
||||
|
||||
static function dump(inExitCode:Int)
|
||||
{
|
||||
if (inExitCode==0)
|
||||
{
|
||||
if (current!=null)
|
||||
current.stop();
|
||||
if (currentParent!=null)
|
||||
currentParent.stop();
|
||||
for(s in stack)
|
||||
s.stop();
|
||||
root.dump();
|
||||
}
|
||||
}
|
||||
|
||||
inline static function now() return haxe.Timer.stamp();
|
||||
}
|
||||
|
748
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/Setup.hx
Normal file
748
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/Setup.hx
Normal file
@ -0,0 +1,748 @@
|
||||
import haxe.io.Eof;
|
||||
import sys.io.Process;
|
||||
import sys.FileSystem;
|
||||
import BuildTool;
|
||||
|
||||
class Setup
|
||||
{
|
||||
static function findAndroidNdkRoot(defines: Map<String,String>, inBaseVersion:Int):String
|
||||
{
|
||||
var bestVersion = 0.0;
|
||||
var result:String = null;
|
||||
|
||||
var ndkDir = defines.get("ANDROID_NDK_DIR");
|
||||
if (ndkDir!=null)
|
||||
{
|
||||
Log.v("Looking in ANDROID_NDK_DIR " + ndkDir);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.v("ANDROID_NDK_DIR not set");
|
||||
if (BuildTool.isMac)
|
||||
{
|
||||
var lib = defines.get("HOME") + "/Library/Android/sdk/ndk";
|
||||
if (FileSystem.exists(lib))
|
||||
{
|
||||
Log.v("trying default " + lib);
|
||||
ndkDir = lib;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ndkDir!=null)
|
||||
{
|
||||
ndkDir = ndkDir.split("\\").join("/");
|
||||
var files:Array<String> = null;
|
||||
var checkFiles:Bool = true;
|
||||
try
|
||||
{
|
||||
files = FileSystem.readDirectory(ndkDir);
|
||||
}
|
||||
catch (e:Dynamic)
|
||||
{
|
||||
Log.warn('ANDROID_NDK_DIR "$ndkDir" does not point to a valid directory');
|
||||
checkFiles=false;
|
||||
}
|
||||
if (checkFiles)
|
||||
for (file in files)
|
||||
{
|
||||
file = file.split("\\").join("/");
|
||||
var version = getNdkVersion(ndkDir + "/" + file);
|
||||
if (inBaseVersion==0 || Std.int(version)==inBaseVersion)
|
||||
{
|
||||
if (version>bestVersion)
|
||||
{
|
||||
bestVersion = version;
|
||||
result = ndkDir + "/" + file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Log.v("Looking in ANDROID_SDK/ndk-bundle");
|
||||
if (defines.exists("ANDROID_SDK"))
|
||||
{
|
||||
Log.v("checks default ndk-bundle in android sdk");
|
||||
var ndkBundle = defines.get("ANDROID_SDK")+"/ndk-bundle";
|
||||
ndkBundle = ndkBundle.split("\\").join("/");
|
||||
var version = getNdkVersion(ndkBundle);
|
||||
if (version>bestVersion && (inBaseVersion==0 || inBaseVersion==Std.int(version)) )
|
||||
{
|
||||
Log.v("Using default ndk-bundle in android sdk");
|
||||
result = ndkBundle;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static public function getNdkVersion(inDirName:String):Float
|
||||
{
|
||||
Log.v("Try to get version from source.properties");
|
||||
var src = toPath(inDirName+"/source.properties");
|
||||
if (sys.FileSystem.exists(src))
|
||||
{
|
||||
var fin = sys.io.File.read(src, false);
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
var str = fin.readLine();
|
||||
var split = str.split ("=");
|
||||
var name = StringTools.trim(split[0]);
|
||||
if (name == "Pkg.Revision")
|
||||
{
|
||||
var revision = StringTools.trim(split[1]);
|
||||
var split2 = revision.split( "." );
|
||||
var result:Float = 1.0 * Std.parseInt(split2[0]) + 0.001 * Std.parseInt(split2[1]);
|
||||
if (result>=8)
|
||||
{
|
||||
Log.v('Deduced NDK version '+result+' from "$inDirName"/source.properties');
|
||||
fin.close();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e:haxe.io.Eof)
|
||||
{
|
||||
Log.v('Could not deduce NDK version from "$inDirName"/source.properties');
|
||||
}
|
||||
fin.close();
|
||||
}
|
||||
|
||||
var dir = inDirName.split("\\").join("/");
|
||||
Log.v('Try to get version from directory name "$dir"');
|
||||
var extract_version = ~/\/?(android-ndk-)?r(\d+)([a-z]?)$/;
|
||||
if (extract_version.match(dir))
|
||||
{
|
||||
var major:Int = Std.parseInt( extract_version.matched(2) );
|
||||
var result:Float = 1.0 * major;
|
||||
var minor = extract_version.matched(3);
|
||||
if (minor!=null && minor.length>0)
|
||||
result += 0.001 * (minor.toLowerCase().charCodeAt(0)-'a'.code);
|
||||
return result;
|
||||
}
|
||||
|
||||
Log.v('Could not deduce NDK version from "$inDirName" - assuming 8');
|
||||
return 8;
|
||||
}
|
||||
|
||||
public static function initHXCPPConfig(ioDefines:Hash<String>)
|
||||
{
|
||||
var env = Sys.environment();
|
||||
// If the user has set it themselves, they mush know what they are doing...
|
||||
if (env.exists("HXCPP_CONFIG"))
|
||||
return;
|
||||
|
||||
var home = "";
|
||||
if (env.exists("HOME"))
|
||||
home = env.get("HOME");
|
||||
else if (env.exists("USERPROFILE"))
|
||||
home = env.get("USERPROFILE");
|
||||
else
|
||||
{
|
||||
Log.warn("No $HOME variable set, \".hxcpp_config.xml\" might be missing");
|
||||
//Sys.println("Warning: No 'HOME' variable set - .hxcpp_config.xml might be missing.");
|
||||
return;
|
||||
}
|
||||
|
||||
ioDefines.set("HXCPP_HOME", home);
|
||||
|
||||
var config = toPath(home+"/.hxcpp_config.xml");
|
||||
ioDefines.set("HXCPP_CONFIG",config);
|
||||
|
||||
if (BuildTool.HXCPP!="")
|
||||
{
|
||||
var src = toPath(BuildTool.HXCPP + "/toolchain/example.hxcpp_config.xml");
|
||||
if (!sys.FileSystem.exists(config))
|
||||
{
|
||||
try
|
||||
{
|
||||
Log.info("", "Copying HXCPP config \"" + src + "\" to \"" + config + "\"");
|
||||
sys.io.File.copy(src,config);
|
||||
}
|
||||
catch(e:Dynamic)
|
||||
{
|
||||
Log.warn("Could not create HXCPP config \"" + config + "\"");
|
||||
//Sys.println("Warning : could not create config: " + config );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function setupMingw(ioDefines:Hash<String>)
|
||||
{
|
||||
// Setup MINGW_ROOT or fail
|
||||
if (!ioDefines.exists("MINGW_ROOT"))
|
||||
{
|
||||
|
||||
var haxelib = PathManager.getHaxelib("minimingw","",false);
|
||||
if (haxelib!=null && haxelib!="")
|
||||
{
|
||||
ioDefines.set("MINGW_ROOT", haxelib);
|
||||
Log.v('Using haxelib version of MinGW, $haxelib');
|
||||
return;
|
||||
}
|
||||
|
||||
var guesses = ["c:/MinGW"];
|
||||
for (guess in guesses)
|
||||
{
|
||||
if (FileSystem.exists(guess))
|
||||
{
|
||||
ioDefines.set("MINGW_ROOT", guess);
|
||||
Log.v('Using default version of MinGW, $guess');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (ioDefines.exists("mingw"))
|
||||
{
|
||||
//when mingw is explicitly indicated but not properly configured, this log will be shown
|
||||
Log.error('Could not guess MINGW_ROOT (tried $guesses) - please set explicitly');
|
||||
}
|
||||
else
|
||||
{
|
||||
//when both mingw and MSVC is not properly configured, this log will be shown
|
||||
Log.error('Could not setup any C++ compiler, please install or reinstall a valid C++ compiler');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static function setupEmscripten(ioDefines:Hash<String>)
|
||||
{
|
||||
// Setup EMSCRIPTEN_SDK if possible - else assume developer has it in path
|
||||
if (!ioDefines.exists("EMSCRIPTEN_SDK"))
|
||||
{
|
||||
var home = ioDefines.get("HXCPP_HOME");
|
||||
var file = home + "/.emscripten";
|
||||
if (FileSystem.exists(file))
|
||||
{
|
||||
var content = sys.io.File.getContent(file);
|
||||
content = content.split("\r").join("");
|
||||
var value = ~/^(\w*)\s*=\s*'(.*)'/;
|
||||
for (line in content.split("\n"))
|
||||
{
|
||||
if (value.match(line))
|
||||
{
|
||||
var name = value.matched(1);
|
||||
var val= value.matched(2);
|
||||
if (name=="EMSCRIPTEN_ROOT")
|
||||
{
|
||||
ioDefines.set("EMSCRIPTEN_SDK", val);
|
||||
}
|
||||
if (name=="PYTHON")
|
||||
ioDefines.set("EMSCRIPTEN_PYTHON", val);
|
||||
if (name=="NODE_JS")
|
||||
ioDefines.set("EMSCRIPTEN_NODE_JS", val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static function isRaspberryPi()
|
||||
{
|
||||
var modelFile = '/sys/firmware/devicetree/base/model';
|
||||
if( !FileSystem.exists( modelFile ) )
|
||||
return false;
|
||||
try {
|
||||
var model = sys.io.File.getContent( modelFile );
|
||||
return ~/Raspberry/.match( model );
|
||||
} catch(e:Dynamic) {
|
||||
trace( e );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static public function startPdbServer()
|
||||
{
|
||||
var oldPath = Sys.getCwd();
|
||||
try
|
||||
{
|
||||
// Run it in hxcpp directory so it does not lock the build directory after build finishes
|
||||
Sys.setCwd(BuildTool.HXCPP);
|
||||
var proc = new Process("mspdbsrv.exe",["-start"]);
|
||||
Tools.addOnExitHook(function(_) {
|
||||
proc.kill();
|
||||
});
|
||||
}
|
||||
catch(e:Dynamic)
|
||||
{
|
||||
Log.v("Could not start mspdbsrv:" + e);
|
||||
}
|
||||
Sys.setCwd(oldPath);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static function setup(inWhat:String,ioDefines:Map<String,String>)
|
||||
{
|
||||
if (ioDefines.exists("HXCPP_CLEAN_ONLY"))
|
||||
return;
|
||||
|
||||
Profile.push("setup " + inWhat);
|
||||
if (inWhat=="androidNdk")
|
||||
{
|
||||
setupAndroidNdk(ioDefines);
|
||||
}
|
||||
else if (inWhat=="blackberry")
|
||||
{
|
||||
setupBlackBerryNativeSDK(ioDefines);
|
||||
}
|
||||
else if (inWhat=="msvc")
|
||||
{
|
||||
setupMSVC(ioDefines, ioDefines.exists("HXCPP_M64"), ioDefines.exists("HXCPP_ARM64"), ioDefines.exists("winrt"));
|
||||
}
|
||||
else if (inWhat=="pdbserver")
|
||||
{
|
||||
startPdbServer();
|
||||
}
|
||||
else if (inWhat=="mingw")
|
||||
{
|
||||
setupMingw(ioDefines);
|
||||
}
|
||||
else if (inWhat=="emscripten")
|
||||
{
|
||||
setupEmscripten(ioDefines);
|
||||
}
|
||||
else if (inWhat=="nvcc")
|
||||
{
|
||||
BuildTool.setupNvcc();
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.error('Unknown setup feature "$inWhat"');
|
||||
//throw 'Unknown setup feature $inWhat';
|
||||
}
|
||||
Profile.pop();
|
||||
}
|
||||
|
||||
static public function setupAndroidNdk(defines:Map<String,String>)
|
||||
{
|
||||
var root:String = null;
|
||||
|
||||
if (Log.verbose) Log.println("");
|
||||
|
||||
var ndkVersion = 0;
|
||||
for (i in 6...20)
|
||||
{
|
||||
if (defines.exists("NDKV" + i))
|
||||
{
|
||||
ndkVersion = i;
|
||||
Log.info("", "\x1b[33;1mRequested Android NDK r" + i + "\x1b[0m");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!defines.exists("ANDROID_NDK_ROOT") || ndkVersion!=0)
|
||||
{
|
||||
root = Setup.findAndroidNdkRoot( defines, ndkVersion );
|
||||
if (root==null)
|
||||
{
|
||||
var ndkDir = defines.exists("ANDROID_NDK_DIR") ? defines.get("ANDROID_NDK_DIR") : "not set";
|
||||
if (ndkVersion!=0)
|
||||
Log.error('ANDROID_NDK_DIR ["$ndkDir"] or ndk-bundle does not contain requested NDK $ndkVersion');
|
||||
else
|
||||
Log.error('ANDROID_NDK_DIR ["$ndkDir"] or ndk-bundle does not contain a matching NDK');
|
||||
}
|
||||
else
|
||||
{
|
||||
Sys.putEnv("ANDROID_NDK_ROOT", root);
|
||||
defines.set("ANDROID_NDK_ROOT", root);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
root = defines.get("ANDROID_NDK_ROOT");
|
||||
Log.info("", "\x1b[33;1mUsing Android NDK root: " + root + "\x1b[0m");
|
||||
}
|
||||
|
||||
if (ndkVersion==0)
|
||||
{
|
||||
var version = Setup.getNdkVersion( root );
|
||||
if (version > 0)
|
||||
{
|
||||
Log.info("", "\x1b[33;1mDetected Android NDK " + version + "\x1b[0m");
|
||||
defines.set("NDKV" + Std.int(version), "1" );
|
||||
ndkVersion = Std.int(version);
|
||||
}
|
||||
else
|
||||
Log.error("Invalid ndk version");
|
||||
}
|
||||
for (i in 5...ndkVersion+1)
|
||||
defines.set("NDKV" + i + "+", "1");
|
||||
|
||||
var arm_type = 'arm-linux-androideabi';
|
||||
var arm_64 = defines.exists('HXCPP_ARM64');
|
||||
if(arm_64) arm_type = 'aarch64-linux-android';
|
||||
|
||||
// Find toolchain
|
||||
if (!defines.exists("TOOLCHAIN_VERSION"))
|
||||
{
|
||||
try
|
||||
{
|
||||
var files = FileSystem.readDirectory(root+"/toolchains");
|
||||
|
||||
// Prefer clang?
|
||||
var extract_version = ~/^arm-linux-androideabi-(\d.*)/;
|
||||
if(arm_64) extract_version = ~/^aarch64-linux-android-(\d.*)/;
|
||||
|
||||
var bestVer="";
|
||||
for (file in files)
|
||||
{
|
||||
if (extract_version.match(file))
|
||||
{
|
||||
var ver = extract_version.matched(1);
|
||||
if (ver<bestVer || bestVer=="")
|
||||
{
|
||||
bestVer = ver;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bestVer!="")
|
||||
{
|
||||
defines.set("TOOLCHAIN_VERSION",bestVer);
|
||||
Log.info("", "\x1b[33;1mDetected Android toolchain: "+arm_type+"-" + bestVer + "\x1b[0m");
|
||||
}
|
||||
}
|
||||
catch(e:Dynamic) { }
|
||||
}
|
||||
|
||||
// See what ANDROID_HOST to use ...
|
||||
try
|
||||
{
|
||||
var prebuilt = root+"/toolchains/";
|
||||
if (defines.exists("TOOLCHAIN_VERSION"))
|
||||
prebuilt += arm_type + "-" + defines.get("TOOLCHAIN_VERSION") + "/prebuilt";
|
||||
else
|
||||
prebuilt += "llvm/prebuilt";
|
||||
var files = FileSystem.readDirectory(prebuilt);
|
||||
for (file in files)
|
||||
{
|
||||
if (!FileSystem.isDirectory (prebuilt + "/" + file))
|
||||
{
|
||||
files.remove (file);
|
||||
}
|
||||
}
|
||||
if (files.length==1)
|
||||
{
|
||||
defines.set("ANDROID_HOST", files[0]);
|
||||
Log.info("", "\x1b[33;1mDetected Android host: " + files[0] + "\x1b[0m");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.info("", "\x1b[33;1mCould not detect ANDROID_HOST (" + files + ") - using default\x1b[0m");
|
||||
}
|
||||
}
|
||||
catch(e:Dynamic) { }
|
||||
|
||||
if(defines.exists('NDKV20+')) {
|
||||
Log.v([
|
||||
"x86 Platform: 16",
|
||||
"arm Platform: 16",
|
||||
"x86_64 Platform: 21",
|
||||
"arm_64 Platform: 21",
|
||||
"Frameworks should set the minSdkVersion for each APK to these values."
|
||||
].join('\n'));
|
||||
}
|
||||
else {
|
||||
globallySetThePlatform(root, defines);
|
||||
}
|
||||
}
|
||||
|
||||
private static function globallySetThePlatform(root:String, defines:Map<String,String>) {
|
||||
var androidPlatform = 5;
|
||||
if (!defines.exists("PLATFORM"))
|
||||
{
|
||||
for (i in 5...100)
|
||||
{
|
||||
var test = "android-" + i;
|
||||
if (defines.exists(test))
|
||||
{
|
||||
defines.set("PLATFORM",test);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (defines.exists("PLATFORM"))
|
||||
{
|
||||
var platform = defines.get("PLATFORM");
|
||||
var id = Std.parseInt( platform.substr("android-".length) );
|
||||
if (id==0 || id==null)
|
||||
Log.error('Badly formed android PLATFORM "$platform" - should be like android-123');
|
||||
androidPlatform = id;
|
||||
Log.info("", "\x1b[33;1mUsing Android NDK platform: " + defines.get("PLATFORM") + "\x1b[0m");
|
||||
}
|
||||
else
|
||||
{
|
||||
var base = root + "/platforms";
|
||||
var best = 0;
|
||||
try
|
||||
{
|
||||
for (file in FileSystem.readDirectory(base))
|
||||
{
|
||||
if (file.substr(0,8)=="android-")
|
||||
{
|
||||
var platform = Std.parseInt(file.substr(8));
|
||||
if (platform>best)
|
||||
best = platform;
|
||||
}
|
||||
}
|
||||
} catch(e:Dynamic) {}
|
||||
|
||||
if (best==0)
|
||||
{
|
||||
Log.error("Could not detect Android API platforms in \"" + base + "\"");
|
||||
//throw "Could not find platform in " + base;
|
||||
}
|
||||
|
||||
Log.info("", "\x1b[33;1mUsing newest Android NDK platform: " + best + "\x1b[0m");
|
||||
defines.set("PLATFORM", "android-" + best);
|
||||
androidPlatform = best;
|
||||
}
|
||||
defines.set("ANDROID_PLATFORM_DEFINE", "HXCPP_ANDROID_PLATFORM=" + androidPlatform);
|
||||
if (Log.verbose) Log.println("");
|
||||
}
|
||||
|
||||
public static function setupBlackBerryNativeSDK(ioDefines:Hash<String>)
|
||||
{
|
||||
if (!ioDefines.exists ("BLACKBERRY_NDK_ROOT"))
|
||||
{
|
||||
Log.error("Could not find BLACKBERRY_NDK_ROOT variable");
|
||||
}
|
||||
|
||||
var fileName = ioDefines.get ("BLACKBERRY_NDK_ROOT");
|
||||
if (BuildTool.isWindows)
|
||||
{
|
||||
fileName += "\\bbndk-env.bat";
|
||||
}
|
||||
else
|
||||
{
|
||||
fileName += "/bbndk-env.sh";
|
||||
}
|
||||
|
||||
if (FileSystem.exists (fileName))
|
||||
{
|
||||
var fin = sys.io.File.read(fileName, false);
|
||||
try
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
var str = fin.readLine();
|
||||
var split = str.split ("=");
|
||||
var name = StringTools.trim (split[0].substr (split[0].lastIndexOf (" ") + 1));
|
||||
switch (name)
|
||||
{
|
||||
case "QNX_HOST", "QNX_TARGET", "QNX_HOST_VERSION", "QNX_TARGET_VERSION":
|
||||
var value = split[1];
|
||||
if (StringTools.startsWith (value, "${") && split.length > 2)
|
||||
{
|
||||
value = split[2].substr (0, split[2].length - 1);
|
||||
}
|
||||
if (StringTools.startsWith(value, "\""))
|
||||
{
|
||||
value = value.substr (1);
|
||||
}
|
||||
if (StringTools.endsWith(value, "\""))
|
||||
{
|
||||
value = value.substr (0, value.length - 1);
|
||||
}
|
||||
if (name == "QNX_HOST_VERSION" || name == "QNX_TARGET_VERSION")
|
||||
{
|
||||
if (Sys.getEnv (name) != null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
value = StringTools.replace (value, "$BASE_DIR", ioDefines.get ("BLACKBERRY_NDK_ROOT"));
|
||||
value = StringTools.replace (value, "%BASE_DIR%", ioDefines.get ("BLACKBERRY_NDK_ROOT"));
|
||||
value = StringTools.replace (value, "$TARGET", "qnx6");
|
||||
value = StringTools.replace (value, "%TARGET%", "qnx6");
|
||||
value = StringTools.replace (value, "$QNX_HOST_VERSION", Sys.getEnv("QNX_HOST_VERSION"));
|
||||
value = StringTools.replace (value, "$QNX_TARGET_VERSION", Sys.getEnv("QNX_TARGET_VERSION"));
|
||||
value = StringTools.replace (value, "%QNX_HOST_VERSION%", Sys.getEnv("QNX_HOST_VERSION"));
|
||||
value = StringTools.replace (value, "%QNX_TARGET_VERSION%", Sys.getEnv("QNX_TARGET_VERSION"));
|
||||
}
|
||||
ioDefines.set(name,value);
|
||||
Sys.putEnv(name,value);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch( ex:Eof )
|
||||
{}
|
||||
fin.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.error("Could not find \"" + fileName + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
public static function setupMSVC(ioDefines:Hash<String>, in64:Bool, inArm64, isWinRT:Bool)
|
||||
{
|
||||
var detectMsvc = !ioDefines.exists("NO_AUTO_MSVC") &&
|
||||
!ioDefines.exists("HXCPP_MSVC_CUSTOM");
|
||||
|
||||
if (ioDefines.exists("HXCPP_MSVC_VER"))
|
||||
{
|
||||
var val = ioDefines.get("HXCPP_MSVC_VER");
|
||||
if (val=="")
|
||||
detectMsvc = false;
|
||||
else
|
||||
{
|
||||
var ival = Std.parseInt(ioDefines.get("HXCPP_MSVC_VER"));
|
||||
if (ival>0)
|
||||
{
|
||||
var varName = "VS" + ival+ "COMNTOOLS";
|
||||
var where = Sys.getEnv(varName);
|
||||
if (where==null)
|
||||
{
|
||||
for (env in Sys.environment().keys())
|
||||
{
|
||||
if (env.substr(0,2)=="VS")
|
||||
{
|
||||
Log.info("Found VS variable: " + env);
|
||||
//Sys.println("Found VS variable " + env);
|
||||
}
|
||||
}
|
||||
Log.error("Could not find specified MSVC version: " + ival);
|
||||
//throw "Could not find specified MSVC version " + ival;
|
||||
}
|
||||
ioDefines.set("HXCPP_MSVC", where );
|
||||
Sys.putEnv("HXCPP_MSVC", where);
|
||||
Log.info("", 'Using MSVC Ver $ival in $where ($varName)');
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.info("", 'Using specified MSVC Ver $val');
|
||||
ioDefines.set("HXCPP_MSVC", val );
|
||||
Sys.putEnv("HXCPP_MSVC", val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (detectMsvc)
|
||||
{
|
||||
var extra:String = "";
|
||||
if (isWinRT)
|
||||
extra += "-winrt";
|
||||
if (inArm64)
|
||||
extra += "-arm64";
|
||||
else if (in64)
|
||||
extra += "64";
|
||||
var xpCompat = false;
|
||||
if (ioDefines.exists("HXCPP_WINXP_COMPAT"))
|
||||
{
|
||||
Sys.putEnv("HXCPP_WINXP_COMPAT","1");
|
||||
xpCompat = true;
|
||||
}
|
||||
Sys.putEnv("msvc_host_arch", ioDefines.exists("windows_arm_host") ? "x86" : "x64" );
|
||||
|
||||
var vc_setup_proc = new Process("cmd.exe", ["/C", BuildTool.HXCPP + "\\toolchain\\msvc" + extra + "-setup.bat" ]);
|
||||
var vars_found = false;
|
||||
var error_string = "";
|
||||
var output = new Array<String>();
|
||||
try{
|
||||
while(true)
|
||||
{
|
||||
var str = vc_setup_proc.stdout.readLine();
|
||||
if (str=="HXCPP_VARS")
|
||||
vars_found = true;
|
||||
else if (!vars_found)
|
||||
{
|
||||
if (str.substr(0,5)=="Error" || ~/missing/.match(str) )
|
||||
error_string = str;
|
||||
|
||||
output.push(str);
|
||||
}
|
||||
else
|
||||
{
|
||||
var pos = str.indexOf("=");
|
||||
var name = str.substr(0,pos);
|
||||
switch(name.toLowerCase())
|
||||
{
|
||||
case "path", "vcinstalldir", "windowssdkdir","framework35version",
|
||||
"frameworkdir", "frameworkdir32", "frameworkversion",
|
||||
"frameworkversion32", "devenvdir", "include", "lib", "libpath", "hxcpp_xp_define",
|
||||
"hxcpp_hack_pdbsrv"
|
||||
:
|
||||
var value = str.substr(pos+1);
|
||||
ioDefines.set(name,value);
|
||||
Log.v(' msvs $name=$value');
|
||||
Sys.putEnv(name,value);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e:Dynamic) {
|
||||
};
|
||||
|
||||
vc_setup_proc.exitCode();
|
||||
vc_setup_proc.close();
|
||||
if (!vars_found || error_string!="")
|
||||
{
|
||||
for (o in output)
|
||||
{
|
||||
Log.info(o);
|
||||
//BuildTool.println(o);
|
||||
}
|
||||
if (error_string!="")
|
||||
{
|
||||
Log.error (error_string);
|
||||
//throw(error_string);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.info("Missing HXCPP_VARS");
|
||||
//BuildTool.println("Missing HXCPP_VARS");
|
||||
}
|
||||
|
||||
Log.error("Could not automatically setup MSVC");
|
||||
//throw("Could not automatically setup MSVC");
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var proc = new Process("cl.exe",[]);
|
||||
var str = proc.stderr.readLine();
|
||||
proc.close();
|
||||
if (str>"")
|
||||
{
|
||||
Log.v("MSVC output:" + str);
|
||||
var reg = ~/(\d{2})\.\d+/i;
|
||||
if (reg.match(str))
|
||||
{
|
||||
var cl_version = Std.parseInt(reg.matched(1));
|
||||
Log.info("", "Using MSVC version: " + cl_version);
|
||||
ioDefines.set("MSVC_VER", cl_version+"");
|
||||
if (cl_version>=17)
|
||||
ioDefines.set("MSVC17+","1");
|
||||
if (cl_version>=18)
|
||||
ioDefines.set("MSVC18+","1");
|
||||
if (cl_version==19)
|
||||
ioDefines.set("MSVC19","1");
|
||||
BuildTool.sAllowNumProcs = cl_version >= 14;
|
||||
var threads = BuildTool.getThreadCount();
|
||||
if (threads>1 && cl_version>=18)
|
||||
ioDefines.set("HXCPP_FORCE_PDB_SERVER","1");
|
||||
}
|
||||
}
|
||||
} catch(e:Dynamic){}
|
||||
//if (cl_version!="") BuildTool.println("Using cl version: " + cl_version);
|
||||
}
|
||||
|
||||
static function toPath(inPath:String)
|
||||
{
|
||||
if (!BuildTool.isWindows)
|
||||
return inPath;
|
||||
var bits = inPath.split("/");
|
||||
return bits.join("\\");
|
||||
}
|
||||
}
|
29
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/Stripper.hx
Normal file
29
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/Stripper.hx
Normal file
@ -0,0 +1,29 @@
|
||||
class Stripper
|
||||
{
|
||||
public var mExe:String;
|
||||
public var mFlags:Array<String>;
|
||||
|
||||
public function new(inExe:String)
|
||||
{
|
||||
mFlags = [];
|
||||
mExe = inExe;
|
||||
}
|
||||
|
||||
public function strip(inTarget:String)
|
||||
{
|
||||
var args = new Array<String>();
|
||||
args = args.concat(mFlags);
|
||||
args.push(inTarget);
|
||||
|
||||
var split = mExe.split(" ");
|
||||
var exe = split.shift();
|
||||
args = split.concat(args);
|
||||
|
||||
var result = ProcessManager.runCommand("", exe, args);
|
||||
if (result!=0)
|
||||
{
|
||||
Tools.exit(result);
|
||||
//throw "Error : " + result + " - build cancelled";
|
||||
}
|
||||
}
|
||||
}
|
106
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/Target.hx
Normal file
106
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/Target.hx
Normal file
@ -0,0 +1,106 @@
|
||||
class Target
|
||||
{
|
||||
public var mBuildDir:String;
|
||||
public var mOutput:String;
|
||||
public var mOutputDir:String;
|
||||
public var mTool:String;
|
||||
public var mToolID:String;
|
||||
private var mExt:String;
|
||||
public var mFullOutputName:String;
|
||||
public var mFullUnstrippedName:String;
|
||||
|
||||
// These attributes are merged by the "merge" command
|
||||
public var mFiles:Array<File>;
|
||||
public var mFileGroups:Array<FileGroup>;
|
||||
public var mDepends:Array<String>;
|
||||
public var mSubTargets:Array<String>;
|
||||
public var mAutoLibs:Array<String>;
|
||||
public var mLibs:Array<String>;
|
||||
public var mLibPaths:Array<String>;
|
||||
public var mFlags:Array<String>;
|
||||
public var mErrors:Array<String>;
|
||||
public var mDirs:Array<String>;
|
||||
|
||||
public function new(inOutput:String, inTool:String,inToolID:String)
|
||||
{
|
||||
mOutput = inOutput;
|
||||
mOutputDir = "";
|
||||
mBuildDir = "";
|
||||
mToolID = inToolID;
|
||||
mTool = inTool;
|
||||
mFiles = [];
|
||||
mDepends = [];
|
||||
mAutoLibs = [];
|
||||
mLibs = [];
|
||||
mLibPaths = [];
|
||||
mFlags = [];
|
||||
mExt = null;
|
||||
mFullOutputName = null;
|
||||
mSubTargets = [];
|
||||
mFileGroups = [];
|
||||
mFlags = [];
|
||||
mErrors=[];
|
||||
mDirs=[];
|
||||
}
|
||||
|
||||
public function merge(other:Target)
|
||||
{
|
||||
mFiles = mFiles.concat(other.mFiles);
|
||||
mFileGroups = mFileGroups.concat(other.mFileGroups);
|
||||
mDepends = mDepends.concat(other.mDepends);
|
||||
mSubTargets = mSubTargets.concat(other.mSubTargets);
|
||||
mLibPaths = mLibPaths.concat(other.mLibPaths);
|
||||
mAutoLibs = mAutoLibs.concat(other.mAutoLibs);
|
||||
mLibs = mLibs.concat(other.mLibs);
|
||||
mFlags = mFlags.concat(other.mFlags);
|
||||
mErrors = mErrors.concat(other.mErrors);
|
||||
mDirs = mDirs.concat(other.mDirs);
|
||||
}
|
||||
|
||||
public function toString() return mToolID;
|
||||
|
||||
public function getExt(inDefault:String)
|
||||
{
|
||||
return mExt==null ? inDefault : mExt;
|
||||
}
|
||||
|
||||
public function setExt(inExt:String)
|
||||
{
|
||||
mExt = inExt;
|
||||
}
|
||||
|
||||
public function addError(inError:String)
|
||||
{
|
||||
mErrors.push(inError);
|
||||
}
|
||||
|
||||
public function addFiles(inGroup:FileGroup, inAsLibrary:Bool)
|
||||
{
|
||||
inGroup.mAsLibrary = inGroup.mAsLibrary || inAsLibrary;
|
||||
mFiles = mFiles.concat([for(file in inGroup.mFiles) file]);
|
||||
mFileGroups.push(inGroup);
|
||||
}
|
||||
|
||||
public function checkError()
|
||||
{
|
||||
if (mErrors.length>0)
|
||||
{
|
||||
Log.error(mErrors.join(", "));
|
||||
//throw mErrors.join("/");
|
||||
}
|
||||
}
|
||||
|
||||
public function clean()
|
||||
{
|
||||
for(dir in mDirs)
|
||||
{
|
||||
Log.info("Remove " + dir + "...");
|
||||
PathManager.removeDirectory(dir);
|
||||
}
|
||||
}
|
||||
|
||||
public function getKey()
|
||||
{
|
||||
return mOutput + (mExt==null ? "" : mExt);
|
||||
}
|
||||
}
|
105
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/ThreadPool.hx
Executable file
105
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/ThreadPool.hx
Executable file
@ -0,0 +1,105 @@
|
||||
#if haxe4
|
||||
import sys.thread.Thread;
|
||||
import sys.thread.Mutex;
|
||||
#else
|
||||
#if neko
|
||||
import neko.vm.Thread;
|
||||
import neko.vm.Mutex;
|
||||
#else
|
||||
import cpp.vm.Thread;
|
||||
import cpp.vm.Mutex;
|
||||
#end
|
||||
#end
|
||||
|
||||
#if cpp
|
||||
import cpp.AtomicInt;
|
||||
#end
|
||||
|
||||
class ThreadPool
|
||||
{
|
||||
var threads:Array<Thread>;
|
||||
var mainThread:Thread;
|
||||
#if cpp
|
||||
var arrayIndex:AtomicInt;
|
||||
#else
|
||||
var arrayIndex:Int;
|
||||
#end
|
||||
var arrayCount:Int;
|
||||
|
||||
public var mutex:Mutex;
|
||||
|
||||
|
||||
public function new(inCount:Int)
|
||||
{
|
||||
mutex = new Mutex();
|
||||
mainThread = Thread.current();
|
||||
threads = [];
|
||||
for(i in 0...inCount)
|
||||
threads.push( Thread.create( function() threadLoop(i) ) );
|
||||
|
||||
// Is this needed?
|
||||
Tools.addOnExitHook( function(_) runJob(null) );
|
||||
}
|
||||
|
||||
function threadLoop(threadId:Int)
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
var job:Int->Void = Thread.readMessage(true);
|
||||
if (job==null)
|
||||
{
|
||||
mainThread.sendMessage("done");
|
||||
break;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
job(threadId);
|
||||
}
|
||||
catch (error:Dynamic)
|
||||
{
|
||||
if (BuildTool.threadExitCode!=0)
|
||||
BuildTool.setThreadError(-1);
|
||||
else
|
||||
Log.warn("Error in compile thread: " + error);
|
||||
}
|
||||
|
||||
mainThread.sendMessage("ok");
|
||||
}
|
||||
}
|
||||
|
||||
public function setArrayCount(inCount:Int)
|
||||
{
|
||||
arrayIndex = 0;
|
||||
arrayCount = inCount;
|
||||
}
|
||||
public function getNextIndex() : Int
|
||||
{
|
||||
#if cpp
|
||||
var index = AtomicInt.atomicInc( cpp.Pointer.addressOf(arrayIndex) );
|
||||
#else
|
||||
mutex.acquire();
|
||||
var index = arrayIndex++;
|
||||
mutex.release();
|
||||
#end
|
||||
|
||||
if (index<arrayCount)
|
||||
return index;
|
||||
return -1;
|
||||
}
|
||||
|
||||
public function runJob(job:Int->Void)
|
||||
{
|
||||
for(thread in threads)
|
||||
thread.sendMessage( job );
|
||||
for(i in 0...threads.length)
|
||||
Thread.readMessage(true);
|
||||
|
||||
// Already printed the error from the thread, just need to exit
|
||||
if (job!=null && BuildTool.threadExitCode!=0)
|
||||
Tools.exit(BuildTool.threadExitCode);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
14
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/Tools.hx
Normal file
14
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/Tools.hx
Normal file
@ -0,0 +1,14 @@
|
||||
class Tools {
|
||||
private static var onExit:Array<Int->Void> = [];
|
||||
|
||||
public static function addOnExitHook(fn:Int->Void) {
|
||||
onExit.push(fn);
|
||||
}
|
||||
|
||||
public static function exit(exitCode:Int) {
|
||||
for (hook in onExit) {
|
||||
hook(exitCode);
|
||||
}
|
||||
Sys.exit(exitCode);
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
-cpp cpp
|
||||
-main BuildTool
|
||||
-D HXCPP_STACK_TRACE
|
||||
-D HXCPP_STACK_LINE
|
||||
-D HXCPP_NEKO_BUILDTOOL=1
|
||||
-D destination=../../../bin/{BINDIR}/BuildTool{EXESUFFIX}
|
4
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/compile.hxml
Normal file
4
Kha/Backends/Kinc-hxcpp/khacpp/tools/hxcpp/compile.hxml
Normal file
@ -0,0 +1,4 @@
|
||||
-neko ../../hxcpp.n
|
||||
-main BuildTool
|
||||
-D neko_v1
|
||||
-debug
|
131
Kha/Backends/Kinc-hxcpp/khacpp/tools/run/RunMain.hx
Normal file
131
Kha/Backends/Kinc-hxcpp/khacpp/tools/run/RunMain.hx
Normal file
@ -0,0 +1,131 @@
|
||||
import sys.FileSystem;
|
||||
|
||||
class RunMain
|
||||
{
|
||||
public static function log(s:String) Sys.println(s);
|
||||
public static function showMessage()
|
||||
{
|
||||
var varName = "HXCPP_NONINTERACTIVE";
|
||||
var nonInteractive:Bool =Sys.getEnv(varName)!=null;
|
||||
if (!nonInteractive)
|
||||
for(arg in Sys.args())
|
||||
if (arg.indexOf("-D"+varName)==0 )
|
||||
nonInteractive = true;
|
||||
|
||||
var dir = Sys.getCwd();
|
||||
|
||||
if (nonInteractive)
|
||||
{
|
||||
Sys.println('HXCPP in $dir is missing hxcpp.n');
|
||||
Sys.exit(-1);
|
||||
}
|
||||
|
||||
log('This version of hxcpp ($dir) appears to be a source/developement version.');
|
||||
log("Before this can be used, you need to:");
|
||||
log(" 1. Rebuild the main command-line tool, this can be done with:");
|
||||
log(" cd tools/hxcpp");
|
||||
log(" haxe compile.hxml");
|
||||
log(" 2. FOR HXCPP API < 330:");
|
||||
log(" Build the binaries appropriate to your system(s), this can be done with:");
|
||||
log(" cd project");
|
||||
log(" neko build.n");
|
||||
|
||||
var gotUserResponse = false;
|
||||
sys.thread.Thread.create(function() {
|
||||
Sys.sleep(30);
|
||||
if (!gotUserResponse)
|
||||
{
|
||||
Sys.println("\nTimeout waiting for response.");
|
||||
Sys.println("Can't continue without hxcpp.n");
|
||||
Sys.exit(-1);
|
||||
}
|
||||
} );
|
||||
|
||||
while(true)
|
||||
{
|
||||
Sys.print("\nWould you like to do this now [y/n]");
|
||||
var code = Sys.getChar(true);
|
||||
gotUserResponse = true;
|
||||
if (code<=32)
|
||||
break;
|
||||
var answer = String.fromCharCode(code);
|
||||
if (answer=="y" || answer=="Y")
|
||||
{
|
||||
log("");
|
||||
setup();
|
||||
if (!executeHxcpp())
|
||||
break;
|
||||
return;
|
||||
}
|
||||
if (answer=="n" || answer=="N")
|
||||
break;
|
||||
}
|
||||
|
||||
Sys.println("\nCan't continue without hxcpp.n");
|
||||
Sys.exit(-1);
|
||||
}
|
||||
|
||||
public static function setup()
|
||||
{
|
||||
log("Compiling hxcpp tool...");
|
||||
run("tools/hxcpp","haxe", [ "compile.hxml"]);
|
||||
log("Initial setup complete.");
|
||||
}
|
||||
|
||||
public static function run(dir:String, command:String, args:Array<String>)
|
||||
{
|
||||
var oldDir:String = "";
|
||||
if (dir!="")
|
||||
{
|
||||
oldDir = Sys.getCwd();
|
||||
Sys.setCwd(dir);
|
||||
}
|
||||
Sys.command(command,args);
|
||||
if (oldDir!="")
|
||||
Sys.setCwd(oldDir);
|
||||
}
|
||||
|
||||
public static function executeHxcpp()
|
||||
{
|
||||
if (!sys.FileSystem.exists("./hxcpp.n"))
|
||||
return false;
|
||||
|
||||
if (Sys.args().indexOf("-DHXCPP_NEKO_BUILDTOOL=1")<0)
|
||||
{
|
||||
var os = Sys.systemName();
|
||||
var isWindows = (new EReg("window","i")).match(os);
|
||||
var isMac = (new EReg("mac","i")).match(os);
|
||||
var isLinux = (new EReg("linux","i")).match(os);
|
||||
var binDir = isWindows ? "Windows64" : isMac ? "Mac64" : isLinux ? "Linux64" : null;
|
||||
if (binDir!=null)
|
||||
{
|
||||
var compiled = 'bin/$binDir/BuildTool';
|
||||
if (isWindows)
|
||||
compiled += ".exe";
|
||||
if (FileSystem.exists(compiled))
|
||||
{
|
||||
var dotN = FileSystem.stat("hxcpp.n").mtime.getTime();
|
||||
var dotExe= FileSystem.stat(compiled).mtime.getTime();
|
||||
if (dotExe<dotN)
|
||||
{
|
||||
var path = Sys.getCwd() + compiled;
|
||||
Sys.println('Warning - $path file is out-of-date. Please delete or rebuild.');
|
||||
}
|
||||
else
|
||||
{
|
||||
Sys.exit( Sys.command( compiled, Sys.args() ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
neko.vm.Loader.local().loadModule("./hxcpp.n");
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function main()
|
||||
{
|
||||
if (!executeHxcpp())
|
||||
showMessage();
|
||||
}
|
||||
}
|
4
Kha/Backends/Kinc-hxcpp/khacpp/tools/run/compile.hxml
Normal file
4
Kha/Backends/Kinc-hxcpp/khacpp/tools/run/compile.hxml
Normal file
@ -0,0 +1,4 @@
|
||||
-neko ../../run.n
|
||||
-main RunMain
|
||||
-D neko_v1
|
||||
-debug
|
51
Kha/Backends/Kinc-hxcpp/khacpp/tools/version/Write.hx
Normal file
51
Kha/Backends/Kinc-hxcpp/khacpp/tools/version/Write.hx
Normal file
@ -0,0 +1,51 @@
|
||||
import sys.io.File;
|
||||
|
||||
class Write
|
||||
{
|
||||
public static function main()
|
||||
{
|
||||
var args = Sys.args();
|
||||
var buildNumber = Std.parseInt(args[0]);
|
||||
if (buildNumber<1 || buildNumber==null)
|
||||
throw "Usage: Write buildNumber";
|
||||
|
||||
|
||||
var jsonFile = "haxelib.json";
|
||||
var lines = File.getContent(jsonFile).split("\n");
|
||||
var idx = 0;
|
||||
var versionMatch = ~/(.*"version"\s*:\s*")(.*)(".*)/;
|
||||
var found = false;
|
||||
var newVersion = "";
|
||||
while(idx<lines.length)
|
||||
{
|
||||
if (versionMatch.match(lines[idx]))
|
||||
{
|
||||
var parts = versionMatch.matched(2).split(".");
|
||||
if (parts.length==3)
|
||||
parts[2] = buildNumber+"";
|
||||
else
|
||||
parts.push(buildNumber+"");
|
||||
newVersion = parts.join(".");
|
||||
lines[idx]=versionMatch.matched(1) + newVersion + versionMatch.matched(3);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
if (!found)
|
||||
throw "Could not find version in " + jsonFile;
|
||||
|
||||
File.saveContent(jsonFile, lines.join("\n") );
|
||||
|
||||
var writeVersionFilename = "include/HxcppVersion.h";
|
||||
var define = "HXCPP_VERSION";
|
||||
var lines = [
|
||||
'#ifndef $define',
|
||||
'#define $define "$newVersion"',
|
||||
'#endif'
|
||||
];
|
||||
File.saveContent( writeVersionFilename, lines.join("\n") );
|
||||
|
||||
Sys.println("hxcpp_release=" + newVersion );
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user