Next: , Previous: , Up: Программный интерфейс   [Contents][Index]


8.6 Фазы сборки

Почти все системы сборки пакетов реализуют понятие фазы сборки: последовательность действий, которые система сборки выполняет при сборке пакета, что приводит к установке побочных продуктов в store. Заметным исключением является “bare-bones” trivial-build-system (see Системы сборки).

As discussed in the previous section, those build systems provide a standard list of phases. For gnu-build-system, the main build phases are the following:

set-paths

Define search path environment variables for all the input packages, including PATH (see Search Paths).

unpack

Распаковать архив исходных текстов и измените текущий каталог на извлеченное дерево исходных текстов. Если источник на самом деле является каталогом, скопировать его в дерево сборки и войдите в этот каталог.

patch-source-shebangs

Изменить shebang, встречающиеся в исходных файлах, чтобы они ссылались на правильные имена файлов хранилища. Например, это изменяет #!/bin/sh на #!/gnu/store/…-bash-4.3/bin/sh.

configure

Запустить сценарий configure с несколькими параметрами по умолчанию, такими как --prefix=/gnu/store/…, а также параметрами, указанными в #:configure-flags аргументе.

build

Запустить make со списком флагов, указанным с помощью #:make-flags. Если аргумент #:parallel-build? истинен (по умолчанию), выполнить сборку с make -j.

check

Запустить make check или другой target, указанный с помощью #:test-target, если только #:tests? #f пройден. Если аргумент #:parallel-tests? истинен (по умолчанию), запустить make check -j.

install

Запустить make install с флагами, перечисленными в #:make-flags.

patch-shebangs

Изменить shebangs на установленные исполняемые файлы.

strip

