Coreclr & Mono Supported launcher and standalone
authorpius.lee <pius.lee@samsung.com>
Mon, 10 Oct 2016 05:12:09 +0000 (14:12 +0900)
committerpius.lee <pius.lee@samsung.com>
Mon, 10 Oct 2016 05:12:09 +0000 (14:12 +0900)
Switch launcher engine with "/etc/.use_mono" file
Now can run assembly standalone with "--standalone" option

Change-Id: I120053756f4d86107dfe716cf5675389b7a9760d

20 files changed:
NativeLauncher/CMakeLists.txt
NativeLauncher/inc/launcher.h
NativeLauncher/src/dotnet/base64.cc [deleted file]
NativeLauncher/src/dotnet/base64.h [deleted file]
NativeLauncher/src/dotnet/dotnet_launcher.cc
NativeLauncher/src/dotnet/dotnet_launcher.h
NativeLauncher/src/launcher.cc
NativeLauncher/src/main.cc [new file with mode: 0644]
NativeLauncher/src/mono/mono_launcher.cc [new file with mode: 0644]
NativeLauncher/src/mono/mono_launcher.h [new file with mode: 0644]
Tizen.Runtime/Tizen.Runtime.Coreclr.csproj [moved from Tizen.Runtime/Tizen.Runtime.csproj with 87% similarity]
Tizen.Runtime/Tizen.Runtime.Coreclr/AssemblyLoader.cs [moved from Tizen.Runtime/Tizen.Runtime/AssemblyLoader.cs with 98% similarity]
Tizen.Runtime/Tizen.Runtime.Coreclr/AssemblyManager.cs [moved from Tizen.Runtime/Tizen.Runtime/AssemblyManager.cs with 55% similarity]
Tizen.Runtime/Tizen.Runtime.Mono.csproj [new file with mode: 0644]
Tizen.Runtime/Tizen.Runtime.Mono/AssemblyManager.cs [new file with mode: 0644]
Tizen.Runtime/Tizen.Runtime/Ini.cs [deleted file]
Tizen.Runtime/Tizen.Runtime/Interop.cs [deleted file]
Tizen.Runtime/Tizen.Runtime/Log.cs
Tizen.Runtime/Tizen.Runtime/test.cs [deleted file]
packaging/dotnet-launcher.spec

index 203ffb7..00657be 100644 (file)
@@ -18,9 +18,13 @@ IF(DEFINED LAUNCHER_CONFIG_PATH)
        SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -DLAUNCHER_CONFIG_PATH=${LAUNCHER_CONFIG_PATH}")
 ENDIF(DEFINED LAUNCHER_CONFIG_PATH)
 
-IF(DEFINED LAUNCHER_ASSEMBLY_PATH)
-       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -DLAUNCHER_ASSEMBLY_PATH=${LAUNCHER_ASSEMBLY_PATH}")
-ENDIF(DEFINED LAUNCHER_ASSEMBLY_PATH)
+IF(DEFINED CORECLR_LAUNCHER_ASSEMBLY_PATH)
+       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -DCORECLR_LAUNCHER_ASSEMBLY_PATH=${CORECLR_LAUNCHER_ASSEMBLY_PATH}")
+ENDIF(DEFINED CORECLR_LAUNCHER_ASSEMBLY_PATH)
+
+IF(DEFINED MONO_LAUNCHER_ASSEMBLY_PATH)
+       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -DMONO_LAUNCHER_ASSEMBLY_PATH=${MONO_LAUNCHER_ASSEMBLY_PATH}")
+ENDIF(DEFINED MONO_LAUNCHER_ASSEMBLY_PATH)
 
 IF(DEFINED DEVICE_API_DIR)
        SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -DDEVICE_API_DIR=${DEVICE_API_DIR}")
@@ -30,7 +34,7 @@ IF(DEFINED RUNTIME_DIR)
        SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -DRUNTIME_DIR=${RUNTIME_DIR}")
 ENDIF(DEFINED RUNTIME_DIR)
 
-SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -pthread -std=c++11 -Wl,--no-as-needed")
+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")
@@ -49,10 +53,11 @@ SET(DOTNET_LAUNCHER "dotnet-launcher")
 SET(MONO_LAUNCHER "mono-launcher")
 
 SET(${DOTNET_LAUNCHER}_SOURCE_FILES
+       src/main.cc
        src/utils.cc
        src/launcher.cc
        src/dotnet/dotnet_launcher.cc
-       src/dotnet/base64.cc
+       src/mono/mono_launcher.cc
 )
 ADD_EXECUTABLE(${DOTNET_LAUNCHER} ${${PROJECT_NAME}_SOURCE_FILES})
 
index f4309b4..399bef5 100644 (file)
@@ -1,28 +1,37 @@
 #ifndef __LAUNCHER_INTERFACE_H__
 #define __LAUNCHER_INTERFACE_H__
 
