Skip to content

Commit ecd3a12

Browse files
committed
feat: host NVIDIA driver fallback
1 parent b30b7dd commit ecd3a12

15 files changed

Lines changed: 2383 additions & 5 deletions

File tree

apps/ll-cli/src/main.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,44 @@ void addInspectCommand(CLI::App &commandParser,
607607
->check(validatorString);
608608
}
609609

610+
// Function to add the extension subcommand
611+
void addExtensionCommand(CLI::App &commandParser,
612+
ExtensionOptions &extensionOptions,
613+
const std::string &group)
614+
{
615+
auto *cliExtension =
616+
commandParser.add_subcommand("extension", _("Manage extension overrides"))
617+
->group(group)
618+
->usage(_("Usage: ll-cli extension SUBCOMMAND [OPTIONS]"));
619+
620+
cliExtension->require_subcommand(1);
621+
622+
auto *cliImportCdi =
623+
cliExtension
624+
->add_subcommand("import-cdi", _("Import CDI rules into extension overrides"))
625+
->usage(_("Usage: ll-cli extension import-cdi [OPTIONS]"));
626+
cliImportCdi
627+
->add_option("--name",
628+
extensionOptions.name,
629+
_("Specify extension name prefix to update"))
630+
->type_name("NAME")
631+
->check(validatorString);
632+
cliImportCdi
633+
->add_option("--config",
634+
extensionOptions.configPath,
635+
_("Specify config path (default: ~/.config/linglong/config.json)"))
636+
->type_name("FILE");
637+
cliImportCdi
638+
->add_option("--cdi",
639+
extensionOptions.cdiPath,
640+
_("Specify CDI JSON path (default: nvidia-ctk cdi generate --format json)"))
641+
->type_name("FILE");
642+
cliImportCdi
643+
->add_flag("--apply-when-installed",
644+
extensionOptions.applyWhenInstalled,
645+
_("Apply overrides even when extension is installed"));
646+
}
647+
610648
} // namespace
611649

612650
using namespace linglong::utils::global;
@@ -690,12 +728,14 @@ You can report bugs to the linyaps team under this project: https://github.com/O
690728
ContentOptions contentOptions{};
691729
RepoOptions repoOptions{};
692730
InspectOptions inspectOptions{};
731+
ExtensionOptions extensionOptions{};
693732

694733
// groups for subcommands
695734
auto *CliBuildInGroup = _("Managing installed applications and runtimes");
696735
auto *CliAppManagingGroup = _("Managing running applications");
697736
auto *CliSearchGroup = _("Finding applications and runtimes");
698737
auto *CliRepoGroup = _("Managing remote repositories");
738+
auto *CliExtensionGroup = _("Managing extensions");
699739

700740
// add all subcommands using the new functions
701741
addRunCommand(commandParser, runOptions, CliAppManagingGroup);
@@ -712,6 +752,7 @@ You can report bugs to the linyaps team under this project: https://github.com/O
712752
addContentCommand(commandParser, contentOptions, CliBuildInGroup);
713753
addPruneCommand(commandParser, CliAppManagingGroup);
714754
addInspectCommand(commandParser, inspectOptions, CliHiddenGroup);
755+
addExtensionCommand(commandParser, extensionOptions, CliExtensionGroup);
715756

