载入中...
搜索中...
未找到
main.cpp
浏览该文件的文档.
1#include "common/config.h"
2#include "cmdline/cmdline.h"
3#include <CLI11.hpp>
4#include <rang.hpp>
5#include <chrono>
6#include <cstdio>
7#include <ctime>
8#include <iostream>
9#include <string>
10#include <vector>
11
12#if defined(EVENGINE_WINDOWS) || defined(_WIN32)
13#define NOMINMAX
14#include <windows.h>
15#include <backward.hpp>
16
17// backward.hpp pulls in <imagehlp.h> with its own packing; declaring the one
18// DbgHelp entry point we call directly avoids including dbghelp.h again.
19extern "C" BOOL WINAPI SymInitialize(HANDLE hProcess, PCSTR UserSearchPath,
20 BOOL fInvadeProcess);
21#endif
22
23#if defined(EVENGINE_ANDROID) || defined(EVENGINE_IOS) || defined(EVENGINE_WEBGPU)
24#include <SDL2/SDL.h>
25#include <SDL2/SDL_main.h>
26#endif
27
28#if defined(EVENGINE_IOS)
29#include "ios/ios.h"
30#endif
31
32#if defined(EVENGINE_WEBGPU)
33#include "webgpu/webplatform.h"
34#endif
35
36using namespace eve;
37using namespace std;
38
39#if defined(EVENGINE_WINDOWS) || defined(_WIN32)
40namespace {
41
42// Unhandled-exception filter: print the exception code and a symbolized stack
43// trace (backward-cpp / DbgHelp), then let the OS terminate as usual.
44LONG WINAPI eveCrashHandler(EXCEPTION_POINTERS *ep) {
45 // DbgHelp must be initialized before StackWalk64, otherwise the walk
46 // produces garbage frames. Ignore the "already initialized" failure.
47 SymInitialize(GetCurrentProcess(), nullptr, TRUE);
48 std::fprintf(stderr, "\n[crash] code=0x%08lX at %p\n",
49 ep->ExceptionRecord->ExceptionCode,
50 ep->ExceptionRecord->ExceptionAddress);
51 try {
52 backward::StackTrace st;
53 // Walk from the handler's own frame: the exception dispatch ran on the
54 // crashing thread's stack, so the crash site is still in the chain.
55 // Walking from ep->ContextRecord produced garbage frames (0xCC) with
56 // DbgHelp StackWalk64 on this setup.
57 st.load_here(64);
58 backward::Printer p;
59 p.snippet = false;
60 p.color_mode = backward::ColorMode::never;
61 p.print(st, stderr);
62 } catch (...) {
63 std::fprintf(stderr, "[crash] backtrace unavailable\n");
64 }
65 std::fflush(stderr);
66 return EXCEPTION_CONTINUE_SEARCH;
67}
68
69} // namespace
70#endif
71
72namespace {
73// Earliest code we control: runs during static initialization, before main().
74const auto gEveStaticInitStart = std::chrono::steady_clock::now();
75} // namespace
76
77static string get_remaining(CLI::App* sub, string default_path = ".") {
78 auto paths = sub->remaining();
79 if (paths.size() > 1) {
80 cerr << rang::fg::red << "Unknown remaining arguments: " << rang::fg::reset << paths[1] << endl;
81 exit(1);
82 }
83 if (paths.size() == 0) {
84 return default_path;
85 }
86 return paths[0];
87}
88
89class MyFormatter : public CLI::Formatter {
90public:
91 std::string make_usage(const CLI::App *app, std::string name) const override {
92 std::string usage = "Usage: ";
93 usage += name;
94 usage += " [Options] [Root Folder]";
95 return usage;
96 }
97};
98
99int main(int argc, char **argv)
100{
101#if defined(EVENGINE_WINDOWS) || defined(_WIN32)
102 SetUnhandledExceptionFilter(&eveCrashHandler);
103 // Diagnostic hook: EVE_TEST_CRASH=1 forces an access violation right after
104 // startup so the crash handler output can be verified.
105 const char *testCrash = std::getenv("EVE_TEST_CRASH");
106 if (testCrash && testCrash[0] != '\0' && testCrash[0] != '0') {
107 std::fprintf(stderr, "[crash] EVE_TEST_CRASH: forcing an access violation\n");
108 *static_cast<volatile int *>(nullptr) = 0;
109 }
110#endif
111 const auto tMain = std::chrono::steady_clock::now();
112 std::fprintf(stderr, "[startup] static-init -> main(): %.1f ms\n",
113 std::chrono::duration<double, std::milli>(tMain - gEveStaticInitStart).count());
114 std::fprintf(stderr, "[startup] process clock() at main(): %.1f ms\n",
115 (double) std::clock() * 1000.0 / (double) CLOCKS_PER_SEC);
116#if defined(EVENGINE_IOS)
117 // UIKit launches with no CLI args; inject `run <bundle game dir>` like Android Activity.
118 // Qualify eve::ios to avoid ambiguity with std::ios after using-directives.
119 static std::string gamePath;
120 static std::vector<char *> injected;
121 if (argc <= 1) {
122 gamePath = eve::ios::getGameDirectory();
123 if (gamePath.empty())
124 gamePath = ".";
125 static char runFlag[] = "run";
126 injected = {argv[0], runFlag, gamePath.data()};
127 argc = static_cast<int>(injected.size());
128 argv = injected.data();
129 }
130 eve::ios::initAudioSessionInterruptionHandler();
131#elif defined(EVENGINE_WEBGPU)
132 // The browser launches with no CLI args; inject `run <game root>` where
133 // the game is the preloaded VFS mount (/game) or the CWD.
134 static std::string gamePath;
135 static std::vector<char *> injected;
136 if (argc <= 1) {
137 gamePath = eve::webgpu_platform::getGameDirectory();
138 if (gamePath.empty())
139 gamePath = ".";
140 static char runFlag[] = "run";
141 injected = {argv[0], runFlag, gamePath.data()};
142 argc = static_cast<int>(injected.size());
143 argv = injected.data();
144 }
145#endif
146 return requireModInst(eve::cmd,Cmdline)->runArgs(argc, argv);
147}
#define requireModInst(N, T)
Definition Module.h:37
glm::vec4 p[6]
const char * name
Definition RockMesh.cpp:21
std::string make_usage(const CLI::App *app, std::string name) const override
Definition main.cpp:91
int main(int argc, char **argv)
Definition main.cpp:99
Definition Build.cpp:11