+#include <string>
+#include <functional>
+
 namespace tizen {
 namespace runtime {
 
 class LauncherInterface
 {
   public:
-    virtual int Initialize() = 0;
+    virtual int Initialize(bool standalone) = 0;
     virtual void Dispose() = 0;
     virtual int RunManagedLauncher() = 0;
-    virtual int Launch(const char* path, int argc, char* argv[]) = 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(LauncherInterface* launcher, int argc, char* argv[]) = 0;
-    virtual void WaitUtilLaunched() = 0;
-
-  protected:
-    virtual void OnCreate() = 0;
-    virtual void OnLaunch() = 0;
-    virtual void OnTerminate() = 0;
+    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;
diff --git a/NativeLauncher/src/dotnet/base64.cc b/NativeLauncher/src/dotnet/base64.cc
deleted file mode 100644 (file)
index 3330082..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-#include "base64.h"
-#include <iostream>
-
-static const std::string base64_chars = 
-"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-"abcdefghijklmnopqrstuvwxyz"
-"0123456789+/";
-
-
-static inline bool is_base64(BYTE c) {
-  return (isalnum(c) || (c == '+') || (c == '/'));
-}
-
-std::string base64_encode(BYTE const* buf, unsigned int bufLen) {
-  std::string ret;
-  int i = 0;
-  int j = 0;
-  BYTE char_array_3[3];
-  BYTE char_array_4[4];
-
-  while (bufLen--) {
-    char_array_3[i++] = *(buf++);
-    if (i == 3) {
-      char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
-      char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
-      char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
-      char_array_4[3] = char_array_3[2] & 0x3f;
-
-      for(i = 0; (i <4) ; i++)
-        ret += base64_chars[char_array_4[i]];
-      i = 0;
-    }
-  }
-
-  if (i)
-  {
-    for(j = i; j < 3; j++)
-      char_array_3[j] = '\0';
-
-    char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
-    char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
-    char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
-    char_array_4[3] = char_array_3[2] & 0x3f;
-
-    for (j = 0; (j < i + 1); j++)
-      ret += base64_chars[char_array_4[j]];
-
-    while((i++ < 3))
-      ret += '=';
-  }
-
-  return ret;
-}
-
-std::vector<BYTE> base64_decode(std::string const& encoded_string) {
-  int in_len = encoded_string.size();
-  int i = 0;
-  int j = 0;
-  int in_ = 0;
-  BYTE char_array_4[4], char_array_3[3];
-  std::vector<BYTE> ret;
-
-  while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
-    char_array_4[i++] = encoded_string[in_]; in_++;
-    if (i ==4) {
-      for (i = 0; i <4; i++)
-        char_array_4[i] = base64_chars.find(char_array_4[i]);
-
-      char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
-      char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
-      char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
-
-      for (i = 0; (i < 3); i++)
-        ret.push_back(char_array_3[i]);
-      i = 0;
-    }
-  }
-
-  if (i) {
-    for (j = i; j <4; j++)
-      char_array_4[j] = 0;
-
-    for (j = 0; j <4; j++)
-      char_array_4[j] = base64_chars.find(char_array_4[j]);
-
-    char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
-    char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
-    char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
-
-    for (j = 0; (j < i - 1); j++) ret.push_back(char_array_3[j]);
-  }
-
-  return ret;
-}
diff --git a/NativeLauncher/src/dotnet/base64.h b/NativeLauncher/src/dotnet/base64.h
deleted file mode 100644 (file)
index 1a6b6ba..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef _BASE64_H_
-#define _BASE64_H_
-
-#include <vector>
-#include <string>
-typedef unsigned char BYTE;
-
-std::string base64_encode(BYTE const* buf, unsigned int bufLen);
-std::vector<BYTE> base64_decode(std::string const&);
-
-#endif
index 4942710..62738a3 100644 (file)
@@ -3,7 +3,6 @@
 
 #include <string>
 #include <fstream>
-#include <thread>
 #include <vector>
 
 #include "utils.h"
@@ -15,43 +14,12 @@ namespace tizen {
 namespace runtime {
 namespace dotnetcore {
 
-
-void CoreRuntime::SetStandaloneExe(const char* exePath, int argc, char* argv[])
-{
-  if (exePath == nullptr)
-  {
-    _ERR("executable path is null");
-    return;
-  }
-
-  if (FileNotExist(exePath))
-  {
-    _ERR("File not exist : %s", exePath);
-    return;
-  }
-
-  isLaunched = true;
-  LaunchParam.path = exePath;
-  LaunchParam.argc = argc;
-  LaunchParam.argv = argv;
-
-  const char *_deviceapi_directory = getenv("DeviceAPIDirectory");
-  const char *_runtime_directory = getenv("RuntimeDirectory");
-  const char *_launcher_assembly = getenv("LauncherAssembly");
-  if (_deviceapi_directory != nullptr)
-    DeviceAPIDirectory = _deviceapi_directory;
-  if (_runtime_directory != nullptr)
-    RuntimeDirectory = _runtime_directory;
-  if (_launcher_assembly != nullptr)
-    LauncherAssembly = _launcher_assembly;
-}
-
 CoreRuntime::CoreRuntime() :
   coreclrLib(nullptr),
   hostHandle(nullptr),
   domainId(-1),
+  PreparedFunction(nullptr),
   LaunchFunction(nullptr),
-  isLaunched(false),
   InitializeClr(nullptr),
   ExecuteAssembly(nullptr),
   Shutdown(nullptr),
@@ -66,8 +34,8 @@ CoreRuntime::CoreRuntime() :
 #ifdef RUNTIME_DIR
   RuntimeDirectory = __STR(RUNTIME_DIR);
 #endif
-#ifdef LAUNCHER_ASSEMBLY_PATH
-  LauncherAssembly = __STR(LAUNCHER_ASSEMBLY_PATH);
+#ifdef CORECLR_LAUNCHER_ASSEMBLY_PATH
+  LauncherAssembly = __STR(CORECLR_LAUNCHER_ASSEMBLY_PATH);
 #endif
 
 #undef __STR
@@ -81,9 +49,22 @@ CoreRuntime::~CoreRuntime()
   Dispose();
 }
 
-int CoreRuntime::Initialize()
+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");
@@ -190,7 +171,7 @@ int CoreRuntime::RunManagedLauncher()
     "UseLatestBehaviorWhenTFMNotSpecified"
   };
   
-//  _DBG("trusted platform assemblies : %s", propertyValues[0]);
+  _DBG("trusted platform assemblies : %s", propertyValues[0]);
   _DBG("app_path : %s", propertyValues[1]);
   _DBG("app_ni_path : %s", propertyValues[2]);
   _DBG("native dll search path : %s", propertyValues[3]);
@@ -224,40 +205,34 @@ int CoreRuntime::RunManagedLauncher()
 
   _DBG("Initialize core clr success");
 
-  void *launchFunctionDelegate;
+  void *preparedFunctionDelegate;
   st = CreateDelegate(hostHandle, domainId,
-      "Tizen.Runtime",
-      "Tizen.Runtime.AssemblyManager",
-      "Launch", &launchFunctionDelegate);
+      "Tizen.Runtime.Coreclr",
+      "Tizen.Runtime.Coreclr.AssemblyManager",
+      "Prepared", &preparedFunctionDelegate);
   if (st < 0)
   {
-    _ERR("Create delegate for Launch managed function is fail! (0x%08x)", st);
+    _ERR("Create delegate for Launch prepared function is fail (0x%08x)", st);
     return 1;
   }
-  LaunchFunction = reinterpret_cast<LaunchFunctionPtr>(launchFunctionDelegate);
+  PreparedFunction = reinterpret_cast<PreparedFunctionPtr>(preparedFunctionDelegate);
 
-  if (isLaunched)
+  if(PreparedFunction != nullptr)
   {
-    bool success = LaunchFunction(LaunchParam.path.c_str(),
-        LaunchParam.argc, LaunchParam.argv);
-    if (!success)
-    {
-      _ERR("Failed to Launching");
-    }
+    PreparedFunction();
   }
 
-  /*
-  unsigned int exitCode;
-  const char* argv[] = {LauncherAssembly.c_str()};
-  st = ExecuteAssembly(hostHandle, domainId,
-      1, argv, LauncherAssembly.c_str(), &exitCode);
-  _DBG("after execute coreclr");
+  void *launchFunctionDelegate;
+  st = CreateDelegate(hostHandle, domainId,
+      "Tizen.Runtime.Coreclr",
+      "Tizen.Runtime.Coreclr.AssemblyManager",
+      "Launch", &launchFunctionDelegate);
   if (st < 0)
   {
-    _ERR("execute core clr fail! (0x%08x / %d)", st, exitCode);
+    _ERR("Create delegate for Launch managed function is fail! (0x%08x)", st);
     return 1;
   }
-  */
+  LaunchFunction = reinterpret_cast<LaunchFunctionPtr>(launchFunctionDelegate);
 
   return 0;
 }
@@ -282,67 +257,32 @@ void CoreRuntime::Dispose()
   _DBG("Dotnet runtime disposed");
 }
 
