summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpius.lee <pius.lee@samsung.com>2016-09-23 16:22:02 +0900
committerpius.lee <pius.lee@samsung.com>2016-09-23 16:22:02 +0900
commit1d184dbef0419136311f9ca300df581721511d27 (patch)
tree7603ee25adb8908ca8d68859a74f6e6f1ef9fb81
parent32fd9cacf2f1de2bf5b99f4eaef17cacf349b8ab (diff)
downloadlauncher-1d184dbef0419136311f9ca300df581721511d27.tar.gz
launcher-1d184dbef0419136311f9ca300df581721511d27.tar.bz2
launcher-1d184dbef0419136311f9ca300df581721511d27.zip
initialize new launcher
Change-Id: I52436781fcc1e00d5e0eace4500b999e4a69ed80
-rw-r--r--NativeLauncher/CMakeLists.txt32
-rw-r--r--NativeLauncher/inc/launcher.h33
-rw-r--r--NativeLauncher/inc/log.h (renamed from NativeLauncher/src/log.h)0
-rw-r--r--NativeLauncher/inc/utils.h21
-rw-r--r--NativeLauncher/src/dotnet/base64.cc94
-rw-r--r--NativeLauncher/src/dotnet/base64.h11
-rw-r--r--NativeLauncher/src/dotnet/dotnet_launcher.cc348
-rw-r--r--NativeLauncher/src/dotnet/dotnet_launcher.h77
-rw-r--r--NativeLauncher/src/environment.h12
-rw-r--r--NativeLauncher/src/launcher.cc516
-rw-r--r--NativeLauncher/src/launcher.h78
-rw-r--r--NativeLauncher/src/tini.hpp162
-rw-r--r--NativeLauncher/src/utils.cc211
-rw-r--r--NativeLauncher/src/waiter/waiter.cc (renamed from NativeLauncher/src/waiter.cc)0
-rw-r--r--NativeLauncher/src/waiter/waiter.h (renamed from NativeLauncher/src/waiter.h)0
-rw-r--r--Tizen.Runtime/Tizen.Runtime/AssemblyManager.cs21
-rw-r--r--packaging/dotnet-launcher.spec3
-rwxr-xr-xtest_build_on_desktop.sh11
18 files changed, 980 insertions, 650 deletions
diff --git a/NativeLauncher/CMakeLists.txt b/NativeLauncher/CMakeLists.txt
index d2ef94e..203ffb7 100644
--- a/NativeLauncher/CMakeLists.txt
+++ b/NativeLauncher/CMakeLists.txt
@@ -30,7 +30,7 @@ IF(DEFINED RUNTIME_DIR)
SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -DRUNTIME_DIR=${RUNTIME_DIR}")
ENDIF(DEFINED RUNTIME_DIR)
-SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -std=c++11")
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -pthread -std=c++11 -Wl,--no-as-needed")
SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Wl,-zdefs" )
#SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden")
SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fPIE")
@@ -43,31 +43,29 @@ SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
SET(CMAKE_CXX_FLAGS_RELEASE "-O2")
SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed")
-SET(${PROJECT_NAME}_SOURCE_FILES
+INCLUDE_DIRECTORIES(inc)
+
+SET(DOTNET_LAUNCHER "dotnet-launcher")
+SET(MONO_LAUNCHER "mono-launcher")
+
+SET(${DOTNET_LAUNCHER}_SOURCE_FILES
+ src/utils.cc
src/launcher.cc
- src/waiter.cc
+ src/dotnet/dotnet_launcher.cc
+ src/dotnet/base64.cc
)
-
-ADD_EXECUTABLE(${PROJECT_NAME} ${${PROJECT_NAME}_SOURCE_FILES})
+ADD_EXECUTABLE(${DOTNET_LAUNCHER} ${${PROJECT_NAME}_SOURCE_FILES})
IF(NOT DEFINED NO_TIZEN)
- TARGET_LINK_LIBRARIES(${PROJECT_NAME} aul)
+ TARGET_LINK_LIBRARIES(${DOTNET_LAUNCHER} aul)
ENDIF(NOT DEFINED NO_TIZEN)
-TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${${PROJECT_NAME}_LDFLAGS} "-pie -ldl")
+TARGET_LINK_LIBRARIES(${DOTNET_LAUNCHER} ${${PROJECT_NAME}_LDFLAGS} "-pie -ldl -lpthread")
-SET_TARGET_PROPERTIES(${PROJECT_NAME}
+SET_TARGET_PROPERTIES(${DOTNET_LAUNCHER}
PROPERTIES SKIP_BUILD_RPATH TRUE
) # remove rpath option that is automatically generated by cmake.
-SET(LAUNCHER_LIB "dnclauncher")
-ADD_LIBRARY(${LAUNCHER_LIB} SHARED src/waiter.cc)
-IF(NOT DEFINED NO_TIZEN)
- TARGET_LINK_LIBRARIES(${LAUNCHER_LIB} aul)
-ENDIF(NOT DEFINED NO_TIZEN)
-TARGET_LINK_LIBRARIES(${LAUNCHER_LIB} ${${PROJECT_NAME}_LDFLAGS} "-ldl")
-
IF(NOT DEFINED NO_TIZEN)
- INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${BINDIR})
- INSTALL(TARGETS ${LAUNCHER_LIB} DESTINATION ${LIBDIR})
+ INSTALL(TARGETS ${DOTNET_LAUNCHER} DESTINATION ${BINDIR})
INSTALL(FILES dotnet.loader DESTINATION ${LOADERDIR})
ENDIF(NOT DEFINED NO_TIZEN)
diff --git a/NativeLauncher/inc/launcher.h b/NativeLauncher/inc/launcher.h
new file mode 100644
index 0000000..f4309b4
--- /dev/null
+++ b/NativeLauncher/inc/launcher.h
@@ -0,0 +1,33 @@
+#ifndef __LAUNCHER_INTERFACE_H__
+#define __LAUNCHER_INTERFACE_H__
+
+namespace tizen {
+namespace runtime {
+
+class LauncherInterface
+{
+ public:
+ virtual int Initialize() = 0;
+ virtual void Dispose() = 0;
+ virtual int RunManagedLauncher() = 0;
+ virtual int Launch(const char* path, int argc, char* argv[]) = 0;
+};
+
+class LaunchpadAdapter
+{
+ public:
+ virtual void LoaderMain(LauncherInterface* launcher, int argc, char* argv[]) = 0;
+ virtual void WaitUtilLaunched() = 0;
+
+ protected:
+ virtual void OnCreate() = 0;
+ virtual void OnLaunch() = 0;
+ virtual void OnTerminate() = 0;
+};
+
+extern LaunchpadAdapter& Launchpad;
+
+} // namespace runtime
+} // namespace tizen
+
+#endif // __LAUNCHER_INTERFACE_H__
diff --git a/NativeLauncher/src/log.h b/NativeLauncher/inc/log.h
index 59f2dc9..59f2dc9 100644
--- a/NativeLauncher/src/log.h
+++ b/NativeLauncher/inc/log.h
diff --git a/NativeLauncher/inc/utils.h b/NativeLauncher/inc/utils.h
new file mode 100644
index 0000000..145a43d
--- /dev/null
+++ b/NativeLauncher/inc/utils.h
@@ -0,0 +1,21 @@
+#ifndef __UTILS_H__
+#define __UTILS_H__
+
+#include <string>
+#include <vector>
+
+#ifndef PATH_SEPARATOR
+#define PATH_SEPARATOR '/'
+#endif
+
+std::string ReadSelfPath ();
+std::string ConcatPath (const std::string& path1, const std::string& path2);
+void AppendPath (std::string& path1, const std::string& path2);
+std::string AbsolutePath (const std::string& path);
+std::string Basename (const std::string& path);
+bool EndWithIgnoreCase (const std::string& str1, const std::string& str2, std::string& filename);
+void AssembliesInDirectory(const std::vector<std::string>& directories, std::string& tpaList);
+bool FileNotExist(const std::string& path);
+std::string JoinStrings(const std::vector<std::string>& strings, const char* const delimeter);
+
+#endif // __UTILS_H__
diff --git a/NativeLauncher/src/dotnet/base64.cc b/NativeLauncher/src/dotnet/base64.cc
new file mode 100644
index 0000000..3330082
--- /dev/null
+++ b/NativeLauncher/src/dotnet/base64.cc
@@ -0,0 +1,94 @@
+#include "base64.h"
+#include <iostream>
+
+static const std::string base64_chars =
+"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+"abcdefghijklmnopqrstuvwxyz"
+"0123456789+/";
+
+
+static inline bool is_base64(BYTE c) {
+ return (isalnum(c) || (c == '+') || (c == '/'));
+}
+
+std::string base64_encode(BYTE const* buf, unsigned int bufLen) {
+ std::string ret;
+ int i = 0;
+ int j = 0;
+ BYTE char_array_3[3];
+ BYTE char_array_4[4];
+
+ while (bufLen--) {
+ char_array_3[i++] = *(buf++);
+ if (i == 3) {
+ char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
+ char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
+ char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
+ char_array_4[3] = char_array_3[2] & 0x3f;
+
+ for(i = 0; (i <4) ; i++)
+ ret += base64_chars[char_array_4[i]];
+ i = 0;
+ }
+ }
+
+ if (i)
+ {
+ for(j = i; j < 3; j++)
+ char_array_3[j] = '\0';
+
+ char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
+ char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
+ char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
+ char_array_4[3] = char_array_3[2] & 0x3f;
+
+ for (j = 0; (j < i + 1); j++)
+ ret += base64_chars[char_array_4[j]];
+
+ while((i++ < 3))
+ ret += '=';
+ }
+
+ return ret;
+}
+
+std::vector<BYTE> base64_decode(std::string const& encoded_string) {
+ int in_len = encoded_string.size();
+ int i = 0;
+ int j = 0;
+ int in_ = 0;
+ BYTE char_array_4[4], char_array_3[3];
+ std::vector<BYTE> ret;
+
+ while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
+ char_array_4[i++] = encoded_string[in_]; in_++;
+ if (i ==4) {
+ for (i = 0; i <4; i++)
+ char_array_4[i] = base64_chars.find(char_array_4[i]);
+
+ char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
+ char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
+ char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
+
+ for (i = 0; (i < 3); i++)
+ ret.push_back(char_array_3[i]);
+ i = 0;
+ }
+ }
+
+ if (i) {
+ for (j = i; j <4; j++)
+ char_array_4[j] = 0;
+
+ for (j = 0; j <4; j++)
+ char_array_4[j] = base64_chars.find(char_array_4[j]);
+
+ char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
+ char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
+ char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
+
+ for (j = 0; (j < i - 1); j++) ret.push_back(char_array_3[j]);
+ }
+
+ return ret;
+}
diff --git a/NativeLauncher/src/dotnet/base64.h b/NativeLauncher/src/dotnet/base64.h
new file mode 100644
index 0000000..1a6b6ba
--- /dev/null
+++ b/NativeLauncher/src/dotnet/base64.h
@@ -0,0 +1,11 @@
+#ifndef _BASE64_H_
+#define _BASE64_H_
+
+#include <vector>
+#include <string>
+typedef unsigned char BYTE;
+
+std::string base64_encode(BYTE const* buf, unsigned int bufLen);
+std::vector<BYTE> base64_decode(std::string const&);
+
+#endif
diff --git a/NativeLauncher/src/dotnet/dotnet_launcher.cc b/NativeLauncher/src/dotnet/dotnet_launcher.cc
new file mode 100644
index 0000000..4942710
--- /dev/null
+++ b/NativeLauncher/src/dotnet/dotnet_launcher.cc
@@ -0,0 +1,348 @@
+
+#include <dlfcn.h>
+
+#include <string>
+#include <fstream>
+#include <thread>
+#include <vector>
+
+#include "utils.h"
+#include "log.h"
+#include "launcher.h"
+#include "dotnet_launcher.h"
+
+namespace tizen {
+namespace runtime {
+namespace dotnetcore {
+
+
+void CoreRuntime::SetStandaloneExe(const char* exePath, int argc, char* argv[])
+{
+ if (exePath == nullptr)
+ {
+ _ERR("executable path is null");
+ return;
+ }
+
+ if (FileNotExist(exePath))
+ {
+ _ERR("File not exist : %s", exePath);
+ return;
+ }
+
+ isLaunched = true;
+ LaunchParam.path = exePath;
+ LaunchParam.argc = argc;
+ LaunchParam.argv = argv;
+
+ const char *_deviceapi_directory = getenv("DeviceAPIDirectory");
+ const char *_runtime_directory = getenv("RuntimeDirectory");
+ const char *_launcher_assembly = getenv("LauncherAssembly");
+ if (_deviceapi_directory != nullptr)
+ DeviceAPIDirectory = _deviceapi_directory;
+ if (_runtime_directory != nullptr)
+ RuntimeDirectory = _runtime_directory;
+ if (_launcher_assembly != nullptr)
+ LauncherAssembly = _launcher_assembly;
+}
+
+CoreRuntime::CoreRuntime() :
+ coreclrLib(nullptr),
+ hostHandle(nullptr),
+ domainId(-1),
+ LaunchFunction(nullptr),
+ isLaunched(false),
+ InitializeClr(nullptr),
+ ExecuteAssembly(nullptr),
+ Shutdown(nullptr),
+ CreateDelegate(nullptr)
+{
+#define __XSTR(x) #x
+#define __STR(x) __XSTR(x)
+
+#ifdef DEVICE_API_DIR
+ DeviceAPIDirectory = __STR(DEVICE_API_DIR);
+#endif
+#ifdef RUNTIME_DIR
+ RuntimeDirectory = __STR(RUNTIME_DIR);
+#endif
+#ifdef LAUNCHER_ASSEMBLY_PATH
+ LauncherAssembly = __STR(LAUNCHER_ASSEMBLY_PATH);
+#endif
+
+#undef __STR
+#undef __XSTR
+
+ _DBG("Constructor called!!");
+}
+
+CoreRuntime::~CoreRuntime()
+{
+ Dispose();
+}
+
+int CoreRuntime::Initialize()
+{
+
+ if (DeviceAPIDirectory.empty())
+ {
+ _ERR("Empty Device API Directory");
+ return 1;
+ }
+ else
+ {
+ DeviceAPIDirectory = AbsolutePath(DeviceAPIDirectory);
+ }
+ if (RuntimeDirectory.empty())
+ {
+ _ERR("Empty Runtime Directory");
+ return 1;
+ }
+ else
+ {
+ RuntimeDirectory = AbsolutePath(RuntimeDirectory);
+ }
+ if (LauncherAssembly.empty())
+ {
+ _ERR("Empty Launcher Assembly");
+ return 1;
+ }
+ else
+ {
+ LauncherAssembly = AbsolutePath(LauncherAssembly);
+ }
+
+ std::string libcoreclr(ConcatPath(RuntimeDirectory, "libcoreclr.so"));
+
+ _DBG("libcoreclr : %s", libcoreclr.c_str());
+
+ coreclrLib = dlopen(libcoreclr.c_str(), RTLD_NOW | RTLD_LOCAL);
+ if (coreclrLib == nullptr)
+ {
+ char *err = dlerror();
+ _ERR("dlopen failed to open libcoreclr.so with error %s", err);
+ return 1;
+ }
+
+#define CORELIB_RETURN_IF_NOSYM(type, variable, name) \
+ do { variable = (type)dlsym(coreclrLib, name); \
+ if (variable == nullptr) { \
+ _ERR(name " is not found in the libcoreclr.so"); \
+ return 1; \
+ }} while(0)
+
+ CORELIB_RETURN_IF_NOSYM(coreclr_initialize_ptr, InitializeClr, "coreclr_initialize");
+ CORELIB_RETURN_IF_NOSYM(coreclr_execute_assembly_ptr, ExecuteAssembly, "coreclr_execute_assembly");
+ CORELIB_RETURN_IF_NOSYM(coreclr_shutdown_ptr, Shutdown, "coreclr_shutdown");
+ CORELIB_RETURN_IF_NOSYM(coreclr_create_delegate_ptr, CreateDelegate, "coreclr_create_delegate");
+
+#undef CORELIB_RETURN_IF_NOSYM
+
+ _DBG("libcoreclr dlopen and dlsym success");
+
+ _DBG("this addr : %x", this);
+ _DBG("coreclr_initialize : %x", InitializeClr);
+
+ return 0;
+}
+
+int CoreRuntime::RunManagedLauncher()
+{
+ void* hostHandle;
+ unsigned int domainId;
+
+ if (FileNotExist(LauncherAssembly))
+ {
+ _ERR("Launcher assembly is not exist in %s", LauncherAssembly.c_str());
+ return 1;
+ }
+
+ std::string launcherDir = Basename(LauncherAssembly);
+ std::vector<std::string> searchDirectories = {
+ RuntimeDirectory, DeviceAPIDirectory, launcherDir
+ };
+
+ std::string trusted_assemblies;
+ AssembliesInDirectory(searchDirectories, trusted_assemblies);
+ std::string trusted_directories = JoinStrings(searchDirectories, ":");
+
+ _DBG("coreclr_dir : %s", RuntimeDirectory.c_str());
+ _DBG("tpa_dirs : %s", trusted_directories.c_str());
+ _DBG("native_so_search_dir : %s", trusted_directories.c_str());
+ _DBG("launcher_assembly : %s", LauncherAssembly.c_str());
+ _DBG("launcher_dir : %s", launcherDir.c_str());
+
+ const char *propertyKeys[] =
+ {
+ "TRUSTED_PLATFORM_ASSEMBLIES",
+ "APP_PATHS",
+ "APP_NI_PATHS",
+ "NATIVE_DLL_SEARCH_DIRECTORIES",
+ "AppDomainCompatSwitch"
+ };
+
+ const char *propertyValues[] =
+ {
+ trusted_assemblies.c_str(),
+ launcherDir.c_str(),
+ launcherDir.c_str(),
+ trusted_directories.c_str(),
+ "UseLatestBehaviorWhenTFMNotSpecified"
+ };
+
+// _DBG("trusted platform assemblies : %s", propertyValues[0]);
+ _DBG("app_path : %s", propertyValues[1]);
+ _DBG("app_ni_path : %s", propertyValues[2]);
+ _DBG("native dll search path : %s", propertyValues[3]);
+ _DBG("app domain compat switch : %s", propertyValues[4]);
+
+ _DBG("before InitializeClr");
+ _DBG("this addr : %x", this);
+ _DBG("coreclr_initialize : %x", InitializeClr);
+
+ std::string selfPath = ReadSelfPath();
+
+ _DBG("self path : %s", selfPath.c_str());
+
+ _DBG("libcoreclr addr : %x", coreclrLib);
+
+ int st = InitializeClr(
+ selfPath.c_str(),
+ //LauncherAssembly.c_str(),
+ "dotnet-launcher",
+ sizeof(propertyKeys) / sizeof(propertyKeys[0]),
+ propertyKeys,
+ propertyValues,
+ &hostHandle,
+ &domainId);
+
+ if (st < 0)
+ {
+ _ERR("initialize core clr fail! (0x%08x)", st);
+ return 1;
+ }
+
+ _DBG("Initialize core clr success");
+
+ void *launchFunctionDelegate;
+ st = CreateDelegate(hostHandle, domainId,
+ "Tizen.Runtime",
+ "Tizen.Runtime.AssemblyManager",
+ "Launch", &launchFunctionDelegate);
+ if (st < 0)
+ {
+ _ERR("Create delegate for Launch managed function is fail! (0x%08x)", st);
+ return 1;
+ }
+ LaunchFunction = reinterpret_cast<LaunchFunctionPtr>(launchFunctionDelegate);
+
+ if (isLaunched)
+ {
+ bool success = LaunchFunction(LaunchParam.path.c_str(),
+ LaunchParam.argc, LaunchParam.argv);
+ if (!success)
+ {
+ _ERR("Failed to Launching");
+ }
+ }
+
+ /*
+ unsigned int exitCode;
+ const char* argv[] = {LauncherAssembly.c_str()};
+ st = ExecuteAssembly(hostHandle, domainId,
+ 1, argv, LauncherAssembly.c_str(), &exitCode);
+ _DBG("after execute coreclr");
+ if (st < 0)
+ {
+ _ERR("execute core clr fail! (0x%08x / %d)", st, exitCode);
+ return 1;
+ }
+ */
+
+ return 0;
+}
+
+void CoreRuntime::Dispose()
+{
+ if (hostHandle != nullptr)
+ {
+ int st = Shutdown(hostHandle, domainId);
+ if (st < 0)
+ {
+ _ERR("shutdown core clr fail! (0x%08x)", st);
+ }
+ }
+
+ if (dlclose(coreclrLib) != 0)
+ {
+ _ERR("libcoreclr.so close failed");
+ }
+ coreclrLib = nullptr;
+
+ _DBG("Dotnet runtime disposed");
+}
+
+int CoreRuntime::Launch(const char* path, int argc, char* argv[])
+{
+ if (LaunchFunction != nullptr)
+ {
+ LaunchFunction(path, argc, argv);
+ }
+ else
+ {
+ LaunchParam.path = path;
+ LaunchParam.argc = argc;
+ LaunchParam.argv = argv;
+ }
+ isLaunched = true;
+
+ return 0;
+}
+
+} // namespace dotnetcore
+} // namespace runtime
+} // namespace tizen
+
+static std::string StandaloneOption("--standalone");
+
+#include "base64.h"
+
+int main(int argc, char *argv[])
+{
+ int i;
+ bool standalone = false;
+ const char* standalonePath = nullptr;
+
+ for (i=1; i<argc; i++)
+ {
+ if (StandaloneOption.compare(argv[i]) == 0)
+ {
+ standalone = true;
+ }
+ else
+ {
+ if (standalonePath == nullptr)
+ standalonePath = argv[i];
+ }
+ }
+
+ tizen::runtime::dotnetcore::CoreRuntime runtime;
+ if (standalone)
+ {
+ runtime.SetStandaloneExe(standalonePath, argc, argv);
+ }
+ else
+ {
+ tizen::runtime::Launchpad.LoaderMain(&runtime, argc, argv);
+ }
+
+ runtime.Initialize();
+ runtime.RunManagedLauncher();
+
+ if (!standalone)
+ {
+ tizen::runtime::Launchpad.WaitUtilLaunched();
+ }
+
+ return 0;
+}
diff --git a/NativeLauncher/src/dotnet/dotnet_launcher.h b/NativeLauncher/src/dotnet/dotnet_launcher.h
new file mode 100644
index 0000000..e1a86b0
--- /dev/null
+++ b/NativeLauncher/src/dotnet/dotnet_launcher.h
@@ -0,0 +1,77 @@
+#include "launcher.h"
+
+extern "C"
+{
+ typedef int (*coreclr_initialize_ptr)(
+ const char* exePath,
+ const char* appDomainFriendlyName,
+ int propertyCount,
+ const char** propertyKeys,
+ const char** propertyValues,
+ void** hostHandle,
+ unsigned int* domainId);
+
+ typedef int (*coreclr_execute_assembly_ptr)(
+ void* hostHandle,
+ unsigned int domainId,
+ int argc,
+ const char** argv,
+ const char* managedAssemblyPath,
+ unsigned int* exitCode);
+
+ typedef int (*coreclr_shutdown_ptr)(
+ void* hostHandle,
+ unsigned int domainId);
+
+ typedef int (*coreclr_create_delegate_ptr)(
+ void* hostHandle,
+ unsigned int domainId,
+ const char* entryPointAssemblyName,
+ const char* entryPointTypeName,
+ const char* entryPointMethodName,
+ void** delegate);
+}
+
+namespace tizen {
+namespace runtime {
+namespace dotnetcore {
+
+typedef bool (*LaunchFunctionPtr)(const char* path, int argc, char* argv[]);
+
+struct LaunchParameter
+{
+ std::string path;
+ int argc;
+ char** argv;
+};
+
+class CoreRuntime : public tizen::runtime::LauncherInterface
+{
+ public:
+ CoreRuntime();
+ ~CoreRuntime();
+ int Initialize() override;
+ void Dispose() override;
+ int RunManagedLauncher() override;
+ int Launch(const char* path, int argc, char* argv[]) override;
+ void SetStandaloneExe(const char* exePath, int argc, char* argv[]);
+
+ private:
+ coreclr_initialize_ptr InitializeClr;
+ coreclr_execute_assembly_ptr ExecuteAssembly;
+ coreclr_shutdown_ptr Shutdown;
+ coreclr_create_delegate_ptr CreateDelegate;
+ std::string DeviceAPIDirectory;
+ std::string RuntimeDirectory;
+ std::string LauncherAssembly;
+ void* coreclrLib;
+ void* hostHandle;
+ unsigned int domainId;
+ LaunchFunctionPtr LaunchFunction;
+ bool isLaunched;
+ LaunchParameter LaunchParam;
+};
+
+} // dotnetcore
+} // namespace runtime
+} // namespace tizen
diff --git a/NativeLauncher/src/environment.h b/NativeLauncher/src/environment.h
deleted file mode 100644
index 6e4e57b..0000000
--- a/NativeLauncher/src/environment.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef __ENVIRONMENT_H__
-
-#ifndef TIZEN_CORECLR_PATH
-#define TIZEN_CORECLR_PATH "/usr/share/coreclr/libcoreclr.so"
-#endif
-
-#ifndef TIZEN_NETCORE_TPA_PATH
-#define TIZEN_NETCORE_TPA_PATH "/usr/share/assemblies"
-#endif
-
-
-#endif // __ENVIRONMENT_H__
diff --git a/NativeLauncher/src/launcher.cc b/NativeLauncher/src/launcher.cc
index 35762f5..518a1d9 100644
--- a/NativeLauncher/src/launcher.cc
+++ b/NativeLauncher/src/launcher.cc
@@ -1,422 +1,190 @@
-#include <dlfcn.h>
-
-#include <cstdlib>
-#include <cstring>
-#include <vector>
-#include <string>
-#include <set>
-#include <sstream>
-#include <fstream>
-#include <memory>
-#include <algorithm>
-
-#include <dirent.h>
-#include <sys/stat.h>
-
-#include <unistd.h>
-#include <limits.h>
-
-#include "environment.h"
-#include "waiter.h"
+#include "launcher.h"
#include "log.h"
-#include "tini.hpp"
-
-#define __XSTR(x) #x
-#define __STR(x) __XSTR(x)
-
-#ifndef NO_TIZEN
-
-#ifndef DEVICE_API_DIR
- #error "DEVICE_API_DIR must be exist."
-#endif
-
-#ifndef RUNTIME_DIR
- #error "RUNTIME_DIR must be exist."
-#endif
-
-#ifndef LAUNCHER_ASSEMBLY_PATH
- #error "LAUNCHER_ASSEMBLY_PATH must be exist."
-#endif
-
-#define CONST const
-#else
-
-#define CONST
-#include <stdlib.h>
-#endif
-
-#ifdef DEVICE_API_DIR
-static CONST std::string DeviceAPIDirectory(__STR(DEVICE_API_DIR));
-#else
-static std::string DeviceAPIDirectory;
-#endif
-#ifdef RUNTIME_DIR
-static CONST std::string RuntimeDirectory(__STR(RUNTIME_DIR));
-#else
-static std::string RuntimeDirectory;
-#endif
-#ifdef LAUNCHER_ASSEMBLY_PATH
-static CONST std::string LauncherAssembly(__STR(LAUNCHER_ASSEMBLY_PATH));
-#else
-static std::string LauncherAssembly;
-#endif
-
-#undef __STR
-#undef __XSTR
-
-#ifndef PATH_SEPARATOR
-#define PATH_SEPARATOR '/'
-#endif
+#include <launchpad.h>
-typedef int (*coreclr_initialize_ptr)(
- const char* exePath,
- const char* appDomainFriendlyName,
- int propertyCount,
- const char** propertyKeys,
- const char** propertyValues,
- void** hostHandle,
- unsigned int* domainId);
+#include <poll.h>
-typedef int (*coreclr_execute_assembly_ptr)(
- void* hostHandle,
- unsigned int domainId,
- int argc,
- const char** argv,
- const char* managedAssemblyPath,
- unsigned int* exitCode);
-
-typedef int (*coreclr_shutdown_ptr)(
- void* hostHandle,
- unsigned int domainId);
-
-typedef int (*coreclr_create_delegate_ptr)(
- void* hostHandle,
- unsigned int domainId,
- const char* entryPointAssemblyName,
- const char* entryPointTypeName,
- const char* entryPointMethodName,
- void** delegate);
-
-std::string ReadSelfPath() {
- char buff[PATH_MAX];
- ssize_t len = ::readlink("/proc/self/exe", buff, sizeof(buff)-1);
- if (len != -1) {
- buff[len] = '\0';
- return std::string(buff);
- }
+#include <map>
+#include <vector>
+#include <functional>
+#include <thread>
- return "";
-}
+namespace tizen {
+namespace runtime {
-static std::string ConcatPath(const std::string& path1, const std::string& path2)
+struct FdHandler
{
- std::string path(path1);
- if (path.back() == PATH_SEPARATOR)
- {
- path.append(path2);
- }
- else
- {
- path += PATH_SEPARATOR;
- path.append(path2);
- }
+ pollfd *info;
+ std::function<void(int)> receiver;
+};
- return path;
-}
-/*
-static void AppendPath(std::string& path1, const std::string& path2)
+class LaunchpadAdapterImpl : public LaunchpadAdapter
{
- if (path1.back() == PATH_SEPARATOR)
- {
- path1.append(path2);
- }
- else
- {
- path1 += PATH_SEPARATOR;
- path1.append(path2);
- }
-}
-*/
-
-static std::string AbsolutePath(const std::string& path)
+ public:
+ LaunchpadAdapterImpl() : isLaunched(false) { }
+ void LoaderMain(LauncherInterface* launcher, int argc, char* argv[]) override;
+ void WaitUtilLaunched() override;
+
+ protected:
+ void OnCreate() override;
+ void OnLaunch() override;
+ void OnTerminate() override;
+
+ private:
+ loader_lifecycle_callback_s callbacks;
+ loader_adapter_s adapter;
+ LauncherInterface* launcher;
+ bool isLaunched;
+ std::string launchPath;
+
+ bool Waiting;
+ std::vector<pollfd> FdList;
+ std::map<int, FdHandler> Handlers;
+
+ std::thread pollingThread;
+};
+
+LaunchpadAdapterImpl LaunchpadImpl;
+LaunchpadAdapter& Launchpad = LaunchpadImpl;
+
+void LaunchpadAdapterImpl::LoaderMain(LauncherInterface* launcher, int argc, char* argv[])
{
- std::string absPath;
-
- char realPath[PATH_MAX];
- if (realpath(path.c_str(), realPath) != nullptr && realPath[0] != '\0')
- {
- absPath.assign(realPath);
- }
+ this->launcher = launcher;
+#define WITH_SELF(data) \
+ LaunchpadAdapterImpl* self = static_cast<LaunchpadAdapterImpl*>(data); \
+ if (self == nullptr) \
+ { \
+ _ERR("No LaunchpadImplData"); \
+ } else
- return absPath;
-}
-static std::string Basename(const std::string& path)
-{
- auto pos = path.find_last_of(PATH_SEPARATOR);
- if (pos != std::string::npos)
+ callbacks.create = [](bundle *extra, int type, void *user_data)
{
- return path.substr(0, pos);
- }
- else
- {
- return std::string(".");
- }
- return path;
-}
-
-static bool EndWithIC(const std::string& str1, const std::string& str2, std::string& filename)
-{
- std::string::size_type len1 = str1.length();
- std::string::size_type len2 = str2.length();
- if (len2 > len1) return false;
-
- int i = 0;
- bool result = std::all_of(str1.cend() - len2, str1.end(),
- [&i, &str2] (char x) {
- return std::tolower(x) == std::tolower(str2[i++]);
- });
- if (result)
+ WITH_SELF(user_data)
+ {
+ self->OnCreate();
+ }
+ };
+ callbacks.launch = [](int argc, char** argv, const char* app_path,
+ const char* appid, const char* pkgid,
+ const char* pkg_type, void* user_data) -> int
{
- filename = str1.substr(0, len1 - len2);
- }
- return result;
-}
-
-static std::string AssembliesInDirectory(const char *directory)
-{
- const std::string ni = ".ni";
- const std::string tpaExtensions[] =
- {".ni.dll", ".dll", ".ni.exe", ".exe"};
- const bool tpaExtensions_ni[] =
- {true, false, true, false};
-
- std::string tpaList;
-
- DIR* dir = opendir(directory);
+ WITH_SELF(user_data)
+ {
+ self->OnLaunch();
+ self->launchPath = std::string(app_path);
+ }
- if (dir == nullptr)
+ return 0;
+ };
+ callbacks.terminate = [](int argc, char **argv, void* user_data) -> int
{
- _ERR("can not open directory : [%s]", directory);
- return std::string();
- }
-
- _DBG("assemblies in %s", directory);
-
- std::set<std::string> addedAssemblies;
-
- struct dirent *entry;
+ _DBG("Terminate!!");
+ WITH_SELF(user_data)
+ {
+ self->OnTerminate();
+ //self->launcher->Launch(self->launchPath.c_str(), argc, argv);
+ }
+ return 0;
+ };
- int tpaCount = sizeof(tpaExtensions) / sizeof(tpaExtensions[0]);
- for (int i=0; i<tpaCount; i++)
+ adapter.loop_begin = [](void *data)
{
- const std::string& ext = tpaExtensions[i];
- bool isNativeExt = tpaExtensions_ni[i];
-
- while ((entry = readdir(dir)) != nullptr)
+ _DBG("start polling...");
+ WITH_SELF(data)
{
- switch (entry->d_type)
+ self->Waiting = true;
+ while(self->Waiting)
{
- case DT_REG: break;
- case DT_LNK:
- case DT_UNKNOWN:
- {
- std::string fullname;
- fullname.append(directory);
- fullname += PATH_SEPARATOR;
- fullname.append(entry->d_name);
-
- struct stat sb;
- if (stat(fullname.c_str(), &sb) == -1)
- continue;
-
- if (!S_ISREG(sb.st_mode))
- continue;
- }
- break;
- default:
+ if (poll(self->FdList.data(), self->FdList.size(), -1) < 0)
continue;
- }
-
- // Check the extension.
- std::string filename(entry->d_name);
- std::string filenameWithoutExt;
- if (!EndWithIC(filename, ext, filenameWithoutExt))
- continue;
- if (!isNativeExt)
- {
- EndWithIC(filenameWithoutExt, ni, filenameWithoutExt);
- }
-
- if (addedAssemblies.find(filenameWithoutExt) == addedAssemblies.end())
- {
- addedAssemblies.insert(filenameWithoutExt);
- std::string assembly;
- assembly.append(directory);
- assembly += PATH_SEPARATOR;
- assembly.append(filename);
- //_DBG("TPA : %s", assembly.c_str());
- tpaList += assembly + ':';
+ _DBG("-----------------------------------------------------------4");
+ for (auto &p : self->FdList)
+ {
+ if ( (p.revents | POLLIN) != 0)
+ self->Handlers[p.fd].receiver(p.fd);
+ }
+ _DBG("-----------------------------------------------------------5");
}
}
- rewinddir(dir);
- }
-
- closedir(dir);
- return tpaList;
-}
-
-static int RunLauncherDll(int argc, char* argv[])
-{
- std::string coreclr_dir(RuntimeDirectory);
- std::string libcoreclr(ConcatPath(coreclr_dir, "libcoreclr.so"));
- std::string tpa_dirs(coreclr_dir + ":" + DeviceAPIDirectory);
- std::string native_so_search_dirs(tpa_dirs);
- std::string launcher_assembly(AbsolutePath(LauncherAssembly));
-
- if (launcher_assembly.empty())
- {
- _ERR("Invalid Launcher assembly path.");
- return 1;
- }
-
- std::string launcher_dir = Basename(launcher_assembly);
- std::string trusted_assemblies = launcher_assembly + ":";
+ _DBG("end polling...");
+ };
- std::istringstream f(tpa_dirs);
- std::string s;
- while (std::getline(f, s, ':'))
+ adapter.loop_quit = [](void *data)
{
- trusted_assemblies += AssembliesInDirectory(s.c_str());
- }
-
- _DBG("libcoreclr : %s", libcoreclr.c_str());
- _DBG("coreclr_dir : %s", coreclr_dir.c_str());
- _DBG("tpa_dirs : %s", tpa_dirs.c_str());
- _DBG("native_so_search_dir : %s", native_so_search_dirs.c_str());
- _DBG("launcher_assembly : %s", launcher_assembly.c_str());
- _DBG("launcher_dir : %s", launcher_dir.c_str());
+ WITH_SELF(data)
+ {
+ self->Waiting = false;
+ }
+ };
- void *coreclrLib = dlopen(libcoreclr.c_str(), RTLD_NOW | RTLD_LOCAL);
- if (coreclrLib == nullptr)
+ adapter.add_fd = [](void *data, int fd, loader_receiver_cb receiver)
{
- char *err = dlerror();
- _ERR("dlopen failed to open libcoreclr.so with error %s", err);
- return 1;
- }
-
-#define CORELIB_RETURN_IF_NOSYM(type, variable, name) \
- type variable; \
- do { variable = (type)dlsym(coreclrLib, name); \
- if (variable == nullptr) { \
- _ERR(name " is not found in the libcoreclr.so"); \
- return 1; \
- }} while(0)
+ WITH_SELF(data)
+ {
+ pollfd info;
+ FdHandler handler;
- CORELIB_RETURN_IF_NOSYM(coreclr_initialize_ptr, coreclr_initialize, "coreclr_initialize");
- CORELIB_RETURN_IF_NOSYM(coreclr_execute_assembly_ptr, coreclr_execute_assembly, "coreclr_execute_assembly");
- CORELIB_RETURN_IF_NOSYM(coreclr_shutdown_ptr, coreclr_shutdown, "coreclr_shutdown");
- CORELIB_RETURN_IF_NOSYM(coreclr_create_delegate_ptr, coreclr_create_delegate, "coreclr_create_delegate");
+ info.fd = fd;
+ info.events = POLLIN;
+ info.revents = 0;
-#undef CORELIB_RETURN_IF_NOSYM
+ self->FdList.push_back(info);
+ handler.info = &((self->FdList).back());
+ handler.receiver = receiver;
- const char *propertyKeys[] =
- {
- "TRUSTED_PLATFORM_ASSEMBLIES",
- "APP_PATHS",
- "APP_NI_PATHS",
- "NATIVE_DLL_SEARCH_DIRECTORIES",
- "AppDomainCompatSwitch"
+ self->Handlers[fd] = handler;
+ }
};
- const char *propertyValues[] =
+ adapter.remove_fd = [](void *user_data, int fd)
{
- trusted_assemblies.c_str(),
- launcher_dir.c_str(),
- launcher_dir.c_str(),
- native_so_search_dirs.c_str(),
- "UseLatestBehaviorWhenTFMNotSpecified"
+ WITH_SELF(user_data)
+ {
+ pollfd *info = self->Handlers[fd].info;
+ self->FdList.erase(self->FdList.begin() - (info - &(self->FdList.front())));
+ self->Handlers.erase(fd);
+ }
};
- //_DBG("trusted platform assemblies : %s", propertyValues[0]);
- _DBG("app_path : %s", propertyValues[1]);
- _DBG("app_ni_path : %s", propertyValues[2]);
- _DBG("native dll search path : %s", propertyValues[3]);
- _DBG("app domain compat switch : %s", propertyValues[4]);
-
- _DBG("before initialize coreclr");
-
- void* hostHandle;
- unsigned int domainId;
-
- std::string selfPath = ReadSelfPath();
-
- int st = coreclr_initialize(selfPath.c_str(),
- "tizen_dotnet_launcher",
- sizeof(propertyKeys) / sizeof(propertyKeys[0]),
- propertyKeys,
- propertyValues,
- &hostHandle,
- &domainId);
-
- _DBG("after initialize coreclr");
- if (st < 0)
- {
- // initialize coreclr fail
- _ERR("initialize core clr fail! (0x%08x)", st);
- _DBG("check your smack label dll and every directories on the way to dlls");
- return 1;
- }
-
- struct stat sb;
- if (stat(launcher_assembly.c_str(), &sb) == -1)
+ pollingThread = std::thread([this, argc, argv]()
{
- _ERR("Launcher assembly is not exist in %s", launcher_assembly.c_str());
- return 1;
- }
+ _DBG("launchpad_loader_main is start");
+ int r = launchpad_loader_main(argc, argv, &(this->callbacks), &(this->adapter), this);
+ _DBG("launchpad_loader_main is finished with [%d]", r);
+ });
+ //pollingThread.detach();
+}
- unsigned int exitCode;
- const char** cargv = const_cast<const char**>(argv);
- st = coreclr_execute_assembly(hostHandle, domainId,
- argc, cargv, launcher_assembly.c_str(), &exitCode);
- _DBG("after execute coreclr");
- if (st < 0)
+void LaunchpadAdapterImpl::WaitUtilLaunched()
+{
+ try
{
- _ERR("execute core clr fail! (0x%08x / %d)", st, exitCode);
- return 1;
+ if (pollingThread.joinable())
+ {
+ pollingThread.join();
+ }
}
-
- st = coreclr_shutdown(hostHandle, domainId);
- if (st < 0)
+ catch (const std::exception& ex)
{
- _ERR("shutdown core clr fail! (0x%08x)", st);
- return 1;
+ _ERR("Exception : %s", ex.what());
}
+}
- if (dlclose(coreclrLib) != 0)
- {
- _ERR("libcoreclr.so close failed");
- return 1;
- }
+void LaunchpadAdapterImpl::OnCreate()
+{
+}
- return 0;
+void LaunchpadAdapterImpl::OnLaunch()
+{
}
-int main(int argc, char *argv[])
+void LaunchpadAdapterImpl::OnTerminate()
{
-#ifdef NO_TIZEN
- const char *_deviceapi_directory = getenv("DeviceAPIDirectory");
- const char *_runtime_directory = getenv("RuntimeDirectory");
- const char *_launcher_assembly = getenv("LauncherAssembly");
- if (_deviceapi_directory != nullptr)
- DeviceAPIDirectory = _deviceapi_directory;
- if (_runtime_directory != nullptr)
- RuntimeDirectory = _runtime_directory;
- if (_launcher_assembly != nullptr)
- LauncherAssembly = _launcher_assembly;
-#endif
- _DBG("launcher started");
- return RunLauncherDll(argc, argv);
}
+
+
+} // namespace runtime
+} // namespace tizen
diff --git a/NativeLauncher/src/launcher.h b/NativeLauncher/src/launcher.h
deleted file mode 100644
index 4800ddf..0000000
--- a/NativeLauncher/src/launcher.h
+++ /dev/null
@@ -1,78 +0,0 @@
-#include <string>
-#include <vector>
-
-namespace dotnet {
-namespace runtime {
-
-typedef int (*coreclr_initialize_ptr)(
- const char* exePath,
- const char* appDomainFriendlyName,
- int propertyCount,
- const char** propertyKeys,
- const char** propertyValues,
- void** hostHandle,
- unsigned int* domainId);
-
-typedef int (*coreclr_execute_assembly_ptr)(
- void* hostHandle,
- unsigned int domainId,
- int argc,
- const char** argv,
- const char* managedAssemblyPath,
- unsigned int* exitCode);
-
-typedef int (*coreclr_shutdown_ptr)(
- void* hostHandle,
- unsigned int domainId);
-
-typedef int (*coreclr_create_delegate_ptr)(
- void* hostHandle,
- unsigned int domainId,
- const char* entryPointAssemblyName,
- const char* entryPointTypeName,
- const char* entryPointMethodName,
- void** delegate);
-
-typedef bool (*AssemblyManager_Initialize)(
- const char* searchableDirectories,
- const char* preloadDllPaths);
-
-typedef void (*AssemblyManager_AddAssemblyDir)(const char* dir);
-typedef void (*AssemblyManager_RemoveAssemblyDir)(const char* dir);
-
-typedef void (*AssemblyManager_Execute)(const char* dllPath);
-typedef void (*AssemblyManager_Finish)(void);
-
-using std::string;
-using std::vector;
-
-class Launcher
-{
- public:
- Launcher();
- ~Launcher();
- void Initialize();
-
- private:
- coreclr_initialize_ptr initializeCoreCLR;
-// coreclr_execute_assembly_ptr executeAssembly;
- coreclr_shutdown_ptr shutdownCoreCLR;
- coreclr_create_delegate_ptr createDelegate;
-
- string TrustedPlatformAssemblies;
- string NativeDllSearchDirectories;
- string AppDomainCompatSwitch;
-
- void *coreclrLib;
-
- AssemblyManager_Initialize assemblyManagerInitialize;
- AssemblyManager_Execute assemblyManagerExecute;
- AssemblyManager_Finish assemblyManagerFinish;
- AssemblyManager_AddAssemblyDir assemblyManagerAddDir;
- AssemblyManager_RemoveAssemblyDir assemblyManagerRemoveDir;
-
- bool initialized;
-};
-
-} // namespace runtime
-} // namespace dotnet
diff --git a/NativeLauncher/src/tini.hpp b/NativeLauncher/src/tini.hpp
deleted file mode 100644
index fac3424..0000000
--- a/NativeLauncher/src/tini.hpp
+++ /dev/null
@@ -1,162 +0,0 @@
-#include <string>
-#include <map>
-#include <vector>
-#include <sstream>
-#include <algorithm>
-#include <functional>
-
-namespace tini
-{
-
-const std::string global = "___GLOBAL";
-
-inline void ltrim(std::string& s)
-{
- s.erase(s.begin(), std::find_if(s.begin(), s.end(),
- std::not1(std::ptr_fun<int, int>(std::isspace))));
-}
-
-inline void rtrim(std::string& s)
-{
- s.erase(std::find_if(s.rbegin(), s.rend(),
- std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
-}
-
-inline void trim(std::string& s)
-{
- ltrim(s);
- rtrim(s);
-}
-
-inline int find_first_nonescaped(const std::string& str, char ch)
-{
- if (!str.empty())
- {
- if (str[0] == ch) return 0;
- for (size_t i=1; i<str.length(); i++)
- {
- if (str[i] == ch && str[i-1] != '\\')
- return i;
- }
- }
- return -1;
-}
-
-inline std::string uncomment(const std::string& str)
-{
- int comment_start = find_first_nonescaped(str, '#');
- if (comment_start < 0) return str;
- return str.substr(0, comment_start);
-}
-
-inline bool get_header(const std::string& str, std::string& header)
-{
- if (str.length() < 2 || str.front() != '[' || str.back() != ']') return false;
- std::string expected = std::string(str.begin()+1, str.end()-1);
- trim(expected);
- if (expected.compare(header) != 0)
- {
- header = expected;
- return true;
- }
- return false;
-}
-
-inline std::pair<std::string, std::string> get_pair(const std::string& str)
-{
- std::string key, value;
- std::string::size_type eq_pos = str.find('=');
- if (eq_pos == std::string::npos)
- {
- key = str;
- }
- else
- {
- key = str.substr(0, eq_pos);
- value = str.substr(eq_pos+1);
- trim(value);
- }
- trim(key);
- return std::pair<std::string, std::string>(key, value);
-}
-
-class ini
-{
- public:
- using pairs = std::map<std::string, std::string>;
- ini()
- {
- }
- ini(const std::string& str)
- {
- std::istringstream input(str);
- init(input);
- }
- ini(std::istream &input)
- {
- init(input);
- }
- inline void init (std::istream &input)
- {
- std::string line;
- std::string title(global);
- while (std::getline(input, line))
- {
- line = uncomment(line);
- if (line.empty()) continue;
- trim(line);
- if (get_header(line, title) && groups.find(title) == groups.end())
- {
- groups[title] = std::map<std::string, std::string>();
- continue;
- }
-
- auto pair = get_pair(line);
- groups[title][pair.first] = pair.second;
- }
- }
- std::string to_string() const
- {
- std::stringstream str_out;
- auto gpair = groups.find(global);
- if (gpair != groups.end())
- {
- for (auto &pair : gpair->second)
- {
- str_out << pair.first << " = " << pair.second << std::endl;
- }
- }
- for (auto &group : groups)
- {
- auto &title = group.first;
- if (title == global) continue;
- auto &pairs = group.second;
- str_out << '[' << title << ']' << std::endl;
- for (auto &pair : pairs)
- {
- str_out << pair.first << " = " << pair.second << std::endl;
- }
- }
-
- return str_out.str();
- }
-
- pairs& operator [](const std::string& group_name)
- {
- if (groups.find(group_name) == groups.end())
- {
- groups[group_name] = pairs();
- }
- return groups[group_name];
- }
-
- std::map<std::string, pairs> groups;
-};
-
-std::ostream& operator << (std::ostream& os, const ini& rhs)
-{
- os << rhs.to_string();
- return os;
-}
-
-} // namespace tini
diff --git a/NativeLauncher/src/utils.cc b/NativeLauncher/src/utils.cc
new file mode 100644
index 0000000..776fd9f
--- /dev/null
+++ b/NativeLauncher/src/utils.cc
@@ -0,0 +1,211 @@
+
+#include <dirent.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <limits.h>
+#include <strings.h>
+
+#include <cstdlib>
+#include <cstring>
+#include <algorithm>
+#include <set>
+#include <vector>
+#include <iterator>
+#include <sstream>
+
+#include "utils.h"
+
+std::string ReadSelfPath()
+{
+ char buff[PATH_MAX];
+ ssize_t len = ::readlink("/proc/self/exe", buff, sizeof(buff)-1);
+ if (len != -1) {
+ buff[len] = '\0';
+ return std::string(buff);
+ }
+
+ return "";
+}
+
+std::string ConcatPath(const std::string& path1, const std::string& path2)
+{
+ std::string path(path1);
+ if (path.back() == PATH_SEPARATOR)
+ {
+ path.append(path2);
+ }
+ else
+ {
+ path += PATH_SEPARATOR;
+ path.append(path2);
+ }
+
+ return path;
+}
+
+void AppendPath(std::string& path1, const std::string& path2)
+{
+ if (path1.back() == PATH_SEPARATOR)
+ {
+ path1.append(path2);
+ }
+ else
+ {
+ path1 += PATH_SEPARATOR;
+ path1.append(path2);
+ }
+}
+
+std::string AbsolutePath(const std::string& path)
+{
+ std::string absPath;
+
+ char realPath[PATH_MAX];
+ if (realpath(path.c_str(), realPath) != nullptr && realPath[0] != '\0')
+ {
+ absPath.assign(realPath);
+ }
+
+ return absPath;
+}
+
+std::string Basename(const std::string& path)
+{
+ auto pos = path.find_last_of(PATH_SEPARATOR);
+ if (pos != std::string::npos)
+ {
+ return path.substr(0, pos);
+ }
+ else
+ {
+ return std::string(".");
+ }
+ return path;
+}
+
+bool EndWithIgnoreCase(const std::string& str1, const std::string& str2, std::string& filename)
+{
+ std::string::size_type len1 = str1.length();
+ std::string::size_type len2 = str2.length();
+ if (len2 > len1) return false;
+
+ int i = 0;
+ bool result = std::all_of(str1.cend() - len2, str1.end(),
+ [&i, &str2] (char x) {
+ return std::tolower(x) == std::tolower(str2[i++]);
+ });
+ if (result)
+ {
+ filename = str1.substr(0, len1 - len2);
+ }
+ return result;
+}
+
+bool FileNotExist(const std::string& path)
+{
+ struct stat sb;
+ return (stat(path.c_str(), &sb) != 0) || !S_ISREG(sb.st_mode);
+}
+
+static bool ExtCheckAndGetFileNameIfExist(const std::string& dir, const std::string& ext, struct dirent* entry, std::string& filename)
+{
+ std::string fname(entry->d_name);
+ if (fname.length() < ext.length() ||
+ fname.compare(fname.length() - ext.length(), ext.length(), ext) != 0)
+ {
+ return false;
+ }
+ std::string fullname = ConcatPath(dir, entry->d_name);
+ switch (entry->d_type)
+ {
+ case DT_REG: break;
+ case DT_LNK:
+ case DT_UNKNOWN:
+ if (FileNotExist(fullname))
+ {
+ return false;
+ }
+ default:
+ return false;
+ }
+
+ filename = fullname;
+
+ return true;
+}
+
+std::string StripNIDLL(const std::string& path)
+{
+ std::string npath(path);
+ if (path.size() < 5) return npath;
+ if (strncasecmp(path.c_str() + path.size() - 4, ".dll", 4))
+ {
+ npath = path.substr(0, path.size()-4);
+ }else if (strncasecmp(path.c_str() + path.size() - 4, ".exe", 4))
+ {
+ npath = path.substr(0, path.size()-4);
+ }
+ if (strncasecmp(npath.c_str() + npath.size() - 3, ".ni", 3))
+ {
+ return npath.substr(0, npath.size()-3);
+ }
+ return npath;
+}
+
+std::string JoinStrings(const std::vector<std::string>& strings, const char* const delimeter)
+{
+ switch (strings.size())
+ {
+ case 0:
+ return "";
+ case 1:
+ return strings[0];
+ default:
+ std::ostringstream os;
+ std::copy(strings.begin(), strings.end()-1, std::ostream_iterator<std::string>(os, delimeter));
+ os << *strings.rbegin();
+ return os.str();
+ }
+}
+
+void AssembliesInDirectory(const std::vector<std::string>& directories, std::string& tpaList)
+{
+ static const std::string tpaExtensions[] =
+ {".ni.dll", ".dll", ".ni.exe", ".exe"};
+
+ std::set<std::string> addedAssemblies;
+
+ DIR* dir = nullptr;
+ struct dirent* entry = nullptr;
+
+ for (auto directory : directories)
+ {
+ dir = opendir(directory.c_str());
+ if (dir == nullptr)
+ {
+ continue;
+ }
+
+ for (auto ext : tpaExtensions)
+ {
+ while ((entry = readdir(dir)) != nullptr)
+ {
+ std::string fullname;
+ if (ExtCheckAndGetFileNameIfExist(directory.c_str(), ext, entry, fullname))
+ {
+ std::string filename = StripNIDLL(fullname);
+ if (addedAssemblies.find(filename) == addedAssemblies.end())
+ {
+ addedAssemblies.insert(filename);
+ tpaList += fullname + ':';
+ }
+ }
+ }
+ rewinddir(dir);
+ }
+ closedir(dir);
+ }
+ if (tpaList.back() == ':')
+ tpaList.pop_back();
+
+}
diff --git a/NativeLauncher/src/waiter.cc b/NativeLauncher/src/waiter/waiter.cc
index 6447d4a..6447d4a 100644
--- a/NativeLauncher/src/waiter.cc
+++ b/NativeLauncher/src/waiter/waiter.cc
diff --git a/NativeLauncher/src/waiter.h b/NativeLauncher/src/waiter/waiter.h
index c4b98fb..c4b98fb 100644
--- a/NativeLauncher/src/waiter.h
+++ b/NativeLauncher/src/waiter/waiter.h
diff --git a/Tizen.Runtime/Tizen.Runtime/AssemblyManager.cs b/Tizen.Runtime/Tizen.Runtime/AssemblyManager.cs
index 0eeaffa..6a13648 100644
--- a/Tizen.Runtime/Tizen.Runtime/AssemblyManager.cs
+++ b/Tizen.Runtime/Tizen.Runtime/AssemblyManager.cs
@@ -3,11 +3,29 @@ using System.IO;
using System.Reflection;
using System.Runtime.Loader;
using System.Linq;
+using System.Runtime.InteropServices;
namespace Tizen.Runtime
{
public static class AssemblyManager
{
+ public static bool Launch(
+ [In] string path,
+ [In] int argc,
+ [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)]
+ [In] string[] argv)
+ {
+ Console.WriteLine($"path : {path}");
+ Console.WriteLine($"argc : {argc}");
+ for (int i=0; i<argc; i++)
+ {
+ Console.WriteLine($"argv[{i}] : " + argv[i]);
+ }
+ Console.WriteLine();
+
+ return true;
+ }
+
public static int Prepared(IntPtr data)
{
try
@@ -82,11 +100,14 @@ namespace Tizen.Runtime
{
try
{
+ /*
preparedCallback = Prepared;
requestedCallback = Requested;
executedCallback = Executed;
Interop.register_launching_callback(preparedCallback, requestedCallback, executedCallback, IntPtr.Zero);
Interop.wait_for_launching(args.Length, args);
+ */
+ Console.WriteLine("HelloWorld!!");
}
catch(Exception e)
{
diff --git a/packaging/dotnet-launcher.spec b/packaging/dotnet-launcher.spec
index d6d4ab4..c82b091 100644
--- a/packaging/dotnet-launcher.spec
+++ b/packaging/dotnet-launcher.spec
@@ -60,7 +60,7 @@ cmake \
-DVERSION=%{version} \
NativeLauncher
-make %{?jobs:-j%jobs}
+make %{?jobs:-j%jobs} VERBOSE=1
xbuild \
/p:Configuration=%{_buildmode} \
@@ -77,5 +77,4 @@ install -p -m 644 Tizen.Runtime/bin/Tizen.Runtime.exe %{buildroot}%{_bindir}
%manifest dotnet-launcher.manifest
%{_loaderdir}/dotnet.loader
%caps(cap_mac_admin,cap_setgid=ei) %{_bindir}/dotnet-launcher
-%caps(cap_mac_admin,cap_setgid=ei) %{_libdir}/libdnclauncher.so
%caps(cap_mac_admin,cap_setgid=ei) %{_bindir}/Tizen.Runtime.exe
diff --git a/test_build_on_desktop.sh b/test_build_on_desktop.sh
index a013029..bcd8337 100755
--- a/test_build_on_desktop.sh
+++ b/test_build_on_desktop.sh
@@ -14,9 +14,10 @@ PreloadPath=`readlink -e ./preloads`
mkdir build
cd build
-cmake -DCMAKE_BUILD_TYPE=Debug -DNO_TIZEN=1 -DLAUNCHER_ASSEMBLY_PATH=Tizen.Runtime.exe -DDEVICE_API_DIR=$TizenDeviceAPIDir -DRUNTIME_DIR=$RuntimeDir ../NativeLauncher/
-make
-xbuild /t:Clean ../Tizen.Runtime/Tizen.Runtime.csproj
+#xbuild /t:Clean ../Tizen.Runtime/Tizen.Runtime.csproj
#xbuild /verbosity:diagnostic /p:CLOG=1 /p:ExternalCscPath=/home/idkiller/work/runtime/roslyn/Binaries/Debug/csccore/csc.exe /p:LauncherConfigPath=$LauncherConfigPath /p:CoreFXRefPath=$CoreFXRefPath /p:TizenDeviceAPIPath=$TizenDeviceAPIPath ../Tizen.Runtime/Tizen.Runtime.csproj
-xbuild /p:CLOG=1 /p:ExternalCscDir=$RoslynCscDir /p:ExternalCscExe=$RoslynCscExe /p:LauncherConfigPath=$LauncherConfigPath /p:CoreFXRefPath=$CoreFXRefPath /p:TizenDeviceAPIPath=$TizenDeviceAPIPath /p:PreloadPath=$PreloadPath ../Tizen.Runtime/Tizen.Runtime.csproj
-cp ../Tizen.Runtime/bin/Tizen.Runtime.* .
+#xbuild /p:CLOG=1 /p:ExternalCscDir=$RoslynCscDir /p:ExternalCscExe=$RoslynCscExe /p:LauncherConfigPath=$LauncherConfigPath /p:CoreFXRefPath=$CoreFXRefPath /p:TizenDeviceAPIPath=$TizenDeviceAPIPath /p:PreloadPath=$PreloadPath ../Tizen.Runtime/Tizen.Runtime.csproj
+#cp ../Tizen.Runtime/bin/Tizen.Runtime.* .
+
+cmake -DCMAKE_BUILD_TYPE=Debug -DNO_TIZEN=1 -DLAUNCHER_ASSEMBLY_PATH=Tizen.Runtime.exe -DDEVICE_API_DIR=$TizenDeviceAPIDir -DRUNTIME_DIR=$RuntimeDir ../NativeLauncher/
+make -j16