Skip to content

Commit

Permalink
feat: support base custom application installation location
Browse files Browse the repository at this point in the history
base可以通过app_home信息设置应用安装位置 如果base设置了app_home,
玲珑在构建时会将PREFIX设置成app_home指定的目录
在运行时也会将应用文件挂载成app_home指定的目录
  • Loading branch information
myml committed Sep 29, 2024
1 parent 847b2de commit 4bec053
Show file tree
Hide file tree
Showing 15 changed files with 101 additions and 35 deletions.
6 changes: 5 additions & 1 deletion api/schema/v1.json
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,10 @@
"description": {
"type": "string",
"description": "description of package info"
},
"app_home": {
"type": "string",
"description": "app_home of package info"
}
}
},
Expand Down Expand Up @@ -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."
}
}
},
Expand Down
27 changes: 16 additions & 11 deletions api/schema/v1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
8 changes: 3 additions & 5 deletions apps/generators/05-initialize/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::string>())
/ "files" },
std::filesystem::path(annotations["org.deepin.linglong.appDir"]) / "files" },
{ "type", "bind" } });
}

Expand Down
9 changes: 6 additions & 3 deletions apps/generators/25-host-env/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <filesystem>
#include <iostream>
#include <string>

extern char **environ;

Expand Down Expand Up @@ -80,9 +81,11 @@ int main()
}

auto annotations = content.at("annotations");
env.push_back("LINGLONG_APPID="
+ annotations.at("org.deepin.linglong.appID").get<std::string>());

auto appID = annotations.at("org.deepin.linglong.appID").get<std::string>();
// appHome
auto appHome = annotations.at("org.deepin.linglong.appHome").get<std::string>();
env.push_back("LINGLONG_APPID=" + appID);
env.push_back("LINGLONG_APPHOME=" + appHome);
std::cout << content.dump() << std::endl;
return 0;
}
5 changes: 5 additions & 0 deletions apps/uab/loader/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions libs/api/src/linglong/api/types/v1/Generators.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,7 @@ j["version"] = x.version;
}

inline void from_json(const json & j, PackageInfoV2& x) {
x.appHome = get_stack_optional<std::string>(j, "app_home");
x.arch = j.at("arch").get<std::vector<std::string>>();
x.base = j.at("base").get<std::string>();
x.channel = j.at("channel").get<std::string>();
Expand All @@ -478,6 +479,9 @@ x.version = j.at("version").get<std::string>();

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;
Expand Down
3 changes: 2 additions & 1 deletion libs/api/src/linglong/api/types/v1/PackageInfo.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ std::string channel;
*/
std::optional<std::vector<std::string>> 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<std::string> description;
/**
Expand Down
4 changes: 4 additions & 0 deletions libs/api/src/linglong/api/types/v1/PackageInfoV2.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ using nlohmann::json;
*/
struct PackageInfoV2 {
/**
* app_home of package info
*/
std::optional<std::string> appHome;
/**
* arch of package info
*/
std::vector<std::string> arch;
Expand Down
22 changes: 17 additions & 5 deletions libs/linglong/src/linglong/builder/linglong_builder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,7 @@ utils::error::Result<void> 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);
}
Expand Down Expand Up @@ -472,6 +471,7 @@ utils::error::Result<void> 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
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -547,6 +547,7 @@ set -e
.runtimeDir = {},
.baseDir = *baseLayerDir,
.appDir = {},
.appHome = baseInfo->appHome,
.patches = {},
.mounts = {},
.masks = {},
Expand All @@ -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(),
Expand Down Expand Up @@ -882,6 +888,10 @@ utils::error::Result<void> 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) {
Expand Down Expand Up @@ -1116,7 +1126,9 @@ utils::error::Result<void> 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),
Expand Down
2 changes: 2 additions & 0 deletions libs/linglong/src/linglong/cli/cli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ int Cli::run(std::map<std::string, docopt::value> &args)
this->printer.printErr(LINGLONG_ERRV(baseLayerDir));
return -1;
}
auto baseInfo = baseLayerDir->info();

auto command = args["COMMAND"].asStringList();
if (command.empty()) {
Expand Down Expand Up @@ -373,6 +374,7 @@ int Cli::run(std::map<std::string, docopt::value> &args)
.runtimeDir = runtimeLayerDir,
.baseDir = *baseLayerDir,
.appDir = *appLayerDir,
.appHome = baseInfo->appHome,
.patches = {},
.mounts = std::move(applicationMounts),
.masks = {},
Expand Down
16 changes: 14 additions & 2 deletions libs/linglong/src/linglong/package/uab_packager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <QCryptographicHash>
#include <QStandardPaths>

#include <string>
#include <unordered_set>
#include <utility>

Expand Down Expand Up @@ -159,6 +160,12 @@ utils::error::Result<void> 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<void> UABPackager::appendLayer(const LayerDir &layer) noexcept
{
LINGLONG_TRACE("append layer to uab")
Expand Down Expand Up @@ -511,8 +518,13 @@ utils::error::Result<void> 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
Expand Down
3 changes: 3 additions & 0 deletions libs/linglong/src/linglong/package/uab_packager.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <QUuid>

#include <filesystem>
#include <string>
#include <unordered_set>

namespace linglong::package {
Expand Down Expand Up @@ -67,6 +68,7 @@ class UABPackager
UABPackager(UABPackager &&) = delete;

utils::error::Result<void> setIcon(const QFileInfo &icon) noexcept;
void setAppHome(const std::string &appHome) noexcept;
utils::error::Result<void> appendLayer(const LayerDir &layer) noexcept;
utils::error::Result<void> pack(const QString &uabFilename) noexcept;
utils::error::Result<void> exclude(const std::vector<std::string> &files) noexcept;
Expand All @@ -85,6 +87,7 @@ class UABPackager
std::unordered_set<std::string> excludeFiles;
std::unordered_set<std::string> includeFiles;
std::optional<QFileInfo> icon{ std::nullopt };
std::optional<std::string> m_appHome;
api::types::v1::UabMetaInfo meta;
QDir buildDir;
};
Expand Down
14 changes: 10 additions & 4 deletions libs/linglong/src/linglong/runtime/container.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
6 changes: 6 additions & 0 deletions libs/linglong/src/linglong/runtime/container_builder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
7 changes: 4 additions & 3 deletions libs/linglong/src/linglong/runtime/container_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ struct ContainerOptions
QString appID;
QString containerID;

std::optional<QDir> runtimeDir; // mount to /runtime
QDir baseDir; // mount to /
std::optional<QDir> appDir; // mount to /opt/apps/${info.appid}/files
std::optional<QDir> runtimeDir; // mount to /runtime
QDir baseDir; // mount to /
std::optional<QDir> appDir; // mount to /opt/apps/${info.appid}/files
std::optional<std::string> appHome; // if appHome exists, mount appDir to appHome

std::vector<api::types::v1::OciConfigurationPatch> patches;
std::vector<ocppi::runtime::config::types::Mount> mounts; // extra mounts
Expand Down

0 comments on commit 4bec053

Please sign in to comment.