-int CoreRuntime::Launch(const char* path, int argc, char* argv[])
+int CoreRuntime::Launch(const char* root, const char* path, int argc, char* argv[])
 {
-  if (LaunchFunction != nullptr)
+  if (path == nullptr)
   {
-    LaunchFunction(path, argc, argv);
+    _ERR("executable path is null");
+    return 1;
   }
-  else
+
+  if (FileNotExist(path))
   {
-    LaunchParam.path = path;
-    LaunchParam.argc = argc;
-    LaunchParam.argv = argv;
+    _ERR("File not exist : %s", path);
+    return 1;
   }
-  isLaunched = true;
 
-  return 0;
-}
-
-}  // namespace dotnetcore
-}  // namespace runtime
-}  // namespace tizen
-
-static std::string StandaloneOption("--standalone");
-
-#include "base64.h"
-
-int main(int argc, char *argv[])
-{
-  int i;
-  bool standalone = false;
-  const char* standalonePath = nullptr;
-
-  for (i=1; i<argc; i++)
+  bool success = false;
+  if (LaunchFunction != nullptr)
   {
-    if (StandaloneOption.compare(argv[i]) == 0)
-    {
-      standalone = true;
-    }
-    else
+    success = LaunchFunction(root, path, argc, argv);
+    if (!success)
     {
-      if (standalonePath == nullptr)
-        standalonePath = argv[i];
+      _ERR("Failed to launch Application %s", path);
     }
   }
-
-  tizen::runtime::dotnetcore::CoreRuntime runtime;
-  if (standalone)
-  {
-    runtime.SetStandaloneExe(standalonePath, argc, argv);
-  }
-  else
-  {
-    tizen::runtime::Launchpad.LoaderMain(&runtime, argc, argv);
-  }
-
-  runtime.Initialize();
-  runtime.RunManagedLauncher();
-
-  if (!standalone)
-  {
-    tizen::runtime::Launchpad.WaitUtilLaunched();
-  }
-
-  return 0;
+  return success ? 0 : 1;
 }
