6.5. Mecanismos de Compilação

6.5.1. Compilando Ports em Paralelo

O framework de ports do FreeBSD suporta compilação paralela usando múltiplos subprocessos do comando make, o que permite que os sistemas SMP utilizem todo o poder disponível da CPU, permitindo que as compilações dos ports sejam mais rápidas e eficazes.

Isso é alcançado passando-se a flag -jX para o make(1) executando no código do fornecedor. Este é o comportamento de compilação padrão dos ports. Infelizmente, nem todos os ports lidam bem com compilações paralelas e pode ser necessário desabilitar explicitamente esse recurso adicionando a variável MAKE_JOBS_UNSAFE=yes. Ela é usada quando um port é conhecido por não funcionar com a opção -jX devido a race conditions e problemas de compilação intermitentes.

Importante:

Ao definir a variável MAKE_JOBS_UNSAFE, é muito importante explicar com um comentário no Makefile, ou pelo menos na mensagem de commit, porque o port não pode ser compilado quando ela está ativa. Caso contrário, é quase impossível corrigir o problema ou testar se ele foi corrigido ao efetuar o commit de uma atualização em uma data posterior.

6.5.2. make, gmake, e imake

Existem várias implementações diferentes do make. O software portado geralmente requer uma implementação específica, como o GNU make, conhecido no FreeBSD como gmake.

Se o port usa o GNU make, adicione o gmake no USES.

A variável MAKE_CMD pode ser usada para referenciar o comando específico configurado pelo USES no Makefile do port. Use o MAKE_CMD apenas dentro dos Makefiles do aplicativo no WRKSRC para chamar o comando make para a implementação esperada pelo software portado.

Se o port é um aplicativo X que usa o Imake para criar o Makefile do Imakefile, defina USES=imake. Veja a seção sobre USES=imake no Capítulo 17, Usando Macros USES para mais detalhes.

Se o Makefile do port tem algo diferente de all como o target de compilação principal, defina a variável ALL_TARGET adequadamente. O mesmo vale para install e INSTALL_TARGET.

6.5.3. Script configure

Se o port usa o script configure para gerar Makefiles a partir do Makefile.in defina GNU_CONFIGURE=yes. Para dar argumentos extras ao script configure (o argumento padrão é --prefix=${PREFIX} --infodir=${PREFIX}/${INFO_PATH} --mandir = ${MANPREFIX}/man --build = ${CONFIGURE_TARGET}), defina estes argumentos extras em CONFIGURE_ARGS. Variáveis ​​de ambiente extras podem ser passadas usando CONFIGURE_ENV.

Tabela 6.1. Variáveis ​​para ports que usam o configure
VariávelSignifica
GNU_CONFIGUREO port usa o script configure para preparar a construção.
HAS_CONFIGUREIgual a GNU_CONFIGURE, exceto que o destino de configuração padrão não é adicionado a CONFIGURE_ARGS.
CONFIGURE_ARGSArgumentos adicionais passados ​​para o script configure.
CONFIGURE_ENVVariáveis de ambiente adicionais a serem definidas para execução de script configure.
CONFIGURE_TARGETSubstitui o target de configuração padrão. O valor padrão é ${MACHINE_ARCH}-portbld-freebsd${OSREL}.

6.5.4. Usando o cmake

Para ports que usam CMake, defina USES=cmake.

Tabela 6.2. Variáveis ​​para ports que usam o cmake
VariávelSignifica
CMAKE_ARGSFlags do CMake especificas para o port a serem passadas para o binário do cmake.
CMAKE_ONPara cada entrada em CMAKE_ON, um valor booleano ativado é adicionado ao CMAKE_ARGS. Veja Exemplo 6.4, “CMAKE_ON and CMAKE_OFF.
CMAKE_OFFPara cada entrada em CMAKE_OFF, um valor booleano desativado é adicionado ao CMAKE_ARGS. Veja Exemplo 6.4, “CMAKE_ON and CMAKE_OFF.
CMAKE_BUILD_TYPETipo de compilação (perfis de compilação predefinidos para o CMake). O padrão é Release ou Debug se a variável WITH_DEBUG estiver definida.
CMAKE_SOURCE_PATHCaminho para o diretório do fonte. O padrão é ${WRKSRC}.
CONFIGURE_ENVVariáveis ​​de ambiente adicionais a serem definidas para o binário do cmake.

