Capítulo 8. Prácticas Avançadas de pkg-plist

8.1. Alterando o pkg-plist Baseado em Variáveis Make

Alguns ports, particularmente os p5- ports, precisam mudar seus pkg-plist dependendo de quais opções eles são configurados com (ou versão de perl, no caso de p5- ports). Para tornar isso fácil, todas as instâncias pkg-plist de %%OSREL%%, %%PERL_VER%% e %%PERL_VERSION%% serão substituídas apropriadamente. O valor de %%OSREL%% é a revisão numérica do sistema operacional (por exemplo,4.9). %%PERL_VERSION%% e %%PERL_VER%% é o número completo da versão perl (por exemplo,5.8.9). Muitos outros %%VARS%% relacionados aos arquivos de documentação do port são descritos na seção relevante.

Para fazer outras substituições, defina PLIST_SUB com uma lista de pares VAR=VALOR e as instâncias de %%VAR%% serão substituídas por VALOR no pkg-plist.

Por exemplo, se um port instalar muitos arquivos em um subdiretório específico da versão, use um placeholder para a versão de modo que o pkg-plist não precise ser gerado novamente toda vez que o port é atualizado. Por exemplo:

OCTAVE_VERSION=	${PORTREVISION}
PLIST_SUB=	OCTAVE_VERSION=${OCTAVE_VERSION}

no Makefile e use %%OCTAVE_VERSION%% onde quer que a versão apareça em pkg-plist. Quando o port é atualizado, não será necessário editar dezenas (ou em alguns casos, centenas) de linhas no pkg-plist.

Se os arquivos são instalados condicionalmente pelas opções definidas no port, a maneira usual de lidar com isso é prefixando as linhas pkg-plist com %%OPT%% para linhas necessárias quando a opção está ativada ou %%NO_OPT%% quando a opção está desativada e adicionando OPTIONS_SUB=yes ao Makefile. Veja OPTIONS_SUB para mais informações.

Por exemplo, se houver arquivos que são instalados apenas quando a opção X11 está ativada, e o Makefile tem:

OPTIONS_DEFINE=	X11
OPTIONS_SUB=	yes

No pkg-plist, insira %%X11%% no início das linhas que serão instaladas apenas quando a opção estiver habilitada, assim:

%%X11%%bin/foo-gui

Esta substituição será feita entre os targets pre-install e do-install, lendo a partir do PLIST e escrevendo em TMPPLIST (padrão:WRKDIR/.PLIST.mktmp). Então, se o port gera o PLIST na hora da compilação, faça isso em ou antes do pre-install. Além disso, se o port precisar editar o arquivo resultante, faça-o em post-install em um arquivo chamado TMPPLIST.

Outra maneira de modificar a lista de empacotamento de um port é baseada na configuração das variáveis PLIST_FILES e PLIST_DIRS. O valor de cada variável é considerado como uma lista de nomes de caminho para gravar no TMPPLIST junto com conteúdo do PLIST. Enquanto os nomes listados no PLIST_FILES e PLIST_DIRS estão sujeitos a substituição do %%VAR%% conforme descrito acima, é melhor usar o ${VAR} diretamente. Exceto por isso, os nomes contidos no PLIST_FILES aparecerão inalterados na lista final de packing, enquanto o @dir será anexado aos nomes do PLIST_DIRS. Para fazer efeito, o PLIST_FILES e o PLIST_DIRS devem ser definidos antes que o TMPPLIST seja escrito, isto é, no pre-install ou antes.

De vez em quando, usar OPTIONS_SUB não é o suficiente. Nesses casos, adicionar uma TAG para PLIST_SUB dentro do Makefile com um valor especial @comment, faz as ferramentas de pacote ignorar a linha. Por exemplo, se alguns arquivos são instalados apenas quando a opção X11 está habilitada e a arquitetura é i386:

.include <bsd.port.pre.mk>

.if ${PORT_OPTIONS:MX11} && ${ARCH} == "i386"
PLIST_SUB+=	X11I386=""
.else
PLIST_SUB+=	X11I386="@comment "
.endif