+
+}  // namespace dotnetcore
+}  // namespace runtime
+}  // namespace tizen
index e1a86b0..92567f6 100644 (file)
@@ -36,25 +36,18 @@ namespace tizen {
 namespace runtime {
 namespace dotnetcore {
 
-typedef bool (*LaunchFunctionPtr)(const char* path, int argc, char* argv[]);
-
-struct LaunchParameter
-{
-  std::string path;
-  int argc;
-  char** argv;
-};
+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() override;
+    int Initialize(bool standalone) override;
     void Dispose() override;
     int RunManagedLauncher() override;
-    int Launch(const char* path, int argc, char* argv[]) override;
-    void SetStandaloneExe(const char* exePath, int argc, char* argv[]);
+    int Launch(const char* root, const char* path, int argc, char* argv[]) override;
 
   private:
     coreclr_initialize_ptr InitializeClr;
@@ -67,9 +60,8 @@ class CoreRuntime : public tizen::runtime::LauncherInterface
     void* coreclrLib;
     void* hostHandle;
     unsigned int domainId;
+    PreparedFunctionPtr PreparedFunction;
     LaunchFunctionPtr LaunchFunction;
-    bool isLaunched;
-    LaunchParameter LaunchParam;
 };
 
 }  // dotnetcore
index 518a1d9..9efd49e 100644 (file)
@@ -2,55 +2,46 @@
 #include "log.h"
 
 #include <launchpad.h>
+#include <aul.h>
 
-#include <poll.h>
+#include <Ecore.h>
 
 #include <map>
 #include <vector>
 #include <functional>
-#include <thread>
+
+#include <unistd.h>
+
 
 namespace tizen {
 namespace runtime {
 
 struct FdHandler
 {
-  pollfd *info;
-  std::function<void(int)> receiver;
+  Ecore_Fd_Handler *handler;
+  loader_receiver_cb receiver;
 };
 
 class LaunchpadAdapterImpl : public LaunchpadAdapter
 {
   public:
     LaunchpadAdapterImpl() : isLaunched(false) { }
-    void LoaderMain(LauncherInterface* launcher, int argc, char* argv[]) override;
-    void WaitUtilLaunched() override;
+    void LoaderMain(int argc, char* argv[]) override;
 
-  protected:
-    void OnCreate() override;
-    void OnLaunch() override;
-    void OnTerminate() 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;
-
-    bool Waiting;
-    std::vector<pollfd> FdList;
-    std::map<int, FdHandler> Handlers;
-
-    std::thread pollingThread;
 };
 
 LaunchpadAdapterImpl LaunchpadImpl;
 LaunchpadAdapter& Launchpad = LaunchpadImpl;
 
-void LaunchpadAdapterImpl::LoaderMain(LauncherInterface* launcher, int argc, char* argv[])
-{
-  this->launcher = launcher;
 #define WITH_SELF(data) \
   LaunchpadAdapterImpl* self = static_cast<LaunchpadAdapterImpl*>(data); \
   if (self == nullptr) \
@@ -58,12 +49,75 @@ void LaunchpadAdapterImpl::LoaderMain(LauncherInterface* launcher, int argc, cha
     _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)
     {
-      self->OnCreate();
+      if (self->OnCreate != nullptr)
+        self->OnCreate();
     }
   };
   callbacks.launch = [](int argc, char** argv, const char* app_path,
@@ -72,8 +126,13 @@ void LaunchpadAdapterImpl::LoaderMain(LauncherInterface* launcher, int argc, cha
   {
     WITH_SELF(user_data)
     {
-      self->OnLaunch();
-      self->launchPath = std::string(app_path);
+      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;
@@ -83,108 +142,30 @@ void LaunchpadAdapterImpl::LoaderMain(LauncherInterface* launcher, int argc, cha
     _DBG("Terminate!!");
     WITH_SELF(user_data)
     {
-      self->OnTerminate();
-      //self->launcher->Launch(self->launchPath.c_str(), argc, argv);
+      if (self->OnTerminate != nullptr)
+        self->OnTerminate(self->appinfo, argc, argv);
     }
     return 0;
   };
 
   adapter.loop_begin = [](void *data)
   {
-    _DBG("start polling...");
-    WITH_SELF(data)
-    {
-      self->Waiting = true;
-      while(self->Waiting)
-      {
-        if (poll(self->FdList.data(), self->FdList.size(), -1) < 0)
-          continue;
-
-        _DBG("-----------------------------------------------------------4");
-        for (auto &p : self->FdList)
-        {
-          if ( (p.revents | POLLIN) != 0)
-            self->Handlers[p.fd].receiver(p.fd);
-        }
-        _DBG("-----------------------------------------------------------5");
-      }
-    }
-    _DBG("end polling...");
+    ecore_main_loop_begin();
   };
 
   adapter.loop_quit = [](void *data)
   {
-    WITH_SELF(data)
-    {
-      self->Waiting = false;
-    }
-  };
-
-  adapter.add_fd = [](void *data, int fd, loader_receiver_cb receiver)
-  {
-    WITH_SELF(data)
-    {
-      pollfd info;
-      FdHandler handler;
-
-      info.fd = fd;
-      info.events = POLLIN;
-      info.revents = 0;
-
-      self->FdList.push_back(info);
-      handler.info = &((self->FdList).back());
-      handler.receiver = receiver;
-
-      self->Handlers[fd] = handler;
-    }
-  };
-
-  adapter.remove_fd = [](void *user_data, int fd)
-  {
-    WITH_SELF(user_data)
-    {
-      pollfd *info = self->Handlers[fd].info;
-      self->FdList.erase(self->FdList.begin() - (info - &(self->FdList.front())));
-      self->Handlers.erase(fd);
-    }
+    ecore_main_loop_quit();
   };
+  adapter.add_fd = Fd_Add;
+  adapter.remove_fd = Fd_Remove;
 
-  pollingThread = std::thread([this, argc, argv]()
-  {
-    _DBG("launchpad_loader_main is start");
-    int r = launchpad_loader_main(argc, argv, &(this->callbacks), &(this->adapter), this);
-    _DBG("launchpad_loader_main is finished with [%d]", r);
-  });
-  //pollingThread.detach();
-}
-
-void LaunchpadAdapterImpl::WaitUtilLaunched()
-{
-  try
-  {
-    if (pollingThread.joinable())
-    {
-      pollingThread.join();
-    }
-  }
-  catch (const std::exception& ex)
-  {
-    _ERR("Exception  : %s", ex.what());
-  }
-}
-
-void LaunchpadAdapterImpl::OnCreate()
-{
-}
-
-void LaunchpadAdapterImpl::OnLaunch()
-{
-}
-
-void LaunchpadAdapterImpl::OnTerminate()
-{
+  _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
diff --git a/NativeLauncher/src/main.cc b/NativeLauncher/src/main.cc
new file mode 100644 (file)
index 0000000..97ff67c
--- /dev/null
@@ -0,0 +1,108 @@
+#include "dotnet/dotnet_launcher.h"
+#include "mono/mono_launcher.h"
+#include "utils.h"
+#include "log.h"
+
+#include <memory>
+
+#include <Ecore.h>
+#include <Eina.h>
+
+static std::string StandaloneOption("--standalone");
+
+int main(int argc, char *argv[])
+{
+  int i;
+  bool standalone = false;
+  const char* standalonePath = nullptr;
+
+  for (i=1; i<argc; i++)
+  {
+    if (StandaloneOption.compare(argv[i]) == 0)
+    {
+      standalone = true;
+    }
+    else
+    {
+      if (standalonePath == nullptr)
+        standalonePath = argv[i];
+    }
+  }
+
+  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);
+  }
+  else
+  {
+    using tizen::runtime::mono::MonoRuntime;
+    std::unique_ptr<LauncherInterface> monoRuntime(new MonoRuntime());
+    runtime = std::move(monoRuntime);
+  }
+
+  if (standalone)
+  {
+    std::string base = Basename(standalonePath);
+    if (runtime->Initialize(true) != 0)
+    {
+      _ERR("Failed to initialize");
+      return 1;
+    }
+    if (runtime->RunManagedLauncher() != 0)
+    {
+      _ERR("Failed to run managed launcher");
+      return 1;
+    }
+    if (!runtime->Launch(base.c_str(), standalonePath, argc, argv))
+    {
+        _ERR("Failed to launch");
+        return 1;
+    }
+  }
+  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;
+}
diff --git a/NativeLauncher/src/mono/mono_launcher.cc b/NativeLauncher/src/mono/mono_launcher.cc
new file mode 100644 (file)
index 0000000..fff1104
--- /dev/null
@@ -0,0 +1,213 @@
+
+#include "mono_launcher.h"
+#include "utils.h"
+#include "log.h"
+
+#include <dlfcn.h>
+#include <string>
+
+namespace tizen {
+namespace runtime {
+namespace mono {
+
+static const char* LIBMONO = "/usr/lib/libmono-2.0.so.1";
+
+MonoRuntime::MonoRuntime() :
+  monolib(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");
+
+#undef MONOLIB_RETURN_IF_NOSYM
+
+  _DBG("libmono dlopen and dlsym success");
+
+  return 0;
+}
+
+void MonoRuntime::Dispose()
+{
+  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("tizen_mono_domain");
+  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[])
+{
+  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;
+  }
+  return 0;
+}
+
+}  // namespace dotnetcore
+}  // namespace runtime
+}  // namespace mono
diff --git a/NativeLauncher/src/mono/mono_launcher.h b/NativeLauncher/src/mono/mono_launcher.h
new file mode 100644 (file)
index 0000000..8aa5a4b
--- /dev/null
@@ -0,0 +1,78 @@
+#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); 
+}
+
+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;
+
+    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
similarity index 87%
rename from Tizen.Runtime/Tizen.Runtime.csproj
rename to Tizen.Runtime/Tizen.Runtime.Coreclr.csproj
index a0fce08..32864ed 100644 (file)
@@ -4,8 +4,8 @@
        <PropertyGroup>
                <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
                <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-               <OutputType>exe</OutputType>
-               <AssemblyName>Tizen.Runtime</AssemblyName>
+               <OutputType>library</OutputType>
+               <AssemblyName>Tizen.Runtime.Coreclr</AssemblyName>
        </PropertyGroup>
 
        <PropertyGroup Condition=" '$(Configuration)' == 'Debug'">
        </PropertyGroup>
 
        <ItemGroup>
-               <Compile Include="Tizen.Runtime/AssemblyManager.cs" />
-               <Compile Include="Tizen.Runtime/AssemblyLoader.cs" />
+               <Compile Include="Tizen.Runtime.Coreclr/AssemblyManager.cs" />
+               <Compile Include="Tizen.Runtime.Coreclr/AssemblyLoader.cs" />
                <Compile Include="Tizen.Runtime/Log.cs" />
-               <Compile Include="Tizen.Runtime/Interop.cs" />
-               <Compile Include="Tizen.Runtime/Ini.cs" />
                <Compile Include="Tizen.Runtime/DefaultConfigAttribute.cs" />
        </ItemGroup>
 
@@ -4,7 +4,7 @@ using System.Reflection;
 using System.Runtime.Loader;
 using System.Collections.Generic;
 
-namespace Tizen.Runtime
+namespace Tizen.Runtime.Coreclr
 {
     public class AssemblyLoader : AssemblyLoadContext
     {
@@ -5,28 +5,43 @@ using System.Runtime.Loader;
 using System.Linq;
 using System.Runtime.InteropServices;
 
-namespace Tizen.Runtime
+namespace Tizen.Runtime.Coreclr
 {
     public static class AssemblyManager
     {
         public static bool Launch(
+                [In] string rootPath,
                 [In] string path,
                 [In] int argc,
-                [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)]
+                [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=2)]
                 [In] string[] argv)
         {
-            Console.WriteLine($"path : {path}");
-            Console.WriteLine($"argc : {argc}");
-            for (int i=0; i<argc; i++)
+            ALog.Debug($"Application Launch path : {path}");
+            try
             {
-                Console.WriteLine($"argv[{i}] : " + argv[i]);
+                DirectoryInfo bindir = new DirectoryInfo(Path.Combine(rootPath, "bin"));
+                DirectoryInfo libdir = new DirectoryInfo(Path.Combine(rootPath, "lib"));
+                if (Directory.Exists(bindir.FullName))
+                {
+                    CurrentAssemblyLoaderContext.AddSearchableDirectory(bindir.FullName);
+                }
+                if (Directory.Exists(libdir.FullName))
+                {
+                    CurrentAssemblyLoaderContext.AddSearchableDirectory(libdir.FullName);
+                }
+                Execute(path, argv);
+            }
+            catch(Exception e)
+            {
+                ALog.Debug("Exception in Launch()");
+                PrintException(e);
+                return false;
             }
-            Console.WriteLine();
 
             return true;
         }
 
-        public static int Prepared(IntPtr data)
+        public static void Prepared()
         {
             try
             {
@@ -44,74 +59,13 @@ namespace Tizen.Runtime
 
                 if (!Initialize(preloadPath))
                 {
-                    return 1;
+                    ALog.Debug($"Failed to Initialized with {preloadPath}");
                 }
             }
             catch(Exception e)
             {
                 ALog.Debug("Exception at Preparing");
                 PrintException(e);
-                return 1;
-            }
-            return 0;
-        }
-
-        public static int Requested(IntPtr data)
-        {
-            return 0;
-        }
-
-        public static int Executed(string path, string app_root, int argc, string[] argv, IntPtr data)
-        {
-            try
-            {
-                DirectoryInfo libdir = new DirectoryInfo(Path.Combine(app_root, "lib"));
-                if (Directory.Exists(libdir.FullName))
-                {
-                    CurrentAssemblyLoaderContext.AddSearchableDirectory(libdir.FullName);
-                }
-                Execute(path, argv);
-            }
-            catch(Exception e)
-            {
-                ALog.Debug("Exception at Executing");
-                PrintException(e);
-                return 1;
-            }
-
-            try
-            {
-                Finish();
-            }
-            catch(Exception e)
-            {
-                ALog.Debug("Exception at Finishing");
-                PrintException(e);
-                return 1;
-            }
-            return 0;
-        }
-
-        static Interop.PreparedCallback preparedCallback;
-        static Interop.RequestedCallback requestedCallback;
-        static Interop.ExecutedCallback executedCallback;
-
-        public static void Main(string[] args)
-        {
-            try
-            {
-                /*
-                preparedCallback = Prepared;
-                requestedCallback = Requested;
-                executedCallback = Executed;
-                Interop.register_launching_callback(preparedCallback, requestedCallback, executedCallback, IntPtr.Zero);
-                Interop.wait_for_launching(args.Length, args);
-                */
-                Console.WriteLine("HelloWorld!!");
-            }
-            catch(Exception e)
-            {
-                PrintException(e);
             }
         }
 
@@ -146,35 +100,6 @@ namespace Tizen.Runtime
                         }
                     }
                 }
-
-                /*
-                string LD_LIBRARY_PATH = Environment.GetEnvironmentVariable("LD_LIBRARY_PATH");
-                if (!string.IsNullOrEmpty(LD_LIBRARY_PATH))
-                {
-                    string[] dirs = LD_LIBRARY_PATH.Split(new char[]{':'}, StringSplitOptions.None);
-                    foreach (string dir in dirs)
-                    {
-                        DirectoryInfo d = new DirectoryInfo(dir);
-                        if (Directory.Exists(d.FullName))
-                        {
-                            CurrentAssemblyLoaderContext.AddSearchableDirectory(d.FullName);
-                        }
-                    }
-                }
-
-                DirectoryInfo libdir = new DirectoryInfo("/lib");
-                if (Directory.Exists(libdir.FullName))
-                {
-                    CurrentAssemblyLoaderContext.AddSearchableDirectory(libdir.FullName);
-                }
-
-                DirectoryInfo usrlibdir = new DirectoryInfo("/usr/lib");
-                if (Directory.Exists(usrlibdir.FullName))
-                {
-                    CurrentAssemblyLoaderContext.AddSearchableDirectory(usrlibdir.FullName);
-                }
-                */
-
             }
             catch (Exception e)
             {
@@ -205,21 +130,6 @@ namespace Tizen.Runtime
             }
         }
 
