Files
GacUI/Tools/Executables/GacGen/Main.cpp
2024-06-07 00:14:28 -07:00

801 lines
23 KiB
C++

#include "GacGen.h"
using namespace vl::collections;
using namespace vl::filesystem;
using namespace vl::presentation::controls;
GuiResourceCpuArchitecture targetCpuArchitecture = GuiResourceCpuArchitecture::Unspecified;
Array<WString>* arguments = 0;
WString executablePath;
void SetTargetCpuArchitecture()
{
if (arguments->Count() > 0)
{
if (arguments->Get(0) == L"/P32" || arguments->Get(0) == L"/D32" || arguments->Get(0) == L"/C32")
{
targetCpuArchitecture = GuiResourceCpuArchitecture::x86;
}
else if (arguments->Get(0) == L"/P64" || arguments->Get(0) == L"/D64" || arguments->Get(0) == L"/C64")
{
targetCpuArchitecture = GuiResourceCpuArchitecture::x64;
}
}
}
#if defined VCZH_MSVC
int wmain(int argc, wchar_t* argv[])
{
executablePath = argv[0];
Array<WString> _arguments(argc - 1);
for (vint i = 1; i < argc; i++)
{
_arguments[i - 1] = argv[i];
}
arguments = &_arguments;
SetTargetCpuArchitecture();
return SetupGacGenNativeController();
}
#elif defined VCZH_GCC
int main(int argc, char* argv[])
{
executablePath = atow(argv[0]);
Array<WString> _arguments(argc - 1);
for (vint i = 1; i < argc; i++)
{
_arguments[i - 1] = atow(argv[i]);
}
arguments = &_arguments;
SetTargetCpuArchitecture();
return SetupGacGenNativeController();
}
#endif
void PrintErrors(List<GuiResourceError>& errors)
{
List<WString> output;
GuiResourceError::SortAndLog(errors, output);
for (auto line : output)
{
PrintErrorMessage(line);
}
}
void SaveErrors(FilePath errorFilePath, List<GuiResourceError>& errors)
{
PrintErrors(errors);
if (WriteErrors(errors, errorFilePath))
{
PrintErrorMessage(L"error> Error information is saved at : " + errorFilePath.GetFullPath());
}
else
{
PrintErrorMessage(L"error> Unable to write : " + errorFilePath.GetFullPath());
}
}
class Callback : public Object, public IGuiResourcePrecompileCallback, public IWfCompilerCallback
{
public:
vint lastPass = -1;
void OnLoadEnvironment()override
{
PrintInformationMessage(L" Workflow: Loading metadata from registered types ...");
}
void OnInitialize(analyzer::WfLexicalScopeManager* manager)override
{
PrintInformationMessage(L" Workflow: Creating metadata from declarations ...");
}
void OnValidateModule(Ptr<WfModule> module)override
{
PrintInformationMessage(L" Workflow: Validating module " + module->name.value + L" ...");
}
void OnGenerateMetadata()override
{
PrintInformationMessage(L" Workflow: Generating metadata ...");
}
void OnGenerateCode(Ptr<WfModule> module)override
{
PrintInformationMessage(L" Workflow: Generating code for module " + module->name.value + L" ...");
}
void OnGenerateDebugInfo()override
{
PrintInformationMessage(L" Workflow: Generating debug information ...");
}
IWfCompilerCallback* GetCompilerCallback()override
{
return this;
}
void PrintPass(vint passIndex)
{
if (lastPass != passIndex)
{
lastPass = passIndex;
switch (passIndex)
{
case IGuiResourceTypeResolver_Precompile::Workflow_Collect:
PrintInformationMessage(L"Pass: (1/8) Collect workflow scripts");
break;
case IGuiResourceTypeResolver_Precompile::Workflow_Compile:
PrintInformationMessage(L"Pass: (2/8) Compile view model scripts");
break;
case IGuiResourceTypeResolver_Precompile::Instance_CollectInstanceTypes:
PrintInformationMessage(L"Pass: (3/8) Collect instances");
break;
case IGuiResourceTypeResolver_Precompile::Instance_CompileInstanceTypes:
PrintInformationMessage(L"Pass: (4/8) Validate instances");
break;
case IGuiResourceTypeResolver_Precompile::Instance_CollectEventHandlers:
PrintInformationMessage(L"Pass: (5/8) Generate instance type stubs");
break;
case IGuiResourceTypeResolver_Precompile::Instance_CompileEventHandlers:
PrintInformationMessage(L"Pass: (6/8) Compile instance type stubs");
break;
case IGuiResourceTypeResolver_Precompile::Instance_GenerateInstanceClass:
PrintInformationMessage(L"Pass: (7/8) Generate instance types");
break;
case IGuiResourceTypeResolver_Precompile::Instance_CompileInstanceClass:
PrintInformationMessage(L"Pass: (8/8) Compile instance types");
break;
}
}
}
void OnPerPass(vint passIndex)override
{
PrintPass(passIndex);
}
void OnPerResource(vint passIndex, Ptr<GuiResourceItem> resource)override
{
PrintPass(passIndex);
PrintInformationMessage(L" " + resource->GetResourcePath());
}
};
struct LoadConfigResult
{
Ptr<GuiResource> resource;
Ptr<CodegenConfig> config;
};
LoadConfigResult LoadConfig(FilePath inputPath)
{
List<GuiResourceError> errors;
auto resource = GuiResource::LoadFromXml(inputPath.GetFullPath(), errors);
for (vint i = errors.Count() - 1; i >= 0; i--)
{
auto error = errors[i];
if (INVLOC.FindFirst(error.message, L"Path of imported folder does not exist:", Locale::None).key == 0)
{
errors.RemoveAt(i);
}
}
if (errors.Count() > 0)
{
PrintErrorMessage(L"error> Failed to load resource.");
PrintErrors(errors);
return {};
}
auto config = CodegenConfig::LoadConfig(resource, errors);
if (!config)
{
PrintErrorMessage(L"error> Failed to load config.");
return {};
}
if (errors.Count() > 0)
{
PrintErrorMessage(L"error> Failed to load resource metadata.");
PrintErrors(errors);
return {};
}
LoadConfigResult result;
result.resource = resource;
result.config = config;
return result;
}
bool LoadDependencies(Ptr<CodegenConfig> config, Dictionary<WString, FilePath>& resourceMappings, const WString& logFolderPostfix, FilePath errorFilePath)
{
if (config->metadata->version == L"")
{
config->metadata->version = GuiResource::CurrentVersionString;
}
if (config->metadata->version != GuiResource::CurrentVersionString)
{
PrintErrorMessage(L"error> Version of the resource should be \"" + WString(GuiResource::CurrentVersionString) + L"\"");
return false;
}
if (config->metadata->dependencies.Count() > 0 && config->metadata->name == L"")
{
PrintErrorMessage(L"error> Name of the resource should not be empty if it has dependencies.");
return false;
}
SortedList<WString> requireds, loaded;
CopyFrom(requireds, config->metadata->dependencies);
while (requireds.Count() > 0)
{
auto required = requireds[requireds.Count() - 1];
requireds.RemoveAt(requireds.Count() - 1);
if (loaded.Contains(required)) continue;
vint index = resourceMappings.Keys().IndexOf(required);
if (index == -1)
{
PrintErrorMessage(L"error> Cannot find the resource file of name: " + required);
return false;
}
FilePath resourceBinary = FilePath(resourceMappings.Values()[index].GetFullPath() + logFolderPostfix) / L"ScriptedResource.bin";
MemoryStream resourceStream;
{
FileStream fileStream(resourceBinary.GetFullPath(), FileStream::ReadOnly);
if (!fileStream.IsAvailable())
{
PrintErrorMessage(L"error> Cannot find binary resource file, please make sure the required resource \"" + required + L"\" has been properly compiled: " + required);
return false;
}
CopyStream(fileStream, resourceStream);
}
loaded.Add(required);
{
resourceStream.SeekFromBegin(0);
stream::internal::ContextFreeReader reader(resourceStream);
WString metadataText;
reader << metadataText;
GuiResourceError::List errors;
auto parser = GetParserManager()->GetParser<XmlDocument>(L"XML");
auto xmlMetadata = parser->Parse({}, metadataText, errors);
if (!xmlMetadata || errors.Count() > 0)
{
PrintErrorMessage(L"error> The binary resource file has an invalid metadata, please make sure the required resource \"" + required + L"\" has been properly compiled: " + required);
return false;
}
auto metadata = Ptr(new GuiResourceMetadata);
metadata->LoadFromXml(xmlMetadata, {}, errors);
if (errors.Count() > 0)
{
PrintErrorMessage(L"error> The binary resource file has an invalid metadata, please make sure the required resource \"" + required + L"\" has been properly compiled: " + required);
return false;
}
CopyFrom(requireds, metadata->dependencies, true);
}
resourceStream.SeekFromBegin(0);
GuiResourceError::List errors;
GetResourceManager()->LoadResourceOrPending(resourceStream, errors, GuiResourceUsage::InstanceClass);
if (errors.Count() > 0)
{
SaveErrors(errorFilePath, errors);
return false;
}
}
List<WString> pendings;
GetResourceManager()->GetPendingResourceNames(pendings);
if (pendings.Count() > 0)
{
PrintErrorMessage(L"error> Unable to find dependencies: "
+ From(pendings)
.Aggregate(WString::Empty, [](const WString& a, const WString& b) {return a == L"" ? b : a + L", " + b; })
);
return false;
}
return true;
}
void CompileResource(bool partialMode, FilePath inputPath, Nullable<FilePath> mappingPath)
{
PrintSuccessMessage(L"gacgen> Clearning logs ... : " + inputPath.GetFullPath());
WString logFolderPostfix;
switch (targetCpuArchitecture)
{
case GuiResourceCpuArchitecture::x86:
logFolderPostfix = L".log/x32";
break;
case GuiResourceCpuArchitecture::x64:
logFolderPostfix = L".log/x64";
break;
default:;
}
FilePath logFolderPath = inputPath.GetFullPath() + logFolderPostfix;
FilePath scriptFilePath = logFolderPath / L"Workflow.txt";
FilePath errorFilePath = logFolderPath / L"Errors.txt";
FilePath workingDir = inputPath.GetFolder();
{
auto loadConfigResult = LoadConfig(inputPath);
if (!loadConfigResult.resource) return;
Dictionary<WString, FilePath> resourceMappings;
if (mappingPath)
{
FileStream fileStream(mappingPath.Value().GetFullPath(), FileStream::ReadOnly);
if (!fileStream.IsAvailable())
{
PrintErrorMessage(L"error> Failed to load mapping file: " + mappingPath.Value().GetFullPath());
return;
}
BomDecoder decoder;
DecoderStream decoderStream(fileStream, decoder);
StreamReader reader(decoderStream);
while (!reader.IsEnd())
{
auto line = reader.ReadLine();
if (line != L"")
{
auto arrow = INVLOC.FindFirst(line, L"=>", Locale::None);
if (arrow.key == -1)
{
PrintErrorMessage(L"warning> Unable to parse mapping information: " + line);
return;
}
auto name = line.Left(arrow.key);
auto value = line.Right(line.Length() - arrow.key - arrow.value);
if (resourceMappings.Keys().Contains(name))
{
PrintErrorMessage(L"warning> Find duplicate mapping information: " + line);
return;
}
resourceMappings.Add(name, value);
}
}
}
if (!LoadDependencies(loadConfigResult.config, resourceMappings, logFolderPostfix, errorFilePath))
{
return;
}
}
if (partialMode)
{
PrintInformationMessage(L"gacgen> Partial mode activated, all output files will be put under " + logFolderPath.GetFullPath());
}
{
Folder logFolder(logFolderPath);
if (logFolder.Exists())
{
if (!logFolder.Delete(true))
{
PrintErrorMessage(L"gacgen> Unable to delete file in the log folder : " + logFolderPath.GetFullPath());
return;
}
}
if (!logFolder.Create(true))
{
Thread::Sleep(500);
if (!logFolder.Create(true))
{
PrintErrorMessage(L"gacgen> Unable to create log folder : " + logFolderPath.GetFullPath());
return;
}
}
}
Ptr<GuiResource> resource;
{
PrintSuccessMessage(L"gacgen> Making : " + inputPath.GetFullPath());
List<GuiResourceError> errors;
resource = GuiResource::LoadFromXml(inputPath.GetFullPath(), errors);
if (errors.Count() > 0)
{
PrintErrorMessage(L"error> Failed to load resource.");
SaveErrors(errorFilePath, errors);
return;
}
}
List<FilePath> cppResourcePaths;
List<FilePath> cppCompressedPaths;
List<FilePath> resResourcePaths;
List<FilePath> resCompressedPaths;
List<FilePath> resAssemblyPaths;
Ptr<CodegenConfig::CppOutput> cppOutput;
Ptr<CodegenConfig::ResOutput> resOutput;
{
Ptr<CodegenConfig> config;
{
List<GuiResourceError> errors;
config = CodegenConfig::LoadConfig(resource, errors);
if (!config)
{
PrintErrorMessage(L"error> Failed to load config.");
return;
}
if (errors.Count() > 0)
{
PrintErrorMessage(L"error> Failed to load resource metadata.");
SaveErrors(errorFilePath, errors);
return;
}
}
{
cppResourcePaths.Add(logFolderPath / L"Resource.bin");
cppCompressedPaths.Add(logFolderPath / L"Compressed.bin");
resResourcePaths.Add(logFolderPath / L"ScriptedResource.bin");
resCompressedPaths.Add(logFolderPath / L"ScriptedCompressed.bin");
resAssemblyPaths.Add(logFolderPath / L"Assembly.bin");
}
cppOutput = config->cppOutput;
switch (targetCpuArchitecture)
{
case GuiResourceCpuArchitecture::x86:
resOutput = config->resOutputx32;
break;
case GuiResourceCpuArchitecture::x64:
resOutput = config->resOutputx64;
break;
default:;
}
if (cppOutput)
{
if (config->cppOutput->resource != L"") cppResourcePaths.Add(workingDir / config->cppOutput->resource);
if (config->cppOutput->compressed != L"") resAssemblyPaths.Add(workingDir / config->cppOutput->compressed);
}
if (resOutput)
{
if (resOutput->resource != L"") resResourcePaths.Add(workingDir / resOutput->resource);
if (resOutput->compressed != L"") resCompressedPaths.Add(workingDir / resOutput->compressed);
if (resOutput->assembly != L"") resAssemblyPaths.Add(workingDir / resOutput->assembly);
}
}
PrintSuccessMessage(L"gacgen> Compiling...");
List<GuiResourceError> errors;
Callback callback;
auto precompiledFolder = PrecompileResource(resource, targetCpuArchitecture, &callback, errors);
if (errors.Count() > 0)
{
SaveErrors(errorFilePath, errors);
return;
}
if (auto compiled = WriteWorkflowScript(precompiledFolder, L"Workflow/InstanceClass", scriptFilePath))
{
if (cppOutput)
{
PrintSuccessMessage(L"gacgen> Generating C++ source code ...");
auto input = Ptr(new WfCppInput(cppOutput->name));
input->multiFile = WfCppFileSwitch::Enabled;
input->reflection = WfCppFileSwitch::Enabled;
input->comment = L"GacGen.exe " + FilePath(inputPath).GetName();
input->defaultFileName = cppOutput->name + L"PartialClasses";
input->includeFileName = cppOutput->name;
CopyFrom(input->normalIncludes, cppOutput->normalIncludes);
CopyFrom(input->reflectionIncludes, cppOutput->reflectionIncludes);
FilePath cppFolder = workingDir / cppOutput->sourceFolder;
if (partialMode)
{
File(logFolderPath / L"CppOutput.txt").WriteAllText(cppFolder.GetFullPath(), false, BomEncoder::Mbcs);
cppFolder = logFolderPath / L"Source";
if (!Folder(cppFolder).Create(true))
{
PrintSuccessMessage(L"gacgen> Unable to create source folder : " + cppFolder.GetFullPath());
}
}
auto output = WriteCppCodesToFile(resource, compiled, input, cppFolder, errors);
if (errors.Count() > 0)
{
SaveErrors(errorFilePath, errors);
return;
}
if (cppOutput->cppResource != L"")
{
WriteEmbeddedResource(resource, input, output, false, cppFolder / cppOutput->cppResource);
}
if (cppOutput->cppCompressed != L"")
{
WriteEmbeddedResource(resource, input, output, true, cppFolder / cppOutput->cppCompressed);
}
}
for (auto filePath : cppResourcePaths)
{
PrintSuccessMessage(L"Generating binary resource file (no script): " + filePath.GetFullPath());
WriteBinaryResource(resource, false, false, filePath, {});
}
for (auto filePath : cppCompressedPaths)
{
PrintSuccessMessage(L"Generating compressed resource file (no script): " + filePath.GetFullPath());
WriteBinaryResource(resource, true, false, filePath, {});
}
for (auto filePath : resResourcePaths)
{
PrintSuccessMessage(L"Generating binary resource files : " + filePath.GetFullPath());
WriteBinaryResource(resource, false, true, filePath, {});
}
for (auto filePath : resCompressedPaths)
{
PrintSuccessMessage(L"Generating compressed resource files : " + filePath.GetFullPath());
WriteBinaryResource(resource, true, true, filePath, {});
}
for (auto filePath : resAssemblyPaths)
{
PrintSuccessMessage(L"Generating assembly files : " + filePath.GetFullPath());
WriteBinaryResource(resource, false, false, {}, filePath);
}
if (partialMode)
{
List<WString> lines;
List<FilePath>* outputPaths[] =
{
&cppResourcePaths,
&cppCompressedPaths,
&resResourcePaths,
&resCompressedPaths,
&resAssemblyPaths,
};
for (vint i = 0; i < sizeof(outputPaths) / sizeof(*outputPaths); i++)
{
auto& paths = *outputPaths[i];
if (paths.Count() == 2)
{
lines.Add(L"copy \"" + paths[0].GetFullPath() + L"\" \"" + paths[1].GetFullPath() + L"\"");
}
}
if (lines.Count() > 0)
{
File(logFolderPath / L"Deploy.bat").WriteAllLines(lines, false, BomEncoder::Mbcs);
}
}
}
}
void DumpResource(FilePath inputPath, FilePath outputPath)
{
PrintSuccessMessage(L"gacgen> Dumping : " + inputPath.GetFullPath());
auto loadConfigResult = LoadConfig(inputPath);
if (!loadConfigResult.resource) return;
auto doc = Ptr(new XmlDocument);
auto xmlRoot = Ptr(new XmlElement);
xmlRoot->name.value = L"ResourceMetadata";
doc->rootElement = xmlRoot;
xmlRoot->subNodes.Add(loadConfigResult.resource->GetMetadata()->SaveToXml());
{
SortedList<WString> paths;
List<Ptr<GuiResourceFolder>> folders;
folders.Add(loadConfigResult.resource);
for (vint i = 0; i < folders.Count(); i++)
{
auto currentFolder = folders[i];
if (currentFolder->GetFileAbsolutePath() != L"" && !paths.Contains(currentFolder->GetFileAbsolutePath()))
{
paths.Add(currentFolder->GetFileAbsolutePath());
}
for (auto item : currentFolder->GetItems())
{
if (item->GetFileAbsolutePath() != L"" && !paths.Contains(item->GetFileAbsolutePath()))
{
paths.Add(item->GetFileAbsolutePath());
}
}
for (auto folder : currentFolder->GetFolders())
{
folders.Add(folder);
}
}
auto xmlInputs = Ptr(new XmlElement);
xmlInputs->name.value = L"Inputs";
xmlRoot->subNodes.Add(xmlInputs);
for (auto path : paths)
{
auto xmlInput = Ptr(new XmlElement);
xmlInput->name.value = L"Input";
xmlInputs->subNodes.Add(xmlInput);
{
auto attr = Ptr(new XmlAttribute);
attr->name.value = L"Path";
attr->value.value = path;
xmlInput->attributes.Add(attr);
}
}
}
{
SortedList<WString> paths;
paths.Add((FilePath(inputPath.GetFullPath() + L".log") / L"x32" / L"Resource.bin").GetFullPath());
paths.Add((FilePath(inputPath.GetFullPath() + L".log") / L"x32" / L"Compressed.bin").GetFullPath());
paths.Add((FilePath(inputPath.GetFullPath() + L".log") / L"x32" / L"ScriptedResource.bin").GetFullPath());
paths.Add((FilePath(inputPath.GetFullPath() + L".log") / L"x32" / L"ScriptedCompressed.bin").GetFullPath());
paths.Add((FilePath(inputPath.GetFullPath() + L".log") / L"x32" / L"Assembly.bin").GetFullPath());
paths.Add((FilePath(inputPath.GetFullPath() + L".log") / L"x64" / L"Resource.bin").GetFullPath());
paths.Add((FilePath(inputPath.GetFullPath() + L".log") / L"x64" / L"Compressed.bin").GetFullPath());
paths.Add((FilePath(inputPath.GetFullPath() + L".log") / L"x64" / L"ScriptedResource.bin").GetFullPath());
paths.Add((FilePath(inputPath.GetFullPath() + L".log") / L"x64" / L"ScriptedCompressed.bin").GetFullPath());
paths.Add((FilePath(inputPath.GetFullPath() + L".log") / L"x64" / L"Assembly.bin").GetFullPath());
auto xmlOutputs = Ptr(new XmlElement);
xmlOutputs->name.value = L"Outputs";
xmlRoot->subNodes.Add(xmlOutputs);
for (auto path : paths)
{
auto xmlOutput = Ptr(new XmlElement);
xmlOutput->name.value = L"Output";
xmlOutputs->subNodes.Add(xmlOutput);
{
auto attr = Ptr(new XmlAttribute);
attr->name.value = L"Path";
attr->value.value = path;
xmlOutput->attributes.Add(attr);
}
}
}
{
FileStream fileStream(outputPath.GetFullPath(), FileStream::WriteOnly);
if (!fileStream.IsAvailable())
{
PrintErrorMessage(L"error> Failed to write file: " + outputPath.GetFullPath());
return;
}
BomEncoder encoder(BomEncoder::Utf8);
EncoderStream encoderStream(fileStream, encoder);
StreamWriter writer(encoderStream);
XmlPrint(doc, writer);
}
}
class GuiReflectionPlugin : public Object, public IGuiPlugin
{
public:
GUI_PLUGIN_NAME(GacUI_Instance_Reflection)
{
}
void Load(bool controllerUnrelatedPlugins, bool controllerRelatedPlugins)override
{
FilePath exeFolder = FilePath(executablePath).GetFolder();
FilePath metadataFolder = exeFolder;
auto binaryName32 = WString::Unmanaged(L"Reflection32.bin");
auto binaryName64 = WString::Unmanaged(L"Reflection64.bin");
{
File metadataOverride = exeFolder / L"Metadata.txt";
if (metadataOverride.Exists())
{
List<WString> lines;
metadataOverride.ReadAllLinesByBom(lines);
if (lines.Count() < 3)
{
Console::WriteLine(L"Metadata.txt should contains 3 lines for <MetadataFolder>, <Binary for x86>, <Binary for x64>.");
CHECK_FAIL(L"Metadata.txt should contains 3 lines for <MetadataFolder>, <Binary for x86>, <Binary for x64>.");
}
metadataFolder = exeFolder / lines[0];
binaryName32 = lines[1];
binaryName64 = lines[2];
}
}
const wchar_t* BINARY_NAME = nullptr;
switch (targetCpuArchitecture)
{
case GuiResourceCpuArchitecture::x86:
BINARY_NAME = binaryName32.Buffer();
break;
case GuiResourceCpuArchitecture::x64:
BINARY_NAME = binaryName64.Buffer();
break;
default:;
}
FilePath binaryPath = metadataFolder / BINARY_NAME;
if (!File(binaryPath).Exists())
{
Console::WriteLine(L"Unable to find the GacUI type metadata file at: " + binaryPath.GetFullPath());
CHECK_FAIL(L"Unable to find the GacUI type metadata file!");
}
#define INSTALL_SERIALIZABLE_TYPE(TYPE) serializableTypes.Add(TypeInfo<TYPE>::content.typeName, Ptr(new SerializableType<TYPE>));
collections::Dictionary<WString, Ptr<ISerializableType>> serializableTypes;
REFLECTION_PREDEFINED_SERIALIZABLE_TYPES(INSTALL_SERIALIZABLE_TYPE)
INSTALL_SERIALIZABLE_TYPE(Color)
INSTALL_SERIALIZABLE_TYPE(GlobalStringKey)
INSTALL_SERIALIZABLE_TYPE(DocumentFontSize)
FileStream fileStream(binaryPath.GetFullPath(), FileStream::ReadOnly);
auto typeLoader = LoadMetaonlyTypes(fileStream, serializableTypes);
auto tm = GetGlobalTypeManager();
tm->AddTypeLoader(typeLoader);
#undef INSTALL_SERIALIZABLE_TYPE
}
void Unload(bool controllerUnrelatedPlugins, bool controllerRelatedPlugins)override
{
}
};
GUI_REGISTER_PLUGIN(GuiReflectionPlugin)
void GuiMain()
{
Console::SetTitle(L"Vczh GacUI Resource Code Generator for C++");
if (arguments->Count() > 0)
{
if (arguments->Get(0) == L"/P32" || arguments->Get(0) == L"/P64")
{
switch (arguments->Count())
{
case 2:
CompileResource(true, arguments->Get(1), {});
return;
case 3:
CompileResource(true, arguments->Get(1), { arguments->Get(2) });
return;
}
}
else if (arguments->Get(0) == L"/D32" || arguments->Get(0) == L"/D64")
{
switch (arguments->Count())
{
case 3:
DumpResource(arguments->Get(1), arguments->Get(2));
return;
}
}
else if (arguments->Get(0) == L"/C32" || arguments->Get(0) == L"/C64")
{
switch (arguments->Count())
{
case 2:
CompileResource(false, arguments->Get(1), {});
return;
}
}
}
PrintErrorMessage(L"Usage");
PrintErrorMessage(L" Compile for x86 or x64 for GacBuild.ps1:");
PrintErrorMessage(L" GacGen.exe /P32 <input-xml> [<mapping-file>]");
PrintErrorMessage(L" GacGen.exe /P64 <input-xml> [<mapping-file>]");
PrintErrorMessage(L" Dump for x86 or x64 for GacBuild.ps1:");
PrintErrorMessage(L" GacGen.exe /D32 <input-xml> <output-xml>");
PrintErrorMessage(L" GacGen.exe /D64 <input-xml> <output-xml>");
PrintErrorMessage(L" Compile for x86 or x64 if you only want one architecture:");
PrintErrorMessage(L" GacGen.exe /C32 <input-xml>");
PrintErrorMessage(L" GacGen.exe /C64 <input-xml>");
}