8.2. Diretórios Vazios

8.2.1. Limpando Diretórios Vazios

Ao ser desinstalado, um port deve remover os diretórios vazios que ele criou. A maioria desses diretórios são removidos automaticamente pelo pkg(8), mas para os diretórios criados fora do ${PREFIX}, ou diretórios vazios, mais alguns passos precisam ser feitos. Isso geralmente é realizando adicionando entradas @dir para esses diretórios.Os subdiretórios devem ser excluídos antes de excluir os diretórios pai.

[...]
@dir /var/games/oneko/saved-games
@dir /var/games/oneko

8.2.2. Criando Diretórios Vazios

Os diretórios vazios criados durante a instalação do port precisam de atenção especial. Eles devem estar presentes quando o pacote é criado. Se eles não forem criados pelo código do port, crie-os no Makefile:

post-install:
	${MKDIR} ${STAGEDIR}${PREFIX}/some/directory

Adicione o diretório ao pkg-plist como qualquer outro. Por exemplo:

@dir some/directory

8.3. Arquivos de Configuração

Se o port instalar arquivos de configuração em PREFIX/etc (ou em outro lugar) não liste-os em pkg-plist. Isso fará com que pkg delete remova os arquivos que foram cuidadosamente editados pelo usuário, e uma reinstalação irá eliminá-los.

Em vez disso, instale arquivos de exemplo com uma extensão filename.sample. A macro @sample automatiza isso, consulte @sample file[file] para entender o que ela faz exatamente. Para cada arquivo de exemplo, adicione uma entrada no pkg-plist:

@sample etc/orbit.conf.sample

Se houver uma boa razão para não instalar um arquivo de configuração por padrão, liste apenas o nome do arquivo de exemplo em pkg-plist, sem o @sample seguido por um espaço e adicione uma mensagem ressaltando que o usuário deve copiar e editar o arquivo antes que o software seja executado.

Quando um port instala sua configuração em um subdiretório de ${PREFIX}/etc, usar ETCDIR, cujo padrão é ${PREFIX}/etc/${PORTNAME}, pode ser substituído nos Makefile dos ports se houver uma convenção para o port usar algum outro diretório. A macro %%ETCDIR%% será usado em seu lugar em pkg-plist.

Os arquivos de configuração de exemplo devem sempre ter o sufixo .sample. Se, por algum motivo histórico, o uso do sufixo padrão não for possível ou se os arquivos de exemplo vierem de algum outro diretório, use esta construção:

@sample etc/orbit.conf-dist etc/orbit.conf

ou

@sample %%EXAMPLESDIR%%/orbit.conf etc/orbit.conf

O formato é @sample sample-file actual-config-file.

8.4. Lista de Pacotes Estática versus Dinâmica

Uma lista de pacotes estáticos é uma lista de pacotes que está disponível na Coleção de Ports ou como pkg-plist (com ou sem substituição de variável), ou embutido no Makefile através do PLIST_FILES e do PLIST_DIRS. Mesmo se o conteúdo for gerado automaticamente por uma ferramenta ou um taget no Makefile antes da inclusão na Coleção de Ports por um committer (por exemplo, usando make makeplist), isso ainda é considerado uma lista estática, já que é possível examiná-la sem ter que baixar ou compilar o distfile.

Uma lista de pacotes dinâmicos é uma lista de pacotes que é gerada no momento em que o port é compilado com base nos arquivos e diretórios que estão instalados. Não é possível examiná-lo antes que o código-fonte do aplicativo portado seja baixado e compilado, ou após executar um make clean.

Embora o uso de listas de pacotes dinâmicos não seja proibido, os mantenedores devem usar listas de pacotes estáticos sempre que possível, já que isso permite aos usuários utilizar grep(1) nos de ports disponíveis para descobrir, por exemplo, qual port instala um determinado arquivo. Listas dinâmicas devem ser usadas principalmente para ports complexos onde a lista de pacotes muda drasticamente com base nos recursos opcionais do port (e assim manter uma lista de pacotes estática é impraticável), ou ports que alteram a lista de pacotes com base na versão do software dependente usado. Por exemplo, ports que geram documentos com Javadoc.