-        public static void Finish()
-        {
-            ALog.Debug("-------- Dll Search Dir");
-            foreach (string dir in CurrentAssemblyLoaderContext.DllDirectories)
-            {
-                ALog.Debug(dir);
-            }
-
-            ALog.Debug("-------- Native Search Dir");
-            foreach (string dir in CurrentAssemblyLoaderContext.NativeDirectories)
-            {
-                ALog.Debug(dir);
-            }
-        }
-
         public static AssemblyLoader CurrentAssemblyLoaderContext
         {
             get;
diff --git a/Tizen.Runtime/Tizen.Runtime.Mono.csproj b/Tizen.Runtime/Tizen.Runtime.Mono.csproj
new file mode 100644 (file)
index 0000000..e570697
--- /dev/null
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" InitialTargets="CheckConfig" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+       
+       <PropertyGroup>
+               <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+               <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+               <OutputType>library</OutputType>
+               <AssemblyName>Tizen.Runtime.Mono</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+       </PropertyGroup>
+
+       <PropertyGroup Condition=" '$(Configuration)' == 'Debug'">
+               <DebugSymbols>true</DebugSymbols>
+               <DebugType>full</DebugType>
+               <OutputPath>bin/</OutputPath>
+               <DefineConstants>DEBUG;TRACE</DefineConstants>
+       </PropertyGroup>
+
+       <PropertyGroup Condition=" '$(Configuration)' == 'Release'">
+               <DebugType>pdbonly</DebugType>
+               <Optimize>true</Optimize>
+               <OutputPath>bin/</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+       </PropertyGroup>
+
+<!-- Roslyn Not Support Assembly Signing yet.
+       <PropertyGroup>
+               <SignAssembly>true</SignAssembly>
+               <AssemblyOriginatorKeyFile>Tizen.Runtime.snk</AssemblyOriginatorKeyFile>
+       </PropertyGroup>
+-->
+
+       <PropertyGroup>
+               <DefineConstants Condition=" '$(CLOG)' != '' ">$(DefineConstants);CLOG</DefineConstants>
+       </PropertyGroup>
+
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Net.Http" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+
+       <ItemGroup>
+               <Compile Include="Tizen.Runtime.Mono/AssemblyManager.cs" />
+               <Compile Include="Tizen.Runtime/Log.cs" />
+               <Compile Include="Tizen.Runtime/DefaultConfigAttribute.cs" />
+       </ItemGroup>
+
+       <Target Name="CheckConfig">
+               <Message Text="MSBuildProjectDirectory = $(MSBuildProjectDirectory)"/>
+       </Target>
+
+       <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+
+       <Target Name="BeforeCompile">
+               <ItemGroup>
+                       <AssemblyAttributes Include="DefaultConfigAttribute" Condition=" $(PreloadPath) != '' ">
+                               <_Parameter1>PreloadPath=$(PreloadPath)</_Parameter1>
+                       </AssemblyAttributes>
+               </ItemGroup>
+
+               <WriteCodeFragment AssemblyAttributes="@(AssemblyAttributes)"
+                       Language="C#"
+                       OutputDirectory="$(IntermediateOutputPath)"
+                       OutputFile="Config.cs">
+                       <Output TaskParameter="OutputFile" ItemName="Compile" />
+               </WriteCodeFragment>
+
+       </Target>
+</Project>
diff --git a/Tizen.Runtime/Tizen.Runtime.Mono/AssemblyManager.cs b/Tizen.Runtime/Tizen.Runtime.Mono/AssemblyManager.cs
new file mode 100644 (file)
index 0000000..ec65ca6
--- /dev/null
@@ -0,0 +1,153 @@
+using System;
+using System.IO;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using Tizen.Runtime;
+
+namespace Tizen.Runtime.Mono
+{
+    public static class AssemblyManager
+    {
+
+        private static SortedSet<string> ResolveDirectories = new SortedSet<string>(); 
+        private static SortedSet<string> ResolveFiles = new SortedSet<string>();
+
+        public static bool Launch(
+                [In] string rootPath,
+                [In] string path,
+                [In] int argc,
+                [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=2)]
+                [In] string[] argv)
+        {
+            ALog.Debug($"Application Launch path : {path}");
+            try
+            {
+                DirectoryInfo bindir = new DirectoryInfo(Path.Combine(rootPath, "bin"));
+                DirectoryInfo libdir = new DirectoryInfo(Path.Combine(rootPath, "lib"));
+                if (Directory.Exists(bindir.FullName))
+                {
+                    ResolveDirectories.Add(bindir.FullName);
+                }
+                if (Directory.Exists(libdir.FullName))
+                {
+                    ResolveDirectories.Add(libdir.FullName);
+                }
+                ResolveFiles.Add(path);
+                Execute(path, argv);
+            }
+            catch(Exception e)
+            {
+                ALog.Debug("Exception in Launch()");
+                PrintException(e);
+                return false;
+            }
+
+            return true;
+        }
+
+        static readonly string[] assemblyExtensions = {".dll", ".exe"};
+
+        public static Assembly AssemblyResolverHandler(object sender, ResolveEventArgs args)
+        {
+            // find dll name + ext in paths for resolving
+            foreach (string path in ResolveDirectories)
+            {
+                foreach (string ext in assemblyExtensions)
+                {
+                    string assemblyPath = Path.Combine(path, new AssemblyName(args.Name).Name + ext);
+                    if (File.Exists(assemblyPath))
+                    {
+                        Assembly assembly = Assembly.LoadFrom(assemblyPath);
+                        return assembly;
+                    }
+                }
+            }
+
+            return null;
+        }
+
+        public static void Prepared()
+        {
+            try
+            {
+                string preloadPath = "";
+                ICustomAttributeProvider assembly = typeof(AssemblyManager).GetTypeInfo().Assembly;
+                var attributes = assembly.GetCustomAttributes(typeof(DefaultConfigAttribute), false);
+                foreach (DefaultConfigAttribute dca in attributes)
+                {
+                    ALog.Debug($"{dca.Key} = {dca.Value}");
+                    if (dca.Key == "PreloadPath")
+                    {
+                        preloadPath = dca.Value;
+                    }
+                }
+
+                if (!Initialize(preloadPath))
+                {
+                    ALog.Debug($"Failed to Initialized with {preloadPath}");
+                }
+
+                AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolverHandler;
+            }
+            catch(Exception e)
+            {
+                ALog.Debug("Exception at Preparing");
+                PrintException(e);
+            }
+        }
+
+        private static void PrintException(Exception exception)
+        {
+            while (exception != null)
+            {
+                ALog.Debug(exception.ToString());
+                exception = exception.InnerException;
+            }
+        }
+
+        public static bool Initialize(string preloadDirectory)
+        {
+            try
+            {
+                if (!string.IsNullOrEmpty(preloadDirectory))
+                {
+                    Console.WriteLine($"[{preloadDirectory}]");
+                    DirectoryInfo d = new DirectoryInfo(preloadDirectory);
+                    if (Directory.Exists(d.FullName))
+                    {
+                        ResolveDirectories.Add(d.FullName);
+                    }
+                }
+            }
+            catch (Exception e)
+            {
+                ALog.Debug("Exception on Initialized");
+                PrintException(e);
+                return false;
+            }
+            return true;
+        }
+
+
+        public static void Execute(string dllPath, string[] argv)
+        {
+            try
+            {
+                FileInfo f = new FileInfo(dllPath);
+                if (File.Exists(f.FullName))
+                {
+                    Assembly asm = Assembly.LoadFile(f.FullName);
+                    if (asm.EntryPoint == null) throw new ArgumentException($"{f.FullName} did not have EntryPoint");
+                    asm.EntryPoint.Invoke(null, new object[]{argv});
+                }
+            }
+            catch (Exception e)
+            {
+                ALog.Debug("Exception on Execute");
+                PrintException(e);
+            }
+        }
+
+    }
+}
diff --git a/Tizen.Runtime/Tizen.Runtime/Ini.cs b/Tizen.Runtime/Tizen.Runtime/Ini.cs
deleted file mode 100644 (file)
index d5c2544..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-using System;
-using System.IO;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace Tizen.Runtime
-{
-    internal class Ini
-    {
-        public string GlobalName = "___GLOBAL";
-        public Ini(Uri path)
-        {
-            if (path.Scheme != "file")
-            {
-                throw new NotSupportedException("Only File Uri is supported now");
-            }
-            string absPath = path.AbsolutePath;
-            Initialize();
-            Contents = File.ReadAllText(absPath);
-        }
-
-        public Ini(string contents)
-        {
-            Initialize();
-            Contents = contents;
-        }
-
-        public string Contents
-        {
-            get { return contents; }
-            
-            set
-            {
-                contents = value;
-                ReadContents(contents);
-            }
-        }
-
-        public Dictionary<string, string> this[string name]
-        {
-            get
-            {
-                if (groups.ContainsKey(name))
-                    return groups[name];
-                return null;
-            }
-        }
-
-        public override string ToString()
-        {
-            string str = "";
-
-            if (groups.ContainsKey(GlobalName))
-            {
-                foreach (var kv in groups[GlobalName])
-                {
-                    str += $"{kv.Key} = {kv.Value}" + Environment.NewLine;
-                }
-            }
-
-            foreach (var gkv in groups)
-            {
-                if (gkv.Key == GlobalName) continue;
-                str += $"[{gkv.Key}]" + Environment.NewLine;
-                foreach (var kv in gkv.Value)
-                {
-                    str += $"{kv.Key} = {kv.Value}" + Environment.NewLine;
-                }
-            }
-
-            return str;
-        }
-
-        public Dictionary<string, string> Global
-        {
-            get
-            {
-                return groups[GlobalName];
-            }
-        }
-
-        private void Initialize()
-        {
-            groups = new Dictionary<string, Dictionary<string, string> >();
-            groups[GlobalName] = new Dictionary<string, string>();
-        }
-
-        private string Uncommont(string str)
-        {
-            int comment_start = str.IndexOf('#');
-            return str.Substring(0, comment_start);
-        }
-
-        private bool GetHeader(string str, ref string groupName)
-        {
-            if (str.Length < 2 || str[0] != '[' || str[str.Length-1] != ']') return false;
-            string expected = str.Substring(1, str.Length-2);
-            groupName = expected.Trim();
-            return true;
-        }
-
-        private void GetKeyValueFromString(string str, out string key, out string value)
-        {
-            int eq_pos = str.IndexOf('=');
-            if (eq_pos == -1)
-            {
-                key = str.Trim();
-                value = "";
-            }
-            else
-            {
-                key = str.Substring(0, eq_pos).Trim();
-                value = str.Substring(eq_pos+1).Trim();
-            }
-        }
-
-        private void ReadContents(string contents)
-        {
-            string key, value;
-            string groupName = GlobalName;
-            string[] lines = contents.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
-
-            foreach (string line in lines)
-            {
-                if (string.IsNullOrWhiteSpace(line)) continue;
-                if (GetHeader(line, ref groupName))
-                {
-                    groups[groupName] = new Dictionary<string, string>();
-                    continue;
-                }
-                GetKeyValueFromString(line, out key, out value);
-                groups[groupName][key] = value;
-            }
-        }
-
-        private Dictionary<string, Dictionary<string, string> > groups;
-        private string contents;
-    }
-}
diff --git a/Tizen.Runtime/Tizen.Runtime/Interop.cs b/Tizen.Runtime/Tizen.Runtime/Interop.cs
deleted file mode 100644 (file)
index 52ceeac..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-using System;
-using System.Runtime.InteropServices;
-
-internal static class Interop
-{
-    public const string Launcher = "dotnet-launcher";
-
-    internal delegate int PreparedCallback(IntPtr userData);
-    internal delegate int RequestedCallback(IntPtr userData);
-
-    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
-    internal delegate int ExecutedCallback(
-            [In] string path,
-            [In] string app_root,
-            [In] int argc, 
-            [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=2)]
-            [In] string[] argv,
-            [In] IntPtr userData);
-
-    [DllImport(Launcher)]
-    internal static extern void register_launching_callback(
-            [MarshalAs(UnmanagedType.FunctionPtr)] PreparedCallback prepared,
-            [MarshalAs(UnmanagedType.FunctionPtr)] RequestedCallback requested,
-            [MarshalAs(UnmanagedType.FunctionPtr)] ExecutedCallback executed, IntPtr userData);
-
-    [DllImport(Launcher)]
-    internal static extern void wait_for_launching(int argc, string[] argv);
-}
index 064a5f3..b27a329 100644 (file)
@@ -1,7 +1,7 @@
 using System;
