From 874787316cdc48fb96fbefd6a4fcd21b74aa882d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thomas=20M=C3=BCller?= <thomas94@gmx.net>
Date: Wed, 4 Jan 2023 13:15:37 +0100
Subject: [PATCH] More robust mechanism to find the binary root dir

---
 include/neural-graphics-primitives/common.h |  5 +++
 src/common.cu                               | 39 +++++++++++++++++++++
 src/testbed.cu                              | 12 ++-----
 3 files changed, 47 insertions(+), 9 deletions(-)

diff --git a/include/neural-graphics-primitives/common.h b/include/neural-graphics-primitives/common.h
index fdf5a99..a4a2c05 100644
--- a/include/neural-graphics-primitives/common.h
+++ b/include/neural-graphics-primitives/common.h
@@ -50,6 +50,8 @@
 	#define NGP_PRAGMA_NO_UNROLL
 #endif
 
+#include <filesystem/path.h>
+
 #include <chrono>
 #include <functional>
 
@@ -61,6 +63,9 @@
 
 NGP_NAMESPACE_BEGIN
 
+filesystem::path get_executable_dir();
+filesystem::path get_root_dir();
+
 bool ends_with(const std::string& str, const std::string& ending);
 bool ends_with_case_insensitive(const std::string& str, const std::string& ending);
 
diff --git a/src/common.cu b/src/common.cu
index e9538ce..2ee41f1 100644
--- a/src/common.cu
+++ b/src/common.cu
@@ -18,11 +18,50 @@
 
 #include <filesystem/path.h>
 
+#ifndef _WIN32
+#  include <unistd.h>
+#  include <linux/limits.h>
+#endif
+
 using namespace tcnn;
 namespace fs = filesystem;
 
 NGP_NAMESPACE_BEGIN
 
+fs::path get_executable_dir() {
+#ifdef _WIN32
+	WCHAR path[MAX_PATH];
+	if (GetModuleFileNameW(NULL, path, MAX_PATH) == 0) {
+		return ".";
+	}
+#else
+	char path[PATH_MAX];
+	ssize_t count = readlink("/proc/self/exe", path, PATH_MAX);
+	if (count == -1) {
+		return ".";
+	}
+#endif
+	return fs::path{path}.parent_path();
+}
+
+filesystem::path get_root_dir() {
+	auto executable_dir = get_executable_dir();
+	fs::path exists_in_root_dir = "./scripts";
+	for (const auto& candidate : {
+		exists_in_root_dir,
+		fs::path{"../"}/exists_in_root_dir,
+		executable_dir/exists_in_root_dir,
+		executable_dir/".."/exists_in_root_dir,
+	}) {
+		if (candidate.exists()) {
+			return candidate.parent_path();
+		}
+	}
+
+	tlog::warning() << "Could not find root directory.";
+	return ".";
+}
+
 bool ends_with(const std::string& str, const std::string& ending) {
 	if (ending.length() > str.length()) {
 		return false;
diff --git a/src/testbed.cu b/src/testbed.cu
index e3b03cb..bc4ffce 100644
--- a/src/testbed.cu
+++ b/src/testbed.cu
@@ -176,12 +176,7 @@ fs::path Testbed::find_network_config(const fs::path& network_config_path) {
 		return network_config_path;
 	}
 
-	fs::path candidate = fs::path{"configs"}/to_string(m_testbed_mode)/network_config_path;
-	if (candidate.exists()) {
-		return candidate;
-	}
-
-	candidate = fs::path{"../"}/candidate;
+	fs::path candidate = get_root_dir()/"configs"/to_string(m_testbed_mode)/network_config_path;
 	if (candidate.exists()) {
 		return candidate;
 	}
@@ -1973,9 +1968,8 @@ void Testbed::prepare_next_camera_path_frame() {
 
 #ifdef _WIN32
 			// Under Windows, try automatically downloading FFmpeg binaries if they don't exist
-			{
-			// if (system(fmt::format("where {} >nul 2>nul", ffmpeg.str()).c_str()) != 0) {
-				fs::path root_dir = fs::path{"scripts"}.exists() ? "." : "..";
+			if (system(fmt::format("where {} >nul 2>nul", ffmpeg.str()).c_str()) != 0) {
+				fs::path root_dir = get_root_dir();
 				if ((root_dir/"external"/"ffmpeg").exists()) {
 					for (const auto& path : fs::directory{root_dir/"external"/"ffmpeg"}) {
 						ffmpeg = path/"bin"/"ffmpeg.exe";
-- 
GitLab