X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=NativeLauncher%2Ftool%2Fni_common.cc;h=08d9d6f300b9658676a336bbbb1f6143d73eb474;hb=33b4aa2fcbb716d081fc13ac6855fc53bd343532;hp=80f1f6c08a861518bd444da0d439d39c9cf74199;hpb=6ce548d772fb85c5b06c153886b447c3a57510e3;p=platform%2Fcore%2Fdotnet%2Flauncher.git diff --git a/NativeLauncher/tool/ni_common.cc b/NativeLauncher/tool/ni_common.cc index 80f1f6c..08d9d6f 100644 --- a/NativeLauncher/tool/ni_common.cc +++ b/NativeLauncher/tool/ni_common.cc @@ -17,7 +17,6 @@ #include #include #include -#include #include "log.h" #include "utils.h" @@ -26,13 +25,14 @@ #include #include #include +#include +#include #include #include #include #include -#include #include #include #include @@ -77,7 +77,8 @@ static const char* CROSSGEN_OPT_SINGLE_FILE_COMPILATION = "--single-file-compila //static const char* CROSSGEN_OPT_PARALLELISM = "--parallelism"; //static const char* CROSSGEN_OPT_PARALLELISM_COUNT = "5"; static const char* CROSSGEN_OPT_RESILIENT = "--resilient"; -static const char* CROSSGEN_OPT_OPTIMIZE = "-O"; +//static const char* CROSSGEN_OPT_OPTIMIZE = "-O"; +static const char* CROSSGEN_OPT_OPTIMIZE_TIME = "--Ot"; static const char* CROSSGEN_OPT_INPUTBUBBLE = "--inputbubble"; static const char* CROSSGEN_OPT_COMPILE_BUBBLE_GENERICS = "--compilebubblegenerics"; static const char* CROSSGEN_OPT_VERBOSE = "--verbose"; @@ -112,17 +113,6 @@ static void waitInterval() } #ifdef UNIQUE_DEFAULT_BASE_ADDR_SUPPORT -static uintptr_t getFileSize(const std::string& path) -{ - struct stat sb; - - if (stat(path.c_str(), &sb) == 0) { - return sb.st_size; - } - - return 0; -} - // Get next base address to be used for system ni image from file // __SYSTEM_BASE_FILE should be checked for existance before calling this function static uintptr_t getNextBaseAddrFromFile() @@ -166,7 +156,7 @@ static uintptr_t getNextBaseAddr() // Save base address of system ni image to file static void updateBaseAddrFile(const std::string& absNIPath, uintptr_t baseAddr) { - uintptr_t niSize = getFileSize(absNIPath); + uintptr_t niSize = getSizeOfImage(absNIPath); if (niSize == 0) { _SERR("File %s doesn't exist", absNIPath.c_str()); return; @@ -201,7 +191,7 @@ static bool isTPADll(const std::string& dllPath) /** * @brief create the directory including parents directory, and - * copy ownership and smack labels to the created directory. + * copy ownership and smack labels to the created directory. * @param[in] target directory path * @param[in] source directory path to get ownership and smack label * @return if directory created successfully, return true otherwise false @@ -240,8 +230,35 @@ static bool createDirsAndCopyOwnerShip(std::string& target_path, const std::stri return true; } -static std::string getNIFilePath(const std::string& dllPath) +static std::string getNIFilePath(const std::string& absDllPath, NIOption* opt) { + std::string dllPath = absDllPath; + if (opt->flags & NI_FLAGS_APPNI) { + std::string niDirPath; + std::string niTmpDirPath; + std::string prevPath; + + prevPath = getBaseName(absDllPath); + niDirPath = concatPath(prevPath, APP_NI_SUB_DIR); + niTmpDirPath = concatPath(prevPath, APP_NI_SUB_TMP_DIR); + + if (opt->flags & NI_FLAGS_APP_UNDER_RO_AREA) { + niTmpDirPath = replaceAll(niTmpDirPath, getBaseName(__pm->getAppRootPath()), __READ_ONLY_APP_UPDATE_DIR); + niDirPath = replaceAll(niDirPath, getBaseName(__pm->getAppRootPath()), __READ_ONLY_APP_UPDATE_DIR); + _INFO("App is installed in RO area. Change NI path to RW area(%s).", niTmpDirPath.c_str()); + } + + if (!isDirectory(niDirPath)) { + if (!createDirsAndCopyOwnerShip(niTmpDirPath, prevPath)) { + niTmpDirPath = prevPath; + _SERR("fail to create dir (%s)", niTmpDirPath.c_str()); + } + dllPath = concatPath(niTmpDirPath, getFileName(absDllPath)); + } else { + dllPath = concatPath(niDirPath, getFileName(absDllPath)); + } + } + size_t index = dllPath.find_last_of("."); if (index == std::string::npos) { _SERR("File doesnot contain extension. fail to get NI file name"); @@ -257,33 +274,9 @@ static std::string getNIFilePath(const std::string& dllPath) return niPath; } -static std::string getAppNIFilePath(const std::string& absDllPath, NIOption* opt) -{ - std::string niDirPath; - std::string prevPath; - - prevPath = getBaseName(absDllPath); - niDirPath = concatPath(prevPath, APP_NI_SUB_DIR); - - if (opt->flags & NI_FLAGS_APP_UNDER_RO_AREA) { - niDirPath = replaceAll(niDirPath, getBaseName(__pm->getAppRootPath()), __READ_ONLY_APP_UPDATE_DIR); - _SERR("App is installed in RO area. Change NI path to RW area(%s).", niDirPath.c_str()); - _ERR("App is installed in RO area. Change NI path to RW area(%s).", niDirPath.c_str()); - } - - if (!isDirectory(niDirPath)) { - if (!createDirsAndCopyOwnerShip(niDirPath, prevPath)) { - niDirPath = prevPath; - _SERR("fail to create dir (%s)", niDirPath.c_str()); - } - } - - return getNIFilePath(concatPath(niDirPath, getFileName(absDllPath))); -} - -static bool checkNIExistence(const std::string& absDllPath) +static bool checkNIExistence(const std::string& absDllPath, NIOption* opt) { - std::string absNIPath = getNIFilePath(absDllPath); + std::string absNIPath = getNIFilePath(absDllPath, opt); if (absNIPath.empty()) { return false; } @@ -301,25 +294,11 @@ static bool checkNIExistence(const std::string& absDllPath) return false; } -static bool checkAppNIExistence(const std::string& absDllPath, NIOption* opt) -{ - std::string absNIPath = getAppNIFilePath(absDllPath, opt); - if (absNIPath.empty()) { - return false; - } - - if (isFile(absNIPath)) { - return true; - } - - return false; -} - static bool checkDllExistInDir(const std::string& path) { bool ret = false; auto func = [&ret](const std::string& f_path, const std::string& f_name) { - if (isManagedAssembly(f_name) || isNativeImage(f_name)) { + if (isManagedAssembly(f_name) || isR2RImage(f_name)) { ret = true; } }; @@ -330,41 +309,18 @@ static bool checkDllExistInDir(const std::string& path) } /* - * Get the list of managed files in the specific directory + * Get the list of managed files in the specific directory (of Application) * Absolute paths of managed files are stored at the result list. - * If native image already exist in the same directory, managed file is ignored. + * If native image already exist in the (same / .native_image) directory, managed file is ignored. */ -static ni_error_e getTargetDllList(const std::string& path, std::vector& fileList) -{ - if (!isDirectory(path)) { - return NI_ERROR_INVALID_PARAMETER; - } - - auto func = [&fileList](const std::string& f_path, const std::string& f_name) { - if (isManagedAssembly(f_path) && !checkNIExistence(f_path)) { - fileList.push_back(getAbsolutePath(f_path)); - } - }; - - scanFilesInDirectory(path, func, 0); - - return NI_ERROR_NONE; -} - -/* - * Get the list of managed files in the specific directory of Application - * Absolute paths of managed files are stored at the result list. - * If native image already exist in the .native_image directory, managed file is ignored. - * - */ -static ni_error_e getAppTargetDllList(const std::string& path, std::vector& fileList, NIOption *opt) +static ni_error_e getTargetDllList(const std::string& path, std::vector& fileList, NIOption *opt) { if (!isDirectory(path)) { return NI_ERROR_INVALID_PARAMETER; } auto func = [&fileList, opt](const std::string& f_path, const std::string& f_name) { - if (isManagedAssembly(f_path) && !checkAppNIExistence(f_path, opt)) { + if (isManagedAssembly(f_path) && !checkNIExistence(f_path, opt)) { fileList.push_back(getAbsolutePath(f_path)); } }; @@ -384,35 +340,23 @@ static void makeArgs(std::vector& args, const std::vectorflags & NI_FLAGS_NO_PIPELINE)) { - args.push_back(CROSSGEN_OPT_OUT_NEAR_INPUT); - args.push_back(CROSSGEN_OPT_SINGLE_FILE_COMPILATION); - } + //args.push_back(OPT_PARALLELISM); //args.push_back(OPT_PARALLELISM_COUNT); args.push_back(CROSSGEN_OPT_RESILIENT); - args.push_back(CROSSGEN_OPT_OPTIMIZE); + args.push_back(CROSSGEN_OPT_OPTIMIZE_TIME); if (opt->flags & NI_FLAGS_INPUT_BUBBLE) { args.push_back(CROSSGEN_OPT_INPUTBUBBLE); args.push_back(CROSSGEN_OPT_COMPILE_BUBBLE_GENERICS); - if (opt->flags & NI_FLAGS_INPUT_BUBBLE_REF) { - INPUTBUBBLE_REF_VECTOR.clear(); - // check inputbubbleref format. - for (const auto &path : opt->inputBubbleRefPath) { - if (checkDllExistInDir(path)) { - INPUTBUBBLE_REF_VECTOR.push_back("--inputbubbleref:" + path + "/*.dll"); - } - } - // add ref path to inputbubble ref - for (const auto &path : refPaths) { - if (checkDllExistInDir(path)) { - INPUTBUBBLE_REF_VECTOR.push_back("--inputbubbleref:" + path + "/*.dll"); - } - } - for (const auto &path : INPUTBUBBLE_REF_VECTOR) { + INPUTBUBBLE_REF_VECTOR.clear(); + for (const auto &path : opt->inputBubbleRefFiles) { + INPUTBUBBLE_REF_VECTOR.push_back("--inputbubbleref:" + path); + } + for (const auto &path : INPUTBUBBLE_REF_VECTOR) { + if (find(args.begin(), args.end(), path) == args.end()) { args.push_back(path.c_str()); } } @@ -424,7 +368,9 @@ static void makeArgs(std::vector& args, const std::vector& args, const std::vectorflags & NI_FLAGS_REF) { - for (const auto &path : opt->refPath) { + for (const auto &path : opt->refFiles) { + REF_VECTOR.push_back("-r:" + path); + } + + std::vector paths = __pm->getPlatformAssembliesPaths(); + for (const auto &path : paths) { + if (checkDllExistInDir(path)) { REF_VECTOR.push_back("-r:" + path + "/*.dll"); } - } else { - std::vector paths = __pm->getPlatformAssembliesPaths(); - for (const auto &path : paths) { - if (checkDllExistInDir(path)) { - REF_VECTOR.push_back("-r:" + path + "/*.dll"); - } - } } if (opt->flags & NI_FLAGS_EXTRA_REF) { @@ -464,7 +408,9 @@ static void makeArgs(std::vector& args, const std::vectorflags & NI_FLAGS_APPNI) { - std::string appNIPath = getAppNIFilePath(dllPath, opt); - moveFile(niPath, appNIPath); - makePdbSymlinkForNI(dllPath, appNIPath); - _SOUT("Native image %s generated successfully.", appNIPath.c_str()); - } else { - _SOUT("Native image %s generated successfully.", niPath.c_str()); + outFile = getNIFilePath(dllPath, opt); + makePdbSymlinkForNI(dllPath, outFile); + + if (opt->flags & NI_FLAGS_INPUT_BUBBLE && opt->flags & NI_FLAGS_NO_PIPELINE) { + outFile = outFile + ".tmp"; + } + + if (niPath != outFile) { + moveFile(niPath, outFile); + } } + + if (opt->flags & NI_FLAGS_RM_ORIGIN_AFTER_NI) { + if (!removeFile(dllPath)) { + _SERR("Fail to remove original file : %s", dllPath.c_str()); + } + } + + if (!(opt->flags & NI_FLAGS_INPUT_BUBBLE && opt->flags & NI_FLAGS_NO_PIPELINE)) { + _SOUT("Native image %s generated successfully.", outFile.c_str()); + } + return NI_ERROR_NONE; } +void setPriority(NIOption* opt) +{ + pid_t pid = getpid(); + if (setpriority(PRIO_PROCESS, pid, opt->priority) == 0) { + std::string str = " "; + if (opt->priority <= -20) { + str = " highest "; + } else if (opt->priority >= 19) { + str = " lowest "; + } + _SOUT("Success to set the%spriority of the process. pid : [%d], priority : [%d]", str.c_str(), pid, getpriority(PRIO_PROCESS, pid)); + } else { + _SERR("Failed to set the priority of the process. pid : [%d], priority : [%d]", pid, getpriority(PRIO_PROCESS, pid)); + } +} + static ni_error_e crossgen2PipeLine(const std::vector& dllList, const std::vector& refPaths, NIOption* opt) { // fork crossgen2 @@ -534,8 +511,13 @@ static ni_error_e crossgen2PipeLine(const std::vector& dllList, con return NI_ERROR_ABNORMAL_PROCESS_TERMINATION; } } else { + if (opt->flags & NI_FLAGS_SET_PRIORITY) { + setPriority(opt); + } std::vector argv; makeArgs(argv, refPaths, opt); + argv.push_back(CROSSGEN_OPT_OUT_NEAR_INPUT); + argv.push_back(CROSSGEN_OPT_SINGLE_FILE_COMPILATION); // add input files at the end of parameter for (const auto &input : dllList) { @@ -565,11 +547,7 @@ static ni_error_e crossgen2NoPipeLine(const std::vector& dllList, c { for (auto& dllPath : dllList) { std::string niPath; - if (opt->flags & NI_FLAGS_APPNI) { - niPath = getAppNIFilePath(dllPath, opt); - } else { - niPath = getNIFilePath(dllPath); - } + niPath = getNIFilePath(dllPath, opt); #ifdef UNIQUE_DEFAULT_BASE_ADDR_SUPPORT uintptr_t baseAddr = 0; @@ -577,6 +555,9 @@ static ni_error_e crossgen2NoPipeLine(const std::vector& dllList, c baseAddr = getNextBaseAddr(); } #endif + if (opt->flags & NI_FLAGS_INPUT_BUBBLE) { + niPath += ".tmp"; + } // fork crossgen2 pid_t pid = fork(); @@ -603,6 +584,9 @@ static ni_error_e crossgen2NoPipeLine(const std::vector& dllList, c return NI_ERROR_ABNORMAL_PROCESS_TERMINATION; } } else { + if (opt->flags & NI_FLAGS_SET_PRIORITY) { + setPriority(opt); + } std::vector argv; makeArgs(argv, refPaths, opt); @@ -647,6 +631,7 @@ static ni_error_e createCoreLibNI(NIOption* opt) { std::string coreLib = concatPath(__pm->getRuntimePath(), "System.Private.CoreLib.dll"); std::string niCoreLib = concatPath(__pm->getRuntimePath(), "System.Private.CoreLib.ni.dll"); + std::string niTmpCoreLib = concatPath(__pm->getRuntimePath(), "System.Private.CoreLib.ni.dll.tmp"); std::string coreLibBackup = concatPath(__pm->getRuntimePath(), "System.Private.CoreLib.dll.Backup"); std::vector dllList; @@ -654,14 +639,29 @@ static ni_error_e createCoreLibNI(NIOption* opt) dllList.push_back(getAbsolutePath(coreLib)); if (!isFile(coreLibBackup) && !isR2RImage(coreLib)) { - if (crossgen2NoPipeLine(dllList, refPaths, opt) == NI_ERROR_NONE && exist(niCoreLib)) { - if (rename(coreLib.c_str(), coreLibBackup.c_str())) { - _SERR("Failed to rename System.Private.CoreLib.dll"); + if (crossgen2NoPipeLine(dllList, refPaths, opt) == NI_ERROR_NONE) { + if (opt->flags & NI_FLAGS_RM_ORIGIN_AFTER_NI) { + std::ofstream output(coreLibBackup); + if (!exist(coreLibBackup)) { + _SERR("Failed to create System.Private.CoreLib.dll.Backup"); + return NI_ERROR_CORE_NI_FILE; + } + copySmackAndOwnership(__pm->getRuntimePath(), coreLibBackup, false); + output.close(); + } else if (rename(coreLib.c_str(), coreLibBackup.c_str())) { + _SERR("Failed to rename from System.Private.CoreLib.dll to System.Private.CoreLib.dll.Backup"); return NI_ERROR_CORE_NI_FILE; } - if (rename(niCoreLib.c_str(), coreLib.c_str())) { - _SERR("Failed to rename System.Private.CoreLib.ni.dll"); - return NI_ERROR_CORE_NI_FILE; + if (opt->flags & NI_FLAGS_INPUT_BUBBLE) { + if (rename(niTmpCoreLib.c_str(), coreLib.c_str())) { + _SERR("Failed to rename from System.Private.CoreLib.ni.dll.tmp to Private.CoreLib.dll"); + return NI_ERROR_CORE_NI_FILE; + } + } else { + if (rename(niCoreLib.c_str(), coreLib.c_str())) { + _SERR("Failed to rename from System.Private.CoreLib.ni.dll to Private.CoreLib.dll"); + return NI_ERROR_CORE_NI_FILE; + } } } else { _SERR("Failed to create native image for %s", coreLib.c_str()); @@ -671,6 +671,25 @@ static ni_error_e createCoreLibNI(NIOption* opt) return NI_ERROR_NONE; } +static void renameAppNITmpPath(NIOption* opt) +{ + std::string niTmpPath = __pm->getAppRootPath() + "/bin/" + APP_NI_SUB_TMP_DIR; + std::string niPath = __pm->getAppRootPath() + "/bin/" + APP_NI_SUB_DIR; + + if (opt->flags & NI_FLAGS_APP_UNDER_RO_AREA) { + niTmpPath = replaceAll(niTmpPath, getBaseName(__pm->getAppRootPath()), __READ_ONLY_APP_UPDATE_DIR); + niPath = replaceAll(niPath, getBaseName(__pm->getAppRootPath()), __READ_ONLY_APP_UPDATE_DIR); + } + + if (isDirectory(niTmpPath)) { + if (rename(niTmpPath.c_str(), niPath.c_str())) { + _SERR("Fail to rename from .native_image_tmp to .native_image"); + } else { + _SOUT("Success to rename from %s to %s", niTmpPath.c_str(), niPath.c_str()); + } + } +} + static ni_error_e doAOTList(std::vector& dllList, const std::string& refPaths, NIOption* opt) { ni_error_e ret = NI_ERROR_NONE; @@ -684,27 +703,29 @@ static ni_error_e doAOTList(std::vector& dllList, const std::string std::string coreLib = concatPath(__pm->getRuntimePath(), "System.Private.CoreLib.dll"); bool hasSPC = false; - std::vector niList; for (auto it = dllList.begin(); it != dllList.end(); it++) { std::string f = *it; if (!isFile(f)) { _SERR("dll file is not exist : %s", f.c_str()); dllList.erase(it--); } - if (!isManagedAssembly(f)) { + else if (!isManagedAssembly(f)) { _SERR("Input file is not a dll file : %s", f.c_str()); dllList.erase(it--); } // handle System.Private.CoreLib.dll separately. // dllList and path manager contain absolute path. So, there is no need to change path to absolute path - if (f == coreLib) { + else if (f == coreLib) { hasSPC = true; dllList.erase(it--); - } else { - niList.push_back(changeExtension(f, ".dll", ".ni.dll")); } } + // Error : Multiple input files matching same simple name + // So, Remove dulicate files from dll list + std::sort(dllList.begin(), dllList.end()); + dllList.erase(unique(dllList.begin(), dllList.end()), dllList.end()); + // In the case of SPC, post-processing is required to change the name of the native image. // In order to avoid repeatedly checking whether the generated native image is an SPC, // the SPC native image generation is performed separately. @@ -730,33 +751,39 @@ static ni_error_e doAOTList(std::vector& dllList, const std::string if (opt->flags & NI_FLAGS_NO_PIPELINE) { ret = crossgen2NoPipeLine(dllList, paths, opt); } else { - // When the forked process in the pipeline state is terminated(WIFSIGNALED(status)), - // retry the generation of the native image - // if the number of .dll files and the number of .ni.dll files are different. - for (int callCnt = 0; callCnt < 2; callCnt++) { - // If an error occurs, perform it twice with the same option. - ret = crossgen2PipeLine(dllList, paths, opt); - if (ret != NI_ERROR_NONE) { - _SERR("Crossgen2 is abnormally terminated. Regenerate native images that failed while running crossgen2."); - dllList.clear(); - for (auto it = niList.begin(); it != niList.end(); it++) { - std::string niPath = *it; - std::string dllPath = changeExtension(niPath, ".ni.dll", ".dll"); - if (crossgen2PostAction(dllPath, niPath, opt) != NI_ERROR_NONE) { - dllList.push_back(dllPath); - } else { - niList.erase(it--); - } + std::vector notCompiled; + ret = crossgen2PipeLine(dllList, paths, opt); + if (ret != NI_ERROR_NONE) { + _SERR("Crossgen2 is abnormally terminated. Regenerate native images that failed while running crossgen2."); + for (auto &dll : dllList) { + std::string tFile = changeExtension(dll, ".dll", ".ni.dll"); + if (opt->flags & NI_FLAGS_INPUT_BUBBLE) { + tFile += ".tmp"; + } + if (!exist(tFile)) { + notCompiled.push_back(dll); } - } else { - break; } - } - // If an error occurs after two crossgen2PipeLine() attempts, - // try crossgen2NoPipeLine() for the last time. - if (ret != NI_ERROR_NONE) { _SERR("Retry running crossgen2 with --no-pipeline mode to avoid termination by OOM."); - ret = crossgen2NoPipeLine(dllList, paths, opt); + ret = crossgen2NoPipeLine(notCompiled, paths, opt); + } + } + + if (ret == NI_ERROR_NONE) { + if (opt->flags & NI_FLAGS_INPUT_BUBBLE) { + for (auto &dll : dllList) { + std::string tmpFile; + std::string niFile = getNIFilePath(dll, opt); + tmpFile = niFile + ".tmp"; + + if (exist(tmpFile)) { + moveFile(tmpFile, niFile); + _SOUT("Native image %s generated successfully.", niFile.c_str()); + } + } + } + if (opt->flags & NI_FLAGS_APPNI) { + renameAppNITmpPath(opt); } } @@ -770,39 +797,26 @@ static ni_error_e doAOTFile(const std::string& dllFile, const std::string& refPa return NI_ERROR_NO_SUCH_FILE; } + if (checkNIExistence(dllFile, opt)) { + _SERR("Native image file is already exist : %s", dllFile.c_str()); + return NI_ERROR_ALREADY_EXIST; + } + if (!isManagedAssembly(dllFile)) { _SERR("Failed. Input parameter is not managed dll (%s)\n", dllFile.c_str()); return NI_ERROR_INVALID_PARAMETER; } - if (checkNIExistence(dllFile)) { - _SERR("Native image file is already exist : %s", dllFile.c_str()); - return NI_ERROR_ALREADY_EXIST; - } - std::vector dllList; dllList.push_back(getAbsolutePath(dllFile)); return doAOTList(dllList, refPaths, opt); } // callback function of "pkgmgrinfo_appinfo_metadata_filter_foreach" -static int appAotCb(pkgmgrinfo_appinfo_h handle, void *userData) +static int getPkgIdCb(pkgmgrinfo_appinfo_h handle, void *userData) { char *pkgId = NULL; int ret = 0; - NIOption **pOptions = (NIOption**)userData; - - if ((*pOptions)->flags & NI_FLAGS_SKIP_RO_APP) { - bool isSystem = false; - int ret = pkgmgrinfo_appinfo_is_system(handle, &isSystem); - if (ret != PMINFO_R_OK) { - _SERR("Failed to check that app is System or not\n"); - return -1; - } - if (isSystem) { - return 0; - } - } ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgId); if (ret != PMINFO_R_OK) { @@ -810,19 +824,33 @@ static int appAotCb(pkgmgrinfo_appinfo_h handle, void *userData) return -1; } - if (removeNIUnderPkgRoot(pkgId) != NI_ERROR_NONE) { - _SERR("Failed to remove previous dlls from [%s]", pkgId); - return -1; + std::vector *pkgList = (std::vector *)userData; + pkgList->push_back(pkgId); + + return 0; +} + +static bool isReadOnlyPkg(std::string pkgId) +{ + int ret = 0; + bool readonly = false; + pkgmgrinfo_pkginfo_h handle; + + ret = pkgmgrinfo_pkginfo_get_pkginfo(pkgId.c_str(), &handle); + if (ret != PMINFO_R_OK) { + _ERR("Fail to get pkginfo"); + return false; } - if (createNIUnderPkgRoot(pkgId, *pOptions) != NI_ERROR_NONE) { - _SERR("Failed to generate NI file [%s]", pkgId); - return -1; - } else { - _SOUT("Complete make application to native image"); + ret = pkgmgrinfo_pkginfo_is_readonly(handle, &readonly); + if (ret != PMINFO_R_OK) { + _ERR("Fail to get is_readonly"); + pkgmgrinfo_pkginfo_destroy_pkginfo(handle); + return false; } - return 0; + pkgmgrinfo_pkginfo_destroy_pkginfo(handle); + return readonly; } ni_error_e initNICommon() @@ -889,14 +917,12 @@ void finalizeNICommon() } } -ni_error_e createNIPlatform(NIOption* opt) +ni_error_e createNIPlatform(std::string& extraInputs, NIOption* opt) { - ni_error_e ret = createNIUnderDirs(__pm->getRuntimePath(), opt); - if (ret != NI_ERROR_NONE) { - return ret; - } + extraInputs += ":" + __pm->getRuntimePath(); + extraInputs += ":" + __pm->getTizenFXPath(); - return createNIUnderDirs(__pm->getTizenFXPath(), opt); + return createNIUnderDirs(extraInputs, opt); } ni_error_e createNIDll(const std::string& dllPath, NIOption* opt) @@ -908,9 +934,24 @@ ni_error_e createNIUnderTAC(const std::string& targetPath, const std::string& re { ni_error_e ret; + bool isAppNI = false; + if (opt->flags & NI_FLAGS_APPNI) { + isAppNI = true; + } + + if (opt->flags & NI_FLAGS_INPUT_BUBBLE) { + std::vector refs; + splitPath(refPaths, refs); + for (auto &p: refs) { + if (isDirectory(p) && checkDllExistInDir(p)) { + opt->inputBubbleRefFiles.push_back(p + "/*.dll"); + } + } + } + // get managed file list from targetPath std::vector dllList; - ret = getTargetDllList(targetPath, dllList); + ret = getTargetDllList(targetPath, dllList, opt); if (ret != NI_ERROR_NONE) { return ret; } @@ -919,10 +960,10 @@ ni_error_e createNIUnderTAC(const std::string& targetPath, const std::string& re std::vector niList; for (auto &dll : dllList) { - if (!checkNIExistence(dll)) { + if (!checkNIExistence(dll, opt)) { needNIList.push_back(dll); } - niList.push_back(getNIFilePath(dll)); + niList.push_back(getNIFilePath(dll, opt)); } if (!needNIList.empty()) { @@ -930,20 +971,24 @@ ni_error_e createNIUnderTAC(const std::string& targetPath, const std::string& re // So, unset NI_FLAGS_APPNI temporally and restore it after running AOT. opt->flags &= ~NI_FLAGS_APPNI; ret = doAOTList(needNIList, refPaths, opt); - opt->flags |= NI_FLAGS_APPNI; + if (isAppNI) { + opt->flags |= NI_FLAGS_APPNI; + } if (ret != NI_ERROR_NONE) { return ret; } } - for (auto &niPath : niList) { - if (exist(niPath)) { - std::string symNIPath = concatPath(targetPath, getFileName(niPath)); - if (!exist(symNIPath)) { - bf::create_symlink(niPath, symNIPath); - copySmackAndOwnership(targetPath.c_str(), symNIPath.c_str(), true); - _SOUT("%s symbolic link file generated successfully.", symNIPath.c_str()); - _INFO("%s symbolic link file generated successfully.", symNIPath.c_str()); + if (isAppNI) { + for (auto &niPath : niList) { + if (exist(niPath)) { + std::string symNIPath = concatPath(targetPath, getFileName(niPath)); + if (!exist(symNIPath)) { + bf::create_symlink(niPath, symNIPath); + copySmackAndOwnership(targetPath.c_str(), symNIPath.c_str(), true); + _SOUT("%s symbolic link file generated successfully.", symNIPath.c_str()); + _INFO("%s symbolic link file generated successfully.", symNIPath.c_str()); + } } } } @@ -960,6 +1005,14 @@ ni_error_e createNIUnderDirs(const std::string& rootPaths, NIOption* opt) std::vector paths; splitPath(rootPaths, paths); + if (opt->flags & NI_FLAGS_INPUT_BUBBLE) { + for (auto &p: paths) { + if (isDirectory(p) && checkDllExistInDir(p)) { + opt->inputBubbleRefFiles.push_back(p + "/*.dll"); + } + } + } + for (const auto &path : paths) { if (!exist(path)) { continue; @@ -970,13 +1023,8 @@ ni_error_e createNIUnderDirs(const std::string& rootPaths, NIOption* opt) if (ret != NI_ERROR_NONE) { return ret; } - } else if (opt->flags & NI_FLAGS_APPNI) { - ret = getAppTargetDllList(path, fileList, opt); - if (ret != NI_ERROR_NONE) { - return ret; - } } else { - ret = getTargetDllList(path, fileList); + ret = getTargetDllList(path, fileList, opt); if (ret != NI_ERROR_NONE) { return ret; } @@ -1060,9 +1108,14 @@ void removeNIPlatform() void removeNIUnderDirs(const std::string& rootPaths) { auto convert = [](const std::string& path, const std::string& filename) { - if (isNativeImage(path)) { - if (remove(path.c_str())) { - _SERR("Failed to remove %s", path.c_str()); + if (isR2RImage(path)) { + std::string assemblyPath = changeExtension(path, ".ni.dll", ".dll"); + if (exist(assemblyPath)) { + if (remove(path.c_str())) { + _SERR("Failed to remove %s", path.c_str()); + } + } else { + _SOUT("%s cannot be removed because there is no %s", path.c_str(), assemblyPath.c_str()); } } }; @@ -1120,23 +1173,47 @@ ni_error_e regenerateAppNI(NIOption* opt) { int ret = 0; pkgmgrinfo_appinfo_metadata_filter_h handle; + std::vector pkgList; ret = pkgmgrinfo_appinfo_metadata_filter_create(&handle); if (ret != PMINFO_R_OK) return NI_ERROR_UNKNOWN; - ret = pkgmgrinfo_appinfo_metadata_filter_add(handle, AOT_METADATA_KEY, METADATA_VALUE); + ret = pkgmgrinfo_appinfo_metadata_filter_add(handle, AOT_METADATA_KEY, METADATA_VALUE_TRUE); if (ret != PMINFO_R_OK) { pkgmgrinfo_appinfo_metadata_filter_destroy(handle); return NI_ERROR_UNKNOWN; } - ret = pkgmgrMDFilterForeach(handle, appAotCb, &opt); + ret = pkgmgrMDFilterForeach(handle, getPkgIdCb, &pkgList); if (ret != 0) { pkgmgrinfo_appinfo_metadata_filter_destroy(handle); return NI_ERROR_UNKNOWN; } + // remove duplicated pkg in the list. + // If one package has multiple apps, there can be duplicate values. + std::sort(pkgList.begin(), pkgList.end()); + pkgList.erase(unique(pkgList.begin(), pkgList.end()), pkgList.end()); + + for (auto pkg : pkgList) { + if (isReadOnlyPkg(pkg) && opt->flags & NI_FLAGS_SKIP_RO_APP) { + continue; + } + + if (removeNIUnderPkgRoot(pkg) != NI_ERROR_NONE) { + _SERR("Failed to remove previous dlls from [%s]", pkg.c_str()); + return NI_ERROR_UNKNOWN; + } + + if (createNIUnderPkgRoot(pkg, opt) != NI_ERROR_NONE) { + _SERR("Failed to generate NI file [%s]", pkg.c_str()); + return NI_ERROR_UNKNOWN; + } else { + _SOUT("Complete make application to native image"); + } + } + pkgmgrinfo_appinfo_metadata_filter_destroy(handle); return NI_ERROR_NONE; } @@ -1145,6 +1222,7 @@ ni_error_e regenerateAppNI(NIOption* opt) static int regenTacCb(pkgmgrinfo_appinfo_h handle, void *userData) { char *pkgId = NULL; + char *root = NULL; NIOption **pOpt = (NIOption**)userData; int ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgId); @@ -1153,6 +1231,18 @@ static int regenTacCb(pkgmgrinfo_appinfo_h handle, void *userData) return -1; } + ret = pkgmgrinfo_appinfo_get_root_path(handle, &root); + if (ret != PMINFO_R_OK) { + _SERR("Failed to get root path"); + return -1; + } + + std::string binPath = concatPath(std::string(root), "bin"); + if (exist(concatPath(binPath, PRE_COMPILED_PACKAGE_FILE))) { + _INFO("The %s is a Pre-Compiled package. So, skip the TAC", pkgId); + return 0; + } + sqlite3 *tac_db = openDB(TAC_APP_LIST_DB); if (!tac_db) { _SERR("Sqlite open error"); @@ -1194,7 +1284,7 @@ ni_error_e regenerateTACNI(NIOption* opt) return NI_ERROR_UNKNOWN; } - ret = pkgmgrinfo_appinfo_metadata_filter_add(handle, TAC_METADATA_KEY, METADATA_VALUE); + ret = pkgmgrinfo_appinfo_metadata_filter_add(handle, TAC_METADATA_KEY, METADATA_VALUE_TRUE); if (ret != PMINFO_R_OK) { pkgmgrinfo_appinfo_metadata_filter_destroy(handle); return NI_ERROR_UNKNOWN; @@ -1211,124 +1301,3 @@ ni_error_e regenerateTACNI(NIOption* opt) return NI_ERROR_NONE; } -static std::vector getUserIds() -{ - std::vector list; - - while (true) { - errno = 0; // so we can distinguish errors from no more entries - passwd* entry = getpwent(); - if (!entry) { - if (errno) { - _SERR("Error while getting userIDs"); - list.clear(); - return list; - } - break; - } - list.push_back(entry->pw_uid); - } - endpwent(); - - return list; -} - -static std::string getAppDataPath(const std::string& pkgId, uid_t uid) -{ - std::string pDataFile; - - tzplatform_set_user(uid); - - const char* tzUserApp = tzplatform_getenv(TZ_USER_APP); - if (tzUserApp != NULL) { - pDataFile = std::string(tzUserApp) + "/" + pkgId + "/data/"; - } - - tzplatform_reset_user(); - - return pDataFile; -} - -ni_error_e removeAppProfileData(const std::string& pkgId) -{ - if (pkgId.empty()) { - return NI_ERROR_INVALID_PARAMETER; - } - - std::vector uidList = getUserIds(); - for (auto& uid : uidList) { - // get data path from pkgid - std::string dataPath = getAppDataPath(pkgId, uid); - if (!dataPath.empty() && exist(dataPath)) { - std::string pDataFile = dataPath + PROFILE_BASENAME; - - if (exist(pDataFile)) { - if (!removeFile(pDataFile)) { - _SERR("Fail to remove profile data file (%s).", pDataFile.c_str()); - return NI_ERROR_UNKNOWN; - } - _SOUT("Profile data (%s) is removed successfully", pDataFile.c_str()); - } - } - } - - return NI_ERROR_NONE; -} - -static int appTypeListCb(pkgmgrinfo_appinfo_h handle, void *user_data) -{ - char *pkgId = NULL; - int ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgId); - if (ret != PMINFO_R_OK || pkgId == NULL) { - _SERR("Fail to get pkgid"); - return 0; - } - - if (removeAppProfileData(pkgId) != NI_ERROR_NONE) { - _SERR("Fail to remove profile data for (%s)", pkgId); - } - - return 0; -} - -static ni_error_e removeAppProfileByAppType(const char* type) -{ - int ret; - - pkgmgrinfo_appinfo_filter_h filter; - - ret = pkgmgrinfo_appinfo_filter_create(&filter); - if (ret != PMINFO_R_OK) { - _SERR("Fail to create appinfo filter"); - return NI_ERROR_UNKNOWN; - } - - ret = pkgmgrinfo_appinfo_filter_add_string(filter, PMINFO_APPINFO_PROP_APP_TYPE, type); - if (ret != PMINFO_R_OK) { - pkgmgrinfo_appinfo_filter_destroy(filter); - _SERR("Fail to add appinfo filter (%s)", type); - return NI_ERROR_UNKNOWN; - } - - ret = pkgmgrinfo_appinfo_filter_foreach_appinfo(filter, appTypeListCb, NULL); - if (ret != PMINFO_R_OK) { - _SERR("Fail to pkgmgrinfo_pkginfo_filter_foreach_pkginfo"); - pkgmgrinfo_appinfo_filter_destroy(filter); - return NI_ERROR_UNKNOWN; - } - - pkgmgrinfo_appinfo_filter_destroy(filter); - - return NI_ERROR_NONE; -} - -void removeAllAppProfileData() -{ - std::vector appTypeList = {"dotnet", "dotnet-nui", "dotnet-inhouse"}; - - for (auto& type : appTypeList) { - if (removeAppProfileByAppType(type) != NI_ERROR_NONE) { - _SERR("Fail to removeAppProfileByAppType for type (%s)", type); - } - } -}