-#if !CLOG
-using Tizen;
-#endif
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
 
 namespace Tizen.Runtime
 {
@@ -35,21 +35,54 @@ namespace Tizen.Runtime
 #endif
     internal static class ALog
     {
-        static string TAG = "Tizen.Runtime";
+        const string Library = "libdlog.so.0";
+        const string TAG = "Tizen.Runtime";
+
+        public static void Debug(string message,
+                [CallerFilePath] string file = "",
+                [CallerMemberName] string func = "",
+                [CallerLineNumber] int line = 0)
+        {
+            Print(LogPriority.DLOG_DEBUG, TAG, message, file, func, line);
+        }
 
-        public static void Debug(string message)
+        public static void Info(string message,
+                [CallerFilePath] string file = "",
+                [CallerMemberName] string func = "",
+                [CallerLineNumber] int line = 0)
         {
-            Log.Debug(TAG, message);
+            Print(LogPriority.DLOG_DEBUG, TAG, message, file, func, line);
         }
 
-        public static void Info(string message)
+        public static void Error(string message,
+                [CallerFilePath] string file = "",
+                [CallerMemberName] string func = "",
+                [CallerLineNumber] int line = 0)
         {
-            Log.Info(TAG, message);
+            Print(LogPriority.DLOG_DEBUG, TAG, message, file, func, line);
         }
 
-        public static void Error(string message)
+        internal enum LogPriority
         {
-            Log.Error(TAG, message);
+            DLOG_UNKNOWN = 0,
+            DLOG_DEFAULT,
+            DLOG_VERBOSE,
+            DLOG_DEBUG,
+            DLOG_INFO,
+            DLOG_WARN,
+            DLOG_ERROR,
+            DLOG_FATAL,
+            DLOG_SILENT,
+            DLOG_PRIO_MAX,
         }
+
+        private static void Print(LogPriority priority, string tag, string message, string file, string func, int line)
+        {
+            FileInfo finfo = new FileInfo(file);
+            Print(priority, tag, "%s: %s(%d) > %s", finfo.Name, func, line, message); 
+        }
+
+        [DllImportAttribute(Library, EntryPoint = "dlog_print")]
+        internal static extern int Print(LogPriority prio, string tag, string fmt, string file, string func, int line, string msg);
     }
 }