Tabela 6.3. Variáveis ​​que os usuários podem definir para compilações com cmake
VariávelSignifica
CMAKE_NOCOLORDesativa o output colorido na compilação. Não é definido por padrão, a menos que BATCH ou PACKAGE_BUILDING esteja definido.

CMake suporta estes perfis de construção: Debug, Release, RelWithDebInfo e MinSizeRel. Debug e Release sistema de respeito de perfis *FLAGS, RelWithDebInfo e MinSizeRel ajustará CFLAGS para -O2 -g e -Os -DNDEBUG correspondentemente. O valor do invólucro inferior CMAKE_BUILD_TYPE é exportado para PLIST_SUB e deve ser usado se o port for instalar *.cmake dependendo do tipo de compilação (veja devel/kf5-kcrash por um exemplo). Por favor, note que alguns projetos podem definir seus próprios perfis de compilação e/ou forçar um tipo específico de compilação CMAKE_BUILD_TYPE dentro de CMakeLists.txt. Para fazer um port para tal projeto respeite CFLAGS e WITH_DEBUG, as definições CMAKE_BUILD_TYPE devem ser removidas desses arquivos.

A maioria dos projetos baseados em CMake suportam um método de compilação out-of-source. A compilação out-of-source de um port é a configuração padrão. Uma compilação in-source pode ser executada usando-se o sufixo :insource. Em uma compilação out-of-source, CONFIGURE_WRKSRC, BUILD_WRKSRC e INSTALL_WRKSRC serão definidos como ${WRKDIR}/.Build e esse diretório será usado para manter todos os arquivos gerados durante os estágios de configuração e compilação, deixando o diretório de origem intacto.

Exemplo 6.3. Exemplo de USES=cmake

Este trecho demonstra o uso do CMake para um port. O CMAKE_SOURCE_PATH geralmente não é necessário, mas pode ser definido quando os fontes não estão localizados no diretório superior ou se apenas um subconjunto do projeto for compilado pelo port.

USES=			cmake
CMAKE_SOURCE_PATH=	${WRKSRC}/subproject

Exemplo 6.4. CMAKE_ON and CMAKE_OFF

Ao adicionar valores booleanos a variável CMAKE_ARGS, será mais fácil usar as variáveis CMAKE_ON e CMAKE_OFF ​​em vez disso. Desta forma:

CMAKE_ON=	VAR1 VAR2
CMAKE_OFF=	VAR3

É equivalente a:

CMAKE_ARGS=	-DVAR1:BOOL=TRUE -DVAR2:BOOL=TRUE -DVAR3:BOOL=FALSE

Importante:

Isto é apenas para os valores padrão desativados do CMAKE_ARGS. Os helpers descritos em Seção 5.13.3.4.2, “OPT_CMAKE_BOOL e OPT_CMAKE_BOOL_OFF usam a mesma semântica, mas para valores opcionais.


6.5.5. Usando scons

Se o port usa SCons, definir USES=scons.

Para fazer os SConstruct de terceiros respeitarem tudo o que é passado para SCons no ambiente (isto é, o mais importante, CC/CXX/CFLAGS/CXXFLAGS), altere o SConstruct para que o Evironment de compilação fique da seguinte forma:

env = Environment(**ARGUMENTS)

Ele poderá então ser modificado com env.Append e env.Replace.

6.5.6. Compilando Aplicações Rust com cargo

Para ports que usam Cargo, defina USES=cargo.

