generate native image files in the .native_image folder for the pkg aot.
[platform/core/dotnet/launcher.git] / NativeLauncher / installer-plugin / ni_common.cc
index 8384fea..4a1e284 100644 (file)
@@ -69,20 +69,74 @@ static void waitInterval()
        }
 }
 
-static bool niExist(const std::string& path, std::string& ni)
+static void updateNiFileInfo(const std::string& dllPath, const std::string& niPath)
 {
-       size_t index = path.find_last_of(".");
+       char* label = NULL;
+
+       // change smack label
+       if (smack_getlabel(dllPath.c_str(), &label, SMACK_LABEL_ACCESS) == 0) {
+               if (smack_setlabel(niPath.c_str(), label, SMACK_LABEL_ACCESS) < 0) {
+                       fprintf(stderr, "Fail to set smack label\n");
+               }
+               free(label);
+       }
+
+       // change owner and groups for generated ni file.
+       struct stat info;
+       if (!stat(dllPath.c_str(), &info)) {
+               if (chown(niPath.c_str(), info.st_uid, info.st_gid) == -1)
+                       fprintf(stderr, "Failed to change owner and group name\n");
+       }
+}
+
+static std::string getNiFilePath(const std::string& dllPath)
+{
+       size_t index = dllPath.find_last_of(".");
        if (index == std::string::npos) {
-               return false;
+               fprintf(stderr, "File doesnot contain extension. fail to get NI file name\n");
+               return "";
        }
-       std::string fName = path.substr(0, index);
-       std::string fExt = path.substr(index, path.length());
+       std::string fName = dllPath.substr(0, index);
+       std::string fExt = dllPath.substr(index, dllPath.length());
 
        // crossgen generate file with lower case extension only
        std::transform(fExt.begin(), fExt.end(), fExt.begin(), ::tolower);
-       std::string f = fName + ".ni" + fExt;
+       std::string niPath = fName + ".ni" + fExt;
+
+       return niPath;
+}
+
+static std::string getAppNIPath(const std::string& niPath)
+{
+       size_t index = niPath.find_last_of("/");
+       if (index == std::string::npos) {
+               fprintf(stderr, "dllPath doesnot contains path info\n");
+               return "";
+       }
+
+       std::string prevPath = niPath.substr(0, index);
+       std::string fileName = niPath.substr(index, niPath.length());
+       std::string niDirPath = prevPath + APP_NI_SUB_DIR;
+
+       if (!isFileExist(niDirPath)) {
+               if (mkdir(niDirPath.c_str(), 0755) == 0) {
+                       updateNiFileInfo(prevPath, niDirPath);
+               } else {
+                       fprintf(stderr, "Fail to create app ni directory (%s)\n", niDirPath.c_str());
+               }
+       }
+
+       return niDirPath + fileName;
+}
+
+static bool niExist(const std::string& path)
+{
+       std::string f = getNiFilePath(path);
+       if (f.empty()) {
+               return false;
+       }
+
        if (isFileExist(f)) {
-               ni = f;
                return true;
        }
 
@@ -91,7 +145,6 @@ static bool niExist(const std::string& path, std::string& ni)
        if (path.find("System.Private.CoreLib.dll") != std::string::npos) {
                std::string coreLibBackup = path + ".Backup";
                if (isFileExist(coreLibBackup)) {
-                       ni = path;
                        return true;
                }
        }
@@ -99,43 +152,51 @@ static bool niExist(const std::string& path, std::string& ni)
        return false;
 }
 