diff --git a/Tizen.Runtime/Tizen.Runtime/test.cs b/Tizen.Runtime/Tizen.Runtime/test.cs
deleted file mode 100644 (file)
index 1c65dbe..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-using Tizen.Runtime;
-
-public class Program
-{
-    public static void Main(string[] args)
-    {
-        if (args.Length < 2)
-        {
-            ALog.Debug("Cancel..");
-            return;
-        }
-        string preload = Environment.GetEnvironmentVariable("PRELOAD_DLLS");
-        string searchable = String.Join(":", args, 1, args.Length - 1);
-
-        if (AssemblyManager.Initialize(searchable, preload))
-        {
-            ALog.Debug("After Initialized...");
-            AssemblyManager.Execute(args[0]);
-        }
-    }
-}
index c82b091..ee96df0 100644 (file)
@@ -56,7 +56,8 @@ cmake \
        -DCMAKE_BUILD_TYPE=%{_buildmode} \
        -DDEVICE_API_DIR=%{_device_api_dir} \
        -DRUNTIME_DIR=%{_runtime_dir} \
-       -DLAUNCHER_ASSEMBLY_PATH=%{_bindir}/Tizen.Runtime.exe \
+       -DCORECLR_LAUNCHER_ASSEMBLY_PATH=%{_bindir}/Tizen.Runtime.Coreclr.dll \
+       -DMONO_LAUNCHER_ASSEMBLY_PATH=%{_bindir}/Tizen.Runtime.Mono.dll \
        -DVERSION=%{version} \
        NativeLauncher
 
