CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
-PROJECT("dotnet-launcher")
+PROJECT("dotnet-tools")
MESSAGE("CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}")
SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -DNO_TIZEN")
ELSE(DEFINED NO_TIZEN)
INCLUDE(FindPkgConfig)
- PKG_CHECK_MODULES(${PROJECT_NAME} REQUIRED aul dlog ecore bundle dlog launchpad)
+ PKG_CHECK_MODULES(${PROJECT_NAME} REQUIRED aul pkgmgr-info pkgmgr-installer dlog ecore bundle dlog launchpad)
ENDIF(DEFINED NO_TIZEN)
FOREACH(flag ${${PROJECT_NAME}_CFLAGS})
SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -DRUNTIME_DIR=${RUNTIME_DIR}")
ENDIF(DEFINED RUNTIME_DIR)
+IF(DEFINED CROSSGEN_PATH)
+ SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -DCROSSGEN_PATH=${CROSSGEN_PATH}")
+ENDIF(DEFINED CROSSGEN_PATH)
+
IF(DEFINED VERSION)
SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -DVERSION=${VERSION}")
ENDIF(DEFINED VERSION)
SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -pthread -std=c++11 -Wl,--no-as-needed -ggdb")
SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Wl,-zdefs" )
#SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden")
-SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fPIE")
+#SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fPIE")
SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fdata-sections -ffunction-sections -Wl,--gc-sections")
SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -D_FILE_OFFSET_BITS=64")
#SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -DLAUNCHING_TIME_MEASURE")
SET(CMAKE_CXX_FLAGS_RELEASE "-O2")
SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed")
-INCLUDE_DIRECTORIES(inc)
+#SET(${PROJECT_NAME}_LDFLAGS ${${PROJECT_NAME}_LDFLAGS} "-pie")
-SET(DOTNET_LAUNCHER "dotnet-launcher")
-SET(MONO_LAUNCHER "mono-launcher")
+INCLUDE_DIRECTORIES(inc launcher util)
+SET(DOTNET_LAUNCHER "dotnet-launcher")
SET(${DOTNET_LAUNCHER}_SOURCE_FILES
- src/main.cc
- src/utils.cc
- src/launcher.cc
- src/dotnet/dotnet_launcher.cc
- src/mono/mono_launcher.cc
+ launcher/main.cc
+ util/utils.cc
+ launcher/launcher.cc
+ launcher/dotnet/dotnet_launcher.cc
+ launcher/mono/mono_launcher.cc
)
-ADD_EXECUTABLE(${DOTNET_LAUNCHER} ${${PROJECT_NAME}_SOURCE_FILES})
+ADD_EXECUTABLE(${DOTNET_LAUNCHER} ${${DOTNET_LAUNCHER}_SOURCE_FILES})
+SET_TARGET_PROPERTIES(${DOTNET_LAUNCHER} PROPERTIES COMPILE_FLAGS "-fPIE")
IF(NOT DEFINED NO_TIZEN)
TARGET_LINK_LIBRARIES(${DOTNET_LAUNCHER} aul)
SET_TARGET_PROPERTIES(${DOTNET_LAUNCHER}
PROPERTIES SKIP_BUILD_RPATH TRUE
- ) # remove rpath option that is automatically generated by cmake.
+) # remove rpath option that is automatically generated by cmake.
+
+SET(NITOOL "nitool")
+SET(${NITOOL}_SOURCE_FILES
+ util/utils.cc
+ installer-plugin/common.cc
+ installer-plugin/nitool.cc
+)
+ADD_EXECUTABLE(${NITOOL} ${${NITOOL}_SOURCE_FILES})
+SET_TARGET_PROPERTIES(${NITOOL} PROPERTIES COMPILE_FLAGS "-fPIE")
+TARGET_LINK_LIBRARIES(${NITOOL} ${${PROJECT_NAME}_LDFLAGS} "-pie")
+
+SET(INSTALLER_PLUGIN "ui-application")
+SET(${INSTALLER_PLUGIN}_SOURCE_FILES
+ util/utils.cc
+ installer-plugin/common.cc
+ installer-plugin/ui-application.cc
+)
+ADD_LIBRARY(${INSTALLER_PLUGIN} SHARED ${${INSTALLER_PLUGIN}_SOURCE_FILES})
+SET_TARGET_PROPERTIES(${INSTALLER_PLUGIN} PROPERTIES COMPILE_FLAGS "-fPIC")
+TARGET_LINK_LIBRARIES(${INSTALLER_PLUGIN} ${${PROJECT_NAME}_LDFLAGS})
IF(NOT DEFINED NO_TIZEN)
INSTALL(TARGETS ${DOTNET_LAUNCHER} DESTINATION ${BINDIR})
+ INSTALL(TARGETS ${NITOOL} DESTINATION ${BINDIR})
+ INSTALL(TARGETS ${INSTALLER_PLUGIN} DESTINATION ${INSTALL_PLUGIN_DIR})
INSTALL(FILES dotnet.loader DESTINATION ${LOADERDIR})
INSTALL(FILES dotnet.launcher DESTINATION ${LOADERDIR})
- INSTALL(FILES dotnet.debugger DESTINATION ${LOADERDIR})
+ INSTALL(FILES dotnet.debugger DESTINATION ${LOADERDIR})
ENDIF(NOT DEFINED NO_TIZEN)
+++ /dev/null
-#ifndef __LAUNCHER_INTERFACE_H__
-#define __LAUNCHER_INTERFACE_H__
-
-#include <string>
-#include <functional>
-
-namespace tizen {
-namespace runtime {
-
-class LauncherInterface
-{
- public:
- virtual int Initialize(bool standalone) = 0;
- virtual void Dispose() = 0;
- virtual int RunManagedLauncher() = 0;
- virtual int Launch(const char* root, const char* path, int argc, char* argv[]) = 0;
-};
-
-struct AppInfo
-{
- std::string root;
- std::string path;
- std::string id;
- std::string pkg;
- std::string type;
-};
-
-class LaunchpadAdapter
-{
- public:
- virtual void LoaderMain(int argc, char* argv[]) = 0;
- std::function<void()> OnCreate = nullptr;
- std::function<void(const AppInfo&, int, char**)> OnLaunch = nullptr;
- std::function<void(const AppInfo&, int, char**)> OnTerminate = nullptr;
-};
-
-extern LaunchpadAdapter& Launchpad;
-
-} // namespace runtime
-} // namespace tizen
-
-#endif // __LAUNCHER_INTERFACE_H__
#include <string>
#include <vector>
+#include <functional>
#ifndef PATH_SEPARATOR
#define PATH_SEPARATOR '/'
#endif
+bool ICompare(const std::string& a, const std::string& b);
+bool ICompare(const std::string& a, int a_offset, const std::string& b, int b_offset, int length);
+bool IsManagedAssembly(const std::string& filename);
+bool IsNativeImage(const std::string& filename);
std::string ReadSelfPath ();
std::string ConcatPath (const std::string& path1, const std::string& path2);
void AppendPath (std::string& path1, const std::string& path2);
bool FileNotExist(const std::string& path);
std::string JoinStrings(const std::vector<std::string>& strings, const char* const delimeter);
+typedef std::function<void (const char*)> FileReader;
+void ScanFilesInDir(const char* directory, FileReader reader, unsigned int depth);
+
#endif // __UTILS_H__
--- /dev/null
+#include <pkgmgr-info.h>
+#include <pkgmgr_installer_info.h>
+#include <aul.h>
+
+#include "log.h"
+#include "utils.h"
+#include "pkgmgr_parser_plugin_interface.h"
+
+#include <wait.h>
+#include <dirent.h>
+#include <sys/stat.h>
+
+#include <algorithm>
+#include <string>
+
+#include "common.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "NETCORE_INSTALLER_PLUGIN"
+
+#ifndef DEVICE_API_DIR
+#error "DEVICE_API_DIR is missed"
+#endif
+
+#ifndef RUNTIME_DIR
+#error "RUNTIME_DIR is missed"
+#endif
+
+#ifndef CROSSGEN_PATH
+#error "CROSSGEN_PATH is missed"
+#endif
+
+#define __XSTR(x) #x
+#define __STR(x) __XSTR(x)
+static const char* DeviceAPIDir = __STR(DEVICE_API_DIR);
+static const char* RuntimeDir = __STR(RUNTIME_DIR);
+static const char* CrossgenPath = __STR(CROSSGEN_PATH);
+static const char* JITPath = __STR(RUNTIME_DIR)"/libclrjit.so";
+#undef __STR
+#undef __XSTR
+
+static void crossgen(const char* dll_path, const char* app_path);
+static void smack_(const char* dll_path);
+
+void create_ni_platform()
+{
+ std::string corlib = ConcatPath(RuntimeDir, "System.Private.CoreLib.dll");
+ std::string nicorlib = ConcatPath(RuntimeDir, "System.Private.CoreLib.ni.dll");
+
+ if (FileNotExist(nicorlib))
+ {
+ crossgen(corlib.c_str(), nullptr);
+ smack_(nicorlib.c_str());
+ }
+
+ const char* platform_dirs[] = {RuntimeDir, DeviceAPIDir};
+ const char* ignores[] = {corlib.c_str()};
+
+ create_ni_under_dirs(platform_dirs, 2, ignores, 1, [](const char* ni){
+ smack_(ni);
+ });
+}
+
+static void smack_(const char* dll_path)
+{
+ static const char* CHKSMACK = "/usr/bin/chsmack";
+ pid_t pid = fork();
+ if (pid == -1)
+ {
+ return;
+ }
+
+ if (pid > 0)
+ {
+ int status;
+ waitpid(pid, &status, 0);
+ if (WIFEXITED(status))
+ {
+ return;
+ }
+ }
+ else
+ {
+ const char* args[] = {
+ CHKSMACK,
+ "-a", "_",
+ dll_path,
+ nullptr
+ };
+ for (const char* arg : args)
+ {
+ printf("%s ", arg);
+ }
+ printf("\n");
+
+ execv(CHKSMACK, const_cast<char*const*>(args));
+
+ exit(0);
+ }
+}
+
+static void crossgen(const char* dll_path, const char* app_path)
+{
+ //pid_t parent = getpid();
+ pid_t pid = fork();
+ if (pid == -1)
+ {
+ return;
+ }
+
+ if (pid > 0)
+ {
+ int status;
+ waitpid(pid, &status, 0);
+ if (WIFEXITED(status))
+ {
+ return;
+ }
+ }
+ else
+ {
+ std::vector<std::string> tpaDir = {
+ RuntimeDir, DeviceAPIDir
+ };
+ std::string tpa;
+ AssembliesInDirectory(tpaDir, tpa);
+
+ std::vector<const char*> argv =
+ {
+ CrossgenPath,
+ "/Trusted_Platform_Assemblies", tpa.c_str(),
+ "/JITPath", JITPath,
+ "/FragileNonVersionable"
+ };
+ if (app_path != nullptr)
+ {
+ argv.push_back("/App_Paths");
+ argv.push_back(app_path);
+ }
+ argv.push_back(dll_path);
+ argv.push_back(nullptr);
+
+ /*
+ for (const char* arg : argv)
+ {
+ printf("%s ", arg);
+ }
+ printf("\n");
+ */
+ printf("+ %s\n", dll_path);
+
+ execv(CrossgenPath, const_cast<char* const*>(argv.data()));
+ exit(0);
+ }
+}
+
+static int get_root_path(const char *pkgid, std::string& root_path)
+{
+ int ret = 0;
+ char *path = 0;
+
+ uid_t uid = 0;
+
+ if (pkgmgr_installer_info_get_target_uid(&uid) < 0)
+ {
+ _ERR("Failed to get UID");
+ return -1;
+ }
+
+ _INFO("user id is %d", uid);
+
+ pkgmgrinfo_pkginfo_h handle;
+ if (uid == 0)
+ {
+ ret = pkgmgrinfo_pkginfo_get_pkginfo(pkgid, &handle);
+ if (ret != PMINFO_R_OK)
+ return -1;
+ }
+ else
+ {
+ ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgid, uid, &handle);
+ if (ret != PMINFO_R_OK)
+ return -1;
+ }
+
+ ret = pkgmgrinfo_pkginfo_get_root_path(handle, &path);
+ if (ret != PMINFO_R_OK) {
+ pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
+ return -1;
+ }
+ root_path = path;
+ pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
+
+ return 0;
+}
+
+static bool NIExist(const std::string& path, std::string& ni)
+{
+ static const char* possible_exts[] = {
+ ".ni.dll", ".NI.dll", ".NI.DLL", ".ni.DLL"
+ };
+ std::string fname = path.substr(0, path.size() - 4);
+
+ struct stat sb;
+
+ for (const char* ext : possible_exts)
+ {
+ std::string f = fname + ext;
+ if (stat(f.c_str(), &sb) == 0)
+ {
+ ni = f;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void create_ni_under_dirs(const char* root_paths[], int count, const char* ignores[], int igcount, after_create cb)
+{
+ std::string app_paths;
+ for (int i=0; i<count; i++)
+ {
+ app_paths += root_paths[i];
+ app_paths += ':';
+ }
+ if (app_paths.back() == ':')
+ app_paths.pop_back();
+
+ auto convert = [&app_paths, ignores, igcount, &cb](const char* path)
+ {
+ for (int i=0; i<igcount; i++)
+ {
+ if (strcmp(path, ignores[i]) == 0)
+ return;
+ }
+ std::string ni;
+ if (IsManagedAssembly(path) && !IsNativeImage(path) && !NIExist(path, ni))
+ {
+ crossgen(path, app_paths.c_str());
+ if (NIExist(path, ni))
+ {
+ if (cb != nullptr)
+ {
+ cb(ni.c_str());
+ }
+ }
+ }
+ };
+
+ for (int i=0; i<count; i++)
+ {
+ ScanFilesInDir(root_paths[i], convert, -1);
+ }
+}
+void create_ni_under_dirs(const char* root_paths[], int count, after_create cb)
+{
+ create_ni_under_dirs(root_paths, count, nullptr, 0, cb);
+}
+void create_ni_under_dirs(const char* root_paths[], int count)
+{
+ create_ni_under_dirs(root_paths, count, nullptr);
+}
+
+int create_ni_under_pkg_root(const char* pkg_name)
+{
+ std::string pkgroot;
+ if (get_root_path(pkg_name, pkgroot) < 0)
+ {
+ return 1;
+ }
+
+ //printf("pkgroot : %s\n", pkgroot.c_str());
+
+ std::string bindir = ConcatPath(pkgroot, "bin");
+ std::string libdir = ConcatPath(pkgroot, "lib");
+
+ //printf("bindir : %s\n", bindir.c_str());
+ //printf("libdir : %s\n", libdir.c_str());
+ _INFO("bindir : %s", bindir.c_str());
+ _INFO("libdir : %s", libdir.c_str());
+
+ const char* paths[] = {
+ bindir.c_str(),
+ libdir.c_str()
+ };
+ create_ni_under_dirs(paths, 2);
+
+ return 0;
+}
--- /dev/null
+#ifndef __INSTALLER_PLUGIN_COMMON_H__
+#define __INSTALLER_PLUGIN_COMMON_H__
+
+#include <functional>
+
+typedef std::function<void (const char*)> after_create;
+void create_ni_under_dirs(const char* root_paths[], int count, const char* ignores[], int igcount, after_create cb);
+void create_ni_under_dirs(const char* root_paths[], int count, after_create cb);
+void create_ni_under_dirs(const char* root_paths[], int count);
+int create_ni_under_pkg_root(const char* pkg_name);
+void create_ni_platform();
+
+#endif // __INSTALLER_PLUGIN_COMMON_H__
--- /dev/null
+#include "common.h"
+
+#include <cstdio>
+#include <cstring>
+
+#include <algorithm>
+
+std::vector<const char*> get_cmd_args(char** begin, char** end)
+{
+ for (char** itr = end-1; itr != begin-1; --itr)
+ {
+ if (itr != end && strncmp(*itr, "--", 2) == 0)
+ {
+ itr++;
+ int len = end - itr;
+ return std::vector<const char*>(len, *itr);
+ }
+ }
+ return std::vector<const char*>(end-begin-1, *(begin+1));
+}
+
+bool cmd_option_exists(char** begin, char** end, const std::string& option)
+{
+ return std::find(begin, end, option) != end;
+}
+
+static void help(const char *argv0)
+{
+ const char* helpdesc =
+ "Usage: %s [args] <root paths or pkg name>\n"
+ " --help - Display this screen\n"
+ " --system - Create NI under System DLLs\n"
+ " --pkg - Create NI for package\n"
+ "\n"
+ "Example:\n"
+ "Create native image for dlls and exes under platform directories\n"
+ "%s --system\n"
+ "Create native image under the package's bin and lib directory\n"
+ "%s --pkg org.tizen.FormsGallery\n\n";
+ printf(helpdesc, argv0, argv0, argv0);
+}
+
+int main(int argc, char* argv[])
+{
+ bool pkg_mode = false;
+
+ if (cmd_option_exists(argv, argv+argc, "--help"))
+ {
+ help(argv[0]);
+ return 0;
+ }
+
+ if (cmd_option_exists(argv, argv+argc, "--system"))
+ {
+ create_ni_platform();
+ return 0;
+ }
+
+ if (cmd_option_exists(argv, argv+argc, "--pkg"))
+ {
+ pkg_mode = true;
+ }
+
+ std::vector<const char*> args = get_cmd_args(argv, argv+argc);
+
+ if (args.size() < 1)
+ {
+ if (pkg_mode)
+ fprintf(stderr, "Package name is missed\n");
+ else
+ fprintf(stderr, "DLL path is missed\n");
+ help(argv[0]);
+ return 1;
+ }
+
+ if (pkg_mode)
+ {
+ for (const char* pkg : args)
+ {
+ if (create_ni_under_pkg_root(pkg) != 0)
+ {
+ fprintf(stderr, "Failed to get root path from [%s]\n", pkg);
+ return 1;
+ }
+ }
+ }
+ else
+ {
+ create_ni_under_dirs(args.data(), args.size());
+ }
+
+ return 0;
+}
--- /dev/null
+#ifndef __PKGMGR_PARSER_PLUGIN_INTERFACE__
+#define __PKGMGR_PARSER_PLUGIN_INTERFACE__
+
+extern "C"
+{
+ typedef struct _xmlDoc xmlDoc;
+ typedef xmlDoc* xmlDocPtr;
+ int PKGMGR_PARSER_PLUGIN_PRE_INSTALL (const char *pkgid);
+ int PKGMGR_PARSER_PLUGIN_PRE_UPGRADE (const char *pkgid);
+ int PKGMGR_PARSER_PLUGIN_PRE_UNINSTALL (const char *pkgid);
+
+ int PKGMGR_PARSER_PLUGIN_INSTALL (xmlDocPtr doc, const char* pkgid);
+ int PKGMGR_PARSER_PLUGIN_UPGRADE (xmlDocPtr doc, const char* pkgid);
+ int PKGMGR_PARSER_PLUGIN_UNINSTALL (xmlDocPtr doc, const char* pkgid);
+
+ int PKGMGR_PARSER_PLUGIN_POST_INSTALL (const char *pkgid);
+ int PKGMGR_PARSER_PLUGIN_POST_UPGRADE (const char *pkgid);
+ int PKGMGR_PARSER_PLUGIN_POST_UNINSTALL (const char *pkgid);
+}
+
+#endif // __PKGMGR_PARSER_PLUGIN_INTERFACE__
--- /dev/null
+#include "common.h"
+#include "log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "NETCORE_INSTALLER_PLUGIN"
+
+#include <cstring>
+#include <pkgmgr-info.h>
+#include <pkgmgr_installer_info.h>
+
+/*
+ * forked crossgen from installer is not working.
+ * because crossgen's capability is not enough.
+ * following command is needed
+ *
+ * setcap cap_dac_override=eip /opt/usr/share/dotnet.tizen/framework/crossgen
+ *
+ */
+
+extern "C" int PKGMGR_PARSER_PLUGIN_POST_INSTALL (const char *pkgid)
+{
+ _INFO("pkg : %s", pkgid);
+
+ uid_t uid = 0;
+
+ if (pkgmgr_installer_info_get_target_uid(&uid) < 0)
+ {
+ _ERR("Failed to get UID");
+ return 0;
+ }
+
+ pkgmgrinfo_pkginfo_h handle;
+ int ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgid, uid, &handle);
+ if (ret != PMINFO_R_OK)
+ {
+ _ERR("Failed to get pkg info");
+ return 0;
+ }
+
+ _INFO("success to get pkg info");
+
+ bool dotnet_exist = false;
+
+ auto dotnet_app_counter = [] (pkgmgrinfo_appinfo_h handle, void *user_data) -> int
+ {
+ char* appid = nullptr;
+ char* type = nullptr;
+ bool* dotnet = static_cast<bool*>(user_data);
+
+ if (pkgmgrinfo_appinfo_get_appid(handle, &appid) != PMINFO_R_OK)
+ {
+ _ERR("Failed to get app id");
+ return 0;
+ }
+
+ _INFO("App id : %s", appid);
+
+ if (pkgmgrinfo_appinfo_get_apptype(handle, &type) != PMINFO_R_OK)
+ {
+ _ERR("Failed to get app type : %s", appid);
+ return 0;
+ }
+
+ _INFO("App type : %s", type);
+
+ if (strcmp(type, "dotnet") == 0)
+ {
+ *dotnet = true;
+ }
+
+ return 0;
+ };
+
+ if (pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP, dotnet_app_counter, &dotnet_exist, uid) != PMINFO_R_OK)
+ {
+ _ERR("Failed to get list of app in pkg : %s", pkgid);
+ return -1;
+ }
+
+ _INFO("Finish to get pkg list");
+
+ pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
+ if (dotnet_exist)
+ {
+ _INFO("dotnet app is exist");
+ return create_ni_under_pkg_root(pkgid) == 0 ? 0 : -1;
+ }
+
+ return 0;
+}
+extern "C" int PKGMGR_PARSER_PLUGIN_POST_UPGRADE (const char *pkgid)
+{
+ return PKGMGR_PARSER_PLUGIN_POST_INSTALL(pkgid);
+}
--- /dev/null
+
+#include <dlfcn.h>
+
+#include <string>
+#include <fstream>
+#include <vector>
+
+#include "utils.h"
+#include "log.h"
+#include "launcher.h"
+#include "dotnet_launcher.h"
+
+namespace tizen {
+namespace runtime {
+namespace dotnetcore {
+
+CoreRuntime::CoreRuntime() :
+ InitializeClr(nullptr),
+ ExecuteAssembly(nullptr),
+ Shutdown(nullptr),
+ CreateDelegate(nullptr),
+ coreclrLib(nullptr),
+ hostHandle(nullptr),
+ domainId(-1),
+ PreparedFunction(nullptr),
+ LaunchFunction(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 CORECLR_LAUNCHER_ASSEMBLY_PATH
+ LauncherAssembly = __STR(CORECLR_LAUNCHER_ASSEMBLY_PATH);
+#endif
+
+#undef __STR
+#undef __XSTR
+
+ _DBG("Constructor called!!");
+}
+
+CoreRuntime::~CoreRuntime()
+{
+ Dispose();
+}
+
+int CoreRuntime::Initialize(bool standalone)
+{
+
+ if (standalone)
+ {
+ 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;
+ }
+
+ 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;
+}
+
+bool CoreRuntime::InitializeCoreClr(const char* assembly_probe_paths, const char* pinvoke_probe_paths)
+{
+ std::vector<std::string> platformDirectories = {
+ RuntimeDirectory, DeviceAPIDirectory
+ };
+
+ std::string trusted_assemblies;
+ AssembliesInDirectory(platformDirectories, trusted_assemblies);
+
+ const char *propertyKeys[] =
+ {
+ "TRUSTED_PLATFORM_ASSEMBLIES",
+ "APP_PATHS",
+ "APP_NI_PATHS",
+ "NATIVE_DLL_SEARCH_DIRECTORIES",
+ "AppDomainCompatSwitch"
+ };
+
+ const char *propertyValues[] =
+ {
+ trusted_assemblies.c_str(),
+ assembly_probe_paths,
+ assembly_probe_paths,
+ pinvoke_probe_paths,
+ "UseLatestBehaviorWhenTFMNotSpecified"
+ };
+
+ std::string selfPath = ReadSelfPath();
+
+ int st = InitializeClr(
+ selfPath.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 false;
+ }
+
+ _DBG("Initialize core clr success");
+ return true;
+}
+
+int CoreRuntime::RunManagedLauncher()
+{
+ 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
+ };
+
+ std::string trusted_directories = JoinStrings(searchDirectories, ":");
+
+ _DBG("coreclr_dir : %s", RuntimeDirectory.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());
+
+ if (!InitializeCoreClr(launcherDir.c_str(), launcherDir.c_str()))
+ {
+ _ERR("Failed to initialize coreclr");
+ return 1;
+ }
+
+ void *preparedFunctionDelegate;
+ int st = CreateDelegate(hostHandle, domainId,
+ "Tizen.Runtime.Coreclr",
+ "Tizen.Runtime.Coreclr.AssemblyManager",
+ "Prepared", &preparedFunctionDelegate);
+ if (st < 0)
+ {
+ _ERR("Create delegate for Launch prepared function is fail (0x%08x)", st);
+ return 1;
+ }
+ PreparedFunction = reinterpret_cast<PreparedFunctionPtr>(preparedFunctionDelegate);
+
+ if(PreparedFunction != nullptr)
+ {
+ PreparedFunction();
+ }
+
+ void *launchFunctionDelegate;
+ st = CreateDelegate(hostHandle, domainId,
+ "Tizen.Runtime.Coreclr",
+ "Tizen.Runtime.Coreclr.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);
+
+ 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* root, const char* path, int argc, char* argv[])
+{
+ if (path == nullptr)
+ {
+ _ERR("executable path is null");
+ return 1;
+ }
+
+ if (FileNotExist(path))
+ {
+ _ERR("File not exist : %s", path);
+ return 1;
+ }
+
+ bool success = false;
+ if (LaunchFunction != nullptr)
+ {
+ success = LaunchFunction(root, path, argc, argv);
+ if (!success)
+ {
+ _ERR("Failed to launch Application %s", path);
+ }
+ return success ? 0 : 1;
+ }
+ else
+ {
+ std::string appRoot = root;
+ std::string appBin = ConcatPath(appRoot, "bin");
+ std::string appLib = ConcatPath(appRoot, "lib");
+ std::string probePath = appBin + ":" + appLib;
+
+ int st = InitializeCoreClr(probePath.c_str(), probePath.c_str());
+ unsigned int ret = 0;
+ st = ExecuteAssembly(hostHandle, domainId, argc, (const char**)argv, path, &ret);
+ if (st < 0)
+ {
+ _ERR("Failed to Execute Assembly %s (0x%08x)", path, st);
+ }
+ return ret;
+ }
+}
+
+} // namespace dotnetcore
+} // namespace runtime
+} // namespace tizen
--- /dev/null
+#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 void (*PreparedFunctionPtr)();
+typedef bool (*LaunchFunctionPtr)(const char* root, const char* path, int argc, char* argv[]);
+
+class CoreRuntime : public tizen::runtime::LauncherInterface
+{
+ public:
+ CoreRuntime();
+ ~CoreRuntime();
+ int Initialize(bool standalone) override;
+ void Dispose() override;
+ int RunManagedLauncher() override;
+ int Launch(const char* root, const char* path, int argc, char* argv[]) override;
+
+ private:
+ bool InitializeCoreClr(const char* assembly_probe_paths, const char* pinvoke_probe_paths);
+ 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;
+ PreparedFunctionPtr PreparedFunction;
+ LaunchFunctionPtr LaunchFunction;
+};
+
+} // dotnetcore
+} // namespace runtime
+} // namespace tizen
--- /dev/null
+#include "launcher.h"
+#include "log.h"
+
+#include <launchpad.h>
+#include <aul.h>
+
+#include <Ecore.h>
+
+#include <map>
+#include <vector>
+#include <functional>
+
+#include <unistd.h>
+
+
+namespace tizen {
+namespace runtime {
+
+struct FdHandler
+{
+ Ecore_Fd_Handler *handler;
+ loader_receiver_cb receiver;
+};
+
+class LaunchpadAdapterImpl : public LaunchpadAdapter
+{
+ public:
+ LaunchpadAdapterImpl() : isLaunched(false) { }
+ void LoaderMain(int argc, char* argv[]) override;
+
+ std::map<int, FdHandler> Handlers;
+
+ private:
+ AppInfo appinfo;
+ loader_lifecycle_callback_s callbacks;
+ loader_adapter_s adapter;
+ LauncherInterface* launcher;
+ bool isLaunched;
+ std::string launchPath;
+};
+
+LaunchpadAdapterImpl LaunchpadImpl;
+LaunchpadAdapter& Launchpad = LaunchpadImpl;
+
+#define WITH_SELF(data) \
+ LaunchpadAdapterImpl* self = static_cast<LaunchpadAdapterImpl*>(data); \
+ if (self == nullptr) \
+ { \
+ _ERR("No LaunchpadImplData"); \
+ } else
+
+static Eina_Bool Fd_Handler(void *data, Ecore_Fd_Handler* handler)
+{
+ WITH_SELF(data)
+ {
+ int fd = ecore_main_fd_handler_fd_get(handler);
+ if (fd == -1)
+ {
+ _ERR("Failed to get the Ecore FD");
+ exit(-1);
+ }
+
+ if (ecore_main_fd_handler_active_get(handler, ECORE_FD_READ))
+ {
+ if (self->Handlers.find(fd) != self->Handlers.end())
+ {
+ self->Handlers[fd].receiver(fd);
+ }
+ }
+ else if (ecore_main_fd_handler_active_get(handler, ECORE_FD_ERROR))
+ {
+ _ERR("Ecore FD Handler Have Error");
+ close(fd);
+ exit(-1);
+ }
+ }
+
+ return ECORE_CALLBACK_CANCEL;
+}
+
+static void Fd_Add(void *data, int fd, loader_receiver_cb receiver)
+{
+ Ecore_Fd_Handler* handler = ecore_main_fd_handler_add(fd,
+ static_cast<Ecore_Fd_Handler_Flags>(ECORE_FD_READ | ECORE_FD_ERROR),
+ Fd_Handler, data, nullptr, nullptr);
+ if (handler == nullptr)
+ {
+ _ERR("Failed to add a FD handler to ecore main loop");
+ close(fd);
+ exit(-1);
+ }
+ WITH_SELF(data)
+ {
+ self->Handlers[fd] = {handler, receiver};
+ }
+}
+
+static void Fd_Remove(void *data, int fd)
+{
+ WITH_SELF(data)
+ {
+ if (self->Handlers.find(fd) != self->Handlers.end())
+ {
+ Ecore_Fd_Handler* handler = self->Handlers[fd].handler;
+ ecore_main_fd_handler_del(handler);
+ self->Handlers.erase(fd);
+ }
+ }
+}
+
+void LaunchpadAdapterImpl::LoaderMain(int argc, char* argv[])
+{
+
+ callbacks.create = [](bundle *extra, int type, void *user_data)
+ {
+ ecore_init();
+ WITH_SELF(user_data)
+ {
+ if (self->OnCreate != nullptr)
+ 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
+ {
+ WITH_SELF(user_data)
+ {
+ self->appinfo.root = std::string(aul_get_app_root_path());
+ self->appinfo.path = app_path;
+ self->appinfo.id = appid;
+ self->appinfo.pkg = pkgid;
+ self->appinfo.type = pkg_type;
+ if (self->OnLaunch != nullptr)
+ self->OnLaunch(self->appinfo, argc, argv);
+ }
+
+ return 0;
+ };
+ callbacks.terminate = [](int argc, char **argv, void* user_data) -> int
+ {
+ _DBG("Terminate!!");
+ WITH_SELF(user_data)
+ {
+ if (self->OnTerminate != nullptr)
+ self->OnTerminate(self->appinfo, argc, argv);
+ }
+ return 0;
+ };
+
+ adapter.loop_begin = [](void *data)
+ {
+ ecore_main_loop_begin();
+ };
+
+ adapter.loop_quit = [](void *data)
+ {
+ ecore_main_loop_quit();
+ };
+ adapter.add_fd = Fd_Add;
+ adapter.remove_fd = Fd_Remove;
+
+ _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);
+}
+
+#undef WITH_SELF
+
+} // namespace runtime
+} // namespace tizen
--- /dev/null
+#ifndef __LAUNCHER_INTERFACE_H__
+#define __LAUNCHER_INTERFACE_H__
+
+#include <string>
+#include <functional>
+
+namespace tizen {
+namespace runtime {
+
+class LauncherInterface
+{
+ public:
+ virtual int Initialize(bool standalone) = 0;
+ virtual void Dispose() = 0;
+ virtual int RunManagedLauncher() = 0;
+ virtual int Launch(const char* root, const char* path, int argc, char* argv[]) = 0;
+};
+
+struct AppInfo
+{
+ std::string root;
+ std::string path;
+ std::string id;
+ std::string pkg;
+ std::string type;
+};
+
+class LaunchpadAdapter
+{
+ public:
+ virtual void LoaderMain(int argc, char* argv[]) = 0;
+ std::function<void()> OnCreate = nullptr;
+ std::function<void(const AppInfo&, int, char**)> OnLaunch = nullptr;
+ std::function<void(const AppInfo&, int, char**)> OnTerminate = nullptr;
+};
+
+extern LaunchpadAdapter& Launchpad;
+
+} // namespace runtime
+} // namespace tizen
+
+#endif // __LAUNCHER_INTERFACE_H__
--- /dev/null
+#include "dotnet/dotnet_launcher.h"
+#include "mono/mono_launcher.h"
+#include "utils.h"
+#include "log.h"
+
+#include <cstdio>
+#include <vector>
+#include <memory>
+
+#include <Ecore.h>
+#include <Eina.h>
+#include <aul.h>
+
+#define __XSTR(x) #x
+#define __STR(x) __XSTR(x)
+
+#ifndef VERSION
+#define LAUNCHER_VERSION_STR "-Unknown-"
+#else
+#define LAUNCHER_VERSION_STR __STR(VERSION)
+#endif
+
+static std::string VersionOption("--version");
+static std::string StandaloneOption("--standalone");
+
+int main(int argc, char *argv[])
+{
+ int i;
+ bool standalone = false;
+ const char* standalonePath = nullptr;
+
+ std::vector<char*> vargs;
+
+ for (i=0; i<argc; i++)
+ {
+ if (VersionOption.compare(argv[i]) == 0)
+ {
+ printf("Dotnet launcher Version %s\n", LAUNCHER_VERSION_STR);
+ return 0;
+ }
+ else if (StandaloneOption.compare(argv[i]) == 0)
+ {
+ standalone = true;
+
+ if (i > argc-1)
+ {
+ fprintf(stderr, "Assembly path must be after \"--standalone\" option\n");
+ return 1;
+ }
+ i++;
+ standalonePath = argv[i];
+ }
+ else
+ {
+ vargs.push_back(argv[i]);
+ }
+ }
+
+ using tizen::runtime::LauncherInterface;
+ using tizen::runtime::Launchpad;
+ using tizen::runtime::AppInfo;
+ std::unique_ptr<LauncherInterface> runtime;
+
+ bool useMono = !FileNotExist("/etc/.use_mono");
+
+ if (!useMono)
+ {
+ using tizen::runtime::dotnetcore::CoreRuntime;
+ std::unique_ptr<LauncherInterface> coreRuntime(new CoreRuntime());
+ runtime = std::move(coreRuntime);
+
+ _DBG("##### CoreCLR Launcher ######");
+ }
+ else
+ {
+ using tizen::runtime::mono::MonoRuntime;
+ std::unique_ptr<LauncherInterface> monoRuntime(new MonoRuntime());
+ runtime = std::move(monoRuntime);
+
+ _DBG("##### Mono Launcher ######");
+ }
+
+ if (standalone)
+ {
+ _DBG("##### Run it standalone #########");
+ const char* appid = getenv("AUL_APPID");
+ _DBG("AUL_APPID : %s", appid);
+ std::string approot;
+ if (appid != nullptr)
+ {
+ const char* approot_path = aul_get_app_root_path();
+ if (approot_path != nullptr)
+ {
+ approot = std::string(approot_path);
+ }
+ }
+ if (approot.empty())
+ {
+ approot = Basename(standalonePath);
+ }
+ if (runtime->Initialize(true) != 0)
+ {
+ _ERR("Failed to initialize");
+ return 1;
+ }
+
+ int args_len = vargs.size();
+ char** args = &vargs[0];
+ if (runtime->Launch(approot.c_str(), standalonePath, args_len, args))
+ {
+ _ERR("Failed to launch");
+ return 0;
+ }
+ }
+ else
+ {
+ Launchpad.OnCreate = [&runtime]()
+ {
+ if (runtime->Initialize(false) != 0)
+ {
+ _ERR("Failed to initialized");
+ }
+ else
+ {
+ auto idle_task = [](void *data) -> Eina_Bool
+ {
+ LauncherInterface* runtime = static_cast<LauncherInterface*>(data);
+ if (runtime->RunManagedLauncher() != 0)
+ {
+ _ERR("Failed to run managed launcher");
+ }
+ return ECORE_CALLBACK_CANCEL;
+ };
+ ecore_idler_add(idle_task, runtime.get());
+ }
+ };
+
+ Launchpad.OnTerminate = [&runtime](const AppInfo& info, int argc, char** argv)
+ {
+ _DBG("terminated with app path : %s", info.path.c_str());
+ _DBG("appid : %s", info.id.c_str());
+ _DBG("pkg : %s", info.pkg.c_str());
+ _DBG("type : %s", info.type.c_str());
+
+ if (runtime->Launch(info.root.c_str(), info.path.c_str(), argc, argv))
+ {
+ _ERR("Failed to launch");
+ }
+ };
+ Launchpad.LoaderMain(argc, argv);
+ }
+
+ return 0;
+}
--- /dev/null
+
+#include "mono_launcher.h"
+#include "utils.h"
+#include "log.h"
+
+#include <dlfcn.h>
+#include <string>
+
+namespace tizen {
+namespace runtime {
+namespace mono {
+
+static const char* DOMAIN_NAME = "tizen_mono_domain";
+static const char* LIBMONO = "/usr/lib/libmono-2.0.so.1";
+
+MonoRuntime::MonoRuntime() :
+ monolib(nullptr),
+ domain(nullptr),
+ launch(nullptr)
+{
+
+#define __XSTR(x) #x
+#define __STR(x) __XSTR(x)
+
+#ifdef MONO_LAUNCHER_ASSEMBLY_PATH
+ launcherAssemblyPath = __STR(MONO_LAUNCHER_ASSEMBLY_PATH);
+#endif
+
+#ifdef DEVICE_API_DIR
+ deviceAPIDirectory = __STR(DEVICE_API_DIR);
+#endif
+#ifdef RUNTIME_DIR
+ runtimeDirectory = __STR(RUNTIME_DIR);
+#endif
+
+#undef __STR
+#undef __XSTR
+}
+
+MonoRuntime::~MonoRuntime()
+{
+ Dispose();
+}
+
+int MonoRuntime::Initialize(bool standalone)
+{
+ if (standalone)
+ {
+ 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)
+ launcherAssemblyPath = _launcher_assembly;
+ }
+
+ if (FileNotExist(LIBMONO))
+ {
+ _DBG("mono is not exist in %s", LIBMONO);
+ return 1;
+ }
+
+ monolib = dlopen(LIBMONO, RTLD_LAZY);
+#define MONOLIB_RETURN_IF_NOSYM(type, variable, name) \
+ do { \
+ variable = (type)dlsym(monolib, name); \
+ if (variable == nullptr) { \
+ _ERR(name " is not found in libmono"); \
+ return 1; \
+ }} while(0)
+
+ MONOLIB_RETURN_IF_NOSYM(mono_set_dirs_ptr, SetDirs, "mono_set_dirs");
+ MONOLIB_RETURN_IF_NOSYM(mono_set_assemblies_path_ptr, SetAssembliesPath, "mono_set_assemblies_path");
+ MONOLIB_RETURN_IF_NOSYM(mono_jit_init_ptr, JitInit, "mono_jit_init");
+ MONOLIB_RETURN_IF_NOSYM(mono_domain_assembly_open_ptr, DomainAssemblyOpen, "mono_domain_assembly_open");
+ MONOLIB_RETURN_IF_NOSYM(mono_assembly_get_image_ptr, AssemblyGetImage, "mono_assembly_get_image");
+ MONOLIB_RETURN_IF_NOSYM(mono_class_from_name_ptr, ClassFromName, "mono_class_from_name");
+ MONOLIB_RETURN_IF_NOSYM(mono_runtime_invoke_ptr, RuntimeInvoke, "mono_runtime_invoke");
+ MONOLIB_RETURN_IF_NOSYM(mono_class_get_method_from_name_ptr, ClassGetMethodFromName, "mono_class_get_method_from_name");
+ MONOLIB_RETURN_IF_NOSYM(mono_object_to_string_ptr, ObjectToString, "mono_object_to_string");
+ MONOLIB_RETURN_IF_NOSYM(mono_string_to_utf8_ptr, StringToUtf8, "mono_string_to_utf8");
+ MONOLIB_RETURN_IF_NOSYM(mono_string_new_ptr, NewString, "mono_string_new");
+ MONOLIB_RETURN_IF_NOSYM(mono_get_string_class_ptr, GetStringClass, "mono_get_string_class");
+ MONOLIB_RETURN_IF_NOSYM(mono_array_new_ptr, ArrayNew, "mono_array_new");
+ MONOLIB_RETURN_IF_NOSYM(mono_array_addr_with_size_ptr, ArrayAddrWithSize, "mono_array_addr_with_size");
+ MONOLIB_RETURN_IF_NOSYM(mono_jit_cleanup_ptr, DomainCleanup, "mono_jit_cleanup");
+ MONOLIB_RETURN_IF_NOSYM(mono_jit_exec_ptr, AssemblyExec, "mono_jit_exec");
+
+#undef MONOLIB_RETURN_IF_NOSYM
+
+ _DBG("libmono dlopen and dlsym success");
+
+ return 0;
+}
+
+void MonoRuntime::Dispose()
+{
+ if (domain != nullptr)
+ {
+ DomainCleanup(domain);
+ }
+ if (monolib != nullptr && dlclose(monolib) != 0)
+ {
+ _ERR("libmono close failed");
+ }
+ monolib = nullptr;
+}
+
+int MonoRuntime::RunManagedLauncher()
+{
+ if (FileNotExist(launcherAssemblyPath.c_str()))
+ {
+ _ERR("Launcher Assembly is not exist in %s", launcherAssemblyPath.c_str());
+ return 1;
+ }
+
+// _DBG("mono_set_dirs(\"%s\", nullptr);", runtimeDirectory.c_str());
+// _DBG("mono_set_assemblies_path(\"%s\");", deviceAPIDirectory.c_str());
+
+// SetDirs(runtimeDirectory.c_str(), nullptr);
+/*
+ std::string assembliesPath = runtimeDirectory+":"+deviceAPIDirectory;
+ _DBG("assembliesPath : %s", assembliesPath.c_str());
+ SetAssembliesPath(assembliesPath.c_str());
+ */
+ SetAssembliesPath(deviceAPIDirectory.c_str());
+
+ domain = JitInit(DOMAIN_NAME);
+ if (domain == nullptr)
+ {
+ _ERR("Failed to init mono jit");
+ return 1;
+ }
+
+ launcherAssembly = DomainAssemblyOpen(domain, launcherAssemblyPath.c_str());
+ if (launcherAssembly == nullptr)
+ {
+ _ERR("Failed to Load Launcher Assembly");
+ return 1;
+ }
+
+ monoImage = AssemblyGetImage(launcherAssembly);
+ if (monoImage == nullptr)
+ {
+ _ERR("Failed to get image from launcher assembly");
+ return 1;
+ }
+
+ assemblyManagerClass = ClassFromName(monoImage, "Tizen.Runtime.Mono", "AssemblyManager");
+ if (assemblyManagerClass == nullptr)
+ {
+ _ERR("Failed to get AssemblyManager class in namespace Tizen.Runtime.Mono from launcher image");
+ return 1;
+ }
+
+ prepareLaunch = ClassGetMethodFromName(assemblyManagerClass, "Prepared", 0);
+ if (prepareLaunch == nullptr)
+ {
+ _ERR("Failed to get Prepared() method from Tizen.Runtime.Mono.AssemblyManager");
+ return 1;
+ }
+ MonoObject* exception = nullptr;
+ RuntimeInvoke(prepareLaunch, nullptr, nullptr, &exception);
+ if (exception != nullptr)
+ {
+ MonoString * exceptionMsg = ObjectToString(exception, nullptr);
+ char* cstringMsg = StringToUtf8(exceptionMsg);
+ _ERR("Failed to invoke method in runtime");
+ _ERR("%s", cstringMsg);
+ free(cstringMsg);
+ return 1;
+ }
+
+ launch = ClassGetMethodFromName(assemblyManagerClass, "Launch", 4);
+
+ return 0;
+}
+
+#define ArrayAddr(array,type,index) ((type*)(void*) ArrayAddrWithSize (array, sizeof (type), index))
+#define ArraySet(array,type,index,value) \
+ do { \
+ type *__p = (type *) ArrayAddr ((array), type, (index)); \
+ *__p = (value); \
+ } while (0)
+
+int MonoRuntime::Launch(const char* root, const char* path, int argc, char* argv[])
+{
+ if (domain == nullptr)
+ {
+ domain = JitInit(DOMAIN_NAME);
+ if (domain == nullptr)
+ {
+ _ERR("Failed to init mono jit");
+ return 1;
+ }
+ }
+ if (launch != nullptr)
+ {
+ MonoString *rootMonoString = NewString(domain, root);
+ MonoString *pathMonoString = NewString(domain, path);
+ MonoArray *argvMonoArray = ArrayNew(domain, GetStringClass(), argc);
+ for (int i=0; i<argc; i++)
+ {
+ MonoString *arg = NewString(domain, argv[i]);
+ ArraySet(argvMonoArray, MonoString*, i, arg);
+ }
+
+ void **args = new void*[argc+2];
+ args[0] = rootMonoString;
+ args[1] = pathMonoString;
+ args[2] = &argc;
+ args[3] = argvMonoArray;
+
+ MonoObject* exception = nullptr;
+ RuntimeInvoke(launch, nullptr, args, &exception);
+ if (exception != nullptr)
+ {
+ MonoString * exceptionMsg = ObjectToString(exception, nullptr);
+ char* cstringMsg = StringToUtf8(exceptionMsg);
+ _ERR("Failed to invoke launch method in runtime");
+ _ERR("%s", cstringMsg);
+ free(cstringMsg);
+ return 1;
+ }
+ }
+ else
+ {
+ std::string appBin = ConcatPath(root, "bin");
+ std::string appLib = ConcatPath(root, "lib");
+ std::string probePath = deviceAPIDirectory + ":" + appBin + ":" + appLib;
+ SetAssembliesPath(probePath.c_str());
+ MonoAssembly* app = DomainAssemblyOpen(domain, path);
+ if (app == nullptr)
+ {
+ _ERR("Failed to open assembly : %s", path);
+ return 1;
+ }
+ AssemblyExec(domain, app, argc, argv);
+ }
+ return 0;
+}
+
+} // namespace dotnetcore
+} // namespace runtime
+} // namespace mono
--- /dev/null
+#include "launcher.h"
+
+extern "C"
+{
+ typedef struct _MonoDomain MonoDomain;
+ typedef struct _NonoAssembly MonoAssembly;
+ typedef struct _MonoImage MonoImage;
+ typedef struct _MonoClass MonoClass;
+ typedef struct _MonoObject MonoObject;
+ typedef struct _MonoMethod MonoMethod;
+ typedef struct _MonoString MonoString;
+ typedef struct _MonoArray MonoArray;
+
+ typedef void (*mono_set_dirs_ptr) (const char *, const char *);
+ typedef void (*mono_set_assemblies_path_ptr) (const char*);
+ typedef MonoDomain* (*mono_jit_init_ptr) (const char *);
+ typedef void (*mono_config_parse_ptr) (const char *);
+ typedef MonoAssembly* (*mono_domain_assembly_open_ptr) (MonoDomain *, const char *);
+ typedef MonoImage* (*mono_assembly_get_image_ptr) (MonoAssembly *);
+ typedef MonoClass* (*mono_class_from_name_ptr) (MonoImage *, const char *, const char *);
+ typedef MonoObject* (*mono_runtime_invoke_ptr) (MonoMethod *, void *, void **, MonoObject **);
+ typedef MonoMethod* (*mono_class_get_method_from_name_ptr) (MonoClass *, const char *, int param_count);
+ typedef MonoString* (*mono_string_new_ptr) (MonoDomain *, const char *);
+ typedef MonoString* (*mono_object_to_string_ptr) (MonoObject *, MonoObject **);
+ typedef char* (*mono_string_to_utf8_ptr) (MonoString *string_obj);
+
+ typedef MonoClass* (*mono_get_string_class_ptr) ();
+ typedef MonoArray* (*mono_array_new_ptr) (MonoDomain *, MonoClass *, uintptr_t);
+ typedef char* (*mono_array_addr_with_size_ptr) (MonoArray *, int, uintptr_t);
+ typedef void (*mono_jit_cleanup_ptr) (MonoDomain *domain);
+ typedef int (*mono_jit_exec_ptr) (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[]);
+}
+
+namespace tizen {
+namespace runtime {
+namespace mono {
+
+class MonoRuntime : public tizen::runtime::LauncherInterface
+{
+ public:
+ MonoRuntime();
+ ~MonoRuntime();
+ int Initialize(bool standalone) override;
+ void Dispose() override;
+ int RunManagedLauncher() override;
+ int Launch(const char* root, const char* path, int argc, char* argv[]) override;
+
+ private:
+ void* monolib;
+ mono_set_dirs_ptr SetDirs;
+ mono_set_assemblies_path_ptr SetAssembliesPath;
+ mono_jit_init_ptr JitInit;
+ mono_domain_assembly_open_ptr DomainAssemblyOpen;
+ mono_assembly_get_image_ptr AssemblyGetImage;
+ mono_class_from_name_ptr ClassFromName;
+ mono_runtime_invoke_ptr RuntimeInvoke;
+ mono_class_get_method_from_name_ptr ClassGetMethodFromName;
+ mono_object_to_string_ptr ObjectToString;
+ mono_string_to_utf8_ptr StringToUtf8;
+ mono_string_new_ptr NewString;
+ mono_get_string_class_ptr GetStringClass;
+ mono_array_new_ptr ArrayNew;
+ mono_array_addr_with_size_ptr ArrayAddrWithSize;
+ mono_jit_cleanup_ptr DomainCleanup;
+ mono_jit_exec_ptr AssemblyExec;
+
+ MonoDomain* domain;
+ MonoAssembly* launcherAssembly;
+ MonoImage* monoImage;
+ MonoClass* assemblyManagerClass;
+ MonoMethod* prepareLaunch;
+ MonoMethod* launch;
+
+ std::string launcherAssemblyPath;
+ std::string deviceAPIDirectory;
+ std::string runtimeDirectory;
+};
+
+
+} // namespace mono
+} // namespace runtime
+} // namespace tizen
--- /dev/null
+
+#include <poll.h>
+
+#ifndef NO_TIZEN
+#include <launchpad.h>
+#include <aul.h>
+#endif
+
+#include <memory>
+#include <vector>
+#include <map>
+#include <poll.h>
+
+#include <iostream>
+
+#include "waiter.h"
+#include "log.h"
+
+namespace dotnet {
+namespace runtime {
+
+struct FdHandler
+{
+ pollfd *info;
+ Receiver receiver;
+};
+
+static volatile bool Waiting_;
+static std::vector<pollfd> Fdlist_;
+static std::map<int, FdHandler> Handlers_;
+static Waiter::AppInfo AppInfo_;
+
+void Waiter::OnPrepared()
+{
+ if (!context.Prepare())
+ {
+ _DBG("Fail to Prepare...");
+ }
+}
+
+void Waiter::OnRequested(const AppInfo& info)
+{
+ // do some job on user id is still system
+
+ if (!context.Request())
+ {
+ _DBG("Fail to Request...");
+ }
+}
+
+void Waiter::OnExecuted(const char *path, const char *app_root, int argc, char *argv[])
+{
+ if (!context.Execute(path, app_root, argc, argv))
+ {
+ _DBG("Fail to Execute...");
+ }
+}
+
+void Waiter::OnWaiting()
+{
+ // Start the loop
+ Waiting_ = true;
+
+ _DBG("start polling...");
+ while (Waiting_)
+ {
+ if (poll(Fdlist_.data(), Fdlist_.size(), -1) < 0)
+ continue;
+
+ for (auto &p : Fdlist_)
+ {
+ if ( (p.revents | POLLIN) != 0 )
+ Handlers_[p.fd].receiver(p.fd);
+ }
+ }
+ _DBG("end polling...");
+}
+
+void Waiter::Stop()
+{
+ // Stop the loop
+
+ Waiting_ = false;
+}
+
+
+void Waiter::RegisterFd(int fd, Receiver receiver)
+{
+ // register fd should be caught in event loop
+
+ _DBG("Register fd %d", fd);
+
+ pollfd info;
+ info.fd = fd;
+ info.events = POLLIN;
+ info.revents = 0;
+
+ FdHandler handler;
+ Fdlist_.push_back(info);
+ handler.info = &Fdlist_.back();
+ handler.receiver = receiver;
+
+ Handlers_[fd] = handler;
+}
+
+void Waiter::DeregisterFd(int fd)
+{
+ // deregister fd should be caught in event loop
+
+ pollfd *info = Handlers_[fd].info;
+ Fdlist_.erase(Fdlist_.begin() - (info - &Fdlist_.front()));
+ Handlers_.erase(fd);
+}
+
+int Waiter::WaitToLaunching(int argc, char *argv[])
+{
+#ifndef NO_TIZEN
+ auto on_create = [](bundle *extra, int type, void *user_data)
+ {
+ _DBG("on_create..."); // XXX
+ Waiter* waiter = static_cast<Waiter*>(user_data);
+ waiter->OnPrepared();
+ };
+
+ auto on_launch = [](int argc, char **argv, const char *app_path,
+ const char *appid, const char *pkgid,
+ const char *pkg_type, void *user_data) -> int
+ {
+ _DBG("on_launch..."); // XXX
+ Waiter* waiter = static_cast<Waiter*>(user_data);
+
+ _DBG ("app path : %s", app_path);
+ _DBG ("app id : %s", appid);
+ _DBG ("pkg id : %s", pkgid);
+ _DBG ("pkg type : %s", pkg_type);
+
+ AppInfo info = {
+ AppPath : app_path,
+ AppId : appid,
+ PkgId : pkgid,
+ PkgType : pkg_type
+ };
+
+ waiter->OnRequested(info);
+ return 0;
+ };
+
+ auto on_terminate = [](int argc, char **argv, void *user_data) -> int
+ {
+ _DBG("on_terminate..."); // XXX
+
+ string app_root(aul_get_app_root_path());
+ Waiter* waiter = static_cast<Waiter*>(user_data);
+ waiter->OnExecuted(argv[0], app_root.c_str(), argc, argv);
+ return 0;
+ };
+
+ auto on_start_loop = [](void *user_data)
+ {
+ _DBG("on_start_loop..."); // XXX
+ Waiter* waiter = static_cast<Waiter*>(user_data);
+ waiter->OnWaiting();
+ };
+
+ auto on_quit_loop = [](void *user_data)
+ {
+ _DBG("on_quit_loop..."); // XXX
+ Waiter* waiter = static_cast<Waiter*>(user_data);
+ waiter->Stop();
+ };
+
+ auto on_add_fd = [](void *user_data, int fd, loader_receiver_cb receiver)
+ {
+ _DBG("on_add_fd..."); // XXX
+ Waiter* waiter = static_cast<Waiter*>(user_data);
+ waiter->RegisterFd(fd, receiver);
+ };
+
+ auto on_remove_fd = [](void *user_data, int fd)
+ {
+ _DBG("on_remove_fd..."); // XXX
+ Waiter* waiter = static_cast<Waiter*>(user_data);
+ waiter->DeregisterFd(fd);
+ };
+
+ _DBG("launcher wait..."); // XXX
+ loader_lifecycle_callback_s callbacks = {
+ .create = on_create,
+ .launch = on_launch,
+ .terminate = on_terminate
+ };
+
+ loader_adapter_s adapter = {
+ .loop_begin = on_start_loop,
+ .loop_quit = on_quit_loop,
+ .add_fd = on_add_fd,
+ .remove_fd = on_remove_fd
+ };
+
+ return launchpad_loader_main(argc, argv, &callbacks, &adapter, this);
+#else
+ if (argc < 2)
+ {
+ _DBG("not enough args : %d", argc);
+ return -1;
+ }
+ _DBG("argv[1] = %s", argv[1]);
+ std::string app_path(argv[1]);
+ std::string app_root;
+ auto pos = app_path.find_last_of('/');
+ if (pos != std::string::npos)
+ app_root = app_path.substr(0, pos);
+ else
+ app_root = ".";
+
+ this->OnPrepared();
+ AppInfo info = {
+ AppPath : argv[1],
+ AppId : "",
+ PkgId : "",
+ PkgType : ""
+ };
+ this->OnRequested(info);
+ this->OnExecuted(app_path.c_str(), app_root.c_str(), argc, argv);
+#endif
+}
+
+void Waiter::SetContext(WaiterContext ctx)
+{
+ context = ctx;
+}
+
+WaiterContext::WaiterContext()
+{
+ Step = Status::Started;
+}
+
+bool WaiterContext::Prepare()
+{
+ if (Step == Status::Started && Prepared != nullptr && Prepared(Data) == 0)
+ {
+ Step = Status::Prepared;
+ return true;
+ }
+ return false;
+}
+
+bool WaiterContext::Request()
+{
+ if (Step == Status::Prepared && Requested != nullptr && Requested(Data) == 0)
+ {
+ Step = Status::Requested;
+ return true;
+ }
+ return false;
+}
+
+bool WaiterContext::Execute(const char *path, const char *app_root, int argc, char *argv[])
+{
+ if (Step == Status::Requested && Executed != nullptr &&
+ Executed(path, app_root, argc, argv, Data) == 0)
+ {
+ Step = Status::Executed;
+ return true;
+ }
+ return false;
+}
+
+} // namespace runtime
+} // namespace dotnet
+
+using dotnet::runtime::Waiter;
+using dotnet::runtime::WaiterContext;
+
+static Waiter waiter;
+
+void register_launching_callback(prepared_callback prepared,
+ requested_callback requested, executed_callback executed, void *data)
+{
+ WaiterContext context;
+ context.Prepared = prepared;
+ context.Requested = requested;
+ context.Executed = executed;
+ context.Data = data;
+
+ waiter.SetContext(context);
+}
+
+void wait_for_launching(int argc, char *argv[])
+{
+ _DBG("wait_for_launching...");
+
+ waiter.WaitToLaunching(argc, argv);
+}
+
--- /dev/null
+#include <string>
+#include <functional>
+
+#include <iostream>
+
+extern "C" {
+ typedef int (*prepared_callback)(void *data);
+ typedef int (*requested_callback)(void *data);
+ typedef int (*executed_callback)(const char* path, const char* app_root, int argc, char *argv[], void *data);
+
+ void register_launching_callback(prepared_callback prepared,
+ requested_callback requested, executed_callback executed, void *data);
+ void wait_for_launching(int argc, char *argv[]);
+}
+
+namespace dotnet {
+namespace runtime {
+
+using std::string;
+using Receiver = std::function<void(int)>;
+
+enum Status
+{
+ Started,
+ Prepared,
+ Requested,
+ Executed
+};
+
+class WaiterContext
+{
+ public:
+ prepared_callback Prepared;
+ requested_callback Requested;
+ executed_callback Executed;
+
+ void *Data;
+
+ WaiterContext();
+ bool Prepare();
+ bool Request();
+ bool Execute(const char *path, const char *app_root, int argc, char *argv[]);
+
+ private:
+ Status Step;
+};
+
+class Waiter
+{
+ public:
+ struct AppInfo
+ {
+ string AppPath;
+ string AppId;
+ string PkgId;
+ string PkgType;
+ };
+
+ int WaitToLaunching(int argc, char *argv[]);
+ void Stop();
+
+ void RegisterFd(int fd, Receiver receiver);
+ void DeregisterFd(int fd);
+ void SetContext(WaiterContext ctx);
+
+ protected:
+ void OnPrepared();
+ void OnRequested(const AppInfo&);
+ void OnWaiting();
+ void OnExecuted(const char *path, const char *app_root, int argc, char *argv[]);
+
+ private:
+ WaiterContext context;
+};
+
+} // namespace runtime
+} // namespace dotnet
+++ /dev/null
-
-#include <dlfcn.h>
-
-#include <string>
-#include <fstream>
-#include <vector>
-
-#include "utils.h"
-#include "log.h"
-#include "launcher.h"
-#include "dotnet_launcher.h"
-
-namespace tizen {
-namespace runtime {
-namespace dotnetcore {
-
-CoreRuntime::CoreRuntime() :
- coreclrLib(nullptr),
- hostHandle(nullptr),
- domainId(-1),
- PreparedFunction(nullptr),
- LaunchFunction(nullptr),
- 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 CORECLR_LAUNCHER_ASSEMBLY_PATH
- LauncherAssembly = __STR(CORECLR_LAUNCHER_ASSEMBLY_PATH);
-#endif
-
-#undef __STR
-#undef __XSTR
-
- _DBG("Constructor called!!");
-}
-
-CoreRuntime::~CoreRuntime()
-{
- Dispose();
-}
-
-int CoreRuntime::Initialize(bool standalone)
-{
-
- if (standalone)
- {
- 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;
- }
-
- 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;
-}
-
-bool CoreRuntime::InitializeCoreClr(const char* assembly_probe_paths, const char* pinvoke_probe_paths)
-{
- std::vector<std::string> platformDirectories = {
- RuntimeDirectory, DeviceAPIDirectory
- };
-
- std::string trusted_assemblies;
- AssembliesInDirectory(platformDirectories, trusted_assemblies);
-
- const char *propertyKeys[] =
- {
- "TRUSTED_PLATFORM_ASSEMBLIES",
- "APP_PATHS",
- "APP_NI_PATHS",
- "NATIVE_DLL_SEARCH_DIRECTORIES",
- "AppDomainCompatSwitch"
- };
-
- const char *propertyValues[] =
- {
- trusted_assemblies.c_str(),
- assembly_probe_paths,
- assembly_probe_paths,
- pinvoke_probe_paths,
- "UseLatestBehaviorWhenTFMNotSpecified"
- };
-
- std::string selfPath = ReadSelfPath();
-
- int st = InitializeClr(
- selfPath.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 false;
- }
-
- _DBG("Initialize core clr success");
- return true;
-}
-
-int CoreRuntime::RunManagedLauncher()
-{
- 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
- };
-
- std::string trusted_directories = JoinStrings(searchDirectories, ":");
-
- _DBG("coreclr_dir : %s", RuntimeDirectory.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());
-
- if (!InitializeCoreClr(launcherDir.c_str(), launcherDir.c_str()))
- {
- _ERR("Failed to initialize coreclr");
- return 1;
- }
-
- void *preparedFunctionDelegate;
- int st = CreateDelegate(hostHandle, domainId,
- "Tizen.Runtime.Coreclr",
- "Tizen.Runtime.Coreclr.AssemblyManager",
- "Prepared", &preparedFunctionDelegate);
- if (st < 0)
- {
- _ERR("Create delegate for Launch prepared function is fail (0x%08x)", st);
- return 1;
- }
- PreparedFunction = reinterpret_cast<PreparedFunctionPtr>(preparedFunctionDelegate);
-
- if(PreparedFunction != nullptr)
- {
- PreparedFunction();
- }
-
- void *launchFunctionDelegate;
- st = CreateDelegate(hostHandle, domainId,
- "Tizen.Runtime.Coreclr",
- "Tizen.Runtime.Coreclr.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);
-
- 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* root, const char* path, int argc, char* argv[])
-{
- if (path == nullptr)
- {
- _ERR("executable path is null");
- return 1;
- }
-
- if (FileNotExist(path))
- {
- _ERR("File not exist : %s", path);
- return 1;
- }
-
- bool success = false;
- if (LaunchFunction != nullptr)
- {
- success = LaunchFunction(root, path, argc, argv);
- if (!success)
- {
- _ERR("Failed to launch Application %s", path);
- }
- return success ? 0 : 1;
- }
- else
- {
- std::string appRoot = root;
- std::string appBin = ConcatPath(appRoot, "bin");
- std::string appLib = ConcatPath(appRoot, "lib");
- std::string probePath = appBin + ":" + appLib;
-
- int st = InitializeCoreClr(probePath.c_str(), probePath.c_str());
- unsigned int ret = 0;
- st = ExecuteAssembly(hostHandle, domainId, argc, (const char**)argv, path, &ret);
- if (st < 0)
- {
- _ERR("Failed to Execute Assembly %s (0x%08x)", path, st);
- }
- return ret;
- }
-}
-
-} // namespace dotnetcore
-} // namespace runtime
-} // namespace tizen
+++ /dev/null
-#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 void (*PreparedFunctionPtr)();
-typedef bool (*LaunchFunctionPtr)(const char* root, const char* path, int argc, char* argv[]);
-
-class CoreRuntime : public tizen::runtime::LauncherInterface
-{
- public:
- CoreRuntime();
- ~CoreRuntime();
- int Initialize(bool standalone) override;
- void Dispose() override;
- int RunManagedLauncher() override;
- int Launch(const char* root, const char* path, int argc, char* argv[]) override;
-
- private:
- bool InitializeCoreClr(const char* assembly_probe_paths, const char* pinvoke_probe_paths);
- 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;
- PreparedFunctionPtr PreparedFunction;
- LaunchFunctionPtr LaunchFunction;
-};
-
-} // dotnetcore
-} // namespace runtime
-} // namespace tizen
+++ /dev/null
-#include "launcher.h"
-#include "log.h"
-
-#include <launchpad.h>
-#include <aul.h>
-
-#include <Ecore.h>
-
-#include <map>
-#include <vector>
-#include <functional>
-
-#include <unistd.h>
-
-
-namespace tizen {
-namespace runtime {
-
-struct FdHandler
-{
- Ecore_Fd_Handler *handler;
- loader_receiver_cb receiver;
-};
-
-class LaunchpadAdapterImpl : public LaunchpadAdapter
-{
- public:
- LaunchpadAdapterImpl() : isLaunched(false) { }
- void LoaderMain(int argc, char* argv[]) override;
-
- std::map<int, FdHandler> Handlers;
-
- private:
- AppInfo appinfo;
- loader_lifecycle_callback_s callbacks;
- loader_adapter_s adapter;
- LauncherInterface* launcher;
- bool isLaunched;
- std::string launchPath;
-};
-
-LaunchpadAdapterImpl LaunchpadImpl;
-LaunchpadAdapter& Launchpad = LaunchpadImpl;
-
-#define WITH_SELF(data) \
- LaunchpadAdapterImpl* self = static_cast<LaunchpadAdapterImpl*>(data); \
- if (self == nullptr) \
- { \
- _ERR("No LaunchpadImplData"); \
- } else
-
-static Eina_Bool Fd_Handler(void *data, Ecore_Fd_Handler* handler)
-{
- WITH_SELF(data)
- {
- int fd = ecore_main_fd_handler_fd_get(handler);
- if (fd == -1)
- {
- _ERR("Failed to get the Ecore FD");
- exit(-1);
- }
-
- if (ecore_main_fd_handler_active_get(handler, ECORE_FD_READ))
- {
- if (self->Handlers.find(fd) != self->Handlers.end())
- {
- self->Handlers[fd].receiver(fd);
- }
- }
- else if (ecore_main_fd_handler_active_get(handler, ECORE_FD_ERROR))
- {
- _ERR("Ecore FD Handler Have Error");
- close(fd);
- exit(-1);
- }
- }
-
- return ECORE_CALLBACK_CANCEL;
-}
-
-static void Fd_Add(void *data, int fd, loader_receiver_cb receiver)
-{
- Ecore_Fd_Handler* handler = ecore_main_fd_handler_add(fd,
- static_cast<Ecore_Fd_Handler_Flags>(ECORE_FD_READ | ECORE_FD_ERROR),
- Fd_Handler, data, nullptr, nullptr);
- if (handler == nullptr)
- {
- _ERR("Failed to add a FD handler to ecore main loop");
- close(fd);
- exit(-1);
- }
- WITH_SELF(data)
- {
- self->Handlers[fd] = {handler, receiver};
- }
-}
-
-static void Fd_Remove(void *data, int fd)
-{
- WITH_SELF(data)
- {
- if (self->Handlers.find(fd) != self->Handlers.end())
- {
- Ecore_Fd_Handler* handler = self->Handlers[fd].handler;
- ecore_main_fd_handler_del(handler);
- self->Handlers.erase(fd);
- }
- }
-}
-
-void LaunchpadAdapterImpl::LoaderMain(int argc, char* argv[])
-{
-
- callbacks.create = [](bundle *extra, int type, void *user_data)
- {
- ecore_init();
- WITH_SELF(user_data)
- {
- if (self->OnCreate != nullptr)
- 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
- {
- WITH_SELF(user_data)
- {
- self->appinfo.root = std::string(aul_get_app_root_path());
- self->appinfo.path = app_path;
- self->appinfo.id = appid;
- self->appinfo.pkg = pkgid;
- self->appinfo.type = pkg_type;
- if (self->OnLaunch != nullptr)
- self->OnLaunch(self->appinfo, argc, argv);
- }
-
- return 0;
- };
- callbacks.terminate = [](int argc, char **argv, void* user_data) -> int
- {
- _DBG("Terminate!!");
- WITH_SELF(user_data)
- {
- if (self->OnTerminate != nullptr)
- self->OnTerminate(self->appinfo, argc, argv);
- }
- return 0;
- };
-
- adapter.loop_begin = [](void *data)
- {
- ecore_main_loop_begin();
- };
-
- adapter.loop_quit = [](void *data)
- {
- ecore_main_loop_quit();
- };
- adapter.add_fd = Fd_Add;
- adapter.remove_fd = Fd_Remove;
-
- _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);
-}
-
-#undef WITH_SELF
-
-} // namespace runtime
-} // namespace tizen
+++ /dev/null
-#include "dotnet/dotnet_launcher.h"
-#include "mono/mono_launcher.h"
-#include "utils.h"
-#include "log.h"
-
-#include <cstdio>
-#include <vector>
-#include <memory>
-
-#include <Ecore.h>
-#include <Eina.h>
-#include <aul.h>
-
-#define __XSTR(x) #x
-#define __STR(x) __XSTR(x)
-
-#ifndef VERSION
-#define LAUNCHER_VERSION_STR "-Unknown-"
-#else
-#define LAUNCHER_VERSION_STR __STR(VERSION)
-#endif
-
-static std::string VersionOption("--version");
-static std::string StandaloneOption("--standalone");
-
-int main(int argc, char *argv[])
-{
- int i;
- bool standalone = false;
- const char* standalonePath = nullptr;
-
- std::vector<char*> vargs;
-
- for (i=0; i<argc; i++)
- {
- if (VersionOption.compare(argv[i]) == 0)
- {
- printf("Dotnet launcher Version %s\n", LAUNCHER_VERSION_STR);
- return 0;
- }
- else if (StandaloneOption.compare(argv[i]) == 0)
- {
- standalone = true;
-
- if (i > argc-1)
- {
- fprintf(stderr, "Assembly path must be after \"--standalone\" option\n");
- return 1;
- }
- i++;
- standalonePath = argv[i];
- }
- else
- {
- vargs.push_back(argv[i]);
- }
- }
-
- using tizen::runtime::LauncherInterface;
- using tizen::runtime::Launchpad;
- using tizen::runtime::AppInfo;
- std::unique_ptr<LauncherInterface> runtime;
-
- bool useMono = !FileNotExist("/etc/.use_mono");
-
- if (!useMono)
- {
- using tizen::runtime::dotnetcore::CoreRuntime;
- std::unique_ptr<LauncherInterface> coreRuntime(new CoreRuntime());
- runtime = std::move(coreRuntime);
-
- _DBG("##### CoreCLR Launcher ######");
- }
- else
- {
- using tizen::runtime::mono::MonoRuntime;
- std::unique_ptr<LauncherInterface> monoRuntime(new MonoRuntime());
- runtime = std::move(monoRuntime);
-
- _DBG("##### Mono Launcher ######");
- }
-
- if (standalone)
- {
- _DBG("##### Run it standalone #########");
- const char* appid = getenv("AUL_APPID");
- _DBG("AUL_APPID : %s", appid);
- std::string approot;
- if (appid != nullptr)
- {
- const char* approot_path = aul_get_app_root_path();
- if (approot_path != nullptr)
- {
- approot = std::string(approot_path);
- }
- }
- if (approot.empty())
- {
- approot = Basename(standalonePath);
- }
- if (runtime->Initialize(true) != 0)
- {
- _ERR("Failed to initialize");
- return 1;
- }
-
- int args_len = vargs.size();
- char** args = &vargs[0];
- if (runtime->Launch(approot.c_str(), standalonePath, args_len, args))
- {
- _ERR("Failed to launch");
- return 0;
- }
- }
- else
- {
- Launchpad.OnCreate = [&runtime]
- {
- auto idle_task = [](void *data) -> Eina_Bool
- {
- LauncherInterface* runtime = static_cast<LauncherInterface*>(data);
- if (runtime->RunManagedLauncher() != 0)
- {
- _ERR("Failed to run managed launcher");
- }
- return ECORE_CALLBACK_CANCEL;
- };
- if (runtime->Initialize(false) != 0)
- {
- _ERR("Failed to initialized");
- return 1;
- }
- ecore_idler_add(idle_task, runtime.get());
- };
-
- Launchpad.OnTerminate = [&runtime](const AppInfo& info, int argc, char** argv)
- {
- _DBG("terminated with app path : %s", info.path.c_str());
- _DBG("appid : %s", info.id.c_str());
- _DBG("pkg : %s", info.pkg.c_str());
- _DBG("type : %s", info.type.c_str());
-
- if (runtime->Launch(info.root.c_str(), info.path.c_str(), argc, argv))
- {
- _ERR("Failed to launch");
- }
- };
- Launchpad.LoaderMain(argc, argv);
- }
-
- return 0;
-}
+++ /dev/null
-
-#include "mono_launcher.h"
-#include "utils.h"
-#include "log.h"
-
-#include <dlfcn.h>
-#include <string>
-
-namespace tizen {
-namespace runtime {
-namespace mono {
-
-static const char* DOMAIN_NAME = "tizen_mono_domain";
-static const char* LIBMONO = "/usr/lib/libmono-2.0.so.1";
-
-MonoRuntime::MonoRuntime() :
- monolib(nullptr),
- domain(nullptr),
- launch(nullptr)
-{
-
-#define __XSTR(x) #x
-#define __STR(x) __XSTR(x)
-
-#ifdef MONO_LAUNCHER_ASSEMBLY_PATH
- launcherAssemblyPath = __STR(MONO_LAUNCHER_ASSEMBLY_PATH);
-#endif
-
-#ifdef DEVICE_API_DIR
- deviceAPIDirectory = __STR(DEVICE_API_DIR);
-#endif
-#ifdef RUNTIME_DIR
- runtimeDirectory = __STR(RUNTIME_DIR);
-#endif
-
-#undef __STR
-#undef __XSTR
-}
-
-MonoRuntime::~MonoRuntime()
-{
- Dispose();
-}
-
-int MonoRuntime::Initialize(bool standalone)
-{
- if (standalone)
- {
- 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)
- launcherAssemblyPath = _launcher_assembly;
- }
-
- if (FileNotExist(LIBMONO))
- {
- _DBG("mono is not exist in %s", LIBMONO);
- return 1;
- }
-
- monolib = dlopen(LIBMONO, RTLD_LAZY);
-#define MONOLIB_RETURN_IF_NOSYM(type, variable, name) \
- do { \
- variable = (type)dlsym(monolib, name); \
- if (variable == nullptr) { \
- _ERR(name " is not found in libmono"); \
- return 1; \
- }} while(0)
-
- MONOLIB_RETURN_IF_NOSYM(mono_set_dirs_ptr, SetDirs, "mono_set_dirs");
- MONOLIB_RETURN_IF_NOSYM(mono_set_assemblies_path_ptr, SetAssembliesPath, "mono_set_assemblies_path");
- MONOLIB_RETURN_IF_NOSYM(mono_jit_init_ptr, JitInit, "mono_jit_init");
- MONOLIB_RETURN_IF_NOSYM(mono_domain_assembly_open_ptr, DomainAssemblyOpen, "mono_domain_assembly_open");
- MONOLIB_RETURN_IF_NOSYM(mono_assembly_get_image_ptr, AssemblyGetImage, "mono_assembly_get_image");
- MONOLIB_RETURN_IF_NOSYM(mono_class_from_name_ptr, ClassFromName, "mono_class_from_name");
- MONOLIB_RETURN_IF_NOSYM(mono_runtime_invoke_ptr, RuntimeInvoke, "mono_runtime_invoke");
- MONOLIB_RETURN_IF_NOSYM(mono_class_get_method_from_name_ptr, ClassGetMethodFromName, "mono_class_get_method_from_name");
- MONOLIB_RETURN_IF_NOSYM(mono_object_to_string_ptr, ObjectToString, "mono_object_to_string");
- MONOLIB_RETURN_IF_NOSYM(mono_string_to_utf8_ptr, StringToUtf8, "mono_string_to_utf8");
- MONOLIB_RETURN_IF_NOSYM(mono_string_new_ptr, NewString, "mono_string_new");
- MONOLIB_RETURN_IF_NOSYM(mono_get_string_class_ptr, GetStringClass, "mono_get_string_class");
- MONOLIB_RETURN_IF_NOSYM(mono_array_new_ptr, ArrayNew, "mono_array_new");
- MONOLIB_RETURN_IF_NOSYM(mono_array_addr_with_size_ptr, ArrayAddrWithSize, "mono_array_addr_with_size");
- MONOLIB_RETURN_IF_NOSYM(mono_jit_cleanup_ptr, DomainCleanup, "mono_jit_cleanup");
- MONOLIB_RETURN_IF_NOSYM(mono_jit_exec_ptr, AssemblyExec, "mono_jit_exec");
-
-#undef MONOLIB_RETURN_IF_NOSYM
-
- _DBG("libmono dlopen and dlsym success");
-
- return 0;
-}
-
-void MonoRuntime::Dispose()
-{
- if (domain != nullptr)
- {
- DomainCleanup(domain);
- }
- if (monolib != nullptr && dlclose(monolib) != 0)
- {
- _ERR("libmono close failed");
- }
- monolib = nullptr;
-}
-
-int MonoRuntime::RunManagedLauncher()
-{
- if (FileNotExist(launcherAssemblyPath.c_str()))
- {
- _ERR("Launcher Assembly is not exist in %s", launcherAssemblyPath.c_str());
- return 1;
- }
-
-// _DBG("mono_set_dirs(\"%s\", nullptr);", runtimeDirectory.c_str());
-// _DBG("mono_set_assemblies_path(\"%s\");", deviceAPIDirectory.c_str());
-
-// SetDirs(runtimeDirectory.c_str(), nullptr);
-/*
- std::string assembliesPath = runtimeDirectory+":"+deviceAPIDirectory;
- _DBG("assembliesPath : %s", assembliesPath.c_str());
- SetAssembliesPath(assembliesPath.c_str());
- */
- SetAssembliesPath(deviceAPIDirectory.c_str());
-
- domain = JitInit(DOMAIN_NAME);
- if (domain == nullptr)
- {
- _ERR("Failed to init mono jit");
- return 1;
- }
-
- launcherAssembly = DomainAssemblyOpen(domain, launcherAssemblyPath.c_str());
- if (launcherAssembly == nullptr)
- {
- _ERR("Failed to Load Launcher Assembly");
- return 1;
- }
-
- monoImage = AssemblyGetImage(launcherAssembly);
- if (monoImage == nullptr)
- {
- _ERR("Failed to get image from launcher assembly");
- return 1;
- }
-
- assemblyManagerClass = ClassFromName(monoImage, "Tizen.Runtime.Mono", "AssemblyManager");
- if (assemblyManagerClass == nullptr)
- {
- _ERR("Failed to get AssemblyManager class in namespace Tizen.Runtime.Mono from launcher image");
- return 1;
- }
-
- prepareLaunch = ClassGetMethodFromName(assemblyManagerClass, "Prepared", 0);
- if (prepareLaunch == nullptr)
- {
- _ERR("Failed to get Prepared() method from Tizen.Runtime.Mono.AssemblyManager");
- return 1;
- }
- MonoObject* exception = nullptr;
- RuntimeInvoke(prepareLaunch, nullptr, nullptr, &exception);
- if (exception != nullptr)
- {
- MonoString * exceptionMsg = ObjectToString(exception, nullptr);
- char* cstringMsg = StringToUtf8(exceptionMsg);
- _ERR("Failed to invoke method in runtime");
- _ERR("%s", cstringMsg);
- free(cstringMsg);
- return 1;
- }
-
- launch = ClassGetMethodFromName(assemblyManagerClass, "Launch", 4);
-
- return 0;
-}
-
-#define ArrayAddr(array,type,index) ((type*)(void*) ArrayAddrWithSize (array, sizeof (type), index))
-#define ArraySet(array,type,index,value) \
- do { \
- type *__p = (type *) ArrayAddr ((array), type, (index)); \
- *__p = (value); \
- } while (0)
-
-int MonoRuntime::Launch(const char* root, const char* path, int argc, char* argv[])
-{
- if (domain == nullptr)
- {
- domain = JitInit(DOMAIN_NAME);
- if (domain == nullptr)
- {
- _ERR("Failed to init mono jit");
- return 1;
- }
- }
- if (launch != nullptr)
- {
- MonoString *rootMonoString = NewString(domain, root);
- MonoString *pathMonoString = NewString(domain, path);
- MonoArray *argvMonoArray = ArrayNew(domain, GetStringClass(), argc);
- for (int i=0; i<argc; i++)
- {
- MonoString *arg = NewString(domain, argv[i]);
- ArraySet(argvMonoArray, MonoString*, i, arg);
- }
-
- void **args = new void*[argc+2];
- args[0] = rootMonoString;
- args[1] = pathMonoString;
- args[2] = &argc;
- args[3] = argvMonoArray;
-
- MonoObject* exception = nullptr;
- RuntimeInvoke(launch, nullptr, args, &exception);
- if (exception != nullptr)
- {
- MonoString * exceptionMsg = ObjectToString(exception, nullptr);
- char* cstringMsg = StringToUtf8(exceptionMsg);
- _ERR("Failed to invoke launch method in runtime");
- _ERR("%s", cstringMsg);
- free(cstringMsg);
- return 1;
- }
- }
- else
- {
- std::string appBin = ConcatPath(root, "bin");
- std::string appLib = ConcatPath(root, "lib");
- std::string probePath = deviceAPIDirectory + ":" + appBin + ":" + appLib;
- SetAssembliesPath(probePath.c_str());
- MonoAssembly* app = DomainAssemblyOpen(domain, path);
- if (app == nullptr)
- {
- _ERR("Failed to open assembly : %s", path);
- return 1;
- }
- int ret = AssemblyExec(domain, app, argc, argv);
- }
- return 0;
-}
-
-} // namespace dotnetcore
-} // namespace runtime
-} // namespace mono
+++ /dev/null
-#include "launcher.h"
-
-extern "C"
-{
- typedef struct _MonoDomain MonoDomain;
- typedef struct _NonoAssembly MonoAssembly;
- typedef struct _MonoImage MonoImage;
- typedef struct _MonoClass MonoClass;
- typedef struct _MonoObject MonoObject;
- typedef struct _MonoMethod MonoMethod;
- typedef struct _MonoString MonoString;
- typedef struct _MonoArray MonoArray;
-
- typedef void (*mono_set_dirs_ptr) (const char *, const char *);
- typedef void (*mono_set_assemblies_path_ptr) (const char*);
- typedef MonoDomain* (*mono_jit_init_ptr) (const char *);
- typedef void (*mono_config_parse_ptr) (const char *);
- typedef MonoAssembly* (*mono_domain_assembly_open_ptr) (MonoDomain *, const char *);
- typedef MonoImage* (*mono_assembly_get_image_ptr) (MonoAssembly *);
- typedef MonoClass* (*mono_class_from_name_ptr) (MonoImage *, const char *, const char *);
- typedef MonoObject* (*mono_runtime_invoke_ptr) (MonoMethod *, void *, void **, MonoObject **);
- typedef MonoMethod* (*mono_class_get_method_from_name_ptr) (MonoClass *, const char *, int param_count);
- typedef MonoString* (*mono_string_new_ptr) (MonoDomain *, const char *);
- typedef MonoString* (*mono_object_to_string_ptr) (MonoObject *, MonoObject **);
- typedef char* (*mono_string_to_utf8_ptr) (MonoString *string_obj);
-
- typedef MonoClass* (*mono_get_string_class_ptr) ();
- typedef MonoArray* (*mono_array_new_ptr) (MonoDomain *, MonoClass *, uintptr_t);
- typedef char* (*mono_array_addr_with_size_ptr) (MonoArray *, int, uintptr_t);
- typedef void (*mono_jit_cleanup_ptr) (MonoDomain *domain);
- typedef int (*mono_jit_exec_ptr) (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[]);
-}
-
-namespace tizen {
-namespace runtime {
-namespace mono {
-
-class MonoRuntime : public tizen::runtime::LauncherInterface
-{
- public:
- MonoRuntime();
- ~MonoRuntime();
- int Initialize(bool standalone) override;
- void Dispose() override;
- int RunManagedLauncher() override;
- int Launch(const char* root, const char* path, int argc, char* argv[]) override;
-
- private:
- void* monolib;
- mono_set_dirs_ptr SetDirs;
- mono_set_assemblies_path_ptr SetAssembliesPath;
- mono_jit_init_ptr JitInit;
- mono_domain_assembly_open_ptr DomainAssemblyOpen;
- mono_assembly_get_image_ptr AssemblyGetImage;
- mono_class_from_name_ptr ClassFromName;
- mono_runtime_invoke_ptr RuntimeInvoke;
- mono_class_get_method_from_name_ptr ClassGetMethodFromName;
- mono_object_to_string_ptr ObjectToString;
- mono_string_to_utf8_ptr StringToUtf8;
- mono_string_new_ptr NewString;
- mono_get_string_class_ptr GetStringClass;
- mono_array_new_ptr ArrayNew;
- mono_array_addr_with_size_ptr ArrayAddrWithSize;
- mono_jit_cleanup_ptr DomainCleanup;
- mono_jit_exec_ptr AssemblyExec;
-
- MonoDomain* domain;
- MonoAssembly* launcherAssembly;
- MonoImage* monoImage;
- MonoClass* assemblyManagerClass;
- MonoMethod* prepareLaunch;
- MonoMethod* launch;
-
- std::string launcherAssemblyPath;
- std::string deviceAPIDirectory;
- std::string runtimeDirectory;
-};
-
-
-} // namespace mono
-} // namespace runtime
-} // namespace tizen
+++ /dev/null
-
-#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();
-
-}
+++ /dev/null
-
-#include <poll.h>
-
-#ifndef NO_TIZEN
-#include <launchpad.h>
-#include <aul.h>
-#endif
-
-#include <memory>
-#include <vector>
-#include <map>
-#include <poll.h>
-
-#include <iostream>
-
-#include "waiter.h"
-#include "log.h"
-
-namespace dotnet {
-namespace runtime {
-
-struct FdHandler
-{
- pollfd *info;
- Receiver receiver;
-};
-
-static volatile bool Waiting_;
-static std::vector<pollfd> Fdlist_;
-static std::map<int, FdHandler> Handlers_;
-static Waiter::AppInfo AppInfo_;
-
-void Waiter::OnPrepared()
-{
- if (!context.Prepare())
- {
- _DBG("Fail to Prepare...");
- }
-}
-
-void Waiter::OnRequested(const AppInfo& info)
-{
- // do some job on user id is still system
-
- if (!context.Request())
- {
- _DBG("Fail to Request...");
- }
-}
-
-void Waiter::OnExecuted(const char *path, const char *app_root, int argc, char *argv[])
-{
- if (!context.Execute(path, app_root, argc, argv))
- {
- _DBG("Fail to Execute...");
- }
-}
-
-void Waiter::OnWaiting()
-{
- // Start the loop
- Waiting_ = true;
-
- _DBG("start polling...");
- while (Waiting_)
- {
- if (poll(Fdlist_.data(), Fdlist_.size(), -1) < 0)
- continue;
-
- for (auto &p : Fdlist_)
- {
- if ( (p.revents | POLLIN) != 0 )
- Handlers_[p.fd].receiver(p.fd);
- }
- }
- _DBG("end polling...");
-}
-
-void Waiter::Stop()
-{
- // Stop the loop
-
- Waiting_ = false;
-}
-
-
-void Waiter::RegisterFd(int fd, Receiver receiver)
-{
- // register fd should be caught in event loop
-
- _DBG("Register fd %d", fd);
-
- pollfd info;
- info.fd = fd;
- info.events = POLLIN;
- info.revents = 0;
-
- FdHandler handler;
- Fdlist_.push_back(info);
- handler.info = &Fdlist_.back();
- handler.receiver = receiver;
-
- Handlers_[fd] = handler;
-}
-
-void Waiter::DeregisterFd(int fd)
-{
- // deregister fd should be caught in event loop
-
- pollfd *info = Handlers_[fd].info;
- Fdlist_.erase(Fdlist_.begin() - (info - &Fdlist_.front()));
- Handlers_.erase(fd);
-}
-
-int Waiter::WaitToLaunching(int argc, char *argv[])
-{
-#ifndef NO_TIZEN
- auto on_create = [](bundle *extra, int type, void *user_data)
- {
- _DBG("on_create..."); // XXX
- Waiter* waiter = static_cast<Waiter*>(user_data);
- waiter->OnPrepared();
- };
-
- auto on_launch = [](int argc, char **argv, const char *app_path,
- const char *appid, const char *pkgid,
- const char *pkg_type, void *user_data) -> int
- {
- _DBG("on_launch..."); // XXX
- Waiter* waiter = static_cast<Waiter*>(user_data);
-
- _DBG ("app path : %s", app_path);
- _DBG ("app id : %s", appid);
- _DBG ("pkg id : %s", pkgid);
- _DBG ("pkg type : %s", pkg_type);
-
- AppInfo info = {
- AppPath : app_path,
- AppId : appid,
- PkgId : pkgid,
- PkgType : pkg_type
- };
-
- waiter->OnRequested(info);
- return 0;
- };
-
- auto on_terminate = [](int argc, char **argv, void *user_data) -> int
- {
- _DBG("on_terminate..."); // XXX
-
- string app_root(aul_get_app_root_path());
- Waiter* waiter = static_cast<Waiter*>(user_data);
- waiter->OnExecuted(argv[0], app_root.c_str(), argc, argv);
- return 0;
- };
-
- auto on_start_loop = [](void *user_data)
- {
- _DBG("on_start_loop..."); // XXX
- Waiter* waiter = static_cast<Waiter*>(user_data);
- waiter->OnWaiting();
- };
-
- auto on_quit_loop = [](void *user_data)
- {
- _DBG("on_quit_loop..."); // XXX
- Waiter* waiter = static_cast<Waiter*>(user_data);
- waiter->Stop();
- };
-
- auto on_add_fd = [](void *user_data, int fd, loader_receiver_cb receiver)
- {
- _DBG("on_add_fd..."); // XXX
- Waiter* waiter = static_cast<Waiter*>(user_data);
- waiter->RegisterFd(fd, receiver);
- };
-
- auto on_remove_fd = [](void *user_data, int fd)
- {
- _DBG("on_remove_fd..."); // XXX
- Waiter* waiter = static_cast<Waiter*>(user_data);
- waiter->DeregisterFd(fd);
- };
-
- _DBG("launcher wait..."); // XXX
- loader_lifecycle_callback_s callbacks = {
- .create = on_create,
- .launch = on_launch,
- .terminate = on_terminate
- };
-
- loader_adapter_s adapter = {
- .loop_begin = on_start_loop,
- .loop_quit = on_quit_loop,
- .add_fd = on_add_fd,
- .remove_fd = on_remove_fd
- };
-
- return launchpad_loader_main(argc, argv, &callbacks, &adapter, this);
-#else
- if (argc < 2)
- {
- _DBG("not enough args : %d", argc);
- return -1;
- }
- _DBG("argv[1] = %s", argv[1]);
- std::string app_path(argv[1]);
- std::string app_root;
- auto pos = app_path.find_last_of('/');
- if (pos != std::string::npos)
- app_root = app_path.substr(0, pos);
- else
- app_root = ".";
-
- this->OnPrepared();
- AppInfo info = {
- AppPath : argv[1],
- AppId : "",
- PkgId : "",
- PkgType : ""
- };
- this->OnRequested(info);
- this->OnExecuted(app_path.c_str(), app_root.c_str(), argc, argv);
-#endif
-}
-
-void Waiter::SetContext(WaiterContext ctx)
-{
- context = ctx;
-}
-
-WaiterContext::WaiterContext()
-{
- Step = Status::Started;
-}
-
-bool WaiterContext::Prepare()
-{
- if (Step == Status::Started && Prepared != nullptr && Prepared(Data) == 0)
- {
- Step = Status::Prepared;
- return true;
- }
- return false;
-}
-
-bool WaiterContext::Request()
-{
- if (Step == Status::Prepared && Requested != nullptr && Requested(Data) == 0)
- {
- Step = Status::Requested;
- return true;
- }
- return false;
-}
-
-bool WaiterContext::Execute(const char *path, const char *app_root, int argc, char *argv[])
-{
- if (Step == Status::Requested && Executed != nullptr &&
- Executed(path, app_root, argc, argv, Data) == 0)
- {
- Step = Status::Executed;
- return true;
- }
- return false;
-}
-
-} // namespace runtime
-} // namespace dotnet
-
-using dotnet::runtime::Waiter;
-using dotnet::runtime::WaiterContext;
-
-static Waiter waiter;
-
-void register_launching_callback(prepared_callback prepared,
- requested_callback requested, executed_callback executed, void *data)
-{
- WaiterContext context;
- context.Prepared = prepared;
- context.Requested = requested;
- context.Executed = executed;
- context.Data = data;
-
- waiter.SetContext(context);
-}
-
-void wait_for_launching(int argc, char *argv[])
-{
- _DBG("wait_for_launching...");
-
- waiter.WaitToLaunching(argc, argv);
-}
-
+++ /dev/null
-#include <string>
-#include <functional>
-
-#include <iostream>
-
-extern "C" {
- typedef int (*prepared_callback)(void *data);
- typedef int (*requested_callback)(void *data);
- typedef int (*executed_callback)(const char* path, const char* app_root, int argc, char *argv[], void *data);
-
- void register_launching_callback(prepared_callback prepared,
- requested_callback requested, executed_callback executed, void *data);
- void wait_for_launching(int argc, char *argv[]);
-}
-
-namespace dotnet {
-namespace runtime {
-
-using std::string;
-using Receiver = std::function<void(int)>;
-
-enum Status
-{
- Started,
- Prepared,
- Requested,
- Executed
-};
-
-class WaiterContext
-{
- public:
- prepared_callback Prepared;
- requested_callback Requested;
- executed_callback Executed;
-
- void *Data;
-
- WaiterContext();
- bool Prepare();
- bool Request();
- bool Execute(const char *path, const char *app_root, int argc, char *argv[]);
-
- private:
- Status Step;
-};
-
-class Waiter
-{
- public:
- struct AppInfo
- {
- string AppPath;
- string AppId;
- string PkgId;
- string PkgType;
- };
-
- int WaitToLaunching(int argc, char *argv[]);
- void Stop();
-
- void RegisterFd(int fd, Receiver receiver);
- void DeregisterFd(int fd);
- void SetContext(WaiterContext ctx);
-
- protected:
- void OnPrepared();
- void OnRequested(const AppInfo&);
- void OnWaiting();
- void OnExecuted(const char *path, const char *app_root, int argc, char *argv[]);
-
- private:
- WaiterContext context;
-};
-
-} // namespace runtime
-} // namespace dotnet
--- /dev/null
+
+#include <dirent.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <limits.h>
+#include <strings.h>
+
+#include <cstdlib>
+#include <cstring>
+#include <algorithm>
+#include <unordered_map>
+#include <vector>
+#include <iterator>
+#include <sstream>
+
+#include "utils.h"
+
+bool ICompare(const std::string& a, const std::string& b)
+{
+ return a.length() == b.length() &&
+ std::equal(b.begin(), b.end(), a.begin(),
+ [](unsigned char a, unsigned char b)
+ { return std::tolower(a) == std::tolower(b); });
+}
+
+bool ICompare(const std::string& a, int a_offset, const std::string& b, int b_offset, int length)
+{
+ return static_cast<int>(a.length()) - length >= a_offset &&
+ static_cast<int>(b.length()) - length >= b_offset &&
+ std::equal(b.begin() + b_offset, b.begin() + b_offset + length, a.begin() + a_offset,
+ [](unsigned char a, unsigned char b)
+ { return std::tolower(a) == std::tolower(b); });
+}
+
+bool IsManagedAssembly(const std::string& filename)
+{
+ return ICompare(filename, filename.size()-4, ".dll", 0, 4) ||
+ ICompare(filename, filename.size()-4, ".exe", 0, 4);
+}
+
+bool IsNativeImage(const std::string& filename)
+{
+ return ICompare(filename, filename.size()-7, ".ni", 0, 3);
+}
+
+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;
+}
+
+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();
+ }
+}
+
+struct AssemblyFile
+{
+ std::string noext;
+ std::string ext;
+};
+
+bool operator == (const AssemblyFile& lhs, const AssemblyFile& rhs)
+{
+ return lhs.noext == rhs.noext && lhs.ext == rhs.ext;
+}
+
+namespace std
+{
+ template<>
+ struct hash<AssemblyFile>
+ {
+ std::size_t operator () (const AssemblyFile& f) const
+ {
+ const std::size_t h1 = std::hash<std::string>{}(f.noext);
+ const std::size_t h2 = std::hash<std::string>{}(f.ext);
+
+ return h1 ^ (h2 << 1);
+ }
+ };
+}
+
+void AssembliesInDirectory(const std::vector<std::string>& directories, std::string& tpaList)
+{
+ std::unordered_map<AssemblyFile, bool> addedAssemblies;
+
+ auto reader = [&addedAssemblies] (const char* path)
+ {
+ std::string _path(path);
+
+ std::string::size_type dotp = _path.rfind('.');
+ std::string ext = dotp != std::string::npos ? _path.substr(dotp) : "";
+ std::string noext;
+ bool ni = false;
+
+ if (IsManagedAssembly(_path))
+ {
+ if (IsNativeImage(_path))
+ {
+ noext = _path.substr(0, _path.size()-7);
+ ni = true;
+ }
+ else
+ {
+ noext = _path.substr(0, _path.size()-4);
+ }
+
+ AssemblyFile f = {noext, ext};
+ addedAssemblies[f] = ni;
+ }
+ };
+
+ for (auto directory : directories)
+ {
+ ScanFilesInDir(directory.c_str(), reader, 1);
+ }
+
+ for (auto kv : addedAssemblies)
+ {
+ tpaList += kv.first.noext + (kv.second ? ".ni" : "") + kv.first.ext + ':';
+ }
+
+ if (tpaList.back() == ':')
+ tpaList.pop_back();
+}
+
+void ScanFilesInDir(const char* directory, FileReader reader, unsigned int depth)
+{
+ DIR *dir;
+ struct dirent* entry;
+ bool isDir;
+
+ dir = opendir(directory);
+
+ if (dir == nullptr)
+ {
+ //_ERR("Can not open directory : %s", directory);
+ return;
+ }
+
+ std::vector<std::string> innerDirectories;
+
+ while ((entry = readdir(dir)) != nullptr)
+ {
+ isDir = false;
+ std::string path = ConcatPath(directory, entry->d_name);
+ switch (entry->d_type)
+ {
+ case DT_REG: break;
+ case DT_DIR:
+ isDir = true;
+ break;
+ case DT_LNK:
+ case DT_UNKNOWN:
+ struct stat sb;
+ if (stat(path.c_str(), &sb) == -1)
+ {
+ continue;
+ }
+
+ if (S_ISREG(sb.st_mode) || S_ISDIR(sb.st_mode))
+ {
+ break;
+ }
+ default:
+ continue;
+ }
+ if (!isDir)
+ {
+ reader(path.c_str());
+ }
+ else if (depth > 1 && strcmp(entry->d_name, ".") && strcmp(entry->d_name, ".."))
+ {
+ innerDirectories.push_back(path);
+ }
+ }
+
+ if (depth != 0)
+ {
+ for (auto& d : innerDirectories)
+ {
+ ScanFilesInDir(d.c_str(), reader, depth-1);
+ }
+ }
+
+ closedir(dir);
+}
BuildRequires: pkgconfig(dlog)
BuildRequires: pkgconfig(ecore)
BuildRequires: pkgconfig(launchpad)
+BuildRequires: pkgconfig(pkgmgr-info)
+BuildRequires: pkgconfig(pkgmgr-installer)
BuildRequires: aul-devel
BuildRequires: mono-compiler
BuildRequires: mono-devel
%define _device_api_dir %{dotnet_assembly_path}
%define _runtime_dir /opt/usr/share/dotnet/shared/Microsoft.NETCore.App/1.0.0
%define _preload_dir /opt/usr/share/dotnet.tizen/preload
+%define _install_plugin_dir /usr/etc/package-manager/parserlib
%description
Launchpad plugin for launching dotnet apps
-DCMAKE_BUILD_TYPE=%{_buildmode} \
-DDEVICE_API_DIR=%{_device_api_dir} \
-DRUNTIME_DIR=%{_runtime_dir} \
+ -DCROSSGEN_PATH=%{_device_api_dir}/crossgen \
-DCORECLR_LAUNCHER_ASSEMBLY_PATH=%{_bindir}/Tizen.Runtime.Coreclr.dll \
-DMONO_LAUNCHER_ASSEMBLY_PATH=%{_bindir}/Tizen.Runtime.Mono.dll \
+ -DINSTALL_PLUGIN_DIR=%{_install_plugin_dir} \
-DVERSION=%{version} \
NativeLauncher
%{_loaderdir}/dotnet.launcher
%{_loaderdir}/dotnet.debugger
%caps(cap_mac_admin,cap_setgid=ei) %{_bindir}/dotnet-launcher
+%caps(cap_mac_admin,cap_setgid=ei) %{_bindir}/nitool
+%caps(cap_mac_admin,cap_setgid=ei) %{_install_plugin_dir}/libui-application.so
%caps(cap_mac_admin,cap_setgid=ei) %{_bindir}/Tizen.Runtime.Coreclr.dll
%caps(cap_mac_admin,cap_setgid=ei) %{_bindir}/Tizen.Runtime.Mono.dll