Удалить символы отладки из файлов ELF (если #:strip-binaries? не является ложным), скопировав их в выходные данные debug, если они доступны (see Установка файлов отладки).

validate-runpath

Validate the RUNPATH of ELF binaries, unless #:validate-runpath? is false (see Системы сборки).

This validation step consists in making sure that all the shared libraries needed by an ELF binary, which are listed as DT_NEEDED entries in its PT_DYNAMIC segment, appear in the DT_RUNPATH entry of that binary. In other words, it ensures that running or using those binaries will not result in a “file not found” error at run time. See -rpath in The GNU Linker, for more information on RUNPATH.

Как обсуждалось в предыдущем разделе, эти системы сборки предоставляют стандартный список фаз. Для gnu-build-system стандартные фазы включают фазу unpack для распаковки архива исходного кода, фазу configure для запуска ./configure, build фаза для запуска make и (среди прочего) фазу install для запуска make install; see Системы сборки, чтобы получить более подробное представление об этих фазах. Точно так же cmake-build-system наследует эти фазы, но его фаза configure запускает cmake вместо ./configure. Другие системы сборки, такие как python-build-system, имеют совершенно другой список стандартных фаз. Весь этот код выполняется на build side: он выполняется, когда вы фактически собираете пакет, в отдельном процессе сборки, порожденном демоном сборки (see Вызов guix-daemon).

Этапы сборки представлены в виде ассоциативных списков или “alists” (see Association Lists in GNU Guile Reference Manual), где каждый ключ является символом имени фазы, а соответствующее значение - процедурой, которая принимает произвольное количество аргументов. По соглашению эти процедуры получают информацию о сборке в виде ключевых параметров, которые они могут использовать или игнорировать.

Например, вот как (guix build gnu-build-system) определяет %standard-phase, переменную, содержащую список фаз сборки 21:

;; The build phases of 'gnu-build-system'.

(define* (unpack #:key source #:allow-other-keys)
  ;; Extract the source tarball.
  (invoke "tar" "xvf" source))

(define* (configure #:key outputs #:allow-other-keys)
  ;; Run the 'configure' script.  Install to output "out".
  (let ((out (assoc-ref outputs "out")))
    (invoke "./configure"
            (string-append "--prefix=" out))))

(define* (build #:allow-other-keys)
  ;; Compile.
  (invoke "make"))

(define* (check #:key (test-target "check") (tests? #true)
                #:allow-other-keys)
  ;; Run the test suite.
  (if tests?
      (invoke "make" test-target)
      (display "test suite not run\n")))

(define* (install #:allow-other-keys)
  ;; Install files to the prefix 'configure' specified.
  (invoke "make" "install"))

(define %standard-phases
  ;; The list of standard phases (quite a few are omitted
  ;; for brevity).  Each element is a symbol/procedure pair.
  (list (cons 'unpack unpack)
        (cons 'configure configure)
        (cons 'build build)
        (cons 'check check)
        (cons 'install install)))

Это показывает, как %standard-phase определяется как список пар символ/процедура (see Pairs in GNU Guile Reference Manual). Первая пара связывает процедуру unpack с символом unpack—именем; вторая пара аналогичным образом определяет фазу configure и так далее. При сборке пакета, который использует gnu-build-system со списком фаз по умолчанию, эти фазы выполняются последовательно. Вы можете увидеть название каждой фазы, запущенной и завершенной, в журнале сборки пакетов, которые вы собираете.

Теперь посмотрим на сами процедуры. Каждая из них определяется с помощью define*: #:key перечисляет параметры ключевого слова, которые принимает процедура, возможно, со значением по умолчанию, а #:allow-other-keys указывает, что другие параметры ключевого слова являются игнорируется (see Optional Arguments in GNU Guile Reference Manual).

Процедура unpack учитывает параметр source, который система сборки использует для передачи имени файла исходного архива (или checkout контроля версий), и игнорирует другие параметры. Фаза configure касается только параметра output, списка имен выходных пакетов, отображающих имена файлов хранилища (see Пакеты со множественным выходом). Она извлекает имя файла для out, вывода по умолчанию, и передает его ./configure в качестве префикса установки, что означает, что make install в конечном итоге скопирует все файлы в этом каталоге (see configuration and makefile conventions in GNU Coding Standards). build и install игнорируют все свои аргументы. check учитывает аргумент test-target, который указывает имя цели Makefile для запуска тестов; она печатает сообщение и пропускает тесты, если tests? ложно.

Список фаз, используемых для конкретного пакета, можно изменить с помощью параметра #:phase системы сборки. Изменение набора фаз сборки сводится к созданию нового списка фаз на основе списка %standard-phase, описанного выше. Это можно сделать с помощью стандартных процедур списков, таких как alist-delete (see SRFI-1 Association Lists in GNU Guile Reference Manual); однако это удобнее делать с помощью modify-phase (see modify-phases).

Вот пример определения пакета, который удаляет фазу configure из %standard-phase и вставляет новую фазу перед фазой build, которая называется set-prefix-in- makefile:

(define-public example
  (package
    (name "example")
    ;; other fields omitted
    (build-system gnu-build-system)
    (arguments
     (list
      #:phases
      #~(modify-phases %standard-phases
          (delete 'configure)
          (add-before 'build 'set-prefix-in-makefile
            (lambda* (#:key inputs #:allow-other-keys)
              ;; Modify the makefile so that its
              ;; 'PREFIX' variable points to #$output and
              ;; 'XMLLINT' points to the correct path.
              (substitute* "Makefile"
                (("PREFIX =.*")
                 (string-append "PREFIX = " #$output "\n"))
                (("XMLLINT =.*")
                 (string-append "XMLLINT = "
                                (search-input-file inputs "/bin/xmllint")
                                "\n"))))))))))

The new phase that is inserted is written as an anonymous procedure, introduced with lambda*; it looks for the xmllint executable under a /bin directory among the package’s inputs (see package Ссылка). It also honors the outputs parameter we have seen before. See Build Utilities, for more about the helpers used by this phase, and for more examples of modify-phases.

Tip: You can inspect the code associated with a package’s #:phases argument interactively, at the REPL (see Using Guix Interactively).

Keep in mind that build phases are code evaluated at the time the package is actually built. This explains why the whole modify-phases expression above is quoted (it comes after the #~ or hash-tilde): it is staged for later execution. See G-Expressions, for an explanation of code staging and the code strata involved.


Footnotes

(21)

Мы представляем упрощенное представление этих фаз сборки, но обязательно взгляните на (guix build gnu-build-system), чтобы увидеть все подробности!


Next: Build Utilities, Previous: Системы сборки, Up: Программный интерфейс   [Contents][Index]