DevOps

Ошибка сборки vhci_hcd deb-пакета для Linux 6.1/6.12

Исправление ошибки 'отказано в доступе' при сборке vhci_hcd для ядер Linux 6.1 и 6.12. Правка Makefile, использование DESTDIR, debian/rules и dh_auto_install для корректной упаковки deb-пакета без записи в /usr/include.

Почему сборка пакета vhci_hcd завершается ошибкой при попытке создать deb-пакет для ядра Linux 6.1 и 6.12?

При сборке vhci_hcd для ядер Linux 6.1 и 6.12 возникает следующая ошибка:

make[2]: выход из каталога «/usr/src/linux-headers-6.12.48+deb13-amd64»
mkdir -vp /usr/include/linux && cp -vf usb-vhci.h /usr/include/linux/
'usb-vhci.h' -> '/usr/include/linux/usb-vhci.h'
cp: невозможно создать обычный файл '/usr/include/linux/usb-vhci.h': Отказано в доступе
make[1]: *** [Makefile:41: default] Ошибка 1
make[1]: выход из каталога «/home/nihi1ist/.src/vhci-hcd/1.15.1/usb-vhci-hcd-1.15.1»
dh_auto_build: error: make -j12 "INSTALL=install --strip-program=true" returned exit code 2
make: *** [debian/rules:19: binary] Ошибка 2
dpkg-buildpackage: ошибка: debian/rules binary subprocess returned exit status 2

Что я делаю не так при сборке пакета vhci_hcd?

vhci_hcd сборка ошибка возникает потому, что upstream Makefile при установке пытается скопировать заголовок прямо в системный каталог /usr/include/linux/, из‑за чего в процессе создания deb-пакета команда cp падает с «Отказано в доступе» для ядер Linux 6.1 и 6.12. Правильный путь — не писать в /usr/include во время сборки пакета: использовать staging (например, debian/tmp) через DESTDIR или поправить Makefile/debian/rules (или временно — fakeroot/ручная установка для теста), а не собирать/устанавливать в систему от root.


Содержание


Почему vhci_hcd сборка завершается ошибкой (отказано в доступе)

В логе видно прямо проблемную строку: Makefile выполняет

mkdir -vp /usr/include/linux && cp -vf usb-vhci.h /usr/include/linux/

(см. исходный Makefile проекта). Такая команда пытается записать файл в системный каталог /usr/include, а процесс сборки deb-пакета запускается не с реальными root‑правами и не должен изменять систему. В результате cp падает с «Отказано в доступе» — обычная реакция ОС на попытку записи в защищённый каталог. Подчёркиваю: даже если вы используете fakeroot, это не даёт права на создание реальных файлов в /usr/include — fakeroot лишь фальсифицирует метаданные при упаковке, но не снимает ограничений файловой системы. См. пример в Makefile: https://raw.githubusercontent.com/linuxbuh/vhci_hcd/main/Makefile.

Почему это плохо для Debian-пакета? Debian-процесс сборки ожидает, что файлы будут установлены в staging-папку (обычно debian/tmp), а затем инструменты dh_* перенесут их в пакет; прямые записи в /usr во время сборки нарушают политику и ломают dh_auto_install/dpkg-buildpackage. Подробно про поведение dh_install и staging смотрите в документации Debian: https://manpages.debian.org/testing/debhelper/dh_install.1.en.html и https://www.debian.org/doc/manuals/maint-guide/dother.en.html.


Правильный способ упаковки Debian: debian/tmp, DESTDIR и dh_install

Идея простая: не писать в системные каталоги при сборке. Вместо этого — установить файлы в staging (например, debian/tmp) и позволить dh_install/debhelper положить их в пакет. Общая практика:

  • upstream Makefile должен поддерживать DESTDIR (и/или PREFIX), чтобы установка шла в $(DESTDIR)$(PREFIX)/...;
  • при сборке в debian/rules запускают make install DESTDIR=$(CURDIR)/debian/tmp (или dh_auto_install -- DESTDIR=$(CURDIR)/debian/tmp), после чего dh_install копирует из debian/tmp.

Пример запуска вручную (что делает dh_auto_install автоматически):

make install DESTDIR=$(pwd)/debian/tmp

Документация debhelper: https://manpages.debian.org/testing/debhelper/dh_install.1.en.html.

Если upstream Makefile уже поддерживает DESTDIR — всё просто. Если нет — нужно править Makefile или в debian/rules вручную скопировать нужные файлы в debian/tmp.


Исправление Makefile: примеры патча и шаблоны INSTALL/DESTDIR

Если Makefile содержит жёстко прописанный путь /usr/include/linux, замените установку на использование DESTDIR и стандартных переменных. Пример «правильной» установки:

Было (проблемный кусок):

make
mkdir -vp /usr/include/linux && cp -vf usb-vhci.h /usr/include/linux/

Станет (рекомендуется):

make
INSTALL ?= install -Dm644
PREFIX ?= /usr
DESTDIR ?=

