summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpius.lee <pius.lee@samsung.com>2016-08-26 16:40:52 +0900
committerpius.lee <pius.lee@samsung.com>2016-08-26 16:40:52 +0900
commitff0921bea8ac44486889b2649ac8dac98bdb23a3 (patch)
treec21e40500c2259845a74192090b54c53c04e13f7
parentfc48672564f10d25b3dfcd2f42cdb38b7deb6951 (diff)
downloadlauncher-ff0921bea8ac44486889b2649ac8dac98bdb23a3.tar.gz
launcher-ff0921bea8ac44486889b2649ac8dac98bdb23a3.tar.bz2
launcher-ff0921bea8ac44486889b2649ac8dac98bdb23a3.zip
Split Native Parts to SharedObject and Executable
Make libdnclauncher.so for waiting and launchpad callbacks. Modify dotnet-launcher to execute managed launcher with libcoreclr.so. Managed Launcher read ini file to read dll lists for preloading. Add Targets file building csproj with corefx and device apis.
-rw-r--r--NativeLauncher/CMakeLists.txt20
-rw-r--r--NativeLauncher/dotnet-launcher.ini3
-rw-r--r--NativeLauncher/src/launcher.cc294
-rw-r--r--NativeLauncher/src/launcher.h30
-rw-r--r--NativeLauncher/src/waiter.cc133
-rw-r--r--NativeLauncher/src/waiter.h55
-rw-r--r--Tizen.Runtime/Tizen.CoreFX.Ref.Targets20
-rw-r--r--Tizen.Runtime/Tizen.Runtime.csproj29
-rw-r--r--Tizen.Runtime/Tizen.Runtime/AssemblyLoader.cs57
-rw-r--r--Tizen.Runtime/Tizen.Runtime/AssemblyManager.cs142
-rw-r--r--Tizen.Runtime/Tizen.Runtime/DefaultConfigAttribute.cs27
-rw-r--r--Tizen.Runtime/Tizen.Runtime/Ini.cs139
-rw-r--r--Tizen.Runtime/Tizen.Runtime/Interop.cs20
-rw-r--r--packaging/dotnet-launcher.spec6
-rwxr-xr-xtest_build_on_desktop.sh19
15 files changed, 755 insertions, 239 deletions
diff --git a/NativeLauncher/CMakeLists.txt b/NativeLauncher/CMakeLists.txt
index e55c12c..8e203a3 100644
--- a/NativeLauncher/CMakeLists.txt
+++ b/NativeLauncher/CMakeLists.txt
@@ -14,14 +14,18 @@ FOREACH(flag ${${PROJECT_NAME}_CFLAGS})
SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
ENDFOREACH(flag)
-IF(DEFINED LAUNCHER_PATH)
- SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -DLAUNCHER_PATH=${LAUNCHER_PATH}")
-ENDIF(DEFINED LAUNCHER_PATH)
+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)
SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -std=c++11")
SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Wl,-zdefs" )
-SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden")
+#SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden")
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")
@@ -48,8 +52,16 @@ SET_TARGET_PROPERTIES(${PROJECT_NAME}
PROPERTIES SKIP_BUILD_RPATH TRUE
) # remove rpath option that is automatically generated by cmake.
+SET(LAUNCHER_LIB "dnclauncher")
+ADD_LIBRARY(${LAUNCHER_LIB} SHARED src/waiter.cc)
+IF(NOT DEFINED NO_TIZEN)
+ TARGET_LINK_LIBRARIES(${LAUNCHER_LIB} aul)
+ENDIF(NOT DEFINED NO_TIZEN)
+TARGET_LINK_LIBRARIES(${LAUNCHER_LIB} ${${PROJECT_NAME}_LDFLAGS} "-ldl")
+
IF(NOT DEFINED NO_TIZEN)
INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${BINDIR})
+ INSTALL(TARGETS ${LAUNCHER_LIB} DESTINATION ${LIBDIR})
INSTALL(FILES dotnet.loader DESTINATION ${LOADERDIR})
INSTALL(FILES dotnet-launcher.ini DESTINATION ${CONFIGDIR})
ENDIF(NOT DEFINED NO_TIZEN)
diff --git a/NativeLauncher/dotnet-launcher.ini b/NativeLauncher/dotnet-launcher.ini
index 9d4809c..ad1d22b 100644
--- a/NativeLauncher/dotnet-launcher.ini
+++ b/NativeLauncher/dotnet-launcher.ini
@@ -1,5 +1,6 @@
[dotnet]
-libcoreclr = libcoreclr.so
+libcoreclr = /opt/usr/share/dotnet/shared/Microsoft.NETCore.App/1.0.0/libcoreclr.so
coreclr_dir = /opt/usr/share/dotnet/shared/Microsoft.NETCore.App/1.0.0
tpa_dirs = /opt/usr/share/dotnet/shared/Microsoft.NETCore.App/1.0.0:/usr/share/assembly
native_so_search_dirs = /opt/usr/share/dotnet/shared/Microsoft.NETCore.App/1.0.0:/usr/share/assembly
+launcher_assembly = /usr/bin/Tizen.Runtime.dll
diff --git a/NativeLauncher/src/launcher.cc b/NativeLauncher/src/launcher.cc
index fcd1555..84c3811 100644
--- a/NativeLauncher/src/launcher.cc
+++ b/NativeLauncher/src/launcher.cc
@@ -1,9 +1,5 @@
#include <dlfcn.h>
-#ifdef LAUNCHING_TIME_MEASURE
-#include <ctime>
-#endif
-
#include <cstdlib>
#include <cstring>
#include <vector>
@@ -17,36 +13,76 @@
#include <dirent.h>
#include <sys/stat.h>
+#include <unistd.h>
+#include <limits.h>
+
#include "environment.h"
#include "waiter.h"
#include "log.h"
#include "tini.hpp"
-#include "launcher.h"
-
-namespace dotnet {
-namespace runtime {
-
-#ifdef LAUNCHER_PATH
#define __STR(x) #x
#define __XSTR(x) __STR(x)
-#define LAUNCHER_CONFIG __XSTR(LAUNCHER_PATH)
+
+#ifdef LAUNCHER_CONFIG_PATH
+#define LAUNCHER_CONFIG __XSTR(LAUNCHER_CONFIG_PATH)
#else
#define LAUNCHER_CONFIG "/etc/dotnet-launcher.ini"
#endif
static const std::string LauncherConfig(LAUNCHER_CONFIG);
-#ifdef LAUNCHER_PATH
-#undef __STR
-#undef __XSTR
+#ifdef LAUNCHER_CONFIG_PATH
#undef LAUNCHER_CONFIG
-#undef LAUNCHER_PATH
+#undef LAUNCHER_CONFIG_PATH
#endif
+#undef __STR
+#undef __XSTR
#ifndef PATH_SEPARATOR
#define PATH_SEPARATOR '/'
#endif
+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);
+
+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 "";
+}
+
+/*
static std::string ConcatPath(const std::string& path1, const std::string& path2)
{
std::string path(path1);
@@ -74,6 +110,7 @@ static void AppendPath(std::string& path1, const std::string& path2)
path1.append(path2);
}
}
+*/
static std::string AbsolutePath(const std::string& path)
{
@@ -134,6 +171,8 @@ static std::string AssembliesInDirectory(const char *directory)
return std::string();
}
+ _DBG("assemblies in %s", directory);
+
std::set<std::string> addedAssemblies;
struct dirent *entry;
@@ -198,20 +237,8 @@ static std::string AssembliesInDirectory(const char *directory)
return tpaList;
}
-Launcher::Launcher()
+static int RunLauncherDll(int argc, char* argv[])
{
-}
-
-Launcher::~Launcher()
-{
-}
-
-void Launcher::Initialize()
-{
-#ifdef LAUNCHING_TIME_MEASURE
- std::clock_t start = std::clock();
-#endif
-
std::ifstream iniStream(LauncherConfig);
std::stringstream iniString;
iniString << iniStream.rdbuf();
@@ -221,82 +248,56 @@ void Launcher::Initialize()
_DBG("%s", launcherIni.to_string().c_str());
auto &dotnet = launcherIni["dotnet"];
- if (dotnet.find("libcoreclr") == dotnet.end())
- dotnet["libcoreclr"] = "libcoreclr.so";
- if (dotnet.find("coreclr_dir") == dotnet.end())
- dotnet["coreclr_dir"] = "/usr/share/dotnet";
- if (dotnet.find("tpa_dir") == dotnet.end())
- dotnet["tpa_dir"] = dotnet["coreclr_dir"] + ":" + "/usr/share/assemblies";
- if (dotnet.find("native_so_search_dirs") == dotnet.end())
- dotnet["native_so_search_dirs"] = dotnet["tpa_dir"];
-
- _DBG("libcoreclr : %s", dotnet["libcoreclr"].c_str());
- _DBG("coreclr_dir : %s", dotnet["coreclr_dir"].c_str());
- _DBG("tpa_dir : %s", dotnet["tpa_dir"].c_str());
- _DBG("native_so_search_dirs : %s", dotnet["native_so_search_dirs"].c_str());
-
- std::string libcoreclr = dotnet["coreclr_dir"] + "/" + dotnet["libcoreclr"];
- std::string tpaDirs = dotnet["tpa_dirs"];
- std::string nativeSoSearchDirs = dotnet["native_so_search_dirs"];
-
- _DBG("libcoreclr.so : [%s]", libcoreclr.c_str());
-
-#ifdef LAUNCHING_TIME_MEASURE
- std::clock_t config_read_time = std::clock();
- _DBG("Reading Config file... : %Lf ms ", (config_read_time - start) / (double)(CLOCKS_PER_SEC / 1000));
-#endif
- coreclrLib = dlopen(libcoreclr.c_str(), RTLD_NOW | RTLD_LOCAL);
- if (coreclrLib == nullptr)
+#define DOTNET_FIND(key, defaultValue) \
+ ((dotnet.find(key) == dotnet.end()) ? defaultValue : dotnet[key])
+ std::string libcoreclr = DOTNET_FIND("libcoreclr", "libcoreclr.so");
+ std::string coreclr_dir = DOTNET_FIND("coreclr_dir", "/opt/usr/share/dotnet/shared/Microsoft.NETCore.App/1.0.0/");
+ std::string tpa_dirs = DOTNET_FIND("tpa_dirs", coreclr_dir + ":" + "/usr/share/assembly");
+ std::string native_so_search_dirs = DOTNET_FIND("native_so_search_dirs", tpa_dirs);
+ std::string launcher_assembly = AbsolutePath(DOTNET_FIND("launcher_assembly", "/usr/bin/Tizen.Runtime.dll"));
+#undef DOTNET_FIND
+
+ std::string launcher_dir = Basename(launcher_assembly);
+ std::string trusted_assemblies = launcher_assembly + ":";
+
+ std::istringstream f(tpa_dirs);
+ std::string s;
+ while (std::getline(f, s, ':'))
{
- char *err = dlerror();
- _ERR("dlopen failed to open libcoreclr.so with error %s", err);
- return;
+ trusted_assemblies += AssembliesInDirectory(s.c_str());
}
- initializeCoreCLR = (coreclr_initialize_ptr)dlsym(coreclrLib, "coreclr_initialize");
- executeAssembly = (coreclr_execute_assembly_ptr)dlsym(coreclrLib, "coreclr_execute_assembly");
- shutdownCoreCLR = (coreclr_shutdown_ptr)dlsym(coreclrLib, "coreclr_shutdown");
+ _DBG("libcoreclr : %s", libcoreclr.c_str());
+ _DBG("coreclr_dir : %s", coreclr_dir.c_str());
+ _DBG("tpa_dirs : %s", tpa_dirs.c_str());
+ _DBG("native_so_search_dir : %s", native_so_search_dirs.c_str());
+ _DBG("launcher_assembly : %s", launcher_assembly.c_str());
+ _DBG("launcher_dir : %s", launcher_dir.c_str());
+ _DBG("-------------------------------------------------");
- if (initializeCoreCLR == nullptr)
- {
- _ERR("coreclr_initialize not found in the libcoreclr.so");
- }
- else if (executeAssembly == nullptr)
- {
- _ERR("coreclr_execute_assembly_ptr not found in the libcoreclr.so");
- }
- else if (shutdownCoreCLR == nullptr)
- {
- _ERR("coreclr_shutdown_ptr not found in the libcoreclr.so");
- }
- else
+ void *coreclrLib = dlopen(libcoreclr.c_str(), RTLD_NOW | RTLD_LOCAL);
+ if (coreclrLib == nullptr)
{
- std::istringstream f(tpaDirs);
- std::string s;
- while (std::getline(f, s, ':'))
- {
- TrustedPlatformAssemblies += AssembliesInDirectory(s.c_str());
- }
- NativeDllSearchDirectories = nativeSoSearchDirs;
- AppDomainCompatSwitch = "UseLatestBehaviorWhenTFMNotSpecified";
+ char *err = dlerror();
+ _ERR("dlopen failed to open libcoreclr.so with error %s", err);
+ return 1;
}
-#ifdef LAUNCHING_TIME_MEASURE
- std::clock_t dlopen_time = std::clock();
- _DBG("dlopen and dlsym time... : %Lf ms ", (dlopen_time - config_read_time) / (double)(CLOCKS_PER_SEC / 1000));
- _DBG("initialize time... : %Lf ms ", (dlopen_time - start) / (double)(CLOCKS_PER_SEC / 1000));
-#endif
+#define CORELIB_RETURN_IF_NOSYM(type, variable, name) \
+ type variable; \
+ do { variable = (type)dlsym(coreclrLib, name); \
+ if (variable == nullptr) { \
+ _ERR(name " is not found in the libcoreclr.so"); \
+ return 1; \
+ }} while(0)
-}
+ CORELIB_RETURN_IF_NOSYM(coreclr_initialize_ptr, coreclr_initialize, "coreclr_initialize");
+ CORELIB_RETURN_IF_NOSYM(coreclr_execute_assembly_ptr, coreclr_execute_assembly, "coreclr_execute_assembly");
+ CORELIB_RETURN_IF_NOSYM(coreclr_shutdown_ptr, coreclr_shutdown, "coreclr_shutdown");
+ CORELIB_RETURN_IF_NOSYM(coreclr_create_delegate_ptr, coreclr_create_delegate, "coreclr_create_delegate");
-void Launcher::Launch(const string& exe_path, const string& app_root, int argc, char *argv[])
-{
- std::string bin_path = Basename(AbsolutePath(exe_path));
- std::string lib_path = ConcatPath(AbsolutePath(app_root), "lib");
- std::string app_path = bin_path + ":" + lib_path;
- std::string app_ni_path = app_path;
- std::string nativeDllSearchDirectories = NativeDllSearchDirectories + app_path;
+#undef CORELIB_RETURN_IF_NOSYM
const char *propertyKeys[] =
{
@@ -309,28 +310,27 @@ void Launcher::Launch(const string& exe_path, const string& app_root, int argc,
const char *propertyValues[] =
{
- TrustedPlatformAssemblies.c_str(),
- app_path.c_str(),
- app_ni_path.c_str(),
- nativeDllSearchDirectories.c_str(),
- AppDomainCompatSwitch.c_str()
+ trusted_assemblies.c_str(),
+ launcher_dir.c_str(),
+ launcher_dir.c_str(),
+ native_so_search_dirs.c_str(),
+ "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]);
_DBG("app domain compat switch : %s", propertyValues[4]);
+ _DBG("before initialize coreclr");
+
void* hostHandle;
unsigned int domainId;
- _DBG("before initialize coreclr");
+ std::string selfPath = ReadSelfPath();
-#ifdef LAUNCHING_TIME_MEASURE
- std::clock_t start = std::clock();
-#endif
- int st = initializeCoreCLR(exe_path.c_str(),
+ int st = coreclr_initialize(selfPath.c_str(),
"tizen_dotnet_launcher",
sizeof(propertyKeys) / sizeof(propertyKeys[0]),
propertyKeys,
@@ -339,76 +339,50 @@ void Launcher::Launch(const string& exe_path, const string& app_root, int argc,
&domainId);
_DBG("after initialize coreclr");
-#ifdef LAUNCHING_TIME_MEASURE
- std::clock_t initialize_coreclr_time = std::clock();
- _DBG("call coreclr_initialize ... : %Lf ms ", (initialize_coreclr_time - start) / (double)(CLOCKS_PER_SEC / 1000));
-#endif
if (st < 0)
{
// initialize coreclr fail
_ERR("initialize core clr fail! (0x%08x)", st);
_DBG("check your smack label dll and every directories on the way to dlls");
+ return 1;
}
- else
+
+ struct stat sb;
+ if (stat(launcher_assembly.c_str(), &sb) == -1)
{
- unsigned int exitCode;
- const char** argvc = const_cast<const char**>(argv);
- st = executeAssembly(hostHandle, domainId, argc, argvc, exe_path.c_str(), &exitCode);
- _DBG("after execute coreclr");
- if (st < 0)
- {
- // execute coreclr fail
- _ERR("execute core clr fail! (0x%08x / %d)", st, exitCode);
- }
- st = shutdownCoreCLR(hostHandle, domainId);
- if (st < 0)
- {
- // shutdown fail
- _ERR("shutdown core clr fail! (0x%08x)", st);
- }
-#ifdef LAUNCHING_TIME_MEASURE
- std::clock_t execute_assembly_time = std::clock();
- _DBG("call execute_assembly_time ... : %Lf ms ", (execute_assembly_time - initialize_coreclr_time) / (double)(CLOCKS_PER_SEC / 1000));
-#endif
+ _ERR("Launcher assembly is not exist in %s", launcher_assembly.c_str());
+ return 1;
+ }
+
+ unsigned int exitCode;
+ const char** cargv = const_cast<const char**>(argv);
+ st = coreclr_execute_assembly(hostHandle, domainId,
+ argc, cargv, launcher_assembly.c_str(), &exitCode);
+ _DBG("after execute coreclr");
+ if (st < 0)
+ {
+ _ERR("execute core clr fail! (0x%08x / %d)", st, exitCode);
+ return 1;
}
+
+ st = coreclr_shutdown(hostHandle, domainId);
+ if (st < 0)
+ {
+ _ERR("shutdown core clr fail! (0x%08x)", st);
+ return 1;
+ }
+
if (dlclose(coreclrLib) != 0)
{
_ERR("libcoreclr.so close failed");
+ return 1;
}
-#ifdef LAUNCHING_TIME_MEASURE
- std::clock_t after_launching_time = std::clock();
- _DBG("launching end time ... : %Lf ms ", (after_launching_time - start) / (double)(CLOCKS_PER_SEC / 1000));
-#endif
-}
-
-} // namespace runtime
-} // namespace dotnet
-using dotnet::runtime::Launcher;
-using dotnet::runtime::Waiter;
+ return 0;
+}
int main(int argc, char *argv[])
{
_DBG("launcher started");
-
- for (int i=0; i<argc; i++)
- {
- _DBG("argv[%d](%d) : [%s]", i, strlen(argv[i]), argv[i]);
- }
-
- std::unique_ptr<Launcher> launcher(new Launcher());
- auto on_prepare = [&launcher]()
- {
- launcher->Initialize();
- };
- auto on_requested = [&launcher]()
- {
- };
- auto on_executed = [&launcher](const std::string& path, const std::string& app_root, int argc, char *argv[])
- {
- _DBG("EXECUTE %s", path.c_str());
- launcher->Launch(path, app_root, argc, argv);
- };
- std::unique_ptr<Waiter> waiter(new Waiter(on_prepare, on_requested, on_executed));
- waiter->WaitToLaunching(argc, argv);
+ return RunLauncherDll(argc, argv);
}
diff --git a/NativeLauncher/src/launcher.h b/NativeLauncher/src/launcher.h
index acba908..4800ddf 100644
--- a/NativeLauncher/src/launcher.h
+++ b/NativeLauncher/src/launcher.h
@@ -25,6 +25,24 @@ typedef int (*coreclr_shutdown_ptr)(
void* hostHandle,
unsigned int domainId);
+typedef int (*coreclr_create_delegate_ptr)(
+ void* hostHandle,
+ unsigned int domainId,
+ const char* entryPointAssemblyName,
+ const char* entryPointTypeName,
+ const char* entryPointMethodName,
+ void** delegate);
+
+typedef bool (*AssemblyManager_Initialize)(
+ const char* searchableDirectories,
+ const char* preloadDllPaths);
+
+typedef void (*AssemblyManager_AddAssemblyDir)(const char* dir);
+typedef void (*AssemblyManager_RemoveAssemblyDir)(const char* dir);
+
+typedef void (*AssemblyManager_Execute)(const char* dllPath);
+typedef void (*AssemblyManager_Finish)(void);
+
using std::string;
using std::vector;
@@ -34,18 +52,26 @@ class Launcher
Launcher();
~Launcher();
void Initialize();
- void Launch(const string& exe_path, const string& app_root, int argc, char *argv[]);
private:
coreclr_initialize_ptr initializeCoreCLR;
- coreclr_execute_assembly_ptr executeAssembly;
+// coreclr_execute_assembly_ptr executeAssembly;
coreclr_shutdown_ptr shutdownCoreCLR;
+ coreclr_create_delegate_ptr createDelegate;
string TrustedPlatformAssemblies;
string NativeDllSearchDirectories;
string AppDomainCompatSwitch;
void *coreclrLib;
+
+ AssemblyManager_Initialize assemblyManagerInitialize;
+ AssemblyManager_Execute assemblyManagerExecute;
+ AssemblyManager_Finish assemblyManagerFinish;
+ AssemblyManager_AddAssemblyDir assemblyManagerAddDir;
+ AssemblyManager_RemoveAssemblyDir assemblyManagerRemoveDir;
+
+ bool initialized;
};
} // namespace runtime
diff --git a/NativeLauncher/src/waiter.cc b/NativeLauncher/src/waiter.cc
index 6f83482..c7cb794 100644
--- a/NativeLauncher/src/waiter.cc
+++ b/NativeLauncher/src/waiter.cc
@@ -30,16 +30,30 @@ static std::vector<pollfd> Fdlist_;
static std::map<int, FdHandler> Handlers_;
static Waiter::AppInfo AppInfo_;
-void Waiter::OnPrepare()
+void Waiter::OnPrepared()
{
- // preload the libraries.
- if (prepare_ != nullptr)
- prepare_();
+ if (!context.Prepare())
+ {
+ _DBG("Fail to Prepare...");
+ }
}
-void Waiter::OnLaunchRequested(const AppInfo& info)
+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()
@@ -98,18 +112,6 @@ void Waiter::DeregisterFd(int fd)
Handlers_.erase(fd);
}
-
-Waiter::Waiter(Action prepare, Action requested, Executor executor)
-{
- prepare_ = prepare;
- requested_ = requested;
- executor_ = executor;
-}
-
-Waiter::~Waiter()
-{
-}
-
int Waiter::WaitToLaunching(int argc, char *argv[])
{
#ifndef NO_TIZEN
@@ -117,7 +119,7 @@ int Waiter::WaitToLaunching(int argc, char *argv[])
{
_DBG("on_create..."); // XXX
Waiter* waiter = static_cast<Waiter*>(user_data);
- waiter->OnPrepare();
+ waiter->OnPrepared();
};
auto on_launch = [](int argc, char **argv, const char *app_path,
@@ -139,7 +141,7 @@ int Waiter::WaitToLaunching(int argc, char *argv[])
PkgType : pkg_type
};
- waiter->OnLaunchRequested(info);
+ waiter->OnRequested(info);
return 0;
};
@@ -149,7 +151,7 @@ int Waiter::WaitToLaunching(int argc, char *argv[])
string app_root(aul_get_app_root_path());
Waiter* waiter = static_cast<Waiter*>(user_data);
- waiter->executor_(argv[0], app_root, argc, argv);
+ waiter->OnExecuted(argv[0], app_root.c_str(), argc, argv);
return 0;
};
@@ -197,7 +199,12 @@ int Waiter::WaitToLaunching(int argc, char *argv[])
return launchpad_loader_main(argc, argv, &callbacks, &adapter, this);
#else
- if (argc < 2) return -1;
+ 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('/');
@@ -206,17 +213,83 @@ int Waiter::WaitToLaunching(int argc, char *argv[])
else
app_root = ".";
- this->OnPrepare();
- AppInfo info = {
- AppPath : argv[1],
- AppId : "",
- PkgId : "",
- PkgType : ""
- };
- this->OnLaunchRequested(info);
- this->executor_(app_path, app_root, argc, argv);
+ 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))
+ {
+ 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);
+}
+
diff --git a/NativeLauncher/src/waiter.h b/NativeLauncher/src/waiter.h
index f233317..c4b98fb 100644
--- a/NativeLauncher/src/waiter.h
+++ b/NativeLauncher/src/waiter.h
@@ -1,13 +1,50 @@
#include <string>
#include <functional>
-using std::string;
+#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:
@@ -18,28 +55,22 @@ class Waiter
string PkgId;
string PkgType;
};
- using Action = std::function<void(void)>;
- using Executor = std::function<void(const string&, const string&, int, char**)>;
-
- Waiter(Action prepare, Action requested, Executor executor);
- ~Waiter();
int WaitToLaunching(int argc, char *argv[]);
void Stop();
void RegisterFd(int fd, Receiver receiver);
void DeregisterFd(int fd);
+ void SetContext(WaiterContext ctx);
protected:
- void OnPrepare();
- void OnLaunchRequested(const AppInfo&);
+ void OnPrepared();
+ void OnRequested(const AppInfo&);
void OnWaiting();
+ void OnExecuted(const char *path, const char *app_root, int argc, char *argv[]);
private:
-
- Action prepare_;
- Action requested_;
- Executor executor_;
+ WaiterContext context;
};
} // namespace runtime
diff --git a/Tizen.Runtime/Tizen.CoreFX.Ref.Targets b/Tizen.Runtime/Tizen.CoreFX.Ref.Targets
index f2484c1..8c1d628 100644
--- a/Tizen.Runtime/Tizen.CoreFX.Ref.Targets
+++ b/Tizen.Runtime/Tizen.CoreFX.Ref.Targets
@@ -1,8 +1,8 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
- <CoreFXRefPath>/opt/usr/share/tizen.net/ref</CoreFXRefPath>
- <TizenDeviceAPIPath>/usr/share/assembly</TizenDeviceAPIPath>
+ <CoreFXRefPath Condition=" '$(CoreFXRefPath)' == '' ">/opt/usr/share/tizen.net/ref</CoreFXRefPath>
+ <TizenDeviceAPIPath Condition=" '$(TizenDeviceAPIPath)' == '' ">/usr/share/assembly</TizenDeviceAPIPath>
</PropertyGroup>
<PropertyGroup>
@@ -11,7 +11,12 @@
<AdditionalLibPaths>$(CoreFXRefPath);$(TizenDeviceAPIPath)</AdditionalLibPaths>
<AddAdditionalExplicitAssemblyReferences>false</AddAdditionalExplicitAssemblyReferences>
<!-- Temporary suppress the warning... -->
- <NoWarn>1701</NoWarn>
+ <NoWarn>1701, 1702</NoWarn>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <CscToolPath>$(ExternalCscDir)</CscToolPath>
+ <CscToolExe>$(ExternalCscExe)</CscToolExe>
</PropertyGroup>
<ItemGroup>
@@ -27,8 +32,11 @@
<ReferencePath Include="@(TizenDeviceAPIAssemblies->'%(Filename).dll')"/>
</ItemGroup>
- <Target Name="BeforeBuild">
+ <Target Name="LogVariables" AfterTargets="Build">
<Message Text="[CoreFX Reference Environment!]"/>
+ <Message Text="CscItem = %(ExternalCscPathItem.FullPath)"/>
+ <Message Text="CscPath = %(ExternalCscDirectory.FullPath)"/>
+ <Message Text="CscExe = %(ExternalCscExe.Identity)"/>
<Message Text="CoreFX dir = $(CoreFXRefPath)"/>
<Message Text="CoreFX dir Check Ok" Condition="Exists('$(CoreFXRefPath)')"/>
<Message Text="Tizen Device API dir = $(TizenDeviceAPIPath)"/>
@@ -40,8 +48,4 @@
<Message Text="CoreFXRefAssemblies = %(CoreFXRefAssemblies.Identity)"/>
<Message Text="TizenDeviceAPIAssemblies = %(TizenDeviceAPIAssemblies.Identity)"/>
</Target>
-
- <PropertyGroup>
- <CheckConfigDependsOn>CheckEnvironment</CheckConfigDependsOn>
- </PropertyGroup>
</Project>
diff --git a/Tizen.Runtime/Tizen.Runtime.csproj b/Tizen.Runtime/Tizen.Runtime.csproj
index ffe4d9c..ed996ac 100644
--- a/Tizen.Runtime/Tizen.Runtime.csproj
+++ b/Tizen.Runtime/Tizen.Runtime.csproj
@@ -4,7 +4,7 @@
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <OutputType>Library</OutputType>
+ <OutputType>exe</OutputType>
<AssemblyName>Tizen.Runtime</AssemblyName>
</PropertyGroup>
@@ -22,21 +22,44 @@
<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>
+ <Compile Include="Tizen.Runtime/AssemblyManager.cs" />
<Compile Include="Tizen.Runtime/AssemblyLoader.cs" />
<Compile Include="Tizen.Runtime/Log.cs" />
- <Compile Include="Tizen.Runtime/AssemblyManager.cs" />
+ <Compile Include="Tizen.Runtime/Interop.cs" />
+ <Compile Include="Tizen.Runtime/Ini.cs" />
+ <Compile Include="Tizen.Runtime/DefaultConfigAttribute.cs" />
</ItemGroup>
<Target Name="CheckConfig">
<Message Text="MSBuildProjectDirectory = $(MSBuildProjectDirectory)"/>
+
+ <ItemGroup>
+ <AssemblyAttributes Include="DefaultConfigAttribute" Condition=" $(LauncherConfigPath) != '' ">
+ <_Parameter1>ConfigPath=$(LauncherConfigPath)</_Parameter1>
+ </AssemblyAttributes>
+ </ItemGroup>
+
+ <WriteCodeFragment AssemblyAttributes="@(AssemblyAttributes)"
+ Language="C#"
+ OutputDirectory="$(IntermediateOutputPath)"
+ OutputFile="ConfigPath.cs">
+ <Output TaskParameter="OutputFile" ItemName="Compile" />
+ </WriteCodeFragment>
+
</Target>
- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildProjectDirectory)/Tizen.CoreFX.Ref.Targets" />
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
diff --git a/Tizen.Runtime/Tizen.Runtime/AssemblyLoader.cs b/Tizen.Runtime/Tizen.Runtime/AssemblyLoader.cs
index e959146..a80e781 100644
--- a/Tizen.Runtime/Tizen.Runtime/AssemblyLoader.cs
+++ b/Tizen.Runtime/Tizen.Runtime/AssemblyLoader.cs
@@ -9,37 +9,80 @@ namespace Tizen.Runtime
public class AssemblyLoader : AssemblyLoadContext
{
private SortedSet<string> _dllDirectories = new SortedSet<string>();
+ private SortedSet<string> _nativeDirectories = new SortedSet<string>();
+
public IEnumerable<string> DllDirectories
{
get { return _dllDirectories; }
}
+ public IEnumerable<string> NativeDirectories
+ {
+ get { return _nativeDirectories; }
+ }
+
public void AddSearchableDirectory(string directory)
{
if (Directory.Exists(directory))
{
_dllDirectories.Add(directory);
+ _nativeDirectories.Add(directory);
}
}
public void RemoveSearchableDirectory(string directory)
{
_dllDirectories.Remove(directory);
+ _nativeDirectories.Remove(directory);
}
protected override Assembly Load(AssemblyName assemblyName)
{
- ALog.Debug($"Load!! : {assemblyName.Name}");
- foreach (string dir in DllDirectories)
+ ALog.Debug($"Load DLL : {assemblyName.Name}");
+ Assembly asm = null;
+
+ try
+ {
+ asm = Assembly.Load(assemblyName);
+ }
+ catch (Exception ex)
+ when (ex is FileNotFoundException ||
+ ex is BadImageFormatException ||
+ ex is FileLoadException)
{
- FileInfo f = new FileInfo(Path.Combine(dir, $"{assemblyName.Name}.dll"));
- ALog.Debug(f.FullName);
- if (File.Exists(f.FullName))
+ ALog.Debug("Search DLL in added directories");
+ foreach (string dir in DllDirectories)
{
- return LoadFromAssemblyPath(f.FullName);
+ FileInfo f = new FileInfo(Path.Combine(dir, $"{assemblyName.Name}.dll"));
+ if (File.Exists(f.FullName))
+ {
+ asm = LoadFromAssemblyPath(f.FullName);
+ break;
+ }
}
}
- return Assembly.Load(assemblyName);
+ return asm;
+ }
+
+ protected override IntPtr LoadUnmanagedDll(string unmanagedDllName)
+ {
+ ALog.Debug($"Load Native : {unmanagedDllName}");
+ IntPtr native = base.LoadUnmanagedDll(unmanagedDllName);
+ if (native == IntPtr.Zero)
+ {
+ ALog.Debug("Search native lib in added directories");
+ foreach (string dir in NativeDirectories)
+ {
+ FileInfo f = new FileInfo(Path.Combine(dir, unmanagedDllName));
+ if (File.Exists(f.FullName))
+ {
+ native = LoadUnmanagedDllFromPath(f.FullName);
+ break;
+ }
+ }
+ }
+
+ return native;
}
}
}
diff --git a/Tizen.Runtime/Tizen.Runtime/AssemblyManager.cs b/Tizen.Runtime/Tizen.Runtime/AssemblyManager.cs
index f7a7810..1f50867 100644
--- a/Tizen.Runtime/Tizen.Runtime/AssemblyManager.cs
+++ b/Tizen.Runtime/Tizen.Runtime/AssemblyManager.cs
@@ -2,25 +2,128 @@
using System.IO;
using System.Reflection;
using System.Runtime.Loader;
+using System.Linq;
namespace Tizen.Runtime
{
public static class AssemblyManager
{
- private static void PrintException(Exception exception)
+ public static int Prepared(IntPtr data)
{
- while (exception != null)
+ try
{
- ALog.Debug(exception.Message);
- ALog.Debug(exception.StackTrace);
- exception = exception.InnerException;
+ string configPath = "file:///etc/dotnet-launcher.ini";
+ ICustomAttributeProvider assembly = typeof(AssemblyManager).GetTypeInfo().Assembly;
+ var attributes = assembly.GetCustomAttributes(typeof(DefaultConfigAttribute), false);
+ if (attributes.Length > 0 && attributes[0] is DefaultConfigAttribute)
+ {
+ DefaultConfigAttribute dca = (DefaultConfigAttribute)attributes[0];
+ FileInfo f = new FileInfo(dca.Config["ConfigPath"]);
+ if (File.Exists(f.FullName))
+ {
+ configPath = "file://"+f.FullName;
+ }
+ }
+
+ Ini ini = new Ini(new Uri(configPath));
+ var dotnet = ini["dotnet"];
+ foreach(var kv in dotnet)
+ {
+ ALog.Debug(kv.Key + " = " + kv.Value);
+ }
+
+ string preloadDlls = "";
+ string preloadDllDirs = "";
+ var preloads = ini["preloads"];
+ if (preloads != null)
+ {
+ foreach (string key in preloads.Keys)
+ {
+ FileInfo f = new FileInfo(key);
+ if (File.Exists(f.FullName))
+ {
+ preloadDlls += f.FullName + ":";
+ preloadDllDirs += f.Directory + ":";
+ }
+ }
+ }
+
+ if (!Initialize(preloadDllDirs, preloadDlls))
+ {
+ return 1;
+ }
}
+ catch(Exception e)
+ {
+ ALog.Debug("Exception at Preparing");
+ PrintException(e);
+ return 1;
+ }
+ return 0;
}
- public static AssemblyLoader CurrentAssemblyLoaderContext
+ public static int Requested(IntPtr data)
{
- get;
- private set;
+ return 0;
+ }
+
+ public static int Executed(string path, string app_root, int argc, string[] argv, IntPtr data)
+ {
+ try
+ {
+ FileInfo f = new FileInfo(path);
+ CurrentAssemblyLoaderContext.AddSearchableDirectory(f.Directory.FullName);
+ DirectoryInfo d = new DirectoryInfo(app_root);
+ CurrentAssemblyLoaderContext.AddSearchableDirectory(d.FullName);
+ Execute(path);
+ }
+ 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);
+ }
+ catch(Exception e)
+ {
+ PrintException(e);
+ }
+ }
+
+ private static void PrintException(Exception exception)
+ {
+ while (exception != null)
+ {
+ ALog.Debug(exception.ToString());
+ exception = exception.InnerException;
+ }
}
public static bool Initialize(string searchableDirectories, string preloadDllPaths)
@@ -31,7 +134,7 @@ namespace Tizen.Runtime
if (searchableDirectories != null)
{
- string[] dirs = searchableDirectories.Split(':');
+ string[] dirs = searchableDirectories.Split(new char[]{':'}, StringSplitOptions.None);
foreach (string dir in dirs)
{
CurrentAssemblyLoaderContext.AddSearchableDirectory(dir);
@@ -40,9 +143,10 @@ namespace Tizen.Runtime
if (preloadDllPaths != null)
{
- string[] dllPaths = preloadDllPaths.Split(':');
+ string[] dllPaths = preloadDllPaths.Split(new char[]{':'}, StringSplitOptions.None);
foreach (string dllPath in dllPaths)
{
+ if (string.IsNullOrWhiteSpace(dllPath)) continue;
FileInfo f = new FileInfo(dllPath);
if (File.Exists(f.FullName))
{
@@ -82,6 +186,24 @@ 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;
+ private set;
}
+
}
}
diff --git a/Tizen.Runtime/Tizen.Runtime/DefaultConfigAttribute.cs b/Tizen.Runtime/Tizen.Runtime/DefaultConfigAttribute.cs
new file mode 100644
index 0000000..f5ba0b0
--- /dev/null
+++ b/Tizen.Runtime/Tizen.Runtime/DefaultConfigAttribute.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+
+[AttributeUsage(AttributeTargets.Assembly)]
+public class DefaultConfigAttribute : Attribute {
+ public DefaultConfigAttribute() : this(string.Empty) {}
+ public DefaultConfigAttribute(string txt)
+ {
+ Config = new Dictionary<string, string>();
+ string[] keyvalues = txt.Split(new string[] {","}, StringSplitOptions.None);
+ foreach (string kvstr in keyvalues)
+ {
+ int eq_pos = kvstr.IndexOf('=');
+ if (eq_pos == -1)
+ throw new FormatException("Config must be written like \"Key1=Value1, Key2=Value2\"");
+
+ string key = kvstr.Substring(0, eq_pos).Trim();
+ string value = kvstr.Substring(eq_pos+1).Trim();
+ Config[key] = value;
+ }
+ }
+ public Dictionary<string, string> Config
+ {
+ get;
+ set;
+ }
+}
diff --git a/Tizen.Runtime/Tizen.Runtime/Ini.cs b/Tizen.Runtime/Tizen.Runtime/Ini.cs
new file mode 100644
index 0000000..d5c2544
--- /dev/null
+++ b/Tizen.Runtime/Tizen.Runtime/Ini.cs
@@ -0,0 +1,139 @@
+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
new file mode 100644
index 0000000..3476a81
--- /dev/null
+++ b/Tizen.Runtime/Tizen.Runtime/Interop.cs
@@ -0,0 +1,20 @@
+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);
+ internal delegate int ExecutedCallback(string path, string app_root, int argc, string[] argv, 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);
+}
diff --git a/packaging/dotnet-launcher.spec b/packaging/dotnet-launcher.spec
index 353ab99..883fae0 100644
--- a/packaging/dotnet-launcher.spec
+++ b/packaging/dotnet-launcher.spec
@@ -43,6 +43,7 @@ Launchpad plugin for launching dotnet apps
cmake \
-DCMAKE_INSTALL_PREFIX=%{_prefix} \
-DPACKAGE_NAME=%{name} \
+ -DLIBDIR=%{_libdir} \
-DBINDIR=%{_bindir} \
-DLOADERDIR=%{_loaderdir} \
-DCONFIGDIR=%{_configdir} \
@@ -57,11 +58,12 @@ xbuild /p:Configuration=%{_buildmode} Tizen.Runtime/Tizen.Runtime.csproj
%install
rm -rf %{buildroot}
%make_install
-install -p -m 644 Tizen.Runtime/bin/Tizen.Runtime.dll %{buildroot}%{_bindir}
+install -p -m 644 Tizen.Runtime/bin/Tizen.Runtime.exe %{buildroot}%{_bindir}
%files
%manifest dotnet-launcher.manifest
%config /etc/dotnet-launcher.ini
%{_loaderdir}/dotnet.loader
%caps(cap_mac_admin,cap_setgid=ei) %{_bindir}/dotnet-launcher
-%caps(cap_mac_admin,cap_setgid=ei) %{_bindir}/Tizen.Runtime.dll
+%caps(cap_mac_admin,cap_setgid=ei) %{_libdir}/libdnclauncher.so
+%caps(cap_mac_admin,cap_setgid=ei) %{_bindir}/Tizen.Runtime.exe
diff --git a/test_build_on_desktop.sh b/test_build_on_desktop.sh
new file mode 100755
index 0000000..90a8583
--- /dev/null
+++ b/test_build_on_desktop.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+#CoreFXRefPath=`readlink -e ../dlls/corefx_refs/`
+#TizenDeviceAPIPath=`readlink -e ../dlls/tizen_deviceapis/`
+CoreFXRefPath=`readlink -e ../dlls/desktop/`
+TizenDeviceAPIPath=`readlink -e ../dlls/tizen_deviceapis/`
+LauncherConfigPath=./dotnet-launcher.ini
+RoslynCscDir=/home/idkiller/work/runtime/roslyn/Binaries/Debug/csccore
+RoslynCscExe=csc
+
+mkdir build
+cd build
+cmake -DCMAKE_BUILD_TYPE=Debug -DNO_TIZEN=1 -DLAUNCHER_CONFIG_PATH=$LauncherConfigPath -DLAUNCHER_ASSEMBLY_PATH=Tizen.Runtime.dll ../NativeLauncher/
+make
+xbuild /t:Clean ../Tizen.Runtime/Tizen.Runtime.csproj
+#xbuild /verbosity:diagnostic /p:CLOG=1 /p:ExternalCscPath=/home/idkiller/work/runtime/roslyn/Binaries/Debug/csccore/csc.exe /p:LauncherConfigPath=$LauncherConfigPath /p:CoreFXRefPath=$CoreFXRefPath /p:TizenDeviceAPIPath=$TizenDeviceAPIPath ../Tizen.Runtime/Tizen.Runtime.csproj
+xbuild /p:CLOG=1 /p:ExternalCscDir=$RoslynCscDir /p:ExternalCscExe=$RoslynCscExe /p:LauncherConfigPath=$LauncherConfigPath /p:CoreFXRefPath=$CoreFXRefPath /p:TizenDeviceAPIPath=$TizenDeviceAPIPath ../Tizen.Runtime/Tizen.Runtime.csproj
+cp ../Tizen.Runtime/bin/Tizen.Runtime.* .
+cp ../NativeLauncher/dotnet-launcher.ini .