716757
auto res = transformOldExec(argc, argv);
717758
CLI11_PARSE(commandParser, std::move(res));
@@ -920,6 +961,8 @@ You can report bugs to the linyaps team under this project: https://github.com/O
920961
result = cli->inspect(*ret, inspectOptions);
921962
} else if (name == "repo") {
922963
result = cli->repo(*ret, repoOptions);
964+
} else if (name == "extension") {
965+
result = cli->extension(*ret, extensionOptions);
923966
} else {
924967
// if subcommand name is not found, print help
925968
std::cout << commandParser.help("", CLI::AppFormatMode::All);

docs/pages/en/guide/reference/driver.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@ The base that applications depend on already includes the appropriate version of
2020

2121
Drivers not included in the base that require additional installation:
2222

23-
- NVIDIA proprietary drivers: Install via `sudo ll-cli install org.deepin.driver.display.nvidia.570-124-04`. The `570-124-04` is the driver version number, which must match the driver version installed on the host system. Check the host driver version through the `/sys/module/nvidia/version` file.
23+
- NVIDIA proprietary drivers: Install via `sudo ll-cli install org.deepin.driver.display.nvidia.570-124-04`. The `570-124-04` is the driver version number, which must match the driver version installed on the host system. Check the host driver version through the `/sys/module/nvidia/version` file. If the extension is not installed, linyaps will attempt to link NVIDIA driver files from the host at runtime.
2424
- Glenfly graphics drivers: Install via `sudo ll-cli install com.glenfly.driver.display.arise`.
2525
- Intel video codec drivers (VAAPI): Install via `sudo ll-cli install org.deepin.driver.media.intel`, which includes support for both new and legacy Intel graphics cards.

docs/pages/guide/reference/driver.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@
2020

2121
不在 base 中携带的,需要额外安装的驱动:
2222

23-
- 英伟达闭源驱动,通过 `sudo ll-cli install org.deepin.driver.display.nvidia.570-124-04` 安装。其中 `570-124-04` 是驱动版本号,需要与宿主机安装的驱动版本匹配,通过宿主机 `/sys/module/nvidia/version` 文件查看宿主机驱动的版本。
23+
- 英伟达闭源驱动,推荐通过 `sudo ll-cli install org.deepin.driver.display.nvidia.570-124-04` 安装。其中 `570-124-04` 是驱动版本号,需要与宿主机安装的驱动版本匹配,通过宿主机 `/sys/module/nvidia/version` 文件查看宿主机驱动的版本。未安装扩展时,linyaps 会在运行时尝试从宿主机自动链接 NVIDIA 驱动文件
2424
- 格兰菲显卡驱动,通过 `sudo ll-cli install com.glenfly.driver.display.arise` 安装。
2525
- 英特尔视频编解码驱动(VAAPI),通过 `sudo ll-cli install org.deepin.driver.media.intel` 安装,包含了新/旧 Intel 显卡的支持。

libs/linglong/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,16 @@ pfl_add_library(
2929
src/linglong/cli/dbus_notifier.h
3030
src/linglong/cli/dummy_notifier.cpp
3131
src/linglong/cli/dummy_notifier.h
32+
src/linglong/cli/extension_override.cpp
33+
src/linglong/cli/extension_override.h
3234
src/linglong/cli/interactive_notifier.h
3335
src/linglong/cli/json_printer.cpp
3436
src/linglong/cli/json_printer.h
3537
src/linglong/cli/printer.h
3638
src/linglong/cli/terminal_notifier.cpp
3739
src/linglong/cli/terminal_notifier.h
40+
src/linglong/extension/cdi.cpp
41+
src/linglong/extension/cdi.h
3842
src/linglong/extension/extension.cpp
3943
src/linglong/extension/extension.h
4044
src/linglong/package/architecture.cpp
@@ -94,6 +98,7 @@ pfl_add_library(
9498
src/linglong/runtime/container_builder.h
9599
src/linglong/runtime/container.cpp
96100
src/linglong/runtime/container.h
101+
src/linglong/runtime/host_nvidia_fallback.cpp
97102
src/linglong/runtime/run_context.cpp
98103
src/linglong/runtime/run_context.h
99104
src/linglong/runtime/security_context.cpp

libs/linglong/src/linglong/cli/cli.cpp

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "linglong/api/types/v1/State.hpp"
2626
#include "linglong/api/types/v1/UpgradeListResult.hpp"
2727
#include "linglong/cli/printer.h"
28+
#include "linglong/cli/extension_override.h"
2829
#include "linglong/common/dir.h"
2930
#include "linglong/common/strings.h"
3031
#include "linglong/oci-cfg-generators/container_cfg_builder.h"
@@ -58,7 +59,9 @@
5859
#include <cstdint>
5960
#include <cstdlib>
6061
#include <filesystem>
62+
#include <fstream>
6163
#include <iostream>
64+
#include <map>
6265
#include <optional>
6366
#include <system_error>
6467
#include <thread>
@@ -519,10 +522,21 @@ int Cli::run(const RunOptions &options)
519522
linglong::runtime::ResolveOptions opts;
520523
opts.baseRef = options.base;
521524
opts.runtimeRef = options.runtime;
522-
// 处理多个扩展
523525
if (!options.extensions.empty()) {
524526
opts.extensionRefs = options.extensions;
525527
}
528+
auto configPath = extension_override::getUserConfigPath();
529+
if (configPath) {
530+
auto overrides = extension_override::loadOverrides(*configPath);
531+
if (overrides) {
532+
if (!overrides->empty()) {
533+
runContext.setExtensionOverrides(std::move(*overrides));
534+
}
535+
} else {
536+
qWarning() << "failed to load extension overrides:"
537+
<< overrides.error().message().c_str();
538+
}
539+
}
526540

527541
// 调整日志输出,打印扩展列表(用逗号拼接)
528542
std::string extStr =
@@ -2327,6 +2341,21 @@ int Cli::inspect(CLI::App *app, const InspectOptions &options)
23272341
return 0;
23282342
}
23292343

2344+
int Cli::extension(CLI::App *app, const ExtensionOptions &options)
2345+
{
2346+
LINGLONG_TRACE("command extension");
2347+
2348+
auto argsParseFunc = [&app](const std::string &name) -> bool {
2349+
return app->get_subcommand(name)->parsed();
2350+
};
2351+
2352+
if (argsParseFunc("import-cdi")) {
2353+
return importCdi(options);
2354+
}
2355+
2356+
return 0;
2357+
}
2358+
23302359
int Cli::getLayerDir(const InspectOptions &options)
23312360
{
23322361
LINGLONG_TRACE("Get Layer dir");
@@ -2388,6 +2417,35 @@ int Cli::getBundleDir(const InspectOptions &options)
23882417
return 0;
23892418
}
23902419

2420+
int Cli::importCdi(const ExtensionOptions &options)
2421+
{
2422+
LINGLONG_TRACE("import CDI config");
2423+
2424+
std::filesystem::path configPath;
2425+
if (options.configPath) {
2426+
configPath = *options.configPath;
2427+
} else {
2428+
auto userConfigPath = extension_override::getUserConfigPath();
2429+
if (!userConfigPath) {
2430+
this->printer.printErr(LINGLONG_ERRV("failed to resolve user config path"));
2431+
return -1;
2432+
}
2433+
configPath = *userConfigPath;
2434+
}
2435+
2436+
auto res = extension_override::importCdiOverrides(configPath,
2437+
options.cdiPath,
2438+
options.name,
2439+
!options.applyWhenInstalled);
2440+
if (!res) {
2441+
this->printer.printErr(res.error());
2442+
return -1;
2443+
}
2444+
2445+
this->printer.printMessage("CDI config imported into " + configPath.string());
2446+
return 0;
2447+
}
2448+
23912449
utils::error::Result<void> Cli::initInteraction()
23922450
{
23932451
LINGLONG_TRACE("initInteraction");

libs/linglong/src/linglong/cli/cli.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,14 @@ struct InspectOptions
134134
std::string dirType{ "layer" };
135135
};
136136

137+
struct ExtensionOptions
138+
{
139+
std::optional<std::string> configPath;
140+
std::optional<std::string> cdiPath;
141+
std::string name{ "org.deepin.driver.display.nvidia" };
142+
bool applyWhenInstalled{ false };
143+
};
144+
137145
enum class TaskType : int {
138146
None,
139147
Install,
@@ -186,6 +194,7 @@ class Cli : public QObject
186194
int content(const ContentOptions &options);
187195
int prune();
188196
int inspect(CLI::App *subcommand, const InspectOptions &options);
197+
int extension(CLI::App *subcommand, const ExtensionOptions &options);
189198

190199
void cancelCurrentTask();
191200

@@ -225,6 +234,7 @@ class Cli : public QObject
225234
std::vector<std::string> getRunningAppContainers(const std::string &appid);
226235
int getLayerDir(const InspectOptions &options);
227236
int getBundleDir(const InspectOptions &options);
237+
int importCdi(const ExtensionOptions &options);
228238
utils::error::Result<void> initInteraction();
229239
void detectDrivers();
230240

0 commit comments

Comments
 (0)