-static void updateNiFileInfo(const std::string& path)
+static int crossgen(const std::string& dllPath, const std::string& appPath, bool enableR2R, bool isAppNI = false)
 {
-       char* label = NULL;
-       std::string niPath;
+       if (!isFileExist(dllPath)) {
+               fprintf(stderr, "dll file is not exist : %s\n", dllPath.c_str());
+               return -1;
+       }
 
-       if (niExist(path, niPath)) {
-               // change smack label
-               if (smack_getlabel(path.c_str(), &label, SMACK_LABEL_ACCESS) == 0) {
-                       if (smack_setlabel(niPath.c_str(), label, SMACK_LABEL_ACCESS) < 0) {
-                               fprintf(stderr, "Fail to set smack label\n");
-                       }
-                       free(label);
-               }
+       if (!isManagedAssembly(dllPath)) {
+               fprintf(stderr, "Input file is not a dll file : %s\n", dllPath.c_str());
+               return -1;
+       }
 
-               // change owner and groups for generated ni file.
-               struct stat info;
-               if (!stat(path.c_str(), &info)) {
-                       if (chown(niPath.c_str(), info.st_uid, info.st_gid) == -1)
-                               fprintf(stderr, "Failed to change owner and group name\n");
-               }
+       if (niExist(dllPath)) {
+               fprintf(stderr, "Already ni file is exist for %s\n", dllPath.c_str());
+               return -1;
        }
-}
 
-static void crossgen(const std::string& dllPath, const std::string& appPath, bool enableR2R)
-{
        std::string absDllPath = absolutePath(dllPath);
+       std::string absNiPath = getNiFilePath(dllPath);
+       if (absNiPath.empty()) {
+               fprintf(stderr, "Fail to get ni file name\n");
+               return -1;
+       }
+
+       if (isAppNI) {
+               absNiPath = getAppNIPath(absNiPath);
+       }
 
        pid_t pid = fork();
        if (pid == -1)
-               return;
+               return -1;
 
        if (pid > 0) {
                int status;
                waitpid(pid, &status, 0);
                if (WIFEXITED(status)) {
-                       updateNiFileInfo(absDllPath);
-                       return;
+                       // Do not use niExist() function to check whether ni file created or not.
+                       // niEixst() return false for System.Private.Corelib.dll
+                       if (isFileExist(absNiPath)) {
+                               updateNiFileInfo(absDllPath, absNiPath);
+                               return 0;
+                       } else {
+                               fprintf(stderr, "Fail to create native image for %s\n", dllPath.c_str());
+                               return -1;
+                       }
                }
        } else {
                std::string jitPath = getRuntimeDir() + "/libclrjit.so";
@@ -159,6 +220,9 @@ static void crossgen(const std::string& dllPath, const std::string& appPath, boo
                }
                argv.push_back(absAppPath.c_str());
 
+               argv.push_back("/out");
+               argv.push_back(absNiPath.c_str());
+
                argv.push_back(absDllPath.c_str());
                argv.push_back(nullptr);
 
@@ -167,6 +231,8 @@ static void crossgen(const std::string& dllPath, const std::string& appPath, boo
                execv(__CROSSGEN_PATH, const_cast<char* const*>(argv.data()));
                exit(0);
        }
+
+       return 0;
 }
 
 static int getRootPath(std::string pkgId, std::string& rootPath)
@@ -238,9 +304,8 @@ static void createCoreLibNI(bool enableR2R)
        std::string niCoreLib = concatPath(getRuntimeDir(), "System.Private.CoreLib.ni.dll");
        std::string coreLibBackup = concatPath(getRuntimeDir(), "System.Private.CoreLib.dll.Backup");
 
-       if (!niExist(coreLib, niCoreLib)) {
-               crossgen(coreLib, std::string(), enableR2R);
-               if (isFileExist(niCoreLib)) {
+       if (!isFileExist(coreLibBackup)) {
+               if (!crossgen(coreLib, std::string(), enableR2R)) {
                        if (rename(coreLib.c_str(), coreLibBackup.c_str())) {
                                fprintf(stderr, "Failed to rename System.Private.CoreLib.dll\n");
                        }
@@ -296,32 +361,16 @@ void finalizeNICommon()
 void createNiPlatform(bool enableR2R)
 {
        const std::string platformDirs[] = {getRuntimeDir(), getTizenFXDir()};
-
        createNiUnderDirs(platformDirs, 2, enableR2R);
 }
 
-void createNiDll(const std::string& dllPath, bool enableR2R)
+int createNiDll(const std::string& dllPath, bool enableR2R)
 {
        createCoreLibNI(enableR2R);
-
-       if (!isFileExist(dllPath)) {
-               fprintf(stderr, "Failed to find dll : %s\n", dllPath.c_str());
-               return;
-       }
-
-       std::string niPath;
-       if (niExist(dllPath, niPath)) {
-               fprintf(stderr, "Already [%s] file is exist\n", niPath.c_str());
-               return;
-       }
-
-       crossgen(dllPath, std::string(), enableR2R);
-       if (!niExist(dllPath, niPath)) {
-               fprintf(stderr, "Failed to create native image for %s\n", dllPath.c_str());
-       }
+       return crossgen(dllPath, std::string(), enableR2R);
 }
 
-void createNiUnderDirs(const std::string rootPaths[], int count, const std::string ignores[], int igcount, afterCreate cb, bool enableR2R)
+void createNiUnderDirs(const std::string rootPaths[], int count, bool enableR2R, bool isAppNI)
 {
        createCoreLibNI(enableR2R);
 
@@ -334,51 +383,30 @@ void createNiUnderDirs(const std::string rootPaths[], int count, const std::stri
        if (appPaths.back() == ':')
                appPaths.pop_back();
 
-       auto convert = [&appPaths, ignores, igcount, &cb, enableR2R](const std::string& path, const char* name) {
-               for (int i = 0; i < igcount; i++) {
-                       if (path == ignores[i])
-                               return;
-               }
-               std::string niPath;
-               if (isManagedAssembly(path)) {
-                       if (niExist(path, niPath)) {
-                               fprintf(stderr, "Already [%s] file is exist\n", niPath.c_str());
-                               return;
-                       }
-                       crossgen(path, appPaths.c_str(), enableR2R);
-                       if (niExist(path, niPath)) {
-                               if (cb != nullptr)
-                                       cb(niPath.c_str());
-                       } else {
-                               fprintf(stderr, "Failed to create native image for %s\n", path.c_str());
-                       }
+       auto convert = [&appPaths, enableR2R, isAppNI](const std::string& path, const char* name) {
+               if (!crossgen(path, appPaths.c_str(), enableR2R, isAppNI)) {
                        waitInterval();
                }
        };
 
-       for (int i = 0; i < count; i++)
+       for (int i = 0; i < count; i++) {
                scanFilesInDir(rootPaths[i], convert, 1);
-}
-void createNiUnderDirs(const std::string rootPaths[], int count, afterCreate cb, bool enableR2R)
-{
-       createNiUnderDirs(rootPaths, count, nullptr, 0, cb, enableR2R);
-}
-void createNiUnderDirs(const std::string rootPaths[], int count, bool enableR2R)
-{
-       createNiUnderDirs(rootPaths, count, nullptr, enableR2R);
+       }
 }
 
 int createNiUnderPkgRoot(const std::string& pkgName, bool enableR2R)
 {
        std::string pkgRoot;
-       if (getRootPath(pkgName, pkgRoot) < 0)
+       if (getRootPath(pkgName, pkgRoot) < 0) {
+               fprintf(stderr, "Failed to get root path from [%s]\n", pkgName.c_str());
                return -1;
+       }
 
        std::string binDir = concatPath(pkgRoot, "bin");
        std::string libDir = concatPath(pkgRoot, "lib");
        std::string paths[] = {binDir, libDir};
 
-       createNiUnderDirs(paths, 2, enableR2R);
+       createNiUnderDirs(paths, 2, enableR2R, true);
 
        return 0;
 }
@@ -386,31 +414,16 @@ int createNiUnderPkgRoot(const std::string& pkgName, bool enableR2R)
 int createNiDllUnderPkgRoot(const std::string& pkgName, const std::string& dllPath, bool enableR2R)
 {
        std::string pkgRoot;
-       if (getRootPath(pkgName, pkgRoot) < 0)
+       if (getRootPath(pkgName, pkgRoot) < 0) {
+               fprintf(stderr, "Failed to get root path from [%s]\n", pkgName.c_str());
                return -1;
+       }
 
        std::string binDir = concatPath(pkgRoot, "bin");
        std::string libDir = concatPath(pkgRoot, "lib");
-       std::string appPaths = binDir + ":" + libDir;
-
-       if (!isFileExist(dllPath)) {
-               fprintf(stderr, "Failed to find dll : %s\n", dllPath.c_str());
-               return -1;
-       }
-
-       std::string niPath;
-       if (niExist(dllPath, niPath)) {
-               fprintf(stderr, "Already [%s] file is exist\n", niPath.c_str());
-               return -1;
-       }
+       std::string paths = binDir + ":" + libDir;
 
-       crossgen(dllPath, appPaths, enableR2R);
-       if (!niExist(dllPath, niPath)) {
-               fprintf(stderr, "Failed to create native image for %s\n", dllPath.c_str());
-               return -1;
-       }
-
-       return 0;
+       return crossgen(dllPath, paths, enableR2R, true);
 }
 
 void removeNiPlatform()
@@ -453,8 +466,10 @@ void removeNiUnderDirs(const std::string rootPaths[], int count)
 int removeNiUnderPkgRoot(const std::string& pkgName)
 {
        std::string pkgRoot;
-       if (getRootPath(pkgName, pkgRoot) < 0)
+       if (getRootPath(pkgName, pkgRoot) < 0) {
+               fprintf(stderr, "Failed to get root path from [%s]\n", pkgName.c_str());
                return -1;
+       }
 
        std::string binDir = concatPath(pkgRoot, "bin");
        std::string libDir = concatPath(pkgRoot, "lib");
@@ -462,6 +477,20 @@ int removeNiUnderPkgRoot(const std::string& pkgName)
 
        removeNiUnderDirs(paths, 2);
 
+       std::string binNIDir = binDir + APP_NI_SUB_DIR;
+       if (isFileExist(binNIDir)) {
+               if (rmdir(binNIDir.c_str()) != 0) {
+                       fprintf(stderr, "Failed to remove app ni dir [%s]\n", binNIDir.c_str());
+               }
+       }
+
+       std::string libNIDir = libDir + APP_NI_SUB_DIR;
+       if (isFileExist(libNIDir)) {
+               if (rmdir(libNIDir.c_str()) != 0) {
+                       fprintf(stderr, "Failed to remove app ni dir [%s]\n", libNIDir.c_str());
+               }
+       }
+
        return 0;
 }
 
@@ -474,7 +503,7 @@ int regenerateAppNI(bool enableR2R)
        if (ret != PMINFO_R_OK)
                return -1;
 
-       ret = pkgmgrinfo_appinfo_metadata_filter_add(handle, "http://tizen.org/metadata/prefer_dotnet_aot", "true");
+       ret = pkgmgrinfo_appinfo_metadata_filter_add(handle, AOT_METADATA_KEY, AOT_METADATA_VALUE);
        if (ret != PMINFO_R_OK) {
                pkgmgrinfo_appinfo_metadata_filter_destroy(handle);
                return -1;