Инфраструктура сборки расширений

Если вы обдумываете распространение ваших модулей расширения QHB, то учтите, что подготовить для них переносимую систему сборки может быть довольно сложно. Поэтому установка QHB включает в себя инфраструктуру сборки расширений, называемую PGXS, поэтому простые модули расширений можно собрать просто на уже установленном сервере. PGXS в основном предназначен для расширений, которые включают в себя код на C/RUST, хотя ее также можно использовать и для расширений на чистом SQL. Обратите внимание, что PGXS не претендует на то, чтобы быть универсальной инфраструктурой системы сборки, которую можно применять для создания любого программного средства, взаимодействующего с QHB; она всего лишь автоматизирует общие правила сборки для простых модулей расширения сервера. Для более сложных пакетов вам, по всей видимости, придется написать собственную систему сборки.

Чтобы использовать инфраструктуру PGXS для вашего расширения, следует написать простой сборочный файл. В нем нужно установить некоторые переменные и включить глобальный сборочный файл PGXS. Вот пример, который создает модуль расширения с именем isbn_issn, состоящий из разделяемой библиотеки, содержащей некоторый код на C, управляющего файла расширения, скрипта SQL, включаемого файла (он требуется только в том случае, если у других модулей возникнет необходимость получить доступ к функциям расширения напрямую, без использования SQL) и текстового файла документации:

MODULES = isbn_issn
EXTENSION = isbn_issn
DATA = isbn_issn--1.0.sql
DOCS = README.isbn_issn
HEADERS_isbn_issn = isbn_issn.h

PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)

Последние три строки всегда должны быть неизменными. Ранее в файле вы присваиваете значения переменным или добавляете собственные правила создания.

Установите одну из этих трех переменных, чтобы указать, что будет собрано:

MODULES
список объектов разделяемой библиотеки, которые должны быть собраны из исходных файлов с одинаковым основанием (не включайте в этот список суффиксы библиотеки)

MODULE_big
разделяемая библиотека, которая должна быть собрана из нескольких исходных файлов (перечислите объектные файлы в OBJS)

PROGRAM
исполняемая программа, которая должна быть собрана (перечислите объектные файлы в OBJS)

Также можно установить следующие переменные:

EXTENSION
имена расширений; для каждого имени нужно предоставить файл расширение.control, который будет установлен в префикс/share/extension

MODULEDIR
подкаталог в каталоге префикс/share в который должны быть установлены файлы DATA и DOCS (если не задан, по умолчанию используется extension, если установлена переменная EXTENSION, или contrib, если нет)

DATA
произвольные файлы для установки в префикс/share/$MODULEDIR

DATA_built
произвольные файлы для установки в префикс/share/$MODULEDIR, которые сначала нужно собрать

DATA_TSEARCH
произвольные файлы для установки в префикс/share/tsearch_data

DOCS
произвольные файлы для установки в префикс/doc/$MODULEDIR

HEADERS
HEADERS_built
Файлы для установки (и, возможно, сборки) в префикс/include/server/$MODULEDIR/$MODULE_big.
В отличие от файлов DATA_built, файлы в HEADERS_built не удаляются целью clean; если хотите их удалить, добавьте их в EXTRA_CLEAN или напишите собственные правила для этого.

HEADERS_$MODULE
HEADERS_built_$MODULE
Файлы для установки (после сборки, если указано) в префикс/include/server/$MODULEDIR/$MODULE, где $MODULE должно быть именем модуля, используемым в MODULES или MODULE_big.
В отличие от файлов DATA_built, файлы в HEADERS_built_$MODULE не удаляются целью clean; если вы хотите их удалить, добавьте их в EXTRA_CLEAN или напишите собственные правила для этого.
Допускается использовать для одного модуля обе переменные или любую их комбинацию, если только в списке MODULES нет двух имен модулей, которые отличаются только наличием префикса built_, что может привести к неоднозначности. В этом (будем надеяться, маловероятном) случае следует использовать только переменные HEADERS_built_$MODULE.

SCRIPTS
скрипт-файлы (не двоичные файлы) для установки в префикс/bin

SCRIPTS_built
скрипт-файлы (не двоичные файлы) для установки в префикс/bin, которые сначала нужно собрать

REGRESS
список регрессионных тестов (без суффикса), см. ниже

REGRESS_OPTS
дополнительные параметры для передачи pg_regress

ISOLATION
список изоляционных тестов, более подробную информацию см. ниже

ISOLATION_OPTS
дополнительные параметры для передачи pg_isolation_regress

TAP_TESTS
флаг, определяющий, нужно ли запускать тесты TAP; см. ниже

NO_INSTALL
не определять цель install; полезна для модулей тестирования, для которых не требуется установка результатов сборки

NO_INSTALLCHECK
не определять цель installcheck; полезна, например, если тестам требуется специальная конфигурация или не используется pg_regress

EXTRA_CLEAN
дополнительные файлы для удаления при make clean

PG_CPPFLAGS
флаги, которые будут добавлены перед другими в CPPFLAGS

PG_CFLAGS
флаги, которые будут добавлены после других в CFLAGS

PG_CXXFLAGS
флаги, которые будут добавлены после других в CXXFLAGS

PG_LDFLAGS
флаги, которые будут добавлены перед другими в LDFLAGS

PG_LIBS
будет добавлена в строку компоновки PROGRAM

SHLIB_LINK
будет добавлена в строку компоновки MODULE_big

PG_CONFIG
путь к программе pg_config в установке QHB, с которой будет проведена сборка (обычно указывается просто pg_config, и используется первая же такая программа в вашем пути PATH)

Поместите этот сборочный файл под именем Makefile в каталог, содержащий ваше расширение. Затем можно выполнить make для компиляции, а потом make install для установки вашего модуля. По умолчанию расширение компилируется и устанавливается для той установки QHB, которая соответствует первой программе pg_config, найденной при поиске по пути в вашем PATH. Можно воспользоваться и другой установкой, настроив PG_CONFIG так, чтобы тот указывал на ее программу pg_config, либо в сборочном файле, либо в командной строке make.

Кроме того, если вы хотите сохранить каталог сборки отдельно, можно запустить make в каталоге за пределами исходного дерева вашего расширения. Эта процедура также называется сборкой с VPATH. Выполняется она так:

mkdir build_dir
cd build_dir
make -f /path/to/extension/source/tree/Makefile
make -f /path/to/extension/source/tree/Makefile install

Как вариант, можно подготовить каталог для сборки с VPATH аналогично тому, как это делается для кода ядра. Один из способов сделать это — использовать скрипт ядра config/prep_buildtree. После этого можно выполнить сборку, установив переменную VPATH для make следующим образом:

make VPATH=/path/to/extension/source/tree
make VPATH=/path/to/extension/source/tree install

Эта процедура может работать с самыми разнообразными расположениями каталогов.

Скрипты, перечисленные в переменной REGRESS, используются для регрессионного тестирования вашего модуля, и вызвать их можно командой make installcheck после выполнения команды make install. Чтобы запустить тестирование, необходим работающий сервер QHB. Скрипт-файлы, перечисленные в REGRESS, должны находиться в подкаталоге с именем sql/ в каталоге вашего расширения. Эти файлы должны иметь расширение .sql, которое нельзя включать в список REGRESS в сборочном файле. Для каждого теста также должен создаваться файл с ожидаемым выводом в подкаталоге expected/, с тем же основанием и расширением .out. Команда make installcheck выполняет каждый тестовый скрипт с помощью psql и сравнивает полученный вывод с соответствующим ожидаемым файлом. Все обнаруженные различия будут записаны в файл regression.diffs в формате diff -c. Обратите внимание, что при попытке запустить тест, в котором отсутствует ожидаемый файл, этот тест будет отображаться как «проблемный», поэтому убедитесь, что у вас есть все ожидаемые файлы.

Скрипты, перечисленные в переменной ISOLATION, используются для нагрузочного тестирования работы модуля при проведении параллельного сеанса, и вызвать их можно командой make installcheck после выполнения команды make install. Чтобы запустить тестирование, необходим работающий сервер QHB. Скрипт-файлы, перечисленные в ISOLATION, должны находиться в подкаталоге specs/ в каталоге вашего расширения. Эти файлы должны иметь расширение .spec, которое нельзя включать в список ISOLATION в сборочном файле. Для каждого теста также должен быть файл с ожидаемым выводом в подкаталоге expected/, с тем же основанием и расширением .out. Команда make installcheck выполняет каждый тестовый скрипт и сравнивает полученный вывод с соответствующим ожидаемым файлом. Все обнаруженные различия будут записаны в файл output_iso/regression.diffs в формате diff -c. Обратите внимание, что при попытке запустить тест, в котором отсутствует ожидаемый файл, этот тест будет отображаться как «проблемный», поэтому убедитесь, что у вас есть все ожидаемые файлы.

Совет
Самый простой способ создать ожидаемые файлы — создать пустые файлы, а затем выполнить тестовый прогон (который, конечно, выявит различиях). Проверьте фактические файлы результатов, сохраненные в каталоге results/ (для тестов REGRESS) или каталоге output_iso/results/ (для тестов ISOLATION), а затем, если они соответствуют вашим ожиданиям от теста, скопируйте их в expected/.