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