8.5. Criação Automatizada da Lista de Pacotes

Primeiro, verifique se o port está quase completo, faltando apenas o pkg-plist. Executar o comando make makeplist irá mostrar um exemplo para o pkg-plist. A saída do makeplist deve ser checada duas vezes quanto à correção, pois ela tenta adivinhar automaticamente algumas coisas e pode errar.

Os arquivos de configuração do usuário devem ser instalados como filename.sample, como é descrito em Arquivos de Configuração. O info/dir não deve ser listado e entradas apropriadas install-info devem ser adicionadas conforme a seção arquivos de informação. Quaisquer bibliotecas instaladas pelo port devem ser listadas conforme especificado na seção bibliotecas compartilhadas.

8.5.1. Expansão do PLIST_SUB com Expressões Regulares

As strings a serem substituídas às vezes precisam ser muito específicas para evitar substituições indesejadas. Esse é um problema comum com valores mais curtos.

Para resolver este problema, para cada PLACEHOLDER=value, um PLACEHOLDER_regex =regex pode ser definido, com o regex do value correspondendo mais precisamente.

Exemplo 1. Usando PLIST_SUB com Expressões Regulares

Os ports Perl podem instalar arquivos dependentes da arquitetura em uma árvore específica. No FreeBSD para facilitar a portabilidade, esta árvore é chamada de mach. Por exemplo, um port que instala um arquivo cujo caminho contém mach poderia ter essa parte da sequência do caminho substituída pelos valores incorretos. Considere este Makefile:

PORTNAME=	Machine-Build
DISTVERSION=	1
CATEGORIES=	devel perl5
MASTER_SITES=	CPAN
PKGNAMEPREFIX=	p5-

MAINTAINER=	perl@FreeBSD.org
COMMENT=	Building machine

USES=		perl5
USE_PERL5=	configure

PLIST_SUB=	PERL_ARCH=mach

Os arquivos instalados pelo port são:

/usr/local/bin/machine-build
/usr/local/lib/perl5/site_perl/man/man1/machine-build.1.gz
/usr/local/lib/perl5/site_perl/man/man3/Machine::Build.3.gz
/usr/local/lib/perl5/site_perl/Machine/Build.pm
/usr/local/lib/perl5/site_perl/mach/5.20/Machine/Build/Build.so

Executar o make makeplist gera incorretamente:

bin/%%PERL_ARCH%%ine-build
%%PERL5_MAN1%%/%%PERL_ARCH%%ine-build.1.gz
%%PERL5_MAN3%%/Machine::Build.3.gz
%%SITE_PERL%%/Machine/Build.pm
%%SITE_PERL%%/%%PERL_ARCH%%/%%PERL_VER%%/Machine/Build/Build.so

Altere a linha PLIST_SUB do Makefile para:

PLIST_SUB=	PERL_ARCH=mach \
		PERL_ARCH_regex=\bmach\b

Agora o make makeplist gera corretamente:

bin/machine-build
%%PERL5_MAN1%%/machine-build.1.gz
%%PERL5_MAN3%%/Machine::Build.3.gz
%%SITE_PERL%%/Machine/Build.pm
%%SITE_PERL%%/%%PERL_ARCH%%/%%PERL_VER%%/Machine/Build/Build.so

8.6. Expandindo a Lista de Pacotes com Keywords

Todas as keywords também podem ter argumentos opcionais entre parênteses. Os argumentos são owner, group e mode. Esse argumento é usado no arquivo ou diretório referenciado. Para alterar o dono, o grupo e o modo de um arquivo de configuração, use:

@sample(games,games,640) etc/config.sample

Os argumentos são opcionais. Se apenas o grupo e o modo precisarem ser alterados, use:

@sample(,games,660) etc/config.sample

Se uma keyword for utilizada em uma entrada de opção, ela precisa ser adicionada após o assistente:

%%FOO%%@sample etc/orbit.conf.sample

Isso é porque os assistentes plist das opções são utilizados para comentar as linhas, e por isso eles precisam ser inseridos no início. Veja OPTIONS_SUB para maiores informações.

8.6.1. @desktop-file-utils

Irá executar o update-desktop-database -q após a instalação e desinstalação. Nunca use diretamente, adicione USES=desktop-file-utils ao Makefile.

8.6.2. @fc directory

Adiciona uma entrada @dir para o diretório passado como um argumento, e executa fc-cache -fs nesse diretório após a instalação e desinstalação.

8.6.3. @fcfontsdir directory

Adiciona uma entrada @dir para o diretório passado como um argumento, e executa fc-cache -fs, mkfontscale e mkfontdir nesse diretório após a instalação e desinstalação. Além disso, na desinstalação, ele remove os arquivos de cache fonts.scale e fonts.dir, se estiverem vazios. Esta keyword é equivalente a adicionar o diretório @fc e o diretório @fontsdir.

8.6.4. @fontsdir directory

Adiciona um entrada @dir para o diretório passado como um argumento, e executa mkfontscale e mkfontdir nesse diretório após a instalação e desinstalação. Além disso, na desinstalação, ele remove os arquivos de cache fonts.scale e fonts.dir, se estiverem vazios.

8.6.5. @glib-schemas

Executa glib-compile-schemas na instalação e desinstalação.

8.6.6. @info file

Adiciona o arquivo passado como argumento ao plist e atualiza o índice do documento info na instalação e desinstalação. Além disso, ele remove o índice se estiver vazio na desinstalação. Isso nunca deve ser usado manualmente, mas sempre INFO. Veja Arquivos de Informação para maiores informações.

8.6.7. @kld directory

Executa o kldxref no diretório na instalação e desinstalação. Além disso, na desinstalação, ele removerá o diretório se estiver vazio.

8.6.8. @rmtry file

O arquivo será removido na desinstalação, e não dará um erro se o arquivo não estiver lá.

8.6.9. @sample file[file]

Isso é usado para lidar com a instalação de arquivos de configuração, através de arquivos de exemplo empacotados com o pacote. O arquivo "atual", não-amostra, ou é o segundo nome do arquivo, se presente, ou o primeiro nome de arquivo sem a extensão .sample.

Isso faz três coisas. Primeiro, adiciona o primeiro arquivo passado como argumento, o arquivo de exemplo, ao plist. Então, na instalação, se o arquivo real não for encontrado, copia o arquivo de exemplo para o arquivo real. E, finalmente, na desinstalação, remove o arquivo atual se ele não tiver sido modificado. Veja Arquivos de Configuração para maiores informações.

8.6.10. @shared-mime-info directory

Executa update-mime-database no diretório na instalação e desinstalação.

8.6.11. @shell file

Adiciona o arquivo passado como argumento ao plist.

Na instalação, adiciona o caminho completo do file em /etc/shells, certificando-se que não é adicionado duas vezes. Na desinstalação, remove-o de /etc/shells.

8.6.12. @terminfo

Não use sozinho. Se o port for instalar arquivos *.terminfo, adicione USES=terminfo no seu Makefile.

Na instalação e desinstalação, se o tic estiver presente, atualize o ${PREFIX}/shared/misc/terminfo.db a partir dos arquivos *.terminfo disponíveis em ${PREFIX}/shared/misc.

8.6.13. Keywords Básicas

Existem algumas keywords que são codificadas e documentadas em pkg-create(8). Por uma questão de completude, elas também estão documentadas aqui.

8.6.13.1. @ [file]

A keyword vazia é um espaço reservado para ser usado quando o proprietário, grupo ou modo do arquivo precisam ser alterados. Por exemplo, para definir o grupo de um arquivo como games e adicionar o bit setgid, adicione:

@(,games,2755) sbin/daemon

8.6.13.2. @preexec command, @postexec command, @preunexec command, @postunexec command