Tabela 6.4. Variáveis ​​que os Usuários Podem Configurar para Compilar cargo
VariávelPadrãoDescrição
CARGO_CRATES Lista de crates que o port depende. Cada entrada precisa ter um formato como cratename-semver por exemplo, libc-0.2.40. Os mantenedores de ports podem gerar essa lista a partir do Cargo.lock usando o comando make cargo-crates. É possível alterar manualmente as versões dos crates, mas tenha em mente as dependências transitivas.
CARGO_FEATURES Lista de recursos da aplicação para compilar (lista separada por espaço).
CARGO_CARGOTOML${WRKSRC}/Cargo.tomlO caminho para o Cargo.toml que será usado.
CARGO_CARGOLOCK${WRKSRC}/Cargo.lockO caminho para o Cargo.lock que será utilizado para o make cargo-crates. É possível especificar mais de um arquivo de bloqueio quando necessário.
CARGO_ENV Uma lista de variáveis ​​de ambiente para passar para o Cargo semelhante a MAKE_ENV.
RUSTFLAGS Flags para passar para o compilador Rust.
CARGO_CONFIGUREyesUse o padrão do-configure.
CARGO_UPDATE_ARGS Argumentos extras para passar para o Cargo durante a fase de configuração. Os argumentos válidos podem ser consultados com cargo update --help.
CARGO_BUILDDEPyesAdiciona uma dependência de compilação em lang/rust.
CARGO_CARGO_BIN${LOCALBASE}/bin/cargoLocalização do binário do cargo.
CARGO_BUILDyesUse o padrão do-build.
CARGO_BUILD_ARGS Argumentos extras para passar para o Cargo durante a fase de compilação. Argumentos válidos podem ser consultados com cargo buil --help.
CARGO_INSTALLyesUse o padrão do-install.
CARGO_INSTALL_ARGS Argumentos extras para passar para o Cargo durante a fase de instalação. Os argumentos válidos podem ser consultados com cargo isntall --help.
CARGO_INSTALL_PATH.Caminho para o crate instalar. Isto é passado para o cargo install via argumento --path. Quando múltiplos caminhos são informados, o cargo install é executado múltiplas vezes.
CARGO_TESTyesUse o padrão do-test.
CARGO_TEST_ARGS Argumentos extras para passar para o Cargo durante a fase de teste. Os argumentos válidos podem ser consultados com cargo test --help.
CARGO_TARGET_DIR${WRKDIR}/targetLocalização do diretório de saída do cargo.
CARGO_DIST_SUBDIRrust/cratesDiretório relativo a DISTDIR onde os arquivos de distribuição do crate serão armazenados.
CARGO_VENDOR_DIR${WRKSRC}/cargo-cratesLocalização do diretório do fornecedor onde todas os crates serão extraídos. Tente manter isto sob PATCH_WRKSRC, para que os patches possam ser aplicados facilmente.
CARGO_USE_GITHUBnoAtiva a busca de crates bloqueadas para commits específicos do Git no GitHub via GH_TUPLE. Isso tentará modificar o Cargo.toml no WRKDIR para apontar para os fontes offline, em vez de buscá-los em um repositório Git durante a compilação.
CARGO_USE_GITLABnoO mesmo que CARGO_USE_GITHUB mas para instâncias GitLab e GL_TUPLE.

Exemplo 6.5. Criando um Port para uma Aplicação Simples em Rust

Criar um port baseado em cargo é um processo de três estágios. Primeiro, precisamos fornecer um modelo de port que busque o arquivo de distribuição do aplicativo:

PORTNAME=	tokei
DISTVERSIONPREFIX=	v
DISTVERSION=	7.0.2
CATEGORIES=	devel

MAINTAINER=	tobik@FreeBSD.org
COMMENT=	Display statistics about your code

USES=		cargo
USE_GITHUB=	yes
GH_ACCOUNT=	Aaronepower

.include <bsd.port.mk>

Gerar uma distinfo inicial:

% make makesum
=> Aaronepower-tokei-v7.0.2_GH0.tar.gz doesn't seem to exist in /usr/ports/distfiles/.
=> Attempting to fetch https://codeload.github.com/Aaronepower/tokei/tar.gz/v7.0.2?dummy=/Aaronepower-tokei-v7.0.2_GH0.tar.gz
fetch: https://codeload.github.com/Aaronepower/tokei/tar.gz/v7.0.2?dummy=/Aaronepower-tokei-v7.0.2_GH0.tar.gz: size of remote file is not known
Aaronepower-tokei-v7.0.2_GH0.tar.gz                     45 kB  239 kBps 00m00s

Agora o arquivo de distribuição está pronto para uso e podemos ir em frente e extrair as dependências crate do pacote Cargo.lock:

% make cargo-crates
CARGO_CRATES=   aho-corasick-0.6.4 \
                ansi_term-0.11.0 \
                arrayvec-0.4.7 \
                atty-0.2.9 \
                bitflags-1.0.1 \
                byteorder-1.2.2 \
                [...]

A saída deste comando precisa ser colada diretamente no Makefile:

PORTNAME=	tokei
DISTVERSIONPREFIX=	v
DISTVERSION=	7.0.2
CATEGORIES=	devel

MAINTAINER=	tobik@FreeBSD.org
COMMENT=	Display statistics about your code

USES=		cargo
USE_GITHUB=	yes
GH_ACCOUNT=	Aaronepower

CARGO_CRATES=   aho-corasick-0.6.4 \
                ansi_term-0.11.0 \
                arrayvec-0.4.7 \
                atty-0.2.9 \
                bitflags-1.0.1 \
                byteorder-1.2.2 \
                [...]

.include <bsd.port.mk>

O distinfo precisa ser regenerado para conter todos os arquivos de distribuição dos crates:

% make makesum
=> rust/crates/aho-corasick-0.6.4.tar.gz doesn't seem to exist in /usr/ports/distfiles/.
=> Attempting to fetch https://crates.io/api/v1/crates/aho-corasick/0.6.4/download?dummy=/rust/crates/aho-corasick-0.6.4.tar.gz
rust/crates/aho-corasick-0.6.4.tar.gz         100% of   24 kB 6139 kBps 00m00s
=> rust/crates/ansi_term-0.11.0.tar.gz doesn't seem to exist in /usr/ports/distfiles/.
=> Attempting to fetch https://crates.io/api/v1/crates/ansi_term/0.11.0/download?dummy=/rust/crates/ansi_term-0.11.0.tar.gz
rust/crates/ansi_term-0.11.0.tar.gz           100% of   16 kB   21 MBps 00m00s
=> rust/crates/arrayvec-0.4.7.tar.gz doesn't seem to exist in /usr/ports/distfiles/.
=> Attempting to fetch https://crates.io/api/v1/crates/arrayvec/0.4.7/download?dummy=/rust/crates/arrayvec-0.4.7.tar.gz
rust/crates/arrayvec-0.4.7.tar.gz             100% of   22 kB 3237 kBps 00m00s
=> rust/crates/atty-0.2.9.tar.gz doesn't seem to exist in /usr/ports/distfiles/.
=> Attempting to fetch https://crates.io/api/v1/crates/atty/0.2.9/download?dummy=/rust/crates/atty-0.2.9.tar.gz
rust/crates/atty-0.2.9.tar.gz                 100% of 5898  B   81 MBps 00m00s
=> rust/crates/bitflags-1.0.1.tar.gz doesn't seem to exist in /usr/ports/distfiles/.
[...]

O port está agora pronto para uma compilação de teste e ajustes adicionais, como criar um plist, escrever uma descrição, adicionar informações de licença, opções, etc. como é normal.

Se você não estiver testando seu port em um ambiente limpo, como com o Poudriere, lembre-se de executar make clean antes de qualquer teste.


Exemplo 6.6. Ativando Recursos Adicionais do Aplicativo

Alguns aplicativos definem recursos adicionais em seus Cargo.toml. Eles podem ser compilados definindo a variável CARGO_FEATURES no port.

Aqui nós habilitamos as features Tokei's json e yaml:

CARGO_FEATURES=	json yaml

Exemplo 6.7. Listando Licenças Crate

