diff --git a/src/main.cpp b/src/main.cpp index d85afe97a..f849e5dc7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -95,7 +95,7 @@ static void set_allowed_options(OptionList *allowed_options); static void print_help(const OptionList &allowed_options); static void print_allowed_options(const OptionList &allowed_options); -static void print_version(); +static void print_version(std::ostream &os); static void print_worldspecs(const std::vector &worldspecs, std::ostream &os, bool print_name = true, bool print_path = true); static void print_modified_quicktune_values(); @@ -143,6 +143,8 @@ int main(int argc, char *argv[]) g_logger.registerThread("Main"); g_logger.addOutputMaxLevel(&stderr_output, LL_ACTION); + porting::osSpecificInit(); + Settings cmd_args; get_env_opts(cmd_args); bool cmd_args_ok = get_cmdline_opts(argc, argv, &cmd_args); @@ -158,10 +160,13 @@ int main(int argc, char *argv[]) if (cmd_args.getFlag("version")) { porting::attachOrCreateConsole(); - print_version(); + print_version(std::cout); return 0; } + // Debug handler + BEGIN_DEBUG_EXCEPTION_HANDLER + if (!setup_log_params(cmd_args)) return 1; @@ -171,22 +176,13 @@ int main(int argc, char *argv[]) } porting::signal_handler_init(); - -#ifdef __ANDROID__ - porting::initAndroid(); - porting::initializePathsAndroid(); -#else porting::initializePaths(); -#endif if (!create_userdata_path()) { errorstream << "Cannot create user data directory" << std::endl; return 1; } - // Debug handler - BEGIN_DEBUG_EXCEPTION_HANDLER - // List gameids if requested if (cmd_args.exists("gameid") && cmd_args.get("gameid") == "list") { list_game_ids(); @@ -215,7 +211,6 @@ int main(int argc, char *argv[]) if (g_settings->getBool("enable_console")) porting::attachOrCreateConsole(); -#ifndef __ANDROID__ // Run unit tests if (cmd_args.getFlag("run-unittests")) { #if BUILD_UNITTESTS @@ -245,7 +240,6 @@ int main(int argc, char *argv[]) return 1; #endif } -#endif // __ANDROID__ GameStartData game_params; #ifdef SERVER @@ -430,19 +424,20 @@ static void print_allowed_options(const OptionList &allowed_options) } } -static void print_version() +static void print_version(std::ostream &os) { - std::cout << PROJECT_NAME_C " " << g_version_hash + os << PROJECT_NAME_C " " << g_version_hash << " (" << porting::getPlatformName() << ")" << std::endl; #ifndef SERVER - std::cout << "Using Irrlicht " IRRLICHT_SDK_VERSION << std::endl; + os << "Using Irrlicht " IRRLICHT_SDK_VERSION << std::endl; #endif #if USE_LUAJIT - std::cout << "Using " << LUAJIT_VERSION << std::endl; + os << "Using " << LUAJIT_VERSION << std::endl; #else - std::cout << "Using " << LUA_RELEASE << std::endl; + os << "Using " << LUA_RELEASE << std::endl; #endif - std::cout << g_build_info << std::endl; + os << "Running on " << porting::get_sysinfo() << std::endl; + os << g_build_info << std::endl; } static void list_game_ids() @@ -718,10 +713,11 @@ static void uninit_common() static void startup_message() { - infostream << PROJECT_NAME_C << " " << g_version_hash - << "\nwith SER_FMT_VER_HIGHEST_READ=" - << (int)SER_FMT_VER_HIGHEST_READ << ", " - << g_build_info << std::endl; + print_version(infostream); + infostream << "SER_FMT_VER_HIGHEST_READ=" << + TOSTRING(SER_FMT_VER_HIGHEST_READ) << + " LATEST_PROTOCOL_VERSION=" << TOSTRING(LATEST_PROTOCOL_VERSION) + << std::endl; } static bool read_config_file(const Settings &cmd_args) diff --git a/src/porting.cpp b/src/porting.cpp index 7784a671f..0d8d86c3e 100644 --- a/src/porting.cpp +++ b/src/porting.cpp @@ -68,9 +68,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "filesys.h" #include "log.h" #include "util/string.h" -#include +#include #include #include +#include #if !defined(SERVER) && defined(_WIN32) // On Windows export some driver-specific variables to encourage Minetest to be @@ -88,7 +89,7 @@ namespace porting Signal handler (grabs Ctrl-C on POSIX systems) */ -bool g_killed = false; +static bool g_killed = false; bool *signal_handler_killstatus() { @@ -96,9 +97,8 @@ bool *signal_handler_killstatus() } #if !defined(_WIN32) // POSIX - #include -void signal_handler(int sig) +static void signal_handler(int sig) { if (!g_killed) { if (sig == SIGINT) { @@ -127,9 +127,8 @@ void signal_handler_init(void) } #else // _WIN32 - #include -BOOL WINAPI event_handler(DWORD sig) +static BOOL WINAPI event_handler(DWORD sig) { switch (sig) { case CTRL_C_EVENT: @@ -164,11 +163,11 @@ void signal_handler_init(void) Path mangler */ -// Default to RUN_IN_PLACE style relative paths -std::string path_share = ".."; -std::string path_user = ".."; -std::string path_locale = path_share + DIR_DELIM + "locale"; -std::string path_cache = path_user + DIR_DELIM + "cache"; +// Nobody should be reading these before initializePaths() is called +std::string path_share = "UNINITIALIZED"; +std::string path_user = "UNINITIALIZED"; +std::string path_locale = "UNINITIALIZED"; +std::string path_cache = "UNINITIALIZED"; std::string getDataPath(const char *subpath) @@ -176,7 +175,7 @@ std::string getDataPath(const char *subpath) return path_share + DIR_DELIM + subpath; } -void pathRemoveFile(char *path, char delim) +[[maybe_unused]] static void pathRemoveFile(char *path, char delim) { // Remove filename and path delimiter int i; @@ -267,9 +266,9 @@ bool getCurrentWorkingDir(char *buf, size_t len) } -bool getExecPathFromProcfs(char *buf, size_t buflen) +static bool getExecPathFromProcfs(char *buf, size_t buflen) { -#ifndef _WIN32 +#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) buflen--; ssize_t len; @@ -396,10 +395,7 @@ bool getCurrentExecPath(char *buf, size_t len) #endif -//// Non-Windows -#if !defined(_WIN32) - -const char *getHomeOrFail() +[[maybe_unused]] static inline const char *getHomeOrFail() { const char *home = getenv("HOME"); // In rare cases the HOME environment variable may be unset @@ -408,8 +404,6 @@ const char *getHomeOrFail() return home; } -#endif - //// Windows #if defined(_WIN32) @@ -449,6 +443,13 @@ bool setSystemPaths() } +//// Android + +#elif defined(__ANDROID__) + +extern bool setSystemPaths(); // defined in porting_android.cpp + + //// Linux #elif defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) @@ -457,11 +458,7 @@ bool setSystemPaths() char buf[BUFSIZ]; if (!getCurrentExecPath(buf, sizeof(buf))) { -#ifdef __ANDROID__ - errorstream << "Unable to read bindir "<< std::endl; -#else FATAL_ERROR("Unable to read bindir"); -#endif return false; } @@ -470,7 +467,7 @@ bool setSystemPaths() // Find share directory from these. // It is identified by containing the subdirectory "builtin". - std::list trylist; + std::vector trylist; std::string static_sharedir = STATIC_SHAREDIR; if (!static_sharedir.empty() && static_sharedir != ".") trylist.push_back(static_sharedir); @@ -479,12 +476,7 @@ bool setSystemPaths() DIR_DELIM + PROJECT_NAME); trylist.push_back(bindir + DIR_DELIM ".."); -#ifdef __ANDROID__ - trylist.push_back(path_user); -#endif - - for (std::list::const_iterator - i = trylist.begin(); i != trylist.end(); ++i) { + for (auto i = trylist.begin(); i != trylist.end(); ++i) { const std::string &trypath = *i; if (!fs::PathExists(trypath) || !fs::PathExists(trypath + DIR_DELIM + "builtin")) { @@ -503,7 +495,6 @@ bool setSystemPaths() break; } -#ifndef __ANDROID__ const char *const minetest_user_path = getenv("MINETEST_USER_PATH"); if (minetest_user_path && minetest_user_path[0] != '\0') { path_user = std::string(minetest_user_path); @@ -511,7 +502,6 @@ bool setSystemPaths() path_user = std::string(getHomeOrFail()) + DIR_DELIM "." + PROJECT_NAME; } -#endif return true; } @@ -586,10 +576,9 @@ void migrateCachePath() void initializePaths() { #if RUN_IN_PLACE - char buf[BUFSIZ]; - infostream << "Using relative paths (RUN_IN_PLACE)" << std::endl; + char buf[BUFSIZ]; bool success = getCurrentExecPath(buf, sizeof(buf)) || getExecPathFromProcfs(buf, sizeof(buf)); @@ -627,17 +616,18 @@ void initializePaths() path_user = execpath; } path_cache = path_user + DIR_DELIM + "cache"; + #else infostream << "Using system-wide paths (NOT RUN_IN_PLACE)" << std::endl; if (!setSystemPaths()) errorstream << "Failed to get one or more system-wide path" << std::endl; - -# ifdef _WIN32 +# ifdef __ANDROID__ + sanity_check(!path_cache.empty()); +# elif defined(_WIN32) path_cache = path_user + DIR_DELIM + "cache"; # else - // Initialize path_cache // First try $XDG_CACHE_HOME/PROJECT_NAME const char *cache_dir = getenv("XDG_CACHE_HOME"); const char *home_dir = getenv("HOME"); @@ -651,9 +641,11 @@ void initializePaths() // If neither works, use $PATH_USER/cache path_cache = path_user + DIR_DELIM + "cache"; } +# endif // _WIN32 + // Migrate cache folder to new location if possible migrateCachePath(); -# endif // _WIN32 + #endif // RUN_IN_PLACE infostream << "Detected share path: " << path_share << std::endl; @@ -727,6 +719,15 @@ bool secure_rand_fill_buf(void *buf, size_t len) #endif +#ifndef __ANDROID__ + +void osSpecificInit() +{ + // nothing here yet +} + +#endif + void attachOrCreateConsole() { #ifdef _WIN32 @@ -794,6 +795,11 @@ int mt_snprintf(char *buf, const size_t buf_size, const char *fmt, ...) return c; } +#ifdef __ANDROID__ +// defined in porting_android.cpp +extern void openURIAndroid(const char *url); +#endif + static bool open_uri(const std::string &uri) { if (uri.find_first_of("\r\n") != std::string::npos) { @@ -804,7 +810,7 @@ static bool open_uri(const std::string &uri) #if defined(_WIN32) return (intptr_t)ShellExecuteA(NULL, NULL, uri.c_str(), NULL, NULL, SW_SHOWNORMAL) > 32; #elif defined(__ANDROID__) - openURIAndroid(uri); + openURIAndroid(uri.c_str()); return true; #elif defined(__APPLE__) const char *argv[] = {"open", uri.c_str(), NULL}; diff --git a/src/porting.h b/src/porting.h index 0c7598805..cd710d191 100644 --- a/src/porting.h +++ b/src/porting.h @@ -301,6 +301,9 @@ inline const char *getPlatformName() bool secure_rand_fill_buf(void *buf, size_t len); +// Call once near beginning of main function. +void osSpecificInit(); + // This attaches to the parents process console, or creates a new one if it doesnt exist. void attachOrCreateConsole(); diff --git a/src/porting_android.cpp b/src/porting_android.cpp index 1ed56015f..4d02eb10a 100644 --- a/src/porting_android.cpp +++ b/src/porting_android.cpp @@ -39,23 +39,19 @@ with this program; if not, write to the Free Software Foundation, Inc., extern int main(int argc, char *argv[]); +namespace porting { + void cleanupAndroid(); // used here + bool setSystemPaths(); // used in porting.cpp +} + void android_main(android_app *app) { - int retval = 0; porting::app_global = app; Thread::setName("Main"); char *argv[] = {strdup(PROJECT_NAME), strdup("--verbose"), nullptr}; - try { - main(ARRLEN(argv) - 1, argv); - } catch (std::exception &e) { - errorstream << "Uncaught exception in main thread: " << e.what() << std::endl; - retval = -1; - } catch (...) { - errorstream << "Uncaught exception in main thread!" << std::endl; - retval = -1; - } + int retval = main(ARRLEN(argv) - 1, argv); free(argv[0]); free(argv[1]); @@ -65,8 +61,8 @@ void android_main(android_app *app) } namespace porting { -android_app *app_global; -JNIEnv *jnienv; +android_app *app_global = nullptr; +JNIEnv *jnienv = nullptr; jclass nativeActivity; jclass findClass(const std::string &classname) @@ -86,9 +82,8 @@ jclass findClass(const std::string &classname) return (jclass) jnienv->CallObjectMethod(cls, findClass, strClassName); } -void initAndroid() +void osSpecificInit() { - porting::jnienv = nullptr; JavaVM *jvm = app_global->activity->vm; JavaVMAttachArgs lJavaVMAttachArgs; lJavaVMAttachArgs.version = JNI_VERSION_1_6; @@ -108,8 +103,7 @@ void initAndroid() #ifdef GPROF // in the start-up code - __android_log_print(ANDROID_LOG_ERROR, PROJECT_NAME_C, - "Initializing GPROF profiler"); + warningstream << "Initializing GPROF profiler" << std::endl; monstartup("libMinetest.so"); #endif } @@ -117,7 +111,7 @@ void initAndroid() void cleanupAndroid() { #ifdef GPROF - errorstream << "Shutting down GPROF profiler" << std::endl; + warningstream << "Shutting down GPROF profiler" << std::endl; setenv("CPUPROFILE", (path_user + DIR_DELIM + "gmon.out").c_str(), 1); moncleanup(); #endif @@ -137,7 +131,7 @@ static std::string readJavaString(jstring j_str) return str; } -void initializePathsAndroid() +bool setSystemPaths() { // Set user and share paths { @@ -149,7 +143,6 @@ void initializePathsAndroid() std::string str = readJavaString((jstring) result); path_user = str; path_share = str; - path_locale = str + DIR_DELIM + "locale"; } // Set cache path @@ -160,9 +153,9 @@ void initializePathsAndroid() "porting::initializePathsAndroid unable to find Java getCachePath method"); jobject result = jnienv->CallObjectMethod(app_global->activity->clazz, getCachePath); path_cache = readJavaString((jstring) result); - - migrateCachePath(); } + + return true; } void showInputDialog(const std::string &acceptButton, const std::string &hint, @@ -183,7 +176,7 @@ void showInputDialog(const std::string &acceptButton, const std::string &hint, jacceptButton, jhint, jcurrent, jeditType); } -void openURIAndroid(const std::string &url) +void openURIAndroid(const char *url) { jmethodID url_open = jnienv->GetMethodID(nativeActivity, "openURI", "(Ljava/lang/String;)V"); @@ -191,7 +184,7 @@ void openURIAndroid(const std::string &url) FATAL_ERROR_IF(url_open == nullptr, "porting::openURIAndroid unable to find Java openURI method"); - jstring jurl = jnienv->NewStringUTF(url.c_str()); + jstring jurl = jnienv->NewStringUTF(url); jnienv->CallVoidMethod(app_global->activity->clazz, url_open, jurl); } diff --git a/src/porting_android.h b/src/porting_android.h index d8cfc18d4..e5e75481d 100644 --- a/src/porting_android.h +++ b/src/porting_android.h @@ -36,16 +36,6 @@ extern android_app *app_global; // java <-> c++ interaction interface extern JNIEnv *jnienv; -// do initialization required on android only -void initAndroid(); - -void cleanupAndroid(); - -/** - * Initializes path_* variables for Android - */ -void initializePathsAndroid(); - /** * show text input dialog in java * @param acceptButton text to display on accept button @@ -57,8 +47,6 @@ void initializePathsAndroid(); void showInputDialog(const std::string &acceptButton, const std::string &hint, const std::string ¤t, int editType); -void openURIAndroid(const std::string &url); - /** * Opens a share intent to the file at path *