CLI: Implement --select-outpus option (#128)
This commit is contained in:
@@ -25,6 +25,13 @@ namespace Il2CppInspector.CLI
|
|||||||
{
|
{
|
||||||
public class App
|
public class App
|
||||||
{
|
{
|
||||||
|
// Default file paths for output modules
|
||||||
|
private const string CsOutDefault = "types.cs";
|
||||||
|
private const string PyOutDefault = "il2cpp.py";
|
||||||
|
private const string CppOutDefault = "cpp";
|
||||||
|
private const string JsonOutDefault = "metadata.json";
|
||||||
|
private const string DllOutDefault = "dll";
|
||||||
|
|
||||||
private class Options
|
private class Options
|
||||||
{
|
{
|
||||||
[Option('i', "bin", Required = false, Separator = ',', HelpText = "IL2CPP binary, APK, AAB, XAPK, IPA, Zip or Linux process map text input file(s) (single file or comma-separated list for split APKs)", Default = new[] { "libil2cpp.so" })]
|
[Option('i', "bin", Required = false, Separator = ',', HelpText = "IL2CPP binary, APK, AAB, XAPK, IPA, Zip or Linux process map text input file(s) (single file or comma-separated list for split APKs)", Default = new[] { "libil2cpp.so" })]
|
||||||
@@ -36,19 +43,22 @@ namespace Il2CppInspector.CLI
|
|||||||
[Option("image-base", Required = false, HelpText = "For ELF memory dumps, the image base address in hex (ignored for standard ELF files and other file formats)")]
|
[Option("image-base", Required = false, HelpText = "For ELF memory dumps, the image base address in hex (ignored for standard ELF files and other file formats)")]
|
||||||
public string ElfImageBaseString { get; set; }
|
public string ElfImageBaseString { get; set; }
|
||||||
|
|
||||||
[Option('c', "cs-out", Required = false, HelpText = "C# output file (when using single-file layout) or path (when using per namespace, assembly or class layout)", Default = "types.cs")]
|
[Option("select-outputs", Required = false, HelpText = "Only generate outputs specified on the command line (use --cs-out, --py-out, --cpp-out, --json-out, --dll-out to select outputs). If not specified, all outputs are generated")]
|
||||||
|
public bool SpecifiedOutputsOnly { get; set; }
|
||||||
|
|
||||||
|
[Option('c', "cs-out", Required = false, HelpText = "(Default: " + CsOutDefault + ") C# output file (when using single-file layout) or path (when using per namespace, assembly or class layout)")]
|
||||||
public string CSharpOutPath { get; set; }
|
public string CSharpOutPath { get; set; }
|
||||||
|
|
||||||
[Option('p', "py-out", Required = false, HelpText = "Python script output file", Default = "il2cpp.py")]
|
[Option('p', "py-out", Required = false, HelpText = "(Default: " + PyOutDefault + ") Python script output file")]
|
||||||
public string PythonOutFile { get; set; }
|
public string PythonOutFile { get; set; }
|
||||||
|
|
||||||
[Option('h', "cpp-out", Required = false, HelpText = "C++ scaffolding / DLL injection project output path", Default = "cpp")]
|
[Option('h', "cpp-out", Required = false, HelpText = "(Default: " + CppOutDefault + ") C++ scaffolding / DLL injection project output path")]
|
||||||
public string CppOutPath { get; set; }
|
public string CppOutPath { get; set; }
|
||||||
|
|
||||||
[Option('o', "json-out", Required = false, HelpText = "JSON metadata output file", Default = "metadata.json")]
|
[Option('o', "json-out", Required = false, HelpText = "(Default: " + JsonOutDefault + ") JSON metadata output file")]
|
||||||
public string JsonOutPath { get; set; }
|
public string JsonOutPath { get; set; }
|
||||||
|
|
||||||
[Option('d', "dll-out", Required = false, HelpText = ".NET assembly shim DLLs output path", Default = "dll")]
|
[Option('d', "dll-out", Required = false, HelpText = "(Default: " + DllOutDefault + ") .NET assembly shim DLLs output path")]
|
||||||
public string DllOutPath { get; set; }
|
public string DllOutPath { get; set; }
|
||||||
|
|
||||||
[Option("metadata-out", Required = false, HelpText = "IL2CPP metadata file output (for extracted or decrypted metadata; ignored otherwise)")]
|
[Option("metadata-out", Required = false, HelpText = "IL2CPP metadata file output (for extracted or decrypted metadata; ignored otherwise)")]
|
||||||
@@ -178,13 +188,25 @@ namespace Il2CppInspector.CLI
|
|||||||
}
|
}
|
||||||
catch (Exception ex) when (ex is InvalidOperationException || ex is DirectoryNotFoundException) {
|
catch (Exception ex) when (ex is InvalidOperationException || ex is DirectoryNotFoundException) {
|
||||||
Console.Error.WriteLine(ex.Message);
|
Console.Error.WriteLine(ex.Message);
|
||||||
Environment.Exit(1);
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check plugin options are valid
|
// Check plugin options are valid
|
||||||
if (!PluginOptions.ParsePluginOptions(options.PluginOptions, PluginOptions.GetPluginOptionTypes()))
|
if (!PluginOptions.ParsePluginOptions(options.PluginOptions, PluginOptions.GetPluginOptionTypes()))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
// Make sure at least one output is specified if the user has restricted outputs
|
||||||
|
if (options.SpecifiedOutputsOnly
|
||||||
|
&& options.CSharpOutPath == null
|
||||||
|
&& options.PythonOutFile == null
|
||||||
|
&& options.CppOutPath == null
|
||||||
|
&& options.JsonOutPath == null
|
||||||
|
&& options.DllOutPath == null) {
|
||||||
|
Console.Error.WriteLine("At least one output must be specified when using --select-outputs.");
|
||||||
|
Console.Error.WriteLine("Use --cs-out, --py-out, --cpp-out, --json-out and/or --dll-out, or omit --select-outputs to generate all output types");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// Check script target is valid
|
// Check script target is valid
|
||||||
if (!PythonScript.GetAvailableTargets().Contains(options.ScriptTarget)) {
|
if (!PythonScript.GetAvailableTargets().Contains(options.ScriptTarget)) {
|
||||||
Console.Error.WriteLine($"Script target {options.ScriptTarget} is invalid.");
|
Console.Error.WriteLine($"Script target {options.ScriptTarget} is invalid.");
|
||||||
@@ -345,22 +367,44 @@ namespace Il2CppInspector.CLI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Determine which outputs to generate
|
||||||
|
var GenerateCS = !string.IsNullOrEmpty(options.CSharpOutPath);
|
||||||
|
var GeneratePython = !string.IsNullOrEmpty(options.PythonOutFile);
|
||||||
|
var GenerateCpp = !string.IsNullOrEmpty(options.CppOutPath) || GeneratePython;
|
||||||
|
var GenerateJSON = !string.IsNullOrEmpty(options.JsonOutPath) || GeneratePython;
|
||||||
|
var GenerateDLL = !string.IsNullOrEmpty(options.DllOutPath);
|
||||||
|
|
||||||
|
if (!options.SpecifiedOutputsOnly)
|
||||||
|
GenerateCS = GeneratePython = GenerateCpp = GenerateJSON = GenerateDLL = true;
|
||||||
|
|
||||||
|
// Set defaults for outputs where the user hasn't specified a path
|
||||||
|
options.CSharpOutPath = options.CSharpOutPath ?? CsOutDefault;
|
||||||
|
options.PythonOutFile = options.PythonOutFile ?? PyOutDefault;
|
||||||
|
options.CppOutPath = options.CppOutPath ?? CppOutDefault;
|
||||||
|
options.JsonOutPath = options.JsonOutPath ?? JsonOutDefault;
|
||||||
|
options.DllOutPath = options.DllOutPath ?? DllOutDefault;
|
||||||
|
|
||||||
|
var NeedAppModel = GeneratePython | GenerateJSON | GenerateCpp;
|
||||||
|
|
||||||
// Write output files for each binary
|
// Write output files for each binary
|
||||||
int imageIndex = 0;
|
int imageIndex = 0;
|
||||||
foreach (var il2cpp in il2cppInspectors) {
|
foreach (var il2cpp in il2cppInspectors) {
|
||||||
Console.WriteLine($"Processing image {imageIndex} - {il2cpp.BinaryImage.Arch} / {il2cpp.BinaryImage.Bits}-bit");
|
Console.WriteLine($"Processing image {imageIndex} - {il2cpp.BinaryImage.Arch} / {il2cpp.BinaryImage.Bits}-bit");
|
||||||
|
|
||||||
// Create model
|
// Create type model
|
||||||
TypeModel model;
|
TypeModel model;
|
||||||
using (new Benchmark("Create .NET type model"))
|
using (new Benchmark("Create .NET type model"))
|
||||||
model = new TypeModel(il2cpp);
|
model = new TypeModel(il2cpp);
|
||||||
|
|
||||||
AppModel appModel;
|
// Create application model only if needed
|
||||||
|
AppModel appModel = null;
|
||||||
|
if (NeedAppModel)
|
||||||
using (new Benchmark("Create C++ application model")) {
|
using (new Benchmark("Create C++ application model")) {
|
||||||
appModel = new AppModel(model, makeDefaultBuild: false).Build(options.UnityVersion, options.CppCompiler);
|
appModel = new AppModel(model, makeDefaultBuild: false).Build(options.UnityVersion, options.CppCompiler);
|
||||||
}
|
}
|
||||||
|
|
||||||
// C# signatures output
|
// C# signatures output
|
||||||
|
if (GenerateCS)
|
||||||
using (new Benchmark("Generate C# code")) {
|
using (new Benchmark("Generate C# code")) {
|
||||||
var writer = new CSharpCodeStubs(model) {
|
var writer = new CSharpCodeStubs(model) {
|
||||||
ExcludedNamespaces = options.ExcludedNamespaces.ToList(),
|
ExcludedNamespaces = options.ExcludedNamespaces.ToList(),
|
||||||
@@ -410,16 +454,19 @@ namespace Il2CppInspector.CLI
|
|||||||
}
|
}
|
||||||
|
|
||||||
// C++ output
|
// C++ output
|
||||||
|
if (GenerateCpp)
|
||||||
using (new Benchmark("Generate C++ code")) {
|
using (new Benchmark("Generate C++ code")) {
|
||||||
new CppScaffolding(appModel).Write(getOutputPath(options.CppOutPath, "", imageIndex));
|
new CppScaffolding(appModel).Write(getOutputPath(options.CppOutPath, "", imageIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
// JSON output
|
// JSON output
|
||||||
|
if (GenerateJSON)
|
||||||
using (new Benchmark("Generate JSON metadata")) {
|
using (new Benchmark("Generate JSON metadata")) {
|
||||||
new JSONMetadata(appModel).Write(getOutputPath(options.JsonOutPath, "json", imageIndex));
|
new JSONMetadata(appModel).Write(getOutputPath(options.JsonOutPath, "json", imageIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Python script output
|
// Python script output
|
||||||
|
if (GeneratePython)
|
||||||
using (new Benchmark($"Generate {options.ScriptTarget} Python script")) {
|
using (new Benchmark($"Generate {options.ScriptTarget} Python script")) {
|
||||||
new PythonScript(appModel).WriteScriptToFile(
|
new PythonScript(appModel).WriteScriptToFile(
|
||||||
getOutputPath(options.PythonOutFile, "py", imageIndex),
|
getOutputPath(options.PythonOutFile, "py", imageIndex),
|
||||||
@@ -429,6 +476,7 @@ namespace Il2CppInspector.CLI
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DLL output
|
// DLL output
|
||||||
|
if (GenerateDLL)
|
||||||
using (new Benchmark("Generate .NET assembly shim DLLs"))
|
using (new Benchmark("Generate .NET assembly shim DLLs"))
|
||||||
new AssemblyShims(model) {
|
new AssemblyShims(model) {
|
||||||
SuppressMetadata = options.SuppressDllMetadata
|
SuppressMetadata = options.SuppressDllMetadata
|
||||||
|
|||||||
Reference in New Issue
Block a user