From: pius.lee Date: Thu, 28 Jul 2016 04:28:52 +0000 (+0900) Subject: Make it runnable with dotnet packages X-Git-Tag: submit/tizen/20161214.063015~30 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b5b9bee354bb91f7e13d88276f0a0aa5c1dc46d6;p=platform%2Fcore%2Fdotnet%2Flauncher.git Make it runnable with dotnet packages add build option for desktop -DNO_TIZEN=1 add config file path build option -DLAUNCHER_PATH=dotnet-launcher.ini fix bugs in default TPL paths --- diff --git a/CMakeLists.txt b/CMakeLists.txt index b711b0d..8998418 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,47 +1,54 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6) PROJECT("dotnet-launcher") -INCLUDE(FindPkgConfig) -PKG_CHECK_MODULES(${PROJECT_NAME} REQUIRED - aul - dlog - ecore - bundle - dlog - launchpad - ) +MESSAGE("CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}") + +IF(DEFINED NO_TIZEN) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -DNO_TIZEN") +ELSE(DEFINED NO_TIZEN) + INCLUDE(FindPkgConfig) + PKG_CHECK_MODULES(${PROJECT_NAME} REQUIRED aul dlog ecore bundle dlog launchpad) +ENDIF(DEFINED NO_TIZEN) 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) + + +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} -fPIE") SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fdata-sections -ffunction-sections -Wl,--gc-sections") SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -D_FILE_OFFSET_BITS=64") -SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") -SET(CMAKE_C_FLAGS_DEBUG "-O0 -g") -SET(CMAKE_C_FLAGS_RELEASE "-O2") +SET(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") +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 src/launcher.cc src/waiter.cc ) + ADD_EXECUTABLE(${PROJECT_NAME} ${${PROJECT_NAME}_SOURCE_FILES}) -TARGET_LINK_LIBRARIES(${PROJECT_NAME} aul) -TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${${PROJECT_NAME}_LDFLAGS} "-pie") +IF(NOT DEFINED NO_TIZEN) + TARGET_LINK_LIBRARIES(${PROJECT_NAME} aul) +ENDIF(NOT DEFINED NO_TIZEN) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${${PROJECT_NAME}_LDFLAGS} "-pie -ldl") SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SKIP_BUILD_RPATH TRUE ) # remove rpath option that is automatically generated by cmake. -CONFIGURE_FILE(${PACKAGE_NAME}.xml.in ${PACKAGE_NAME}.xml) - -INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin) -INSTALL(FILES ${PACKAGE_NAME}.xml DESTINATION ${MANIFESTDIR}) -INSTALL(FILES packaging/dotnet.loader DESTINATION ${LOADERDIR}) - +IF(NOT DEFINED NO_TIZEN) + INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${BINDIR}) + INSTALL(FILES packaging/dotnet.loader DESTINATION ${LOADERDIR}) + INSTALL(FILES packaging/dotnet-launcher.ini DESTINATION ${CONFIGDIR}) +ENDIF(NOT DEFINED NO_TIZEN) diff --git a/packaging/dotnet-launcher.spec b/packaging/dotnet-launcher.spec index c9dca6e..2bbc40a 100644 --- a/packaging/dotnet-launcher.spec +++ b/packaging/dotnet-launcher.spec @@ -1,8 +1,8 @@ Name: dotnet-launcher Summary: Launchpad plugin for dotnet apps -Version: 0.1.0 +Version: 0.0.1 Release: 1 -Group: Application Framework/Daemons +Group: Application Framework/Application State Management License: Apache License, Version 2.0 Source0: %{name}-%{version}.tar.gz @@ -21,25 +21,28 @@ Requires(postun): /sbin/ldconfig Requires(postun): /usr/bin/systemctl Requires(preun): /usr/bin/systemctl -%define _sys_bin %{TZ_SYS_BIN} -%define _sys_sbin %{TZ_SYS_SBIN} -%define _sys_share %{TZ_SYS_RO_SHARE} -%define _manifestdir %{TZ_SYS_RO_PACKAGES} -%define _loaderdir %{TZ_SYS_RO_SHARE}/aul +%define _loaderdir %{_prefix}/share/aul +%define _configdir /etc %description -Launchpad for dotnet apps +Launchpad plugin for launching dotnet apps %prep %setup -q %build +%if 0%{?tizen_build_devel_mode} +%define _buildmode Debug +%else +%define _buildmode Release +%endif cmake \ -DCMAKE_INSTALL_PREFIX=%{_prefix} \ - -DMANIFESTDIR=%{_manifestdir} \ -DPACKAGE_NAME=%{name} \ -DBINDIR=%{_bindir} \ -DLOADERDIR=%{_loaderdir} \ + -DCONFIGDIR=%{_configdir} \ + -DCMAKE_BUILD_TYPE=%{_buildmode} \ -DVERSION=%{version} make %{?jobs:-j%jobs} @@ -48,11 +51,8 @@ make %{?jobs:-j%jobs} rm -rf %{buildroot} %make_install -%post - %files -%manifest dotnet-launchpad.manifest -%{_manifestdir}/%{name}.xml +%manifest dotnet-launcher.manifest +%config /etc/dotnet-launcher.ini %{_loaderdir}/dotnet.loader -%attr(0755,root,root) %{_bindir}/dotnet-loader -%caps(cap_mac_admin,cap_mac_override,cap_setgid=ei) %{_bindir}/dotnet-loader +%caps(cap_mac_admin,cap_setgid=ei) %{_bindir}/dotnet-launcher diff --git a/packaging/dotnet.loader b/packaging/dotnet.loader index 43e2d21..67094b9 100644 --- a/packaging/dotnet.loader +++ b/packaging/dotnet.loader @@ -1,6 +1,6 @@ [LOADER] -NAME dotnet-loader -EXE /usr/bin/dotnet-loader +NAME dotnet-launcher +EXE /usr/bin/dotnet-launcher APP_TYPE dotnet DETECTION_METHOD TIMEOUT|DEMAND TIMEOUT 5000 diff --git a/src/launcher.cc b/src/launcher.cc index 631f7e5..66bc440 100644 --- a/src/launcher.cc +++ b/src/launcher.cc @@ -1,9 +1,13 @@ +#include + #include #include #include #include #include #include +#include +#include #include #include @@ -14,8 +18,24 @@ #include "tini.hpp" -#ifndef LAUNCHER_CONFIG -#define LAUNCHER_CONFIG "/usr/share/dotnet/dotnet-launcher.ini" +#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) +#else +#define LAUNCHER_CONFIG "/etc/dotnet-launcher.ini" +#endif +static const std::string LauncherConfig(LAUNCHER_CONFIG); +#ifdef LAUNCHER_PATH +#undef __STR +#undef __XSTR +#undef LAUNCHER_CONFIG +#undef LAUNCHER_PATH #endif static std::string AbsolutePath(const std::string& path) @@ -23,7 +43,7 @@ static std::string AbsolutePath(const std::string& path) std::string absPath; char realPath[PATH_MAX]; - if (realpath(path, realPath) != nullptr && realPath[0] != '\0') + if (realpath(path.c_str(), realPath) != nullptr && realPath[0] != '\0') { absPath.assign(realPath); } @@ -52,7 +72,11 @@ static std::string AssembliesInDirectory(const char *directory) DIR* dir = opendir(directory); - if (dir == nullptr) return std::string(); + if (dir == nullptr) + { + _ERR("can not open directory : %s", directory); + return std::string(); + } std::map, bool> addedAssemblies; @@ -86,13 +110,18 @@ static std::string AssembliesInDirectory(const char *directory) std::string filename(entry->d_name); int extPos = filename.find_last_of('.'); if (extPos <= 0) continue; + bool notUsedExtension = true; for (auto ext : tpaExtensions) { int extLength = strlen(ext); - if (filename.compare(extPos-1, extLength, ext) != 0) - continue; - } + if (filename.compare(extPos, extLength, ext) == 0) + { + notUsedExtension = false; + break; + } + } + if (notUsedExtension) continue; std::string filenameWithoutExt; bool isNativeImage = extPos > niExtensionSize ? @@ -108,7 +137,6 @@ static std::string AssembliesInDirectory(const char *directory) std::string ext = filename.substr(extPos); std::pair key(filenameWithoutExt, ext); - std::cout << " " << filenameWithoutExt << ext << " " << isNativeImage << std::endl; if (addedAssemblies.count(key)) { isNativeImage = isNativeImage || addedAssemblies[key]; @@ -128,6 +156,7 @@ static std::string AssembliesInDirectory(const char *directory) } tpaList.append(pair.first.second); tpaList.append(":"); + _DBG("TPA : %s/%s%s", directory, pair.first.first.c_str(), pair.first.second.c_str()); } closedir(dir); @@ -144,46 +173,56 @@ Launcher::~Launcher() void Launcher::Initialize() { - std::ifstream iniStream(LAUNCHER_CONFIG); + std::ifstream iniStream(LauncherConfig); std::stringstream iniString; iniString << iniStream.rdbuf(); tini::ini launcherIni(iniString); - auto &dotnet = ini["dotnet"]; + _DBG("config file [%s]", LauncherConfig.c_str()); + _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 (dontet.find("native_so_search_dirs") == dotnet.end()) + 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"]; - void* coreclrLib = dlopen(libcoreclr, RTLD_NOW | RTLD_LOCAL); + _DBG("libcoreclr.so : [%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); - goto CoreClrLibClose; + return; } 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"); - if (coreclr_initialize_ptr == nullptr) + if (initializeCoreCLR == nullptr) { - _ERR("coreclr_initialize_ptr not found in the libcoreclr.so"); + _ERR("coreclr_initialize not found in the libcoreclr.so"); } - else if (coreclr_execute_assembly_ptr == nullptr) + else if (executeAssembly == nullptr) { _ERR("coreclr_execute_assembly_ptr not found in the libcoreclr.so"); } - else if (coreclr_shutdown_ptr == nullptr) + else if (shutdownCoreCLR == nullptr) { _ERR("coreclr_shutdown_ptr not found in the libcoreclr.so"); } @@ -193,29 +232,27 @@ void Launcher::Initialize() std::string s; while (std::getline(f, s, ':')) { - TrustedPlatformAssemblies += AssembliesInDirectory(s); + TrustedPlatformAssemblies += AssembliesInDirectory(s.c_str()); } NativeDllSearchDirectories = nativeSoSearchDirs; AppDomainCompatSwitch = "UseLatestBehaviorWhenTFMNotSpecified"; } +} -CoreClrLibClose: +void Launcher::Dispose() +{ if (dlclose(coreclrLib) != 0) { _ERR("libcoreclr.so close failed"); } } -void Launcher::Dispose() -{ -} - void Launcher::Launch(const string& exe_path, int argc, char *argv[]) { - std::string bin_path = Basename(exe_path); - std::string app_home = Basename(app_path); + std::string bin_path = Basename(AbsolutePath(exe_path)); + std::string app_home = Basename(bin_path); std::string lib_path = app_home + "/lib"; - std::string app_path = bin_path + ":" + lib_path + std::string app_path = bin_path + ":" + lib_path; std::string app_ni_path = app_path; std::string nativeDllSearchDirectories = NativeDllSearchDirectories + app_path; @@ -237,51 +274,82 @@ void Launcher::Launch(const string& exe_path, int argc, char *argv[]) AppDomainCompatSwitch.c_str() }; + //_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]); + void* hostHandle; unsigned int domainId; - int st = initializeCoreCLR(exe_path, + _DBG("before initialize coreclr"); + + int st = initializeCoreCLR(exe_path.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"); exit(-1); } unsigned int exitCode; - st = executeAssembly(hostHandle, domainId, argc, argv, exe_path, &exitCode); + st = executeAssembly(hostHandle, domainId, + argc, const_cast(argv), exe_path.c_str(), &exitCode); if (st < 0) { // execute coreclr fail + _ERR("execute core clr fail! (0x%08x)", st); exit(-1); } + _DBG("after execute coreclr"); st = shutdownCoreCLR(hostHandle, domainId); if (st < 0) { // shutdown fail + _ERR("shutdown core clr fail! (0x%08x)", st); exit(-1); } } +} // namespace runtime +} // namespace dotnet + +using dotnet::runtime::Launcher; +using dotnet::runtime::Waiter; + int main(int argc, char *argv[]) { + _DBG("launcher started"); + + for (int i=0; i launcher(new Launcher()); auto on_prepare = [&launcher]() { - launcher.Initialize(); + launcher->Initialize(); }; auto on_requested = [&launcher]() { }; auto on_executed = [&launcher](const std::string& path, int argc, char *argv[]) { - launcher.launch(path, argc, argv); - } + _DBG("EXECUTE %s", path.c_str()); + launcher->Launch(path, argc, argv); + }; std::unique_ptr waiter(new Waiter(on_prepare, on_requested, on_executed)); + waiter->WaitToLaunching(argc, argv); } diff --git a/src/launcher.h b/src/launcher.h index eb53100..946fed4 100644 --- a/src/launcher.h +++ b/src/launcher.h @@ -45,6 +45,8 @@ class Launcher string TrustedPlatformAssemblies; string NativeDllSearchDirectories; string AppDomainCompatSwitch; + + void *coreclrLib; }; } // namespace runtime diff --git a/src/log.h b/src/log.h index c5b6f9d..59f2dc9 100644 --- a/src/log.h +++ b/src/log.h @@ -1,7 +1,14 @@ #ifndef __LOG_H__ #define __LOG_H__ +#ifndef NO_TIZEN #include +#else +#include +#define LOGE(fmt, args...) printf(fmt, ##args) +#define LOGD(fmt, args...) printf(fmt, ##args) +#define LOGI(fmt, args...) printf(fmt, ##args) +#endif #ifdef LOG_TAG #undef LOG_TAG @@ -9,15 +16,15 @@ #define LOG_TAG "NETCORE_LAUNCHER" #ifndef _ERR -#define _ERR(fmt, args...) LOGE(fmt "\n", __func__, __LINE__, ##args) +#define _ERR(fmt, args...) LOGE(fmt "\n", ##args) #endif #ifndef _DBG -#define _DBG(fmt, args...) LOGD(fmt "\n", __func__, __LINE__, ##args) +#define _DBG(fmt, args...) LOGD(fmt "\n", ##args) #endif #ifndef _INFO -#define _INFO(fmt, args...) LOGI(fmt "\n", __func__, __LINE__, ##args) +#define _INFO(fmt, args...) LOGI(fmt "\n", ##args) #endif #endif /* __LOG_H__ */ diff --git a/src/waiter.cc b/src/waiter.cc index 0f622be..7f6eeef 100644 --- a/src/waiter.cc +++ b/src/waiter.cc @@ -1,20 +1,27 @@ -#include "waiter.h" #include + +#ifndef NO_TIZEN #include +#endif #include #include #include #include +#include + +#include "waiter.h" +#include "log.h" + namespace dotnet { namespace runtime { -struct Waiter::FdHandler; +struct FdHandler { pollfd *info; - Receiver re; + Receiver receiver; }; static volatile bool Waiting_; @@ -25,9 +32,11 @@ static Waiter::AppInfo AppInfo_; void Waiter::OnPrepare() { // preload the libraries. + if (prepare_ != nullptr) + prepare_(); } -void Waiter::OnLaunchRequested() +void Waiter::OnLaunchRequested(const AppInfo& info) { // do some job on user id is still system } @@ -37,6 +46,7 @@ void Waiter::OnWaiting() // Start the loop Waiting_ = true; + _DBG("start polling..."); while (Waiting_) { if (poll(Fdlist_.data(), Fdlist_.size(), -1) < 0) @@ -45,9 +55,10 @@ void Waiter::OnWaiting() for (auto &p : Fdlist_) { if ( (p.revents | POLLIN) != 0 ) - Handlers_[p.fd].receiver(); + Handlers_[p.fd].receiver(p.fd); } } + _DBG("end polling..."); } void Waiter::Stop() @@ -62,6 +73,8 @@ void Waiter::RegisterFd(int fd, Receiver receiver) { // register fd should be caught in event loop + _DBG("Register fd %d", fd); + pollfd info; info.fd = fd; info.events = POLLIN; @@ -96,20 +109,28 @@ Waiter::~Waiter() { } -void Waiter::WaitToLaunching(int argc, char *argv[]) +int Waiter::WaitToLaunching(int argc, char *argv[]) { +#ifndef NO_TIZEN auto on_create = [](bundle *extra, int type, void *user_data) { + _DBG("on_create..."); // XXX Waiter* waiter = static_cast(user_data); waiter->OnPrepare(); }; auto on_launch = [](int argc, char **argv, const char *app_path, const char *appid, const char *pkgid, - const char *pkg_type, void *user_data) + const char *pkg_type, void *user_data) -> int { + _DBG("on_launch..."); // XXX Waiter* waiter = static_cast(user_data); + _DBG ("app path : %s", app_path); + _DBG ("app id : %s", appid); + _DBG ("pkg id : %s", pkgid); + _DBG ("pkg type : %s", pkg_type); + AppInfo info = { AppPath : app_path, AppId : appid, @@ -118,43 +139,51 @@ void Waiter::WaitToLaunching(int argc, char *argv[]) }; waiter->OnLaunchRequested(info); + return 0; }; - auto on_terminate = [](int argc, char **argv, void *user_data) + auto on_terminate = [](int argc, char **argv, void *user_data) -> int { + _DBG("on_terminate..."); // XXX Waiter* waiter = static_cast(user_data); - waiter->executor_(argv[LOADER_ARG_PATH], argc, argv); + waiter->executor_(argv[0], argc, argv); + return 0; }; auto on_start_loop = [](void *user_data) { + _DBG("on_start_loop..."); // XXX Waiter* waiter = static_cast(user_data); waiter->OnWaiting(); }; auto on_quit_loop = [](void *user_data) { + _DBG("on_quit_loop..."); // XXX Waiter* waiter = static_cast(user_data); waiter->Stop(); }; auto on_add_fd = [](void *user_data, int fd, loader_receiver_cb receiver) { + _DBG("on_add_fd..."); // XXX Waiter* waiter = static_cast(user_data); waiter->RegisterFd(fd, receiver); }; auto on_remove_fd = [](void *user_data, int fd) { + _DBG("on_remove_fd..."); // XXX Waiter* waiter = static_cast(user_data); waiter->DeregisterFd(fd); }; + _DBG("launcher wait..."); // XXX loader_lifecycle_callback_s callbacks = { .create = on_create, .launch = on_launch, .terminate = on_terminate - } + }; loader_adapter_s adapter = { .loop_begin = on_start_loop, @@ -164,6 +193,18 @@ void Waiter::WaitToLaunching(int argc, char *argv[]) }; return launchpad_loader_main(argc, argv, &callbacks, &adapter, this); +#else + if (argc < 2) return -1; + this->OnPrepare(); + AppInfo info = { + AppPath : argv[1], + AppId : "", + PkgId : "", + PkgType : "" + }; + this->OnLaunchRequested(info); + this->executor_(argv[1], argc, argv); +#endif } } // namespace runtime diff --git a/src/waiter.h b/src/waiter.h index 4315d0c..5fa9dd3 100644 --- a/src/waiter.h +++ b/src/waiter.h @@ -1,10 +1,13 @@ #include +#include using std::string; namespace dotnet { namespace runtime { +using Receiver = std::function; + class Waiter { public: @@ -16,7 +19,6 @@ class Waiter string PkgType; }; using Action = std::function; - using Receiver = std::function; using Executor = std::function; Waiter(Action prepare, Action requested, Executor executor);