230 lines
8.3 KiB
C++
230 lines
8.3 KiB
C++
#include "MetaCoreEditor/MetaCoreBuiltinModules.h"
|
|
#include "MetaCoreEditor/MetaCoreEditorServices.h"
|
|
|
|
#include <cstdlib>
|
|
#include <filesystem>
|
|
#include <iostream>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <string_view>
|
|
|
|
namespace {
|
|
|
|
void MetaCorePrintUsage() {
|
|
std::cerr
|
|
<< "Usage: MetaCoreBuildPackageTool <project-root> [options]\n"
|
|
<< "Options:\n"
|
|
<< " --player <path> Path to MetaCorePlayer.exe\n"
|
|
<< " --output <directory> Build output base directory\n"
|
|
<< " --platform <windows|linux|android|web>\n"
|
|
<< " --graphics <opengl|vulkan|webgl|webgpu>\n"
|
|
<< " --arch <x64|arm64|wasm32>\n"
|
|
<< " --no-cook Package without cooking first\n"
|
|
<< " --no-loose-content Do not copy loose Assets/Scenes\n"
|
|
<< " --no-runtime-config Do not copy Runtime configuration\n"
|
|
<< " --use-cooked-assets Enable cooked asset loading in packaged runtime config\n";
|
|
}
|
|
|
|
[[nodiscard]] bool MetaCoreParseBuildPlatform(
|
|
std::string_view value,
|
|
MetaCore::MetaCoreBuildPlatform& outputPlatform
|
|
) {
|
|
if (value == "windows") {
|
|
outputPlatform = MetaCore::MetaCoreBuildPlatform::Windows;
|
|
} else if (value == "linux") {
|
|
outputPlatform = MetaCore::MetaCoreBuildPlatform::Linux;
|
|
} else if (value == "android") {
|
|
outputPlatform = MetaCore::MetaCoreBuildPlatform::Android;
|
|
} else if (value == "web") {
|
|
outputPlatform = MetaCore::MetaCoreBuildPlatform::Web;
|
|
} else {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
[[nodiscard]] bool MetaCoreParseGraphicsBackend(
|
|
std::string_view value,
|
|
MetaCore::MetaCoreGraphicsBackend& outputBackend
|
|
) {
|
|
if (value == "opengl") {
|
|
outputBackend = MetaCore::MetaCoreGraphicsBackend::OpenGL;
|
|
} else if (value == "vulkan") {
|
|
outputBackend = MetaCore::MetaCoreGraphicsBackend::Vulkan;
|
|
} else if (value == "webgl") {
|
|
outputBackend = MetaCore::MetaCoreGraphicsBackend::WebGL;
|
|
} else if (value == "webgpu") {
|
|
outputBackend = MetaCore::MetaCoreGraphicsBackend::WebGPU;
|
|
} else {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
[[nodiscard]] bool MetaCoreParseBuildArchitecture(
|
|
std::string_view value,
|
|
MetaCore::MetaCoreBuildArchitecture& outputArchitecture
|
|
) {
|
|
if (value == "x64") {
|
|
outputArchitecture = MetaCore::MetaCoreBuildArchitecture::X64;
|
|
} else if (value == "arm64") {
|
|
outputArchitecture = MetaCore::MetaCoreBuildArchitecture::Arm64;
|
|
} else if (value == "wasm32") {
|
|
outputArchitecture = MetaCore::MetaCoreBuildArchitecture::Wasm32;
|
|
} else {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
[[nodiscard]] bool MetaCoreSetProjectPathEnvironment(const std::filesystem::path& projectRoot) {
|
|
#if defined(_WIN32)
|
|
return _putenv_s("METACORE_PROJECT_PATH", projectRoot.string().c_str()) == 0;
|
|
#else
|
|
return setenv("METACORE_PROJECT_PATH", projectRoot.string().c_str(), 1) == 0;
|
|
#endif
|
|
}
|
|
|
|
[[nodiscard]] bool MetaCoreConsumePathOption(
|
|
int& index,
|
|
int argc,
|
|
char* argv[],
|
|
std::filesystem::path& outputPath
|
|
) {
|
|
if (index + 1 >= argc) {
|
|
return false;
|
|
}
|
|
++index;
|
|
outputPath = argv[index];
|
|
return true;
|
|
}
|
|
|
|
void MetaCorePrintDependencyReport(
|
|
const MetaCore::MetaCoreBuildPlayerPackageResult& result,
|
|
std::ostream& output
|
|
) {
|
|
output << "Dependencies: " << result.DependencyReport.size() << '\n';
|
|
for (const MetaCore::MetaCoreBuildDependencyReportEntry& entry : result.DependencyReport) {
|
|
if (entry.Status == "Cooked" || entry.Status == "SkippedGeneratedSubAsset") {
|
|
continue;
|
|
}
|
|
output << " [" << entry.Status << "] " << entry.AssetGuid.ToString()
|
|
<< " reason=" << entry.Reason;
|
|
if (entry.ReferencedBy.IsValid()) {
|
|
output << " referenced_by=" << entry.ReferencedBy.ToString();
|
|
}
|
|
if (!entry.AssetType.empty()) {
|
|
output << " type=" << entry.AssetType;
|
|
}
|
|
if (!entry.AssetPath.empty()) {
|
|
output << " path=" << entry.AssetPath.generic_string();
|
|
}
|
|
if (!entry.Message.empty()) {
|
|
output << " message=" << entry.Message;
|
|
}
|
|
output << '\n';
|
|
}
|
|
}
|
|
|
|
} // namespace
|
|
|
|
int main(int argc, char* argv[]) {
|
|
if (argc < 2) {
|
|
MetaCorePrintUsage();
|
|
return 1;
|
|
}
|
|
if (std::string_view(argv[1]) == "--help" || std::string_view(argv[1]) == "-h") {
|
|
MetaCorePrintUsage();
|
|
return 0;
|
|
}
|
|
|
|
const std::filesystem::path projectRoot = std::filesystem::absolute(argv[1]).lexically_normal();
|
|
if (!std::filesystem::exists(projectRoot / "MetaCore.project.json")) {
|
|
std::cerr << "MetaCore project descriptor was not found: "
|
|
<< (projectRoot / "MetaCore.project.json").string() << '\n';
|
|
return 1;
|
|
}
|
|
|
|
MetaCore::MetaCoreBuildPlayerPackageRequest request;
|
|
for (int index = 2; index < argc; ++index) {
|
|
const std::string_view argument = argv[index];
|
|
if (argument == "--player") {
|
|
if (!MetaCoreConsumePathOption(index, argc, argv, request.PlayerExecutablePath)) {
|
|
std::cerr << "--player requires a path\n";
|
|
return 1;
|
|
}
|
|
} else if (argument == "--output") {
|
|
if (!MetaCoreConsumePathOption(index, argc, argv, request.OutputDirectory)) {
|
|
std::cerr << "--output requires a directory\n";
|
|
return 1;
|
|
}
|
|
} else if (argument == "--platform") {
|
|
if (index + 1 >= argc || !MetaCoreParseBuildPlatform(argv[++index], request.Target.Platform)) {
|
|
std::cerr << "--platform requires one of: windows, linux, android, web\n";
|
|
return 1;
|
|
}
|
|
} else if (argument == "--graphics") {
|
|
if (index + 1 >= argc || !MetaCoreParseGraphicsBackend(argv[++index], request.Target.GraphicsBackend)) {
|
|
std::cerr << "--graphics requires one of: opengl, vulkan, webgl, webgpu\n";
|
|
return 1;
|
|
}
|
|
} else if (argument == "--arch") {
|
|
if (index + 1 >= argc || !MetaCoreParseBuildArchitecture(argv[++index], request.Target.Architecture)) {
|
|
std::cerr << "--arch requires one of: x64, arm64, wasm32\n";
|
|
return 1;
|
|
}
|
|
} else if (argument == "--no-cook") {
|
|
request.CookBeforePackage = false;
|
|
} else if (argument == "--no-loose-content") {
|
|
request.CopyLooseProjectContent = false;
|
|
} else if (argument == "--no-runtime-config") {
|
|
request.CopyRuntimeConfig = false;
|
|
} else if (argument == "--use-cooked-assets") {
|
|
request.UseCookedAssetsInPackage = true;
|
|
} else if (argument == "--help" || argument == "-h") {
|
|
MetaCorePrintUsage();
|
|
return 0;
|
|
} else {
|
|
std::cerr << "Unknown option: " << argument << '\n';
|
|
MetaCorePrintUsage();
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
if (!MetaCoreSetProjectPathEnvironment(projectRoot)) {
|
|
std::cerr << "Failed to set METACORE_PROJECT_PATH\n";
|
|
return 1;
|
|
}
|
|
|
|
MetaCore::MetaCoreEditorModuleRegistry moduleRegistry;
|
|
const std::unique_ptr<MetaCore::MetaCoreIModule> coreServicesModule =
|
|
MetaCore::MetaCoreCreateBuiltinCoreServicesModule();
|
|
coreServicesModule->Startup(moduleRegistry);
|
|
|
|
const auto buildService = moduleRegistry.ResolveService<MetaCore::MetaCoreIBuildService>();
|
|
if (buildService == nullptr) {
|
|
coreServicesModule->Shutdown(moduleRegistry);
|
|
moduleRegistry.ShutdownServices();
|
|
std::cerr << "BuildService is not available\n";
|
|
return 1;
|
|
}
|
|
|
|
const MetaCore::MetaCoreBuildPlayerPackageResult result =
|
|
buildService->BuildPlayerPackage(request);
|
|
|
|
coreServicesModule->Shutdown(moduleRegistry);
|
|
moduleRegistry.ShutdownServices();
|
|
|
|
if (!result.Success) {
|
|
std::cerr << "Build package failed: " << result.Error << '\n';
|
|
MetaCorePrintDependencyReport(result, std::cerr);
|
|
return 1;
|
|
}
|
|
|
|
std::cout << "Build package created: " << result.OutputRoot.string() << '\n'
|
|
<< "Copied files: " << result.CopiedFiles.size() << '\n'
|
|
<< "Cooked assets: " << result.CookedAssets.size() << '\n';
|
|
MetaCorePrintDependencyReport(result, std::cout);
|
|
return 0;
|
|
}
|