install:
	$(INSTALL) usb-vhci.h "$(DESTDIR)$(PREFIX)/include/linux/usb-vhci.h"

Такая правка разрешает сборщику употреблять DESTDIR=$(CURDIR)/debian/tmp и избежать записи в систему. Если вы не можете править upstream напрямую, создайте патч в debian/patches (quilt) и применяйте его при сборке пакета.

Заметьте: использование install -D сохраняет права и создает промежуточные директории корректно. Простые cp/mkdir с абсолютными путями — плохая практика для пакетов.


debian/rules и dh_auto_install: переопределение и примеры

Частый и удобный способ — добавить в debian/rules переопределение dh_auto_install, чтобы передать DESTDIR:

Пример минимального debian/rules (debhelper/dh):

make
#!/usr/bin/make -f
%:
	dh $@

override_dh_auto_install:
	dh_auto_install -- DESTDIR=$(CURDIR)/debian/tmp

Запуск dh_auto_install с дополнительными аргументами передаст их make’у (если Makefile поддерживает DESTDIR). После этого dh_install найдёт файлы в debian/tmp и упакует их в .deb. Подробности: https://manpages.debian.org/testing/debhelper/dh_install.1.en.html и обсуждение типичных проблем в сообществе: https://unix.stackexchange.com/questions/84162/building-debian-package-fails-at-dh-auto-install-stage.

Если Makefile полностью игнорирует DESTDIR, в override_dh_auto_install можно вручную создать нужные каталоги и скопировать файлы в debian/tmp через install -Dm644 ....


Особенности сборки для linux 6.1 и linux 6.12

Отдельно: помимо проблемы с путями, код модуля может требовать небольшого обновления для новых версий ядра. В репозитории уже упоминались совместимые правки (например, замена show_debug_output на debug_output_show, добавление нужных include), см. обсуждение: https://github.com/linuxbuh/vhci_hcd/issues/1. Также убедитесь, что установлены заголовки для нужного ядра (linux-headers-6.12...) и что вы собираете модуль против корректного каталога сборки — часто используют:

make KVERSION="$(uname -r)" KSRC=/lib/modules/$(uname -r)/build

или по инструкции из README: https://github.com/linuxbuh/vhci_hcd/blob/main/README.md и примеры в сторонних форках: https://github.com/augin/vhci_hcd. Если модуль не компилируется под 6.12 — возможно, нужны патчи к исходникам (API-измения).


Пошаговое решение: команды и проверка

  1. Проверьте Makefile на жёсткие /usr/include упоминания:
  • grep -n "/usr/include" Makefile
  1. Если есть — исправьте Makefile на использование DESTDIR/PREFIX или добавьте секцию install с install -Dm644 ....
  2. Если не хотите менять upstream прямо сейчас — в debian/rules переопределите dh_auto_install и вручную скопируйте файлы в debian/tmp:
mkdir -p debian/tmp/usr/include/linux
install -Dm644 usb-vhci.h debian/tmp/usr/include/linux/usb-vhci.h
  1. Соберите пакет обычной командой (без sudo):
  • dpkg-buildpackage -us -uc или debuild -us -uc
  1. Проверьте содержимое staging и итогового пакета:
  • ls debian/tmp/usr/include/linux/usb-vhci.h
  • dpkg -c ../vhci_hcd_*.deb | grep usb-vhci.h

Если сборка всё ещё требует прав доступа — это признак того, что где-то остались абсолютные записи в Makefile или что вы пытались выполнять install вне staging.


Отладка и проверка: как убедиться, что всё ок

  • Внимательно следите за выводом dh_auto_install в логе сборки: он должен показывать установку в debian/tmp, а не в /usr.
  • После успешной сборки проверьте .deb через dpkg -c — нужный заголовок и файлы должны быть внутри пакета, а не в вашей системе.
  • Для тестовой загрузки модуля используйте ручную установку модулей (только для проверки): sudo insmod drivers/usb/usbip/usbip-core.ko && sudo insmod drivers/usb/usbip/vhci-hcd.ko (см. инструкции установки модулей: https://askubuntu.com/questions/1303403/how-to-install-usbip-vhci-hcd-drivers-on-an-aws-ec2-ubuntu-kernel-version). Но не используйте sudo make install для формирования пакета — это обходной путь, а не решение.

Если после всех правок остаются ошибки, сверяйтесь с issue-трекером проекта и логами компиляции — возможно, требуется адаптация к API ядра 6.12 (см. обсуждения в репозитории).


Источники


Заключение

Вы ничего магического не делаете — дело в Makefile и в политике сборки Debian: пакет пытается писать в /usr/include/linux/, а при создании deb-пакета так делать нельзя. Решение — заставить установку писать в staging (debian/tmp) через DESTDIR/PREFIX или исправить Makefile/debian/rules (переопределение dh_auto_install), проверить совместимость с ядрами linux 6.1/6.12 и, при необходимости, внести небольшие патчи в код модуля. После этого vhci_hcd сборка и упаковка в deb-пакет пройдут корректно.

Авторы
Проверено модерацией
Модерация