Skip to content

Commit 7933fa1

Browse files
committed
new function for analyze crashs and other things
1 parent d3216d5 commit 7933fa1

12 files changed

Lines changed: 432 additions & 104 deletions

File tree

README.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,21 @@ Using this utility (Inspired by [HxCompileU](https://github.com/Slushi-Github/hx
77

88
This is inspired by an attempt by the [RetroNX Team](https://github.com/retronx-team) to use Haxe on the Nintendo Switch. I used part of the [original project](https://github.com/retronx-team/switch-haxe) for this, so credit goes to them for achieving this in the first place!
99

10-
**This project is being tested with Haxe 4.3.7 and a Nintendo Switch V2 with firmware 20.4.0 (AMS 1.9.4).**
10+
**This project is being tested with Haxe 4.3.6 and a Nintendo Switch V2 with firmware 20.4.0 and Atmosphère 1.9.5.**
1111

1212
Officially there are supported libraries to be used in conjunction with HaxeNXCompiler:
1313

1414
- [hx_libnx](https://github.com/Slushi-Github/hx_libnx): Haxe/hxcpp @:native bindings for libnx, the Nintendo Switch's homebrew library.
1515

1616
-----
1717

18+
## Current problems:
19+
20+
- Apparently there is no full support for `sys.net.Socket`.
21+
- Critical issue related to hxcpp and its garbage collector when the program ends, causing Atmosphère to crash sometimes.
22+
23+
-----
24+
1825
## How?
1926

2027
Well... Unlike the Wii U, where using hxcpp causes many problems, and to achieve that I had to use [Reflaxe/C++ (Amazing library!)](https://github.com/SomeRanDev/reflaxe.CPP) to be able to use Haxe on that console. With the Nintendo Switch, hxcpp compiles perfectly!
@@ -102,6 +109,14 @@ After that, you will get your executable ``HaxeNXCompiler`` in the "export" fold
102109

103110
-----
104111

112+
#### You can get errors from a log file using the following command:
113+
114+
``{haxeNXCompilerProgram} --crashAnalyzer`` or ``{haxeNXCompilerProgram} --ca``
115+
116+
**THIS IS TOO EXPERIMENTAL!**
117+
118+
-----
119+
105120
and that's it! if your compilation was successful on both Haxe and Nintendo Switch side, your ``.nro``, ``.ncap`` and ``.elf`` files will be in ``yourOutputFolder/switchFiles``.
106121

107122

src/JsonFile.hx

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ typedef JsonStruct = {
5454
deleteTempFiles:Bool,
5555
extraLibs:Array<String>,
5656
projectDefines:Array<String>,
57+
makeFileMaxJobs:Int,
5758
}
5859

5960
/**
@@ -66,7 +67,10 @@ class JsonFile {
6667
*/
6768
public static function checkJson():Bool {
6869
try {
69-
if (FileSystem.exists(SlushiUtils.getPathFromCurrentTerminal() + "/haxeNXConfig.json")) {
70+
if (!FileSystem.exists(SlushiUtils.getPathFromCurrentTerminal() + "/haxeNXConfig.json")) {
71+
return false;
72+
}
73+
else if (FileSystem.exists(SlushiUtils.getPathFromCurrentTerminal() + "/haxeNXConfig.json")) {
7074
var jsonFile:JsonStruct = JsonFile.getJson();
7175
if (jsonFile == null) {
7276
throw "JSON file is invalid, please check it";
@@ -89,28 +93,32 @@ class JsonFile {
8993
var jsonContent:Dynamic = Json.parse(File.getContent(SlushiUtils.getPathFromCurrentTerminal() + "/haxeNXConfig.json"));
9094

9195
var jsonStructure:JsonStruct = {
92-
programVersion: jsonContent.programVersion,
96+
programVersion: jsonContent.programVersion ?? Main.version,
9397
haxeConfig: {
94-
sourceDir: jsonContent.haxeConfig.sourceDir,
95-
hxMain: jsonContent.haxeConfig.hxMain,
96-
cppOutDir: jsonContent.haxeConfig.cppOutDir,
97-
debugMode: jsonContent.haxeConfig.debugMode ?? false,
98-
othersOptions: jsonContent.haxeConfig.othersOptions,
99-
errorReportingStyle: jsonContent.haxeConfig.errorReportingStyle ?? "pretty",
98+
sourceDir: jsonContent.haxeConfig?.sourceDir,
99+
hxMain: jsonContent.haxeConfig?.hxMain ?? "Main",
100+
cppOutDir: jsonContent.haxeConfig?.cppOutDir ?? "build",
101+
debugMode: jsonContent.haxeConfig?.debugMode ?? false,
102+
othersOptions: jsonContent.haxeConfig?.othersOptions ?? new Array<String>(),
103+
errorReportingStyle: jsonContent.haxeConfig?.errorReportingStyle ?? "pretty",
100104
},
101105
switchConfig: {
102-
projectName: jsonContent.switchConfig.projectName ?? "Project",
103-
consoleIP: jsonContent.switchConfig.consoleIP ?? "0.0.0.0",
104-
appVersion: jsonContent.switchConfig.appVersion ?? "1.0.0",
105-
appTitle: jsonContent.switchConfig.appTitle ?? "Project",
106-
appAuthor: jsonContent.switchConfig.appAuthor ?? "None",
106+
projectName: jsonContent.switchConfig?.projectName ?? "Project",
107+
consoleIP: jsonContent.switchConfig?.consoleIP ?? "0.0.0.0",
108+
appVersion: jsonContent.switchConfig?.appVersion ?? "1.0.0",
109+
appTitle: jsonContent.switchConfig?.appTitle ?? "Project",
110+
appAuthor: jsonContent.switchConfig?.appAuthor ?? "None",
107111
},
108112
deleteTempFiles: jsonContent.deleteTempFiles ?? false,
109-
extraLibs: jsonContent.extraLibs,
110-
projectDefines: jsonContent.projectDefines,
113+
extraLibs: jsonContent.extraLibs ?? new Array<String>(),
114+
projectDefines: jsonContent.projectDefines ?? new Array<String>(),
115+
makeFileMaxJobs: jsonContent.makeFileMaxJobs ?? 2,
111116
};
112117
return jsonStructure;
113118
}
119+
else {
120+
SlushiUtils.printMsg("[haxeNXConfig.json] not found!", ERROR);
121+
}
114122
} catch (e) {
115123
throw "Error loading [haxeNXConfig.json]: " + e;
116124
}
@@ -148,6 +156,7 @@ class JsonFile {
148156
deleteTempFiles: true,
149157
extraLibs: [],
150158
projectDefines: [],
159+
makeFileMaxJobs: 2,
151160
};
152161

153162
try {
@@ -173,7 +182,7 @@ class JsonFile {
173182
var defines:String = "";
174183

175184
defines += "-D HAXENXCOMPILER_VERSION=\\\"" + Main.version + "\\\" ";
176-
defines += "-D HAXENXCOMPILER_JSON_SWITCH_PROJECTNAME=\\\"" + jsonFile.switchConfig.projectName + "\\\" ";
185+
defines += "-D HAXENXCOMPILER_JSON_SWITCH_PROJECTNAME=\\\"" + jsonFile.switchConfig?.projectName + "\\\" ";
177186

178187
var dateNow:Date = Date.now();
179188
var dateString = dateNow.getHours() + ":" + StringTools.lpad(dateNow.getMinutes() + "", "0", 2) + ":"

src/Main.hx

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
package src;
88

9+
import src.utils.CrashAnalyzer;
910
import haxe.CallStack;
1011

1112
import src.SlushiUtils;
@@ -23,8 +24,8 @@ import src.utils.DevKitProUtils;
2324
* Author: Slushi
2425
*/
2526
class Main {
26-
public static var haxenxcompilerString = "\x1b[38;5;214mHaxe\033[0m\x1b[38;5;81mN\x1b[38;5;1mX\033[0mCompiler (Based on \x1b[38;5;214mHx\033[0mCompile\x1b[38;5;74mU\033[0m)";
27-
public static final version:String = "2.0.0";
27+
public static final haxenxcompilerString = "\x1b[38;5;214mHaxe\033[0m\x1b[38;5;81mN\x1b[38;5;1mX\033[0mCompiler (Based on \x1b[38;5;214mHx\033[0mCompile\x1b[38;5;74mU\033[0m)";
28+
public static final version:String = "2.1.0";
2829
static var stdin = Sys.stdin();
2930
static var stdout = Sys.stdout();
3031
static var args = Sys.args();
@@ -40,23 +41,26 @@ class Main {
4041
SlushiUtils.printMsg('$haxenxcompilerString v$version -- Created by \033[96mSlushi\033[0m', NONE);
4142
}
4243

43-
if (JsonFile.checkJson() == false) {
44-
return;
44+
if (args[0] != "--import" && args[0] != "--i" && args[0] != "--prepare" && args[0] != "--p") {
45+
// if (!JsonFile.checkJson())
46+
return;
4547
}
4648

4749
switch (args[0]) {
4850
case "--prepare" | "--p":
49-
JsonFile.createJson();
51+
SlushiUtils.prepareProject(false, "");
5052
case "--import" | "--i":
51-
JsonFile.importJSON(args[1]);
53+
SlushiUtils.prepareProject(true, args[1]);
5254
case "--compile" | "--c":
5355
MainCompiler.start(args[1], args[2]);
5456
case "--searchProblem" | "--sp":
5557
DevKitProUtils.searchProblem(args[1]);
58+
case "--crashAnalyzer" | "--ca":
59+
CrashAnalyzer.initWithFile();
5660
case "--send" | "--s":
5761
DevKitProUtils.send(args[1]);
5862
case "--help" | "--h":
59-
SlushiUtils.printMsg("Usage: HaxeNXCompiler [command]\nCommands:\n\t--prepare, --p: Creates a new haxeNXConfig.json in the current directory.\n\t--import, --i \033[3mHAXE_LIB\033[0m: Imports a JSON file from a Haxe lib to the current directory \n\t--compile, --c: Compiles the project. \n\t\tAdd \"--debug\" to enable Haxe debug mode \n\t--searchProblem, --sp \033[3mLINE_ADDRESS\033[0m: search for a line of code in the [.elf] file from a line address of some log using devkitA64's aarch64-none-elf-addr2line program \n\t--send, --s: Sends the .nro file to the Nintendo Switch using DevKitPro's nxlink program \n\t\tAdd \"--server\" or \"--s\" to start the a cosnole server via nxlink\n\t--version, --v: Shows the version of the compiler\n\t--help, --h: Shows this message",
63+
SlushiUtils.printMsg("Usage: HaxeNXCompiler [command]\nCommands:\n\t--prepare, --p: Creates a new haxeNXConfig.json in the current directory.\n\t--import, --i \033[3mHAXE_LIB\033[0m: Imports a JSON file from a Haxe lib to the current directory \n\t--compile, --c: Compiles the project. \n\t\tAdd \"--debug\" to enable Haxe debug mode \n\t--searchProblem, --sp \033[3mLINE_ADDRESS\033[0m: search for a line of code in the [.elf] file from a line address of some log using devkitA64's aarch64-none-elf-addr2line program \n\t--send, --s: Sends the .nro file to the Nintendo Switch using DevKitPro's nxlink program \n\t\tAdd \"--server\" or \"--s\" to start the a cosnole server via DevKitPro's nxlink program\n\t--version, --v: Shows the version of the compiler\n\t--help, --h: Shows this message",
6064
NONE);
6165
default:
6266
SlushiUtils.printMsg("Invalid argument: [" + args.join(" ") + "], use \033[3m--help\033[0m argument for more information", NONE);

src/SlushiUtils.hx

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,4 +125,38 @@ class SlushiUtils {
125125
}
126126
}
127127
}
128+
129+
130+
/**
131+
* Prepares the new project, first it checks if the user has installed DevKitPro and DevKitA64
132+
* @param imported
133+
* @param lib
134+
*/
135+
public static function prepareProject(imported:Bool, ?lib:String):Void {
136+
var fail:Bool = false;
137+
var devkitproEnv = Sys.getEnv("DEVKITPRO");
138+
139+
SlushiUtils.printMsg("Preparing project...", PROCESSING);
140+
141+
if (devkitproEnv == null || !FileSystem.exists(devkitproEnv)) {
142+
SlushiUtils.printMsg("DEVKITPRO environment variable not found", ERROR);
143+
fail = true;
144+
}
145+
else if ((devkitproEnv == null || !FileSystem.exists(devkitproEnv + "/devkitA64")) && !fail) {
146+
SlushiUtils.printMsg("DevkitA64 not found", ERROR);
147+
fail = true;
148+
}
149+
150+
if (fail) {
151+
SlushiUtils.printMsg("Failed to prepare project. Can't find DevKitPro or DevKitA64, please install them (Or add them to your PATH) and try again:\n\thttps://devkitpro.org/wiki/devkitPro_pacman", NONE);
152+
return;
153+
}
154+
155+
if (imported) {
156+
JsonFile.importJSON(lib);
157+
}
158+
else {
159+
JsonFile.createJson();
160+
}
161+
}
128162
}

src/compilers/HaxeCompiler.hx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ class HaxeCompiler {
8989
-D HAXENXCOMPILER_VERSION="${Main.version}"
9090
-D HAXENXCOMPILER_JSON_SWITCH_PROJECTNAME="${jsonFile.switchConfig.projectName}"
9191
${finalHxDefines().main}
92+
${finalHxDefines().hxlibs}
9293
# Extra options
9394
${finalOtherOptions()}
9495
${finalHxDefines().hxDef}
@@ -166,8 +167,8 @@ class HaxeCompiler {
166167
return libs;
167168
}
168169

169-
static function finalHxDefines():{main:String, hxDef:String} {
170-
var defines = {main: "", hxDef: ""};
170+
static function finalHxDefines():{main:String, hxDef:String, hxlibs:String} {
171+
var defines = {main: "", hxDef: "", hxlibs: ""};
171172

172173
for (define in Defines.parseHXDefines().main) {
173174
defines.main += define + "\n\t";
@@ -177,6 +178,10 @@ class HaxeCompiler {
177178
defines.hxDef += define + "\n\t";
178179
}
179180

181+
for (define in Defines.parseHXDefines().hxlibs) {
182+
defines.hxlibs += define + "\n\t";
183+
}
184+
180185
return defines;
181186
}
182187

src/compilers/MainCompiler.hx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ class MainCompiler {
3030
* Starts the compilation of the project.
3131
*/
3232
public static function start(arg2:String, arg3:String):Void {
33+
34+
if (!FileSystem.exists(SlushiUtils.getPathFromCurrentTerminal() + "/haxeNXConfig.json")) {
35+
SlushiUtils.printMsg("Can't find [haxeNXConfig.json]", ERROR);
36+
return;
37+
}
38+
3339
var jsonVersion:String = JsonFile.getJson().programVersion;
3440
var forced:Bool = jsonVersion.endsWith(":forced");
3541
var versionStr = forced ? jsonVersion.split(":")[0] : jsonVersion;

src/compilers/NXLinker.hx

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,21 @@ using StringTools;
2020

2121
/**
2222
* The NXLinker class is used to link the project to Nintendo Switch
23-
* using [DevKitPro](https://devkitpro.org) MakeFile.
23+
* using [DevKitPro](https://devkitpro.org) MakeFile as a placeholder
2424
*
2525
* Author: Slushi.
2626
*/
2727
class NXLinker {
2828
static var jsonFile:JsonStruct = JsonFile.getJson();
2929
static var exitCodeNum:Int = 0;
3030

31+
/**
32+
* The maximum number of jobs that can be executed in parallel
33+
*
34+
* For now it's hardcoded to 2
35+
*/
36+
static var maxJobs:Int = 2;
37+
3138
public static function init() {
3239
if (HaxeCompiler.getExitCode() != 0) {
3340
return;
@@ -38,13 +45,33 @@ class NXLinker {
3845
return;
3946
}
4047

48+
if (jsonFile.switchConfig == null) {
49+
SlushiUtils.printMsg("Error loading [haxeNXConfig.json -> switchConfig]", ERROR);
50+
return;
51+
}
52+
53+
if (jsonFile.haxeConfig == null) {
54+
SlushiUtils.printMsg("Error loading [haxeNXConfig.json -> haxeConfig]", ERROR);
55+
return;
56+
}
57+
58+
if (jsonFile.haxeConfig?.cppOutDir == null) {
59+
SlushiUtils.printMsg("Error loading [haxeNXConfig.json -> haxeConfig.cppOutDir]", ERROR);
60+
return;
61+
}
62+
4163
// Check if all required fields are set
42-
if (jsonFile.switchConfig.projectName == "") {
64+
if (jsonFile.switchConfig?.projectName == "") {
4365
SlushiUtils.printMsg("projectName in [haxeNXConfig.json -> switchConfig.projectName] is empty", ERROR);
4466
exitCodeNum = 3;
4567
return;
4668
}
4769

70+
maxJobs = jsonFile.makeFileMaxJobs ?? 2;
71+
if (maxJobs <= 0) {
72+
maxJobs = 2;
73+
}
74+
4875
SlushiUtils.printMsg("Trying to compile to a \x1b[38;5;1mNintendo Switch\033[0m project -> \x1b[38;5;110m[" + jsonFile.switchConfig.projectName + "]\033[0m...", PROCESSING);
4976

5077
SlushiUtils.printMsg("Creating Makefile...", PROCESSING);
@@ -122,10 +149,10 @@ class NXLinker {
122149
return;
123150
}
124151

125-
SlushiUtils.printMsg("Compiling to ARM64/\x1b[38;5;1mNintendo Switch\033[0m...\n------------------", PROCESSING);
152+
SlushiUtils.printMsg("Compiling to ARM64/\x1b[38;5;1mNintendo Switch\033[0m using " + maxJobs + " threads...\n------------------", PROCESSING);
126153

127154
var startTime:Float = Sys.time();
128-
var compileProcess = Sys.command("make");
155+
var compileProcess = Sys.command("make" + " -j" + maxJobs);
129156

130157
if (compileProcess != 0) {
131158
SlushiUtils.printMsg("\x1b[38;5;1m------------------\033[0m", NONE);

0 commit comments

Comments
 (0)