96 if (!is_directory(gamePath, ec)) {
97 cerr << rang::fg::red <<
"Not a directory: " << rang::fg::reset << gamePath << endl;
101 std::string sdkRoot = resolveSdkRoot(sdk);
102 if (sdkRoot.empty()) {
103 cerr << rang::fg::red
104 <<
"Cannot locate the target SDK. Pass --sdk <dir>, set $EVENGINE_SDK, "
105 "or run from <sdk>/bin/<runtime>."
106 << rang::fg::reset << endl;
111 std::string gameName = gamePath;
112 while (!gameName.empty() && (gameName.back() ==
'/' || gameName.back() ==
'\\'))
114 if (gameName.find_first_of(
"/\\") != string::npos)
115 gameName = std::filesystem::path(gameName).filename().string();
116 if (gameName.empty()) gameName =
"game";
118 path outDir = output.empty() ? path(gameName +
"-package") : path(output);
119 create_directories(outDir, ec);
121 path sdkBin = path(sdkRoot) /
"bin";
122 path sdkPlat = path(sdkRoot) /
"platform";
125 path runtimeSrc = sdkBin / kEveRuntimeName;
126 path runtimeDst = outDir / kEveRuntimeName;
127 if (!copyFileIf(runtimeSrc, runtimeDst)) {
128 cerr << rang::fg::red <<
"SDK missing " << runtimeSrc.string() << rang::fg::reset << endl;
132#ifdef EVENGINE_WINDOWS
134 std::vector<path> crtCandidates;
135 if (exists(sdkBin)) crtCandidates.push_back(sdkBin);
137 for (
const auto& msroot : {
"C:/Program Files/Microsoft Visual Studio"}) {
138 path base = path(msroot);
139 if (exists(base /
"18")) base = base /
"18";
140 for (
const auto& entry : directory_iterator(base, ec)) {
141 if (!entry.is_directory())
continue;
142 path redist = entry.path() /
"Community" /
"VC" /
"Redist" /
"MSVC";
143 if (!exists(redist))
continue;
144 for (
const auto& ver : directory_iterator(redist, ec)) {
145 for (
const auto& crtDir : {
"x64",
"debug_nonredist/x64"}) {
146 path crt = ver.path() / crtDir;
147 if (!exists(crt))
continue;
148 for (
const auto& sub : directory_iterator(crt, ec)) {
149 if (!sub.is_directory())
continue;
150 const std::string
n = sub.path().filename().string();
151 if (
n.find(
"Microsoft.VC") == 0 && (
n.find(
".CRT") != string::npos ||
152 n.find(
"DebugCRT") != string::npos))
153 crtCandidates.push_back(sub.path());
159 if (exists(path(
"C:/Windows/System32"))) crtCandidates.push_back(path(
"C:/Windows/System32"));
163 for (
const auto& dll : {
"vulkan-1.dll",
"msvcp140.dll",
"msvcp140_1.dll",
164 "msvcp140_2.dll",
"vcruntime140.dll",
"vcruntime140_1.dll",
165 "concrt140.dll",
"msvcp140d.dll",
"vcruntime140d.dll",
166 "vcruntime140_1d.dll",
"ucrtbased.dll",
"concrt140d.dll"}) {
167 if (!copyFirst(dll, crtCandidates, outDir))
168 cerr << rang::fg::yellow <<
"note: runtime DLL not found (may be system-installed): "
169 << dll << rang::fg::reset << endl;
173#ifdef EVENGINE_MACOSX
177 path sdkLib = path(sdkRoot) /
"lib";
178 if (exists(sdkLib)) {
179 for (
const auto& entry : directory_iterator(sdkLib, ec)) {
180 if (entry.is_regular_file() && entry.path().extension() ==
".dylib")
181 copyFileIf(entry.path(), outDir / entry.path().filename());
188 if (exists(sdkPlat)) {
189 for (
const auto& entry : directory_iterator(sdkPlat, ec)) {
190 copy(entry.path(), outDir / entry.path().filename(),
191 copy_options::recursive | copy_options::overwrite_existing, ec);
197 path archive = outDir /
"game.eve";
199 cerr << rang::fg::red <<
"Failed to package game archive." << rang::fg::reset << endl;
203 cout << rang::fg::green <<
"Built game package -> " << rang::fg::reset << outDir.string() << endl;
204 cout <<
" run: " << runtimeDst.string() << endl;