@@ -66,15 +67,23 @@ xbuild \
        /p:Configuration=%{_buildmode} \
        /p:PreloadPath=%{_preload_dir} \
        /p:TizenDeviceAPIPath=%{_device_api_dir} \
-       Tizen.Runtime/Tizen.Runtime.csproj
+       Tizen.Runtime/Tizen.Runtime.Coreclr.csproj
+
+xbuild \
+       /p:Configuration=%{_buildmode} \
+       /p:PreloadPath=%{_preload_dir} \
+       /p:TizenDeviceAPIPath=%{_device_api_dir} \
+       Tizen.Runtime/Tizen.Runtime.Mono.csproj
 
 %install
 rm -rf %{buildroot}
 %make_install
-install -p -m 644 Tizen.Runtime/bin/Tizen.Runtime.exe %{buildroot}%{_bindir}
+install -p -m 644 Tizen.Runtime/bin/Tizen.Runtime.Coreclr.dll %{buildroot}%{_bindir}
+install -p -m 644 Tizen.Runtime/bin/Tizen.Runtime.Mono.dll %{buildroot}%{_bindir}
 
 %files
 %manifest dotnet-launcher.manifest
 %{_loaderdir}/dotnet.loader
 %caps(cap_mac_admin,cap_setgid=ei) %{_bindir}/dotnet-launcher
-%caps(cap_mac_admin,cap_setgid=ei) %{_bindir}/Tizen.Runtime.exe
+%caps(cap_mac_admin,cap_setgid=ei) %{_bindir}/Tizen.Runtime.Coreclr.dll
+%caps(cap_mac_admin,cap_setgid=ei) %{_bindir}/Tizen.Runtime.Mono.dll