Executa o command como parte do processo de instalação ou desinstalação.

@preexec command

Executar o command como parte dos scripts pre-install.

@postexec command

Executar o command como parte dos scripts post-install.

@preunexec command

Executar o command como parte dos scripts pre-deinstall.

@postunexec command

Executar o command como parte dos scripts post-deinstall.

E se o command contém qualquer uma dessas sequências em algum lugar, elas são expandidas em linha. Para estes exemplos, assuma que @cwd está configurado para /usr/local e o último arquivo extraído foi bin/emacs.

%F

Expandir para o último nome de arquivo extraído (conforme especificado). No caso do exemplo bin/emacs.

%D

Expandir para o prefixo do diretório atual, como definido no @cwd. No caso do exemplo /usr/local.

%B

Expandir para o nome de base do nome completo do arquivo, ou seja, o prefixo do diretório atual mais o último arquivo, menos o nome do arquivo final. No exemplo, isso seria /usr/local/bin.

%f

Expandir para a parte do nome do arquivo do nome totalmente qualificado, ou o inverso de %B. No caso do exemplo, emacs.

Essas keywords estão aqui para ajudá-lo a configurar o pacote para que ele esteja tão pronto quanto possível. Elas não devem ser abusadas para iniciar serviços, interromper serviços ou executar quaisquer outros comandos que modificarão o sistema em execução.

8.6.13.3. @mode mode

Define a permissão padrão para todos os arquivos extraídos posteriormente para mode. O formato é o mesmo usado por chmod(1). Use sem um argumento para voltar às permissões padrão (modo do arquivo enquanto estava sendo empacotado).

Este deve ser um modo numérico, como 644, 4755 ou 600. Não pode ser um modo relativo como u+s.

8.6.13.4. @owner user

Define a propriedade padrão para todos os arquivos subsequentes para user. Use sem um argumento para voltar à propriedade padrão (root).

8.6.13.5. @group group

Define a propriedade de grupo padrão para todos os arquivos subsequentes para group. Use sem um argumento para retornar à propriedade do grupo padrão (wheel).

8.6.13.6. @comment string

Esta linha é ignorada no momento de empacotar.

8.6.13.7. @dir directory

Declara o nome do diretório. Por padrão, os diretórios criados sob PREFIX por uma instalação de pacote são automaticamente removidos. Use isto quando um diretório vazio sob PREFIX precisa ser criado ou quando o diretório precisa ter proprietário, grupo ou modo não padrão. Diretórios fora de PREFIX precisam ser registrados. Por exemplo, /var/db/${PORTNAME} precisa ter uma entrada @dir enquanto ${PREFIX}/shared/${PORTNAME} não, se contiver arquivos ou usar o proprietário, grupo e modo padrão.

8.6.13.8. @exec command, @unexec command (Descontinuado)

Executa o command como parte do processo de instalação ou desinstalação. Por favor, use @preexec command, @postexec command, @preunexec command, @postunexec command no lugar.

8.6.13.9. @dirrm directory (Descontinuado)

Declara o nome do diretório a ser excluído na desinstalação. Por padrão, os diretórios criados sob PREFIX por uma instalação de pacote são excluídos quando o pacote é desinstalado.

8.6.13.10. @dirrmtry directory (Descontinuado)

Declara o nome do diretório a ser removido, como para a keyword @dirrm, mas não emite um aviso se o diretório não puder ser removido.

8.6.14. Criando Novas Keywords

Os arquivos da lista de pacotes podem ser estendidos por keywords definidas no diretório ${PORTSDIR}/Keywords. As configurações de cada keyword são armazenadas em um arquivo UCL chamado keyword.ucl. O arquivo deve conter pelo menos uma destas seções:

  • attributes

  • action

  • pre-install

  • post-install

  • pre-deinstall

  • post-deinstall

  • pre-upgrade

  • post-upgrade

8.6.14.1. attributes