Os crates têm suas próprias licenças. É importante saber o que elas são ao adicionar o bloco LICENSE para o port (verSeção 5.7, “Licenças”). O target auxiliar cargo-crates-licenses tentará listar todas as licenças de todos os crates definidos no CARGO_CRATES.

% make cargo-crates-licenses
aho-corasick-0.6.4  Unlicense/MIT
ansi_term-0.11.0    MIT
arrayvec-0.4.7      MIT/Apache-2.0
atty-0.2.9          MIT
bitflags-1.0.1      MIT/Apache-2.0
byteorder-1.2.2     Unlicense/MIT
[...]

Nota:

Os nomes das licenças geradas com make cargo-create-licenses são expressões de licenças do SPDX 2.1 que não correspondem aos nomes de licença definidos na estrutura de ports. Eles precisam ser traduzidos para os nomes de Tabela 5.7, “Lista de Licenças Predefinidas”.


6.5.7. Usando meson

Para ports que usam Meson, defina USES=meson.

Tabela 6.5. Variáveis ​​para ports que usam o meson
VariávelDescrição
MESON_ARGSFlags do Meson especificas para o port a serem passadas para o binário do meson.
MESON_BUILD_DIRCaminho para o diretório de compilação relativo ao WRKSRC. O padrão é _build.

Exemplo 6.8. Exemplo de USES=meson

Este trecho demonstra o uso do Meson para um port.

USES=		meson
MESON_ARGS=	-Dfoo=enabled

6.5.8. Compilando Aplicações Go

Para ports que usam Go, defina USES=go. Consulte Seção 17.33, “go para obter a lista de variáveis que podem ser configuradas para controlar o processo de compilação.

Exemplo 6.9. Criando um Port para uma Aplicação Baseada em Módulos Go

Criar um port baseado em Go é um processo de cinco estágios. Primeiro, precisamos fornecer um modelo de port que baixa o arquivo de distribuição do aplicativo:

PORTNAME=	ghq
DISTVERSIONPREFIX=	v
DISTVERSION=	0.12.5
CATEGORIES=	devel

MAINTAINER=	tobik@FreeBSD.org
COMMENT=	Remote repository management made easy

USES=		go:modules
USE_GITHUB=	yes
GH_ACCOUNT=	motemen

.include <bsd.port.mk>

Gerar uma distinfo inicial:

% make makesum
===>  License MIT accepted by the user
=> motemen-ghq-v0.12.5_GH0.tar.gz doesn't seem to exist in /usr/ports/distfiles/.
=> Attempting to fetch https://codeload.github.com/motemen/ghq/tar.gz/v0.12.5?dummy=/motemen-ghq-v0.12.5_GH0.tar.gz
fetch: https://codeload.github.com/motemen/ghq/tar.gz/v0.12.5?dummy=/motemen-ghq-v0.12.5_GH0.tar.gz: size of remote file is not known
motemen-ghq-v0.12.5_GH0.tar.gz                          32 kB  177 kBps    00s

Agora o arquivo de distribuição está pronto para uso e podemos extrair as dependências necessárias de módulos Go. Esta etapa requer a instalação do ports-mgmt/modules2tuple:

% make gomod-vendor
[...]
GH_TUPLE=	\
		Songmu:gitconfig:v0.0.2:songmu_gitconfig/vendor/github.com/Songmu/gitconfig \
		daviddengcn:go-colortext:186a3d44e920:daviddengcn_go_colortext/vendor/github.com/daviddengcn/go-colortext \
		go-yaml:yaml:v2.2.2:go_yaml_yaml/vendor/gopkg.in/yaml.v2 \
		golang:net:3ec191127204:golang_net/vendor/golang.org/x/net \
		golang:sync:112230192c58:golang_sync/vendor/golang.org/x/sync \
		golang:xerrors:3ee3066db522:golang_xerrors/vendor/golang.org/x/xerrors \
		motemen:go-colorine:45d19169413a:motemen_go_colorine/vendor/github.com/motemen/go-colorine \
		urfave:cli:v1.20.0:urfave_cli/vendor/github.com/urfave/cli

A saída deste comando precisa ser colada diretamente no Makefile:

PORTNAME=	ghq
DISTVERSIONPREFIX=	v
DISTVERSION=	0.12.5
CATEGORIES=	devel

MAINTAINER=	tobik@FreeBSD.org
COMMENT=	Remote repository management made easy

USES=		go:modules
USE_GITHUB=	yes
GH_ACCOUNT=	motemen
GH_TUPLE=	Songmu:gitconfig:v0.0.2:songmu_gitconfig/vendor/github.com/Songmu/gitconfig \
		daviddengcn:go-colortext:186a3d44e920:daviddengcn_go_colortext/vendor/github.com/daviddengcn/go-colortext \
		go-yaml:yaml:v2.2.2:go_yaml_yaml/vendor/gopkg.in/yaml.v2 \
		golang:net:3ec191127204:golang_net/vendor/golang.org/x/net \
		golang:sync:112230192c58:golang_sync/vendor/golang.org/x/sync \
		golang:xerrors:3ee3066db522:golang_xerrors/vendor/golang.org/x/xerrors \
		motemen:go-colorine:45d19169413a:motemen_go_colorine/vendor/github.com/motemen/go-colorine \
		urfave:cli:v1.20.0:urfave_cli/vendor/github.com/urfave/cli

.include <bsd.port.mk>

O distinfo precisa ser gerado novamente para conter todos os arquivos de distribuição:

% make makesum
=> Songmu-gitconfig-v0.0.2_GH0.tar.gz doesn't seem to exist in /usr/ports/distfiles/.
=> Attempting to fetch https://codeload.github.com/Songmu/gitconfig/tar.gz/v0.0.2?dummy=/Songmu-gitconfig-v0.0.2_GH0.tar.gz
fetch: https://codeload.github.com/Songmu/gitconfig/tar.gz/v0.0.2?dummy=/Songmu-gitconfig-v0.0.2_GH0.tar.gz: size of remote file is not known
Songmu-gitconfig-v0.0.2_GH0.tar.gz                    5662  B  936 kBps    00s
=> daviddengcn-go-colortext-186a3d44e920_GH0.tar.gz doesn't seem to exist in /usr/ports/distfiles/.
=> Attempting to fetch https://codeload.github.com/daviddengcn/go-colortext/tar.gz/186a3d44e920?dummy=/daviddengcn-go-colortext-186a3d44e920_GH0.tar.gz
fetch: https://codeload.github.com/daviddengcn/go-colortext/tar.gz/186a3d44e920?dummy=/daviddengcn-go-colortext-186a3d44e920_GH0.tar.gz: size of remote file is not known
daviddengcn-go-colortext-186a3d44e920_GH0.tar.        4534  B 1098 kBps    00s
[...]

O port está agora pronto para uma compilação de teste e ajustes adicionais, como criar um plist, escrever uma descrição, adicionar informações de licença, opções, etc. como é normal.

Se você não estiver testando seu port em um ambiente limpo, como com o Poudriere, lembre-se de executar make clean antes de qualquer teste.


Exemplo 6.10. Definindo o Nome do Binário ou o Caminho da Instalação

Alguns ports precisam instalar o binário resultante com um nome diferente ou em um caminho diferente do padrão ${PREFIX}/bin. Isso pode ser feito usando a sintaxe de tupla GO_TARGET, por exemplo:

GO_TARGET=  ./cmd/ipfs:ipfs-go

irá instalar o binário ipfs como ${PREFIX}/bin/ipfs-go e

GO_TARGET=  ./dnscrypt-proxy:${PREFIX}/sbin/dnscrypt-proxy

irá instalar dnscrypt-proxy em ${PREFIX}/sbin.


All FreeBSD documents are available for download at https://download.freebsd.org/ftp/doc/

Questions that are not answered by the documentation may be sent to <freebsd-questions@FreeBSD.org>.
Send questions about this document to <freebsd-doc@FreeBSD.org>.