From: Woongsuk Cho Date: Wed, 31 Jan 2024 07:17:32 +0000 (+0900) Subject: AOT support for RPK X-Git-Tag: accepted/tizen/unified/20240220.115648~4 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fdotnet%2Flauncher.git;a=commitdiff_plain;h=eabcb6e080199e94e8e92a11b111c01bcba7bdaf AOT support for RPK The RPK (Resource Package) can contain dlls for resources and NUIGadget. For RPK, Dlls can be located under lib and res/allowed directory. AOT for RPK is enabled by metadata "http://tizen.org/metadata/prefer_dotnet_aot". It triggered by metadata installer plugin and dotnettool(--ni-pkg, --ni-regen-all-app). --- diff --git a/NativeLauncher/inc/ni_common.h b/NativeLauncher/inc/ni_common.h index 0493216..28b387f 100644 --- a/NativeLauncher/inc/ni_common.h +++ b/NativeLauncher/inc/ni_common.h @@ -135,11 +135,11 @@ void removeNIUnderDirs(const std::string& rootPaths); ni_error_e removeNIUnderPkgRoot(const std::string& pkgId); /** - * @brief regenerate native images of all installed applications + * @brief regenerate native images of all installed packages (tpk, rpk) * @param[in] flags additional flags for the image generator * @return ni_error_e */ -ni_error_e regenerateAppNI(NIOption* opt); +ni_error_e regeneratePkgNI(NIOption* opt); /** * @brief regenerate native image of TAC for all shared assembly. diff --git a/NativeLauncher/inc/utils.h b/NativeLauncher/inc/utils.h index 524264e..7a3f33b 100644 --- a/NativeLauncher/inc/utils.h +++ b/NativeLauncher/inc/utils.h @@ -289,18 +289,30 @@ int pkgmgrGetPkgInfo(const std::string& pkgId, pkgmgrinfo_pkginfo_h* handle); int pkgmgrGetAppInfo(const std::string& appId, pkgmgrinfo_appinfo_h* handle); /** - * @brief Executes the metadata filter query for all the installed packages. + * @brief Executes the metadata filter query for appinfo. * This function is a wrapper of pkgmgrinfo_appinfo_metadata_filter_foreach() to handle multi-user case * @param[in] metadata filter handle * @param[in] callback function * @param[in] user data * @return 0 if success, otherwise -1 */ -int pkgmgrMDFilterForeach(pkgmgrinfo_appinfo_metadata_filter_h handle, +int pkgmgrAppMDFilterForeach(pkgmgrinfo_appinfo_metadata_filter_h handle, pkgmgrinfo_app_list_cb app_cb, void *user_data); /** + * @brief Executes the metadata filter query for pkginfo. + * This function is a wrapper of pkgmgrinfo_pkginfo_metadata_filter_foreach() + * @param[in] metadata filter handle + * @param[in] callback function + * @param[in] user data + * @return 0 if success, otherwise -1 + */ +int pkgmgrPkgMDFilterForeach(pkgmgrinfo_pkginfo_metadata_filter_h handle, + pkgmgrinfo_pkg_list_cb app_cb, + void *user_data); + +/** * @brief Prints HW Clock log * @param[in] format `printf`-like format string * @param[in] ... `printf`-like variadic list of arguments corresponding to the format string @@ -319,4 +331,18 @@ const char* getNCDBStartupHook(); */ bool isNCDBStartupHookProvided(); +/** + * @brief get paths where the resource dll is located in RPK package + * @param[in] root path + * @return std::string colon-separated string of rpk target paths + */ +std::string getResourcePaths(const std::string& rootPath); + +/** + * @brief check the package is rpk type + * @param[in] pkgId package ID + * @return bool + */ +bool isRPK(const std::string& pkgId); + #endif /* __UTILS_H__ */ diff --git a/NativeLauncher/installer-plugin/prefer_dotnet_aot_plugin.cc b/NativeLauncher/installer-plugin/prefer_dotnet_aot_plugin.cc index 840a40b..bfe3afb 100644 --- a/NativeLauncher/installer-plugin/prefer_dotnet_aot_plugin.cc +++ b/NativeLauncher/installer-plugin/prefer_dotnet_aot_plugin.cc @@ -33,6 +33,11 @@ static bool aotPluginInstalled = false; static bool aotPluginFinished = false; +typedef struct metadata_s { + const char* key; + const char* value; +} metadata_t; + extern "C" int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgId, const char *appId, GList *list) { // Can be multiple apps in one package @@ -50,13 +55,20 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgId, const char *app } } - std::string metaValue = getMetadataValue(std::string(pkgId), AOT_METADATA_KEY); - if (metaValue.empty()) { - _ERR("Failed to get metadata from [%s]", pkgId); - return -1; + bool doAOT = false; + GList* iter = list; + while (iter) { + metadata_t* md = static_cast(iter->data); + if (strcmp(AOT_METADATA_KEY, md->key) == 0) { + if (strcmp(METADATA_VALUE_TRUE, md->value) == 0) { + doAOT = true; + break; + } + } + iter = g_list_next(iter); } - if (metaValue == METADATA_VALUE_TRUE) { + if (doAOT) { _DBG("Prefer dotnet application AOT set TRUE"); if (initNICommon() != NI_ERROR_NONE) { diff --git a/NativeLauncher/tool/dotnettool.cc b/NativeLauncher/tool/dotnettool.cc index eac0f2a..3e43773 100644 --- a/NativeLauncher/tool/dotnettool.cc +++ b/NativeLauncher/tool/dotnettool.cc @@ -340,7 +340,7 @@ int main(int argc, char* argv[]) return -1; } - int ret = regenerateAppNI(opt); + int ret = regeneratePkgNI(opt); if (ret != NI_ERROR_NONE) { _SERR("Failed to regenerate all app NI"); } diff --git a/NativeLauncher/tool/ni_common.cc b/NativeLauncher/tool/ni_common.cc index 08d9d6f..d6515e8 100644 --- a/NativeLauncher/tool/ni_common.cc +++ b/NativeLauncher/tool/ni_common.cc @@ -812,22 +812,21 @@ static ni_error_e doAOTFile(const std::string& dllFile, const std::string& refPa return doAOTList(dllList, refPaths, opt); } -// callback function of "pkgmgrinfo_appinfo_metadata_filter_foreach" -static int getPkgIdCb(pkgmgrinfo_appinfo_h handle, void *userData) +static ni_error_e removeAndCreateNI(const char* pkgId, NIOption* pOptions) { - char *pkgId = NULL; - int ret = 0; - - ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgId); - if (ret != PMINFO_R_OK) { - _SERR("Failed to get pkgid"); - return -1; + if (removeNIUnderPkgRoot(pkgId) != NI_ERROR_NONE) { + _SERR("Failed to remove previous dlls from [%s]", pkgId); + return NI_ERROR_UNKNOWN; } - std::vector *pkgList = (std::vector *)userData; - pkgList->push_back(pkgId); + if (createNIUnderPkgRoot(pkgId, pOptions) != NI_ERROR_NONE) { + _SERR("Failed to generate NI file [%s]", pkgId); + return NI_ERROR_UNKNOWN; + } else { + _SOUT("Complete make native image for pkg (%s)", pkgId); + } - return 0; + return NI_ERROR_NONE; } static bool isReadOnlyPkg(std::string pkgId) @@ -852,6 +851,73 @@ static bool isReadOnlyPkg(std::string pkgId) pkgmgrinfo_pkginfo_destroy_pkginfo(handle); return readonly; } +#if 0 +// callback function of "pkgmgrinfo_appinfo_metadata_filter_foreach" +static int appAotCb(pkgmgrinfo_appinfo_h handle, void *userData) +{ + char *pkgId = NULL; + int ret = 0; + ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgId); + if (ret != PMINFO_R_OK) { + _SERR("Failed to get pkgid"); + return -1; + } + + NIOption **pOptions = (NIOption**)userData; + if (isReadOnlyPkg(pkgId) && (*pOptions)->flags & NI_FLAGS_SKIP_RO_APP) { + return 0; + } + + return removeAndCreateNI(pkgId, *pOptions); +} + +// callback function of "pkgmgrinfo_pkginfo_metadata_filter_foreach" +static int pkgAotCb(pkgmgrinfo_pkginfo_h handle, void *userData) +{ + char *pkgId = NULL; + int ret = 0; + NIOption **pOptions = (NIOption**)userData; + + ret = pkgmgrinfo_pkginfo_get_pkgid(handle, &pkgId); + if (ret != PMINFO_R_OK) { + _SERR("Failed to get pkgid"); + return -1; + } + + return removeAndCreateNI(pkgId, *pOptions); +} +#endif +// callback function of "pkgmgrinfo_appinfo_metadata_filter_foreach" +static int appAotCb(pkgmgrinfo_appinfo_h handle, void *userData) +{ + char *pkgId = NULL; + int ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgId); + if (ret != PMINFO_R_OK) { + _SERR("Failed to get pkgid"); + return -1; + } + + std::vector *pkgList = (std::vector *)userData; + pkgList->push_back(pkgId); + + return 0; +} + +// callback function of "pkgmgrinfo_pkginfo_metadata_filter_foreach" +static int pkgAotCb(pkgmgrinfo_pkginfo_h handle, void *userData) +{ + char *pkgId = NULL; + int ret = pkgmgrinfo_pkginfo_get_pkgid(handle, &pkgId); + if (ret != PMINFO_R_OK) { + _SERR("Failed to get pkgid"); + return -1; + } + + std::vector *pkgList = (std::vector *)userData; + pkgList->push_back(pkgId); + + return 0; +} ni_error_e initNICommon() { @@ -1040,6 +1106,8 @@ ni_error_e createNIUnderDirs(const std::string& rootPaths, NIOption* opt) ni_error_e createNIUnderPkgRoot(const std::string& pkgId, NIOption* opt) { + ni_error_e ret; + if (!isR2RImage(concatPath(__pm->getRuntimePath(), "System.Private.CoreLib.dll"))) { _SERR("The native image of System.Private.CoreLib does not exist.\n" "Run the command to create the native image\n" @@ -1053,27 +1121,40 @@ ni_error_e createNIUnderPkgRoot(const std::string& pkgId, NIOption* opt) return NI_ERROR_INVALID_PACKAGE; } - __pm->setAppRootPath(rootPath); - char* extraDllPaths = pluginGetExtraDllPath(); if (extraDllPaths && extraDllPaths[0] != '\0') { opt->flags |= NI_FLAGS_EXTRA_REF; splitPath(extraDllPaths, opt->extraRefPath); } - opt->flags |= NI_FLAGS_APPNI; - - if (isReadOnlyArea(rootPath)) { - opt->flags |= NI_FLAGS_APP_UNDER_RO_AREA; - opt->flags |= NI_FLAGS_NO_PIPELINE; - _SERR("Only no-pipeline mode supported for RO app. Set no-pipeline option forcibly"); + if (isRPK(pkgId)) { + opt->flags &= ~NI_FLAGS_APPNI; + std::string paths = getResourcePaths(rootPath); + if (!paths.empty()) { + ret = createNIUnderDirs(paths, opt); + } else { + _SERR("Failed to get rpk paths from [%s]", pkgId.c_str()); + ret = NI_ERROR_UNKNOWN; + } } else { - opt->flags &= ~NI_FLAGS_APP_UNDER_RO_AREA; + __pm->setAppRootPath(rootPath); + + opt->flags |= NI_FLAGS_APPNI; + + if (isReadOnlyArea(rootPath)) { + opt->flags |= NI_FLAGS_APP_UNDER_RO_AREA; + opt->flags |= NI_FLAGS_NO_PIPELINE; + _SERR("Only no-pipeline mode supported for RO app. Set no-pipeline option forcibly"); + } else { + opt->flags &= ~NI_FLAGS_APP_UNDER_RO_AREA; + } + + // create native image under bin and lib directory + // tac directory is skipped in the createNIUnderDirs. + ret = createNIUnderDirs(__pm->getAppPaths(), opt); } - // create native image under bin and lib directory - // tac directory is skipped in the createNIUnderDirs. - return createNIUnderDirs(__pm->getAppPaths(), opt); + return ret; } void removeNIPlatform() @@ -1129,66 +1210,100 @@ void removeNIUnderDirs(const std::string& rootPaths) ni_error_e removeNIUnderPkgRoot(const std::string& pkgId) { + std::vector paths; + std::string rootPath = getRootPath(pkgId); if (rootPath.empty()) { _SERR("Failed to get root path from [%s]", pkgId.c_str()); return NI_ERROR_INVALID_PACKAGE; } - __pm->setAppRootPath(rootPath); - - // getAppNIPaths returns bin/.native_image, lib/.native_image and .tac_symlink. - std::string appNIPaths = __pm->getAppNIPaths(); - std::vector paths; - splitPath(appNIPaths, paths); - for (const auto &path : paths) { - if (!isReadOnlyArea(path)) { - // Only the native image inside the TAC should be removed. - if (strstr(path.c_str(), TAC_SYMLINK_SUB_DIR) != NULL) { + if (isRPK(pkgId)) { + std::string rpkPaths = getResourcePaths(rootPath); + if (rpkPaths.empty()) { + _SERR("Failed to get rpk path from [%s]", pkgId.c_str()); + return NI_ERROR_UNKNOWN; + } + splitPath(rpkPaths, paths); + for (const auto &path : paths) { + if (isDirectory(path)) { removeNIUnderDirs(path); - } else { - if (isDirectory(path)) { - if (!removeAll(path.c_str())) { - _SERR("Failed to remove app ni dir [%s]", path.c_str()); + } + } + } else { + __pm->setAppRootPath(rootPath); + + // getAppNIPaths returns bin/.native_image, lib/.native_image and .tac_symlink. + std::string appNIPaths = __pm->getAppNIPaths(); + splitPath(appNIPaths, paths); + for (const auto &path : paths) { + if (!isReadOnlyArea(path)) { + // Only the native image inside the TAC should be removed. + if (strstr(path.c_str(), TAC_SYMLINK_SUB_DIR) != NULL) { + removeNIUnderDirs(path); + } else { + if (isDirectory(path)) { + if (!removeAll(path.c_str())) { + _SERR("Failed to remove app ni dir [%s]", path.c_str()); + } } } } } - } - // In special cases, the ni file may exist in the dll location. - // The code below is to avoid this exceptional case. - std::string appPaths = __pm->getAppPaths(); - splitPath(appPaths, paths); - for (const auto &path : paths) { - if (isDirectory(path)) { - removeNIUnderDirs(path); + // In special cases, the ni file may exist in the dll location. + // The code below is to avoid this exceptional case. + std::string appPaths = __pm->getAppPaths(); + splitPath(appPaths, paths); + for (const auto &path : paths) { + if (isDirectory(path)) { + removeNIUnderDirs(path); + } } } return NI_ERROR_NONE; } -ni_error_e regenerateAppNI(NIOption* opt) +ni_error_e regeneratePkgNI(NIOption* opt) { - int ret = 0; - pkgmgrinfo_appinfo_metadata_filter_h handle; std::vector pkgList; + ni_error_e ret = NI_ERROR_NONE; - 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_TRUE); - if (ret != PMINFO_R_OK) { - pkgmgrinfo_appinfo_metadata_filter_destroy(handle); - return NI_ERROR_UNKNOWN; + // iterates for Packages's metadata (RPK) + pkgmgrinfo_pkginfo_metadata_filter_h pkgHandle; + if (pkgmgrinfo_pkginfo_metadata_filter_create(&pkgHandle) == PMINFO_R_OK) { + if (pkgmgrinfo_pkginfo_metadata_filter_add(pkgHandle, AOT_METADATA_KEY, METADATA_VALUE_TRUE) == PMINFO_R_OK) { + if (pkgmgrPkgMDFilterForeach(pkgHandle, pkgAotCb, &pkgList) != 0) { + ret = NI_ERROR_UNKNOWN; + _ERR("pkgmgrPkgMDFilterForeach failed"); + } + } else { + ret = NI_ERROR_UNKNOWN; + _ERR("pkgmgrinfo_pkginfo_metadata_filter_add failed"); + } + pkgmgrinfo_pkginfo_metadata_filter_destroy(pkgHandle); + } else { + ret = NI_ERROR_UNKNOWN; + _ERR("pkgmgrinfo_pkginfo_metadata_filter_create failed"); } - ret = pkgmgrMDFilterForeach(handle, getPkgIdCb, &pkgList); - if (ret != 0) { - pkgmgrinfo_appinfo_metadata_filter_destroy(handle); - return NI_ERROR_UNKNOWN; + // iterate for App's metadata + pkgmgrinfo_appinfo_metadata_filter_h appHandle; + if (pkgmgrinfo_appinfo_metadata_filter_create(&appHandle) == PMINFO_R_OK) { + if (pkgmgrinfo_appinfo_metadata_filter_add(appHandle, AOT_METADATA_KEY, METADATA_VALUE_TRUE) == PMINFO_R_OK) { + if (pkgmgrAppMDFilterForeach(appHandle, appAotCb, &pkgList) != 0) { + ret = NI_ERROR_UNKNOWN; + _ERR("pkgmgrAppMDFilterForeach failed"); + } + } else { + ret = NI_ERROR_UNKNOWN; + _ERR("pkgmgrinfo_appinfo_metadata_filter_add failed"); + } + pkgmgrinfo_appinfo_metadata_filter_destroy(appHandle); + } else { + ret = NI_ERROR_UNKNOWN; + _ERR("pkgmgrinfo_appinfo_metadata_filter_create failed"); } // remove duplicated pkg in the list. @@ -1201,21 +1316,15 @@ ni_error_e regenerateAppNI(NIOption* opt) continue; } - if (removeNIUnderPkgRoot(pkg) != NI_ERROR_NONE) { + if (removeAndCreateNI(pkg.c_str(), opt) != 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; + ret = NI_ERROR_UNKNOWN; } else { _SOUT("Complete make application to native image"); } } - pkgmgrinfo_appinfo_metadata_filter_destroy(handle); - return NI_ERROR_NONE; + return ret; } // callback function of "pkgmgrinfo_appinfo_metadata_filter_foreach" @@ -1290,7 +1399,7 @@ ni_error_e regenerateTACNI(NIOption* opt) return NI_ERROR_UNKNOWN; } - ret = pkgmgrMDFilterForeach(handle, regenTacCb, &opt); + ret = pkgmgrAppMDFilterForeach(handle, regenTacCb, &opt); if (ret != 0) { pkgmgrinfo_appinfo_metadata_filter_destroy(handle); return NI_ERROR_UNKNOWN; diff --git a/NativeLauncher/tool/nitool.cc b/NativeLauncher/tool/nitool.cc index 943852e..f323f7a 100644 --- a/NativeLauncher/tool/nitool.cc +++ b/NativeLauncher/tool/nitool.cc @@ -85,7 +85,7 @@ int main(int argc, char* argv[]) } else if (cmdOptionExists(argv, argv+argc, "--reset-pkg")) { rmPkgMode = true; } else if (cmdOptionExists(argv, argv+argc, "--regen-all-app")) { - regenerateAppNI(opt->flags); + regeneratePkgNI(opt->flags); return 0; } else { help(argv[0]); diff --git a/NativeLauncher/tool/tac_common.cc b/NativeLauncher/tool/tac_common.cc index 94ff439..401cf8b 100644 --- a/NativeLauncher/tool/tac_common.cc +++ b/NativeLauncher/tool/tac_common.cc @@ -169,7 +169,7 @@ tac_error_e tac_restoreDB() return TAC_ERROR_UNKNOWN; } - ret = pkgmgrMDFilterForeach(handle, tac_restoreDBCb, NULL); + ret = pkgmgrAppMDFilterForeach(handle, tac_restoreDBCb, NULL); if (ret != 0) { pkgmgrinfo_appinfo_metadata_filter_destroy(handle); return TAC_ERROR_UNKNOWN; @@ -482,7 +482,7 @@ tac_error_e tlc_restoreDB() return TAC_ERROR_UNKNOWN; } - ret = pkgmgrMDFilterForeach(handle, tlc_restoreDBCb, NULL); + ret = pkgmgrAppMDFilterForeach(handle, tlc_restoreDBCb, NULL); if (ret != 0) { pkgmgrinfo_appinfo_metadata_filter_destroy(handle); return TAC_ERROR_UNKNOWN; diff --git a/NativeLauncher/util/utils.cc b/NativeLauncher/util/utils.cc index 37ba52e..f91ca65 100644 --- a/NativeLauncher/util/utils.cc +++ b/NativeLauncher/util/utils.cc @@ -812,7 +812,7 @@ int pkgmgrGetAppInfo(const std::string& appId, pkgmgrinfo_appinfo_h* handle) return 0; } -int pkgmgrMDFilterForeach(pkgmgrinfo_appinfo_metadata_filter_h handle, +int pkgmgrAppMDFilterForeach(pkgmgrinfo_appinfo_metadata_filter_h handle, pkgmgrinfo_app_list_cb app_cb, void *user_data) { @@ -824,7 +824,6 @@ int pkgmgrMDFilterForeach(pkgmgrinfo_appinfo_metadata_filter_h handle, return -1; } - ret = pkgmgrinfo_appinfo_usr_metadata_filter_foreach(handle, app_cb, user_data, uid); if (ret != PMINFO_R_OK) { _ERR("Failed to execute the metadata filter query (%d)", ret); @@ -834,6 +833,21 @@ int pkgmgrMDFilterForeach(pkgmgrinfo_appinfo_metadata_filter_h handle, return 0; } +int pkgmgrPkgMDFilterForeach(pkgmgrinfo_pkginfo_metadata_filter_h handle, + pkgmgrinfo_pkg_list_cb pkg_cb, + void *user_data) +{ + int ret = 0; + + ret = pkgmgrinfo_pkginfo_metadata_filter_foreach(handle, pkg_cb, user_data); + if (ret != PMINFO_R_OK) { + _ERR("Failed to execute the metadata filter query (%d)", ret); + return -1; + } + + return 0; +} + void printHWClockLog(const char* format, ...) { char buf[1024] = {0,}; @@ -884,3 +898,33 @@ bool isNCDBStartupHookProvided() return false; } + +std::string getResourcePaths(const std::string& rootPath) +{ + return rootPath + "/lib" + ":" + rootPath + "/res/allowed"; +} + +bool isRPK(const std::string& pkgId) +{ + char *type = NULL; + pkgmgrinfo_pkginfo_h pkg_handle; + int ret = pkgmgrGetPkgInfo(pkgId, &pkg_handle); + if (ret != 0) { + return false; + } + ret = pkgmgrinfo_pkginfo_get_type(pkg_handle, &type); + if (ret != PMINFO_R_OK) { + pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle); + return false; + } + + if (strncmp("rpk", type, 3) == 0) { + pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle); + return true; + } + + pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle); + + return false; +} +