Altera o dono, grupo ou modo usado pela keyword. Contém uma matriz associativa em que as chaves possíveis são owner, group e mode. Os valores são, respectivamente, um nome de usuário, um nome de grupo e um modo de arquivo. Por exemplo:

attributes: { owner: "games", group: "games", mode: 0555 }

8.6.14.2. action

Define o que acontece com o parâmetro da keyword. Contém uma matriz onde os valores possíveis são:

setprefix

Define o prefixo para as próximas entradas do plist.

dir

Registra um diretório para ser criado na instalação e removido na desinstalação.

dirrm

Registra um diretório a ser excluído na desinstalação. Descontinuado.

dirrmtry

Registra um diretório para tentar deletar na desinstalação. Descontinuado.

file

Registra um arquivo.

setmode

Define o modo para as próximas entradas do plist.

setowner

Define o dono para as próximas entradas do plist.

setgroup

Define o grupo para as próximas entradas do plist.

comment

Não faz nada, é o equivalente a não entrar em uma seção action.

ignore_next

Ignora a próxima entrada no plist.

8.6.14.3. arguments

Se definido para true, adiciona manipulação de argumentos, dividindo toda a linha, %@, em argumentos numerados,%1, %2, e assim por diante. Por exemplo, para esta linha:

@foo some.content other.content

%1 e %2 irão conter:

some.content
other.content

Também afeta como a entrada action funciona. Quando há mais de um argumento, o número do argumento deve ser especificado. Por exemplo:

actions: [file(1)]

8.6.14.4. pre-install, post-install, pre-deinstall, post-deinstall, pre-upgrade, post-upgrade

Essas keywords contêm um script sh(1) a ser executado antes ou depois da instalação, desinstalação, ou atualização do pacote. Além do habitual placeholder @exec %foo descrito em @preexec command, @postexec command, @preunexec command, @postunexec command, há um novo %@, que representa o argumento da keyword.

8.6.14.5. Exemplos de Keywords Customizadas

Exemplo 2. Exemplo de uma Keyword @dirrmtryecho

Esta keyword faz duas coisas, adiciona uma linha @dirrmtry directory na lista de empacotamento, e escreve no log quando o diretório é removido ao desinstalar o pacote.

actions: [dirrmtry]
post-deinstall: <<EOD
  echo "Directory %D/%@ removed."
EOD
Exemplo 3. Exemplo na vida real, como o @sample é implementado

Esta keyword faz três coisas. Ela adiciona o primeiro filename passado como um argumento para @sample na lista de empacotamento, ele adiciona instruções ao script de post-install para copiar o exemplo para o arquivo de configuração real, se ele ainda não existir, e adiciona instruções ao script post-deinstall para remover o arquivo de configuração se ele não tiver sido modificado.

actions: [file(1)]
arguments: true
post-install: <<EOD
  case "%1" in
  /*) sample_file="%1" ;;
  *) sample_file="%D/%1" ;;
  esac
  target_file="${sample_file%.sample}"
  set -- %@
  if [ $# -eq 2 ]; then
      target_file=${2}
  fi
  case "${target_file}" in
  /*) target_file="${target_file}" ;;
  *) target_file="%D/${target_file}" ;;
  esac
  if ! [ -f "${target_file}" ]; then
    /bin/cp -p "${sample_file}" "${target_file}" && \
      /bin/chmod u+w "${target_file}"
  fi
EOD
pre-deinstall: <<EOD
  case "%1" in
  /*) sample_file="%1" ;;
  *) sample_file="%D/%1" ;;
  esac
  target_file="${sample_file%.sample}"
  set -- %@
  if [ $# -eq 2 ]; then
      set -- %@
      target_file=${2}
  fi
  case "${target_file}" in
  /*) target_file="${target_file}" ;;
  *) target_file="%D/${target_file}" ;;
  esac
  if cmp -s "${target_file}" "${sample_file}"; then
    rm -f "${target_file}"
  else
    echo "You may need to manually remove ${target_file} if it is no longer needed."
  fi
EOD

Última alteração em: 11 de dezembro de 2021 por Sergio Carlavilla Delgado