Add "--version" option for dotnet-launcher
[platform/core/dotnet/launcher.git] / NativeLauncher / src / dotnet / dotnet_launcher.cc
1
2 #include <dlfcn.h>
3
4 #include <string>
5 #include <fstream>
6 #include <vector>
7
8 #include "utils.h"
9 #include "log.h"
10 #include "launcher.h"
11 #include "dotnet_launcher.h"
12
13 namespace tizen {
14 namespace runtime {
15 namespace dotnetcore {
16
17 CoreRuntime::CoreRuntime() :
18   coreclrLib(nullptr),
19   hostHandle(nullptr),
20   domainId(-1),
21   PreparedFunction(nullptr),
22   LaunchFunction(nullptr),
23   InitializeClr(nullptr),
24   ExecuteAssembly(nullptr),
25   Shutdown(nullptr),
26   CreateDelegate(nullptr)
27 {
28 #define __XSTR(x) #x
29 #define __STR(x) __XSTR(x)
30
31 #ifdef DEVICE_API_DIR
32   DeviceAPIDirectory = __STR(DEVICE_API_DIR);
33 #endif
34 #ifdef RUNTIME_DIR
35   RuntimeDirectory = __STR(RUNTIME_DIR);
36 #endif
37 #ifdef CORECLR_LAUNCHER_ASSEMBLY_PATH
38   LauncherAssembly = __STR(CORECLR_LAUNCHER_ASSEMBLY_PATH);
39 #endif
40
41 #undef __STR
42 #undef __XSTR
43
44   _DBG("Constructor called!!");
45 }
46
47 CoreRuntime::~CoreRuntime()
48 {
49   Dispose();
50 }
51
52 int CoreRuntime::Initialize(bool standalone)
53 {
54
55   if (standalone)
56   {
57     const char *_deviceapi_directory = getenv("DeviceAPIDirectory");
58     const char *_runtime_directory = getenv("RuntimeDirectory");
59     const char *_launcher_assembly = getenv("LauncherAssembly");
60     if (_deviceapi_directory != nullptr)
61       DeviceAPIDirectory = _deviceapi_directory;
62     if (_runtime_directory != nullptr)
63       RuntimeDirectory = _runtime_directory;
64     if (_launcher_assembly != nullptr)
65       LauncherAssembly = _launcher_assembly;
66   }
67
68   if (DeviceAPIDirectory.empty())
69   {
70     _ERR("Empty Device API Directory");
71     return 1;
72   }
73   else
74   {
75     DeviceAPIDirectory = AbsolutePath(DeviceAPIDirectory);
76   }
77   if (RuntimeDirectory.empty())
78   {
79     _ERR("Empty Runtime Directory");
80     return 1;
81   }
82   else
83   {
84     RuntimeDirectory = AbsolutePath(RuntimeDirectory);
85   }
86   if (LauncherAssembly.empty())
87   {
88     _ERR("Empty Launcher Assembly");
89     return 1;
90   }
91   else
92   {
93     LauncherAssembly = AbsolutePath(LauncherAssembly);
94   }
95
96   std::string libcoreclr(ConcatPath(RuntimeDirectory, "libcoreclr.so"));
97
98   _DBG("libcoreclr : %s", libcoreclr.c_str());
99
100   coreclrLib = dlopen(libcoreclr.c_str(), RTLD_NOW | RTLD_LOCAL);
101   if (coreclrLib == nullptr)
102   {
103     char *err = dlerror();
104     _ERR("dlopen failed to open libcoreclr.so with error %s", err);
105     return 1;
106   }
107
108 #define CORELIB_RETURN_IF_NOSYM(type, variable, name) \
109   do { variable = (type)dlsym(coreclrLib, name); \
110     if (variable == nullptr) { \
111       _ERR(name " is not found in the libcoreclr.so"); \
112       return 1; \
113     }} while(0)
114
115   CORELIB_RETURN_IF_NOSYM(coreclr_initialize_ptr, InitializeClr, "coreclr_initialize");
116   CORELIB_RETURN_IF_NOSYM(coreclr_execute_assembly_ptr, ExecuteAssembly, "coreclr_execute_assembly");
117   CORELIB_RETURN_IF_NOSYM(coreclr_shutdown_ptr, Shutdown, "coreclr_shutdown");
118   CORELIB_RETURN_IF_NOSYM(coreclr_create_delegate_ptr, CreateDelegate, "coreclr_create_delegate");
119
120 #undef CORELIB_RETURN_IF_NOSYM
121
122   _DBG("libcoreclr dlopen and dlsym success");
123
124   _DBG("this addr : %x", this);
125   _DBG("coreclr_initialize : %x", InitializeClr);
126
127   return 0;
128 }
129
130 int CoreRuntime::RunManagedLauncher()
131 {
132   void* hostHandle;
133   unsigned int domainId;
134
135   if (FileNotExist(LauncherAssembly))
136   {
137     _ERR("Launcher assembly is not exist in %s", LauncherAssembly.c_str());
138     return 1;
139   }
140
141   std::string launcherDir = Basename(LauncherAssembly);
142   std::vector<std::string> searchDirectories = {
143     RuntimeDirectory, DeviceAPIDirectory, launcherDir
144   };
145
146   std::string trusted_assemblies;
147   AssembliesInDirectory(searchDirectories, trusted_assemblies);
148   std::string trusted_directories = JoinStrings(searchDirectories, ":");
149
150   _DBG("coreclr_dir : %s", RuntimeDirectory.c_str());
151   _DBG("tpa_dirs : %s", trusted_directories.c_str());
152   _DBG("native_so_search_dir : %s", trusted_directories.c_str());
153   _DBG("launcher_assembly : %s", LauncherAssembly.c_str());
154   _DBG("launcher_dir : %s", launcherDir.c_str());
155
156   const char *propertyKeys[] =
157   {
158     "TRUSTED_PLATFORM_ASSEMBLIES",
159     "APP_PATHS",
160     "APP_NI_PATHS",
161     "NATIVE_DLL_SEARCH_DIRECTORIES",
162     "AppDomainCompatSwitch"
163   };
164
165   const char *propertyValues[] =
166   {
167     trusted_assemblies.c_str(),
168     launcherDir.c_str(),
169     launcherDir.c_str(),
170     trusted_directories.c_str(),
171     "UseLatestBehaviorWhenTFMNotSpecified"
172   };
173   
174   //_DBG("trusted platform assemblies : %s", propertyValues[0]);
175   _DBG("app_path : %s", propertyValues[1]);
176   _DBG("app_ni_path : %s", propertyValues[2]);
177   _DBG("native dll search path : %s", propertyValues[3]);
178   _DBG("app domain compat switch : %s", propertyValues[4]);
179
180   _DBG("before InitializeClr");
181   _DBG("this addr : %x", this);
182   _DBG("coreclr_initialize : %x", InitializeClr);
183
184   std::string selfPath = ReadSelfPath();
185
186   _DBG("self path : %s", selfPath.c_str());
187
188   _DBG("libcoreclr addr : %x", coreclrLib);
189
190   int st = InitializeClr(
191       selfPath.c_str(),
192       //LauncherAssembly.c_str(),
193       "dotnet-launcher",
194       sizeof(propertyKeys) / sizeof(propertyKeys[0]),
195       propertyKeys,
196       propertyValues,
197       &hostHandle,
198       &domainId);
199
200   if (st < 0)
201   {
202     _ERR("initialize core clr fail! (0x%08x)", st);
203     return 1;
204   }
205
206   _DBG("Initialize core clr success");
207
208   void *preparedFunctionDelegate;
209   st = CreateDelegate(hostHandle, domainId,
210       "Tizen.Runtime.Coreclr",
211       "Tizen.Runtime.Coreclr.AssemblyManager",
212       "Prepared", &preparedFunctionDelegate);
213   if (st < 0)
214   {
215     _ERR("Create delegate for Launch prepared function is fail (0x%08x)", st);
216     return 1;
217   }
218   PreparedFunction = reinterpret_cast<PreparedFunctionPtr>(preparedFunctionDelegate);
219
220   if(PreparedFunction != nullptr)
221   {
222     PreparedFunction();
223   }
224
225   void *launchFunctionDelegate;
226   st = CreateDelegate(hostHandle, domainId,
227       "Tizen.Runtime.Coreclr",
228       "Tizen.Runtime.Coreclr.AssemblyManager",
229       "Launch", &launchFunctionDelegate);
230   if (st < 0)
231   {
232     _ERR("Create delegate for Launch managed function is fail! (0x%08x)", st);
233     return 1;
234   }
235   LaunchFunction = reinterpret_cast<LaunchFunctionPtr>(launchFunctionDelegate);
236
237   return 0;
238 }
239
240 void CoreRuntime::Dispose()
241 {
242   if (hostHandle != nullptr)
243   {
244     int st = Shutdown(hostHandle, domainId);
245     if (st < 0)
246     {
247       _ERR("shutdown core clr fail! (0x%08x)", st);
248     }
249   }
250
251   if (dlclose(coreclrLib) != 0)
252   {
253     _ERR("libcoreclr.so close failed");
254   }
255   coreclrLib = nullptr;
256
257   _DBG("Dotnet runtime disposed");
258 }
259
260 int CoreRuntime::Launch(const char* root, const char* path, int argc, char* argv[])
261 {
262   if (path == nullptr)
263   {
264     _ERR("executable path is null");
265     return 1;
266   }
267
268   if (FileNotExist(path))
269   {
270     _ERR("File not exist : %s", path);
271     return 1;
272   }
273
274   bool success = false;
275   if (LaunchFunction != nullptr)
276   {
277     success = LaunchFunction(root, path, argc, argv);
278     if (!success)
279     {
280       _ERR("Failed to launch Application %s", path);
281     }
282   }
283   return success ? 0 : 1;
284 }
285
286 }  // namespace dotnetcore
287 }  // namespace runtime
288 }  // namespace tizen