From 1eecbe3c63f346ab24c8fa5a6cae2e289d21c1a7 Mon Sep 17 00:00:00 2001 From: myml Date: Wed, 9 Oct 2024 14:28:53 +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_prefix信息设置应用安装位置 如果base设置了app_prefix, 玲珑在构建时会将PREFIX设置成app_prefix指定的目录 在运行时也会将应用文件挂载成app_prefix指定的目录 --- api/schema/v1.json | 4 ++++ api/schema/v1.yaml | 3 +++ apps/generators/05-initialize/src/main.cpp | 6 ++--- apps/generators/25-host-env/src/main.cpp | 9 +++++--- apps/uab/loader/src/main.cpp | 5 +++++ .../src/linglong/api/types/v1/Generators.hpp | 4 ++++ .../linglong/api/types/v1/PackageInfoV2.hpp | 5 +++++ .../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 +++--- 14 files changed, 88 insertions(+), 18 deletions(-) diff --git a/api/schema/v1.json b/api/schema/v1.json index 6470f6986..29fd8c8c7 100644 --- a/api/schema/v1.json +++ b/api/schema/v1.json @@ -615,6 +615,10 @@ "compatible_version": { "type": "string", "description": "record linyaps package is compatible with linyaps component version" + }, + "app_prefix": { + "type": "string", + "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 9eca96ab8..80ca0cf20 100644 --- a/api/schema/v1.yaml +++ b/api/schema/v1.yaml @@ -495,6 +495,9 @@ $defs: compatible_version: type: string description: record linyaps package is compatible with linyaps component version + app_prefix: + type: string + 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. PackageInfo: title: PackageInfo description: this is the each item output of ll-cli list --json diff --git a/apps/generators/05-initialize/src/main.cpp b/apps/generators/05-initialize/src/main.cpp index 5a11102b8..b5514c905 100644 --- a/apps/generators/05-initialize/src/main.cpp +++ b/apps/generators/05-initialize/src/main.cpp @@ -58,10 +58,8 @@ int main() }); mounts.push_back( - { { "destination", - std::filesystem::path("/opt/apps") / annotations["org.deepin.linglong.appID"] - / "files" }, - { "options", nlohmann::json::array({ "rbind", "rw" }) }, + { { "destination", annotations["org.deepin.linglong.appPrefix"] }, + { "options", nlohmann::json::array({ "rbind", "ro" }) }, { "source", std::filesystem::path(annotations["org.deepin.linglong.appDir"].get()) / "files" }, diff --git a/apps/generators/25-host-env/src/main.cpp b/apps/generators/25-host-env/src/main.cpp index 84cc00da5..3cfa55bf0 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; @@ -79,9 +80,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(); + // appPrefix + auto appPrefix = annotations.at("org.deepin.linglong.appPrefix").get(); + env.push_back("LINGLONG_APPID=" + appID); + env.push_back("LINGLONG_APP_PREFIX=" + appPrefix); 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..cee7d64db 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.appPrefix) { + annotations["org.deepin.linglong.appPrefix"] = *opts.appPrefix; + } else { + annotations["org.deepin.linglong.appPrefix"] = "/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 25c881ae3..1cdfa703c 100644 --- a/libs/api/src/linglong/api/types/v1/Generators.hpp +++ b/libs/api/src/linglong/api/types/v1/Generators.hpp @@ -567,6 +567,7 @@ j["version"] = x.version; } inline void from_json(const json & j, PackageInfoV2& x) { +x.appPrefix = get_stack_optional(j, "app_prefix"); x.arch = j.at("arch").get>(); x.base = j.at("base").get(); x.channel = j.at("channel").get(); @@ -587,6 +588,9 @@ x.version = j.at("version").get(); inline void to_json(json & j, const PackageInfoV2 & x) { j = json::object(); +if (x.appPrefix) { +j["app_prefix"] = x.appPrefix; +} j["arch"] = x.arch; j["base"] = x.base; j["channel"] = x.channel; diff --git a/libs/api/src/linglong/api/types/v1/PackageInfoV2.hpp b/libs/api/src/linglong/api/types/v1/PackageInfoV2.hpp index 107bfd312..0d5f1e645 100644 --- a/libs/api/src/linglong/api/types/v1/PackageInfoV2.hpp +++ b/libs/api/src/linglong/api/types/v1/PackageInfoV2.hpp @@ -34,6 +34,11 @@ using nlohmann::json; */ struct PackageInfoV2 { /** +* 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 appPrefix; +/** * 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 436486f9c..bd33b7678 100644 --- a/libs/linglong/src/linglong/builder/linglong_builder.cpp +++ b/libs/linglong/src/linglong/builder/linglong_builder.cpp @@ -271,7 +271,7 @@ utils::error::Result pullDependency(const package::FuzzyRefe auto tmpTask = service::PackageTask::createTemporaryTask(); auto partChanged = [&ref, module](const uint fetched, const uint requested) { - auto percentage = (uint)((((double)fetched) / requested) * 100); + auto percentage = (uint)((((double)fetched) / requested) * 100); auto progress = QString("(%1/%2 %3%)").arg(fetched).arg(requested).arg(percentage); printReplacedText(QString("%1%2%3%4 %5") .arg(ref->id, -25) // NOLINT @@ -491,6 +491,7 @@ utils::error::Result Builder::build(const QStringList &args) noexcept if (!baseRef) { return LINGLONG_ERR("pull base binary", baseRef); } + auto baseInfo = baseLayerDir->info(); printReplacedText(QString("%1%2%3%4") .arg(baseRef->id, -25) // NOLINT .arg(baseRef->version.toString(), -15) // NOLINT @@ -639,6 +640,7 @@ set -e .runtimeDir = {}, .baseDir = *baseLayerDir, .appDir = {}, + .appPrefix = baseInfo->appPrefix, .patches = {}, .mounts = {}, .masks = {}, @@ -649,7 +651,12 @@ set -e // 构建安装路径 QString installPrefix = "/runtime"; if (this->project.package.kind != "runtime") { - installPrefix = QString::fromStdString("/opt/apps/" + this->project.package.id + "/files"); + if (baseInfo->appPrefix) { + installPrefix = QString::fromStdString(*baseInfo->appPrefix); + } else { + installPrefix = + QString::fromStdString("/opt/apps/" + this->project.package.id + "/files"); + } } opts.mounts.push_back({ .destination = installPrefix.toStdString(), @@ -1096,6 +1103,10 @@ utils::error::Result Builder::exportUAB(const QString &destination, const if (!baseDir) { return LINGLONG_ERR(baseDir); } + auto info = baseDir->info(); + if (info->appPrefix) { + packager.setappPrefix(*info->appPrefix); + } packager.appendLayer(*baseDir); if (this->project.runtime) { @@ -1278,6 +1289,13 @@ utils::error::Result Builder::run(const QStringList &modules, if (!baseRef) { return LINGLONG_ERR(baseRef); } + auto baseDir = this->repo.getLayerDir(*baseRef, "binary"); + if (!baseDir) { + return LINGLONG_ERR(baseDir); + } + auto baseInfo = baseDir->info(); + options.baseDir = QDir(baseDir->absolutePath()); + options.appPrefix = baseInfo->appPrefix; 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 d85be55af..62fe65157 100644 --- a/libs/linglong/src/linglong/cli/cli.cpp +++ b/libs/linglong/src/linglong/cli/cli.cpp @@ -386,6 +386,7 @@ int Cli::run() this->printer.printErr(LINGLONG_ERRV(baseLayerDir)); return -1; } + auto baseInfo = baseLayerDir->info(); auto commands = options.commands; if (commands.empty()) { @@ -539,6 +540,7 @@ int Cli::run() .runtimeDir = runtimeLayerDir, .baseDir = *baseLayerDir, .appDir = *appLayerDir, + .appPrefix = baseInfo->appPrefix, .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 2e285fd13..897e9919d 100644 --- a/libs/linglong/src/linglong/package/uab_packager.cpp +++ b/libs/linglong/src/linglong/package/uab_packager.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -167,6 +168,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::setAppPrefix(const std::string &appPrefix) noexcept +{ + m_appPrefix = appPrefix; +} + utils::error::Result UABPackager::appendLayer(const LayerDir &layer) noexcept { LINGLONG_TRACE("append layer to uab") @@ -546,8 +553,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 appPrefix = "/opt/apps/" + appID + "/files"; + if (m_appPrefix) { + appPrefix = QString::fromStdString(*m_appPrefix); + } + stream << appPrefix + "/lib" << Qt::endl; + stream << appPrefix + "/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 265e40bd8..dbcc5ae24 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 { @@ -68,6 +69,7 @@ class UABPackager UABPackager(UABPackager &&) = delete; utils::error::Result setIcon(const QFileInfo &icon) noexcept; + void setAppPrefix(const std::string &appPrefix) 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; @@ -86,6 +88,7 @@ class UABPackager std::unordered_set excludeFiles; std::unordered_set includeFiles; std::optional icon{ std::nullopt }; + std::optional m_appPrefix; 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..4db51a34b 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 appPrefix = "/opt/apps/" + this->appID.toStdString() + "/files"; + if (cfg.annotations) { + auto annotations = *cfg.annotations; + if (annotations.find("org.deepin.linglong.appPrefix") != annotations.end()) { + appPrefix = annotations["org.deepin.linglong.appPrefix"]; + } + } + ofs << appPrefix + "/lib" << std::endl; + ofs << appPrefix + "/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 b56f6d245..5d9f71cbf 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.appPrefix) { + annotations["org.deepin.linglong.appPrefix"] = *opts.appPrefix; + } else { + annotations["org.deepin.linglong.appPrefix"] = + "/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 8cdd511b7..5a332d095 100644 --- a/libs/linglong/src/linglong/runtime/container_builder.h +++ b/libs/linglong/src/linglong/runtime/container_builder.h @@ -21,9 +21,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 appPrefix; // if appPrefix exists, mount appDir to appPrefix std::vector patches; std::vector mounts; // extra mounts