From 4bec0533bbdc96f943cf8ec7a17e10ef5e42ff88 Mon Sep 17 00:00:00 2001 From: myml Date: Sun, 29 Sep 2024 14:09:37 +0800 Subject: [PATCH] feat: support base custom application installation location MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit base可以通过app_home信息设置应用安装位置 如果base设置了app_home, 玲珑在构建时会将PREFIX设置成app_home指定的目录 在运行时也会将应用文件挂载成app_home指定的目录 --- api/schema/v1.json | 6 ++++- api/schema/v1.yaml | 27 +++++++++++-------- apps/generators/05-initialize/src/main.cpp | 8 +++--- apps/generators/25-host-env/src/main.cpp | 9 ++++--- apps/uab/loader/src/main.cpp | 5 ++++ .../src/linglong/api/types/v1/Generators.hpp | 4 +++ .../src/linglong/api/types/v1/PackageInfo.hpp | 3 ++- .../linglong/api/types/v1/PackageInfoV2.hpp | 4 +++ .../src/linglong/builder/linglong_builder.cpp | 22 +++++++++++---- libs/linglong/src/linglong/cli/cli.cpp | 2 ++ .../src/linglong/package/uab_packager.cpp | 16 +++++++++-- .../src/linglong/package/uab_packager.h | 3 +++ .../src/linglong/runtime/container.cpp | 14 +++++++--- .../linglong/runtime/container_builder.cpp | 6 +++++ .../src/linglong/runtime/container_builder.h | 7 ++--- 15 files changed, 101 insertions(+), 35 deletions(-) diff --git a/api/schema/v1.json b/api/schema/v1.json index 4d665f482..89f4016d7 100644 --- a/api/schema/v1.json +++ b/api/schema/v1.json @@ -552,6 +552,10 @@ "description": { "type": "string", "description": "description of package info" + }, + "app_home": { + "type": "string", + "description": "app_home of package info" } } }, @@ -626,7 +630,7 @@ }, "description": { "type": "string", - "description": "description of package info" + "description": "application install location. The field is intended solely for the use of the base, indicating the installation path of applications built using that base." } } }, diff --git a/api/schema/v1.yaml b/api/schema/v1.yaml index dd13864f1..9689c04e9 100644 --- a/api/schema/v1.yaml +++ b/api/schema/v1.yaml @@ -170,18 +170,20 @@ $defs: description: version of build file exclude: type: array - description: exclude files during exporting UAB. Every item should be absolute path in container. - It could be a directory or a regular file. - e.g. - /usr/share/locale (exclude all files which in this directory) - - /usr/lib/libavfs.a (exclude one file) + description: + exclude files during exporting UAB. Every item should be absolute path in container. + It could be a directory or a regular file. + e.g. - /usr/share/locale (exclude all files which in this directory) + - /usr/lib/libavfs.a (exclude one file) items: type: string include: type: array - description: include files during exporting UAB. For example, the packer can declare a - file/directory (e.g. /usr/share/locale/zh_CN) in the excluded directory - (e.g. /usr/share/locale) to exclude all files in /usr/share/locale - except /usr/share/locale/zh_CN. + description: + include files during exporting UAB. For example, the packer can declare a + file/directory (e.g. /usr/share/locale/zh_CN) in the excluded directory + (e.g. /usr/share/locale) to exclude all files in /usr/share/locale + except /usr/share/locale/zh_CN. items: type: string package: @@ -441,6 +443,9 @@ $defs: description: type: string description: description of package info + app_home: + type: string + description: app_home of package info PackageInfo: title: PackageInfo description: this is the each item output of ll-cli list --json @@ -497,7 +502,7 @@ $defs: $ref: "#/$defs/ApplicationConfigurationPermissions" description: type: string - description: description of package info + description: application install location. The field is intended solely for the use of the base, indicating the installation path of applications built using that base. CommonResult: title: CommonResult description: this is common error result of ll-cli command --json @@ -644,7 +649,7 @@ $defs: type: string description: version of linglong at the time of generating the file config: - $ref: '#/$defs/RepoConfig' + $ref: "#/$defs/RepoConfig" layers: title: RepositoryCacheLayers type: object @@ -660,7 +665,7 @@ $defs: type: string description: ostree commit hash info: - $ref: '#/$defs/PackageInfoV2' + $ref: "#/$defs/PackageInfoV2" type: object properties: # NOTE: "properties" is auto generated by referring all types is $defs diff --git a/apps/generators/05-initialize/src/main.cpp b/apps/generators/05-initialize/src/main.cpp index 5a11102b8..e428b7304 100644 --- a/apps/generators/05-initialize/src/main.cpp +++ b/apps/generators/05-initialize/src/main.cpp @@ -58,13 +58,11 @@ int main() }); mounts.push_back( - { { "destination", - std::filesystem::path("/opt/apps") / annotations["org.deepin.linglong.appID"] - / "files" }, + { { "destination", annotations["org.deepin.linglong.appHome"] }, + // TODO 是否应该使用ro权限? { "options", nlohmann::json::array({ "rbind", "rw" }) }, { "source", - std::filesystem::path(annotations["org.deepin.linglong.appDir"].get()) - / "files" }, + std::filesystem::path(annotations["org.deepin.linglong.appDir"]) / "files" }, { "type", "bind" } }); } diff --git a/apps/generators/25-host-env/src/main.cpp b/apps/generators/25-host-env/src/main.cpp index 5dc894fa6..0a2c7a76a 100644 --- a/apps/generators/25-host-env/src/main.cpp +++ b/apps/generators/25-host-env/src/main.cpp @@ -6,6 +6,7 @@ #include #include +#include extern char **environ; @@ -80,9 +81,11 @@ int main() } auto annotations = content.at("annotations"); - env.push_back("LINGLONG_APPID=" - + annotations.at("org.deepin.linglong.appID").get()); - + auto appID = annotations.at("org.deepin.linglong.appID").get(); + // appHome + auto appHome = annotations.at("org.deepin.linglong.appHome").get(); + env.push_back("LINGLONG_APPID=" + appID); + env.push_back("LINGLONG_APPHOME=" + appHome); std::cout << content.dump() << std::endl; return 0; } diff --git a/apps/uab/loader/src/main.cpp b/apps/uab/loader/src/main.cpp index 5a4a81f8e..a7ea25f07 100644 --- a/apps/uab/loader/src/main.cpp +++ b/apps/uab/loader/src/main.cpp @@ -641,6 +641,11 @@ int main([[maybe_unused]] int argc, [[maybe_unused]] char **argv) auto appDir = std::filesystem::path{ layerFilesDir }.parent_path(); annotations["org.deepin.linglong.appDir"] = appDir.string(); + if (opts.appHome) { + annotations["org.deepin.linglong.appHome"] = *opts.appHome; + } else { + annotations["org.deepin.linglong.appHome"] = "/opt/apps/" + opts.appID + "/files"; + } config.annotations = std::move(annotations); // replace commands diff --git a/libs/api/src/linglong/api/types/v1/Generators.hpp b/libs/api/src/linglong/api/types/v1/Generators.hpp index 88b91df14..b0291aad3 100644 --- a/libs/api/src/linglong/api/types/v1/Generators.hpp +++ b/libs/api/src/linglong/api/types/v1/Generators.hpp @@ -460,6 +460,7 @@ j["version"] = x.version; } inline void from_json(const json & j, PackageInfoV2& x) { +x.appHome = get_stack_optional(j, "app_home"); x.arch = j.at("arch").get>(); x.base = j.at("base").get(); x.channel = j.at("channel").get(); @@ -478,6 +479,9 @@ x.version = j.at("version").get(); inline void to_json(json & j, const PackageInfoV2 & x) { j = json::object(); +if (x.appHome) { +j["app_home"] = x.appHome; +} j["arch"] = x.arch; j["base"] = x.base; j["channel"] = x.channel; diff --git a/libs/api/src/linglong/api/types/v1/PackageInfo.hpp b/libs/api/src/linglong/api/types/v1/PackageInfo.hpp index 9290552f2..a6eed815b 100644 --- a/libs/api/src/linglong/api/types/v1/PackageInfo.hpp +++ b/libs/api/src/linglong/api/types/v1/PackageInfo.hpp @@ -54,7 +54,8 @@ std::string channel; */ std::optional> command; /** -* description of package info +* application install location. The field is intended solely for the use of the base, +* indicating the installation path of applications built using that base. */ std::optional description; /** diff --git a/libs/api/src/linglong/api/types/v1/PackageInfoV2.hpp b/libs/api/src/linglong/api/types/v1/PackageInfoV2.hpp index 4a5d791b8..385c300e2 100644 --- a/libs/api/src/linglong/api/types/v1/PackageInfoV2.hpp +++ b/libs/api/src/linglong/api/types/v1/PackageInfoV2.hpp @@ -34,6 +34,10 @@ using nlohmann::json; */ struct PackageInfoV2 { /** +* app_home of package info +*/ +std::optional appHome; +/** * arch of package info */ std::vector arch; diff --git a/libs/linglong/src/linglong/builder/linglong_builder.cpp b/libs/linglong/src/linglong/builder/linglong_builder.cpp index af7051381..a069cb019 100644 --- a/libs/linglong/src/linglong/builder/linglong_builder.cpp +++ b/libs/linglong/src/linglong/builder/linglong_builder.cpp @@ -222,8 +222,7 @@ utils::error::Result splitDevelop(QString installFilepath, iter.next(); auto filepath = iter.filePath(); qDebug() << filepath; - // $PROJECT_ROOT/.../files to /opt/apps/${appid} - // $PROJECT_ROOT/ to /runtime/ + // $PROJECT_ROOT/.../files to installPrefix filepath.replace(0, src.length(), prefix); installRules.append(filepath); } @@ -472,6 +471,7 @@ utils::error::Result Builder::build(const QStringList &args) noexcept if (!baseLayerDir) { return LINGLONG_ERR(baseLayerDir); } + auto baseInfo = baseLayerDir->info(); printReplacedText(QString("%1%2%3%4") .arg(base->id, -25) // NOLINT .arg(base->version.toString(), -15) // NOLINT @@ -505,8 +505,8 @@ set -e scriptContent.push_back('\n'); // Do some checks after run container if (this->project.package.kind == "app") { - scriptContent.append("# POST BUILD PROCESS\n"); - scriptContent.append(LINGLONG_BUILDER_HELPER "/main-check.sh\n"); + // scriptContent.append("# POST BUILD PROCESS\n"); + // scriptContent.append(LINGLONG_BUILDER_HELPER "/main-check.sh\n"); } auto writeBytes = scriptContent.size(); auto bytesWrite = entry.write(scriptContent.c_str()); @@ -547,6 +547,7 @@ set -e .runtimeDir = {}, .baseDir = *baseLayerDir, .appDir = {}, + .appHome = baseInfo->appHome, .patches = {}, .mounts = {}, .masks = {}, @@ -557,7 +558,12 @@ set -e // 构建安装路径 QString installPrefix = "/runtime"; if (this->project.package.kind != "runtime") { - installPrefix = QString::fromStdString("/opt/apps/" + this->project.package.id + "/files"); + if (baseInfo->appHome) { + installPrefix = QString::fromStdString(*baseInfo->appHome); + } else { + installPrefix = + QString::fromStdString("/opt/apps/" + this->project.package.id + "/files"); + } } opts.mounts.push_back({ .destination = installPrefix.toStdString(), @@ -882,6 +888,10 @@ utils::error::Result Builder::exportUAB(const QString &destination, const if (!baseDir) { return LINGLONG_ERR(baseDir); } + auto info = baseDir->info(); + if (info->appHome) { + packager.setAppHome(*info->appHome); + } packager.appendLayer(*baseDir); if (this->project.runtime) { @@ -1116,7 +1126,9 @@ utils::error::Result Builder::run(const QStringList &args) if (!baseDir) { return LINGLONG_ERR(baseDir); } + auto baseInfo = baseDir->info(); options.baseDir = QDir(baseDir->absolutePath()); + options.appHome = baseInfo->appHome; if (this->project.runtime) { auto ref = pullDependency(QString::fromStdString(*this->project.runtime), diff --git a/libs/linglong/src/linglong/cli/cli.cpp b/libs/linglong/src/linglong/cli/cli.cpp index d2cef197d..41e9a9ac5 100644 --- a/libs/linglong/src/linglong/cli/cli.cpp +++ b/libs/linglong/src/linglong/cli/cli.cpp @@ -271,6 +271,7 @@ int Cli::run(std::map &args) this->printer.printErr(LINGLONG_ERRV(baseLayerDir)); return -1; } + auto baseInfo = baseLayerDir->info(); auto command = args["COMMAND"].asStringList(); if (command.empty()) { @@ -373,6 +374,7 @@ int Cli::run(std::map &args) .runtimeDir = runtimeLayerDir, .baseDir = *baseLayerDir, .appDir = *appLayerDir, + .appHome = baseInfo->appHome, .patches = {}, .mounts = std::move(applicationMounts), .masks = {}, diff --git a/libs/linglong/src/linglong/package/uab_packager.cpp b/libs/linglong/src/linglong/package/uab_packager.cpp index 334ae75d9..8fe49ce01 100644 --- a/libs/linglong/src/linglong/package/uab_packager.cpp +++ b/libs/linglong/src/linglong/package/uab_packager.cpp @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -159,6 +160,12 @@ utils::error::Result UABPackager::setIcon(const QFileInfo &newIcon) noexce return LINGLONG_OK; } +// set app install dir, default is /opt/apps/$appid/files +void UABPackager::setAppHome(const std::string &appHome) noexcept +{ + m_appHome = appHome; +} + utils::error::Result UABPackager::appendLayer(const LayerDir &layer) noexcept { LINGLONG_TRACE("append layer to uab") @@ -511,8 +518,13 @@ utils::error::Result UABPackager::prepareBundle(const QDir &bundleDir) noe QTextStream stream{ &ldConf }; stream << "/runtime/lib" << Qt::endl; stream << "/runtime/lib/" + arch->getTriplet() << Qt::endl; - stream << "/opt/apps/" + appID + "/files/lib" << Qt::endl; - stream << "/opt/apps/" + appID + "/files/lib/" + arch->getTriplet() << Qt::endl; + auto appHome = "/opt/apps/" + appID + "/files"; + if (m_appHome) { + appHome = QString::fromStdString(*m_appHome); + } + stream << appHome + "/lib" << Qt::endl; + stream << appHome + "/lib/" + arch->getTriplet() << Qt::endl; + stream.flush(); // copy ll-box diff --git a/libs/linglong/src/linglong/package/uab_packager.h b/libs/linglong/src/linglong/package/uab_packager.h index ed511d661..ff4968e91 100644 --- a/libs/linglong/src/linglong/package/uab_packager.h +++ b/libs/linglong/src/linglong/package/uab_packager.h @@ -17,6 +17,7 @@ #include #include +#include #include namespace linglong::package { @@ -67,6 +68,7 @@ class UABPackager UABPackager(UABPackager &&) = delete; utils::error::Result setIcon(const QFileInfo &icon) noexcept; + void setAppHome(const std::string &appHome) noexcept; utils::error::Result appendLayer(const LayerDir &layer) noexcept; utils::error::Result pack(const QString &uabFilename) noexcept; utils::error::Result exclude(const std::vector &files) noexcept; @@ -85,6 +87,7 @@ class UABPackager std::unordered_set excludeFiles; std::unordered_set includeFiles; std::optional icon{ std::nullopt }; + std::optional m_appHome; api::types::v1::UabMetaInfo meta; QDir buildDir; }; diff --git a/libs/linglong/src/linglong/runtime/container.cpp b/libs/linglong/src/linglong/runtime/container.cpp index 09e7e90b9..2eee9f915 100644 --- a/libs/linglong/src/linglong/runtime/container.cpp +++ b/libs/linglong/src/linglong/runtime/container.cpp @@ -151,10 +151,16 @@ Container::run(const ocppi::runtime::config::types::Process &process) noexcept ofs << "/runtime/lib" << std::endl; ofs << "/runtime/lib/" + arch->getTriplet().toStdString() << std::endl; - ofs << "/opt/apps/" + this->appID.toStdString() + "/files/lib" << std::endl; - ofs << "/opt/apps/" + this->appID.toStdString() + "/files/lib/" - + arch->getTriplet().toStdString() - << std::endl; + + auto appHome = "/opt/apps/" + this->appID.toStdString() + "/files"; + if (cfg.annotations) { + auto annotations = *cfg.annotations; + if (annotations.find("org.deepin.linglong.appHome") != annotations.end()) { + appHome = annotations["org.deepin.linglong.appHome"]; + } + } + ofs << appHome + "/lib" << std::endl; + ofs << appHome + "/lib/" + arch->getTriplet().toStdString() << std::endl; } this->cfg.mounts->push_back(ocppi::runtime::config::types::Mount{ .destination = "/etc/ld.so.conf.d/zz_deepin-linglong-app.conf", diff --git a/libs/linglong/src/linglong/runtime/container_builder.cpp b/libs/linglong/src/linglong/runtime/container_builder.cpp index 659d592c0..bbad37b06 100644 --- a/libs/linglong/src/linglong/runtime/container_builder.cpp +++ b/libs/linglong/src/linglong/runtime/container_builder.cpp @@ -248,6 +248,12 @@ auto getOCIConfig(const ContainerOptions &opts) noexcept if (opts.appDir) { annotations["org.deepin.linglong.appDir"] = opts.appDir->absolutePath().toStdString(); } + if (opts.appHome) { + annotations["org.deepin.linglong.appHome"] = *opts.appHome; + } else { + annotations["org.deepin.linglong.appHome"] = + "/opt/apps/" + opts.appID.toStdString() + "/files"; + } config->annotations = std::move(annotations); QDir configDotDDir = QFileInfo(containerConfigFilePath).dir().filePath("config.d"); diff --git a/libs/linglong/src/linglong/runtime/container_builder.h b/libs/linglong/src/linglong/runtime/container_builder.h index 8e87b3141..57069ba51 100644 --- a/libs/linglong/src/linglong/runtime/container_builder.h +++ b/libs/linglong/src/linglong/runtime/container_builder.h @@ -22,9 +22,10 @@ struct ContainerOptions QString appID; QString containerID; - std::optional runtimeDir; // mount to /runtime - QDir baseDir; // mount to / - std::optional appDir; // mount to /opt/apps/${info.appid}/files + std::optional runtimeDir; // mount to /runtime + QDir baseDir; // mount to / + std::optional appDir; // mount to /opt/apps/${info.appid}/files + std::optional appHome; // if appHome exists, mount appDir to appHome std::vector patches; std::vector mounts; // extra mounts