InglêsFrancêsEspanhol

Ad


favicon do OnWorks

contras - Online na nuvem

Execute contras no provedor de hospedagem gratuita OnWorks no Ubuntu Online, Fedora Online, emulador online do Windows ou emulador online do MAC OS

Este é o comando cons que pode ser executado no provedor de hospedagem gratuita OnWorks usando uma de nossas várias estações de trabalho online gratuitas, como Ubuntu Online, Fedora Online, emulador online do Windows ou emulador online do MAC OS

PROGRAMA:

NOME


Contras - Um sistema de construção de software

DESCRIÇÃO


Um guia e referência para a versão 2.2.0

Copyright (c) 1996-2000 Free Software Foundation, Inc.

Este programa é um software livre; você pode redistribuí-lo e / ou modificá-lo nos termos do
a GNU General Public License conforme publicada pela Free Software Foundation; qualquer
versão 2 da licença ou (a seu critério) qualquer versão posterior.

Este programa é distribuído na esperança de que seja útil, mas SEM NENHUMA GARANTIA;
sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou ADEQUAÇÃO A UM DETERMINADO FIM.
Consulte a GNU General Public License para obter mais detalhes.

Você deve ter recebido uma cópia da GNU General Public License junto com este programa;
veja o arquivo COPYING. Caso contrário, escreva para a Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, EUA.

Introdução


Desvantagens é um sistema para construir, principalmente, software, mas é bastante diferente de
sistemas de construção de software anteriores. Contras foi projetado desde o início para lidar
facilmente com a construção de software distribuído por vários diretórios de origem. Contras
torna mais fácil criar scripts de construção que são simples, compreensíveis e de fácil manutenção.
Contras garante que software complexo seja reproduzível com facilidade e precisão.

Cons usa uma série de técnicas para fazer tudo isso. Os scripts de construção são apenas
Scripts Perl, tornando-os fáceis de compreender e muito flexíveis. Escopo global de
variáveis ​​são substituídas por um mecanismo de importação / exportação para compartilhar informações entre
scripts, melhorando significativamente a legibilidade e manutenção de cada script.
Construção ambientes são apresentados: estes são objetos Perl que capturam o
informações necessárias para controlar o processo de construção. Vários ambientes são usados
quando diferentes semânticas são necessárias para gerar produtos na árvore de construção. Contras
implementa análise de dependência automática e usa isso para sequenciar globalmente todo o
Construir. As compilações de variantes são facilmente produzidas a partir de uma única árvore de origem. Construção inteligente
subsetting é possível, ao trabalhar em mudanças localizadas. Substituições podem ser configuradas para
sobrescrever facilmente as instruções de construção sem modificar nenhum script. Criptográfico MD5
assinaturas estão associados a arquivos derivados e são usados ​​para determinar com precisão se
um determinado arquivo precisa ser reconstruído.

Oferecendo todos os itens acima e muito mais, o Cons permanece simples e fácil de usar. Isso vai,
esperançosamente, fique claro ao ler o restante deste documento.

Sua marca Contras? Sua marca não Faço?


Contras é um fazer substituição. Nos parágrafos a seguir, veremos alguns dos
características indesejáveis ​​de make - e ambientes de construção típicos baseados em make - que
motivou o desenvolvimento de Cons.

Construa complexidade

Os sistemas tradicionais baseados em marca de qualquer tamanho tendem a se tornar bastante complexos. A marca original
a utilidade e seus derivados contribuíram para essa tendência de várias maneiras. Fazer é
não é bom para lidar com sistemas espalhados por vários diretórios. Vários trabalhos-
os arredores são usados ​​para superar essa dificuldade; a escolha usual é fazer invocar
se recursivamente para cada subdiretório de uma construção. Isso leva a um código complicado, em
que muitas vezes não é claro como uma variável é definida, ou que efeito a configuração de uma variável
terá na construção como um todo. A linguagem de script make foi gradualmente ampliada
para fornecer mais possibilidades, mas estas têm servido em grande parte para desordenar uma já
linguagem excessivamente estendida. Muitas vezes, as compilações são feitas em várias passagens para fornecer
produtos apropriados de um diretório para outro diretório. Isso representa mais
aumento na complexidade do build.

Construa reprodutibilidade

A ruína de todas as marcas sempre foi o tratamento correto das dependências. Na maioria das vezes, um
é feita uma tentativa de fazer um trabalho razoável de dependências dentro de um único diretório, mas não
tentativa séria é feita para fazer o trabalho entre os diretórios. Mesmo quando as dependências são
funcionando corretamente, o make depende de uma comparação simples de carimbo de data / hora para determinar se
um arquivo desatualizado em relação aos seus dependentes não é, em geral, adequado para
determinar quando um arquivo deve ser recuperado. Se uma biblioteca externa, por exemplo, é
reconstruído e, em seguida, `` encaixado '' no lugar, os carimbos de data / hora em seus arquivos recém-criados podem
bem ser mais cedo do que a última compilação local, uma vez que foi construída antes de se tornar visível.

Variante Constrói

Make fornece apenas recursos limitados para lidar com compilações variantes. Com a proliferação
de plataformas de hardware e a necessidade de código depurável vs. otimizado, a capacidade de
criar facilmente essas variantes é essencial. Mais importante, se forem criadas variantes,
é importante ser capaz de separar as variantes ou reproduzir o
original ou variante à vontade. Com o make é muito difícil separar as compilações em
vários diretórios de construção, separados da fonte. E se esta técnica não for usada,
também é virtualmente impossível garantir a qualquer momento qual variante está presente em
a árvore, sem recorrer a uma reconstrução completa.

Repositórios

Make fornece apenas suporte limitado para a construção de software a partir do código que existe em um
estrutura de diretório do repositório central. O recurso VPATH do GNU make (e alguns outros
fazer implementações) se destina a fornecer isso, mas não funciona como esperado:
muda o caminho do arquivo de destino para o nome VPATH muito cedo em sua análise e, portanto,
procura todas as dependências no diretório VPATH. Para garantir o desenvolvimento correto
compilações, é importante ser capaz de criar um arquivo em um diretório de compilação local e ter
quaisquer arquivos em um repositório de código (um diretório VPATH, em termos de make) que dependem do local
arquivo seja reconstruído corretamente. Isso não é possível com VPATH, sem muitos códigos de
conhecimento de repositório complexo diretamente nos makefiles.

Guardando it simples


Algumas das dificuldades com o make foram citadas acima. Neste e subsequente
seções, apresentaremos os Contras e mostraremos como essas questões são tratadas.

Perl Scripts

Cons é baseado em Perl. Ou seja, scripts Cons -Recruta e Construir arquivos, o equivalente
para Makefile or makefile--todos são escritos em Perl. Isso fornece um benefício imediato: o
linguagem para escrever scripts é familiar. Mesmo que você não seja um Perl
programador, ajuda saber que Perl é basicamente uma linguagem declarativa simples,
com um fluxo de controle bem definido e semântica familiar. Possui variáveis ​​que se comportam
basicamente da maneira que você esperaria, sub-rotinas, fluxo de controle e assim por diante. Lá
não é nenhuma sintaxe especial introduzida para Cons. O uso de Perl como linguagem de script
simplifica a tarefa de expressar a solução apropriada para o, muitas vezes complexo
requisitos de uma construção.

Olá, Mundo!

Para fundamentar a discussão a seguir, veja como você poderia construir o Olá, Mundo! C
aplicativo com Cons:

$ env = novos cons ();
Programa $ env 'hello', 'hello.c';

Se você instalar este script em um diretório, nomeando o script Construir, e criar o
ola.c arquivo fonte no mesmo diretório, então você pode digitar `cons hello 'para construir o
aplicação:

% cons olá
cc -c olá.c -o olá.o
cc -o olá olá.

Construção ambientes

Uma simplificação fundamental do Cons é a ideia de um formação meio Ambiente. Uma construção
ambiente é um objeto caracterizado por um conjunto de pares de chave / valor e um conjunto de métodos.
Para dizer ao Cons como construir algo, você invoca o método apropriado por meio de um
ambiente de construção apropriado. Considere o seguinte exemplo:

$ env = novos contras (
CC => 'gcc',
LIBS => 'libworld.a'
);

Programa $ env 'hello', 'hello.c';

Neste caso, em vez de usar o ambiente de construção padrão, como está, temos
sobrescreveu o valor de `CC 'para que o equivalente GNU C Compiler seja usado. Desde a
esta versão de Olá, Mundo! requer uma biblioteca, libworld.a, especificamos que qualquer
programa vinculado neste ambiente deve ser vinculado a essa biblioteca. Se a biblioteca
já existe, muito bem, mas se não, então também teremos que incluir a declaração:

Biblioteca $ env 'libworld', 'world.c';

Agora, se você digitar `cons hello ', a biblioteca será construída antes que o programa seja vinculado, e,
claro, `gcc 'será usado para compilar ambos os módulos:

% cons olá
gcc -c olá.c -o olá.o
gcc -c mundo.c -o mundo.o
ar r libworld.a mundo.o
ar: criando libworld.a
ranlib libworld.a
gcc -o olá olá.o libworld.a

Automático e completar dependência análise

Com Cons, as dependências são tratadas automaticamente. Continuando com o exemplo anterior, observe
que quando modificamos mundo.c, mundo.o é recompilado, libworld.a recriado, e Olá
vinculado novamente:

% vi mundo.c
[EDIT]
% cons olá
gcc -c mundo.c -o mundo.o
ar r libworld.a mundo.o
ar: criando libworld.a
ranlib libworld.a
gcc -o olá olá.o libworld.a

Este é um exemplo relativamente simples: Contras `` sabe '' mundo.o depende de mundo.c, Porque
a dependência é explicitamente configurada pelo método `Library '. Ele também sabe que libworld.a
depende de mundo.o e que Olá depende de libworld.a, tudo por razões semelhantes.

Agora acontece que ola.c também inclui o arquivo de definição de interface, mundo.h:

% emacsworld.h
[EDIT]
% cons olá
gcc -c olá.c -o olá.o
gcc -o olá olá.o libworld.a

Como os Cons sabem disso ola.c inclui mundo.hE isso olá. deve, portanto, ser
recompilado? Por enquanto, basta dizer que, ao considerar ou não olá. é acima-
até o momento, Cons invoca um scanner para sua dependência, ola.c. Este scanner enumera o
arquivos incluídos por ola.c para criar uma lista de dependências adicionais, além daquelas
tornado explícito pelo script Cons. Este processo é recursivo: quaisquer arquivos incluídos por
os arquivos incluídos também serão verificados.

Não é caro? A resposta é - depende. Se você fizer uma construção completa de um grande sistema,
o tempo de digitalização é insignificante. Se você reconstruir um sistema grande, o Cons irá
passar um bom tempo pensando sobre isso antes de decidir que nada tem que ser
feito (embora não necessariamente mais tempo do que fazer!). A boa notícia é que Cons torna
muito fácil subconjuntos inteligentes de sua construção, quando você está trabalhando em mudanças localizadas.

Automático global construir sequenciamento

Porque o Cons faz uma análise de dependência completa e precisa, e faz isso globalmente, para o
toda a compilação, Cons é capaz de usar essas informações para assumir o controle total do sequenciamento
da construção. Esta sequência é evidente nos exemplos acima e é equivalente ao que
você esperaria para make, dado um conjunto completo de dependências. Com Contras, isso estende
trivialmente para compilações maiores de vários diretórios. Como resultado, toda a complexidade envolvida
em garantir que uma construção seja organizada corretamente - incluindo várias passagens hierárquicas
builds - é eliminado. Discutiremos isso com mais detalhes nas próximas seções.

Prédio grande árvores - ainda apenas por as simples


A hierarquia of construir Scripts

Uma construção maior, em Cons, é organizada criando uma hierarquia de construir Scripts. No topo
da árvore é um script chamado Construir. O resto dos scripts, por convenção, são cada um
chamado Recruta. Esses scripts são conectados entre si, de forma muito simples, pelo `Build ',
Comandos `Export 'e` Import'.

A Construa comando

O comando `Build 'leva uma lista de Recruta nomes de arquivos e organiza para que sejam
incluído na construção. Por exemplo:

Build qw (
drivers / display / Conscript
drivers / mouse / Conscript
analisador / conscrito
utilitários / Conscript
);

Esta é uma hierarquia simples de dois níveis de scripts de construção: todas as subsidiárias Recruta arquivos
são mencionados no nível superior Construir Arquivo. Observe que nem todos os diretórios da árvore
necessariamente têm scripts de construção associados a eles.

Isso também pode ser escrito como um script de vários níveis. Por exemplo, o Construir arquivo pode
contém este comando:

Build qw (
analisador / conscrito
motoristas / recruta
utilitários / Conscript
);

e os votos de Recruta arquivo no Drivers diretório pode conter este:

Build qw (
exibir / recrutar
mouse / conscrito
);

A experiência tem mostrado que o antigo modelo é um pouco mais fácil de entender, uma vez que o
toda a árvore de construção é colocada à sua frente, no nível superior. Esquemas híbridos são
Também é possível. Um componente mantido separadamente que precisa ser incorporado a um
árvore de construção, por exemplo, pode se conectar à árvore de construção em um lugar, mas definir a sua própria
hierarquia de construção.

Por padrão, o Cons não muda seu diretório de trabalho para o diretório que contém um
subsidiário Recruta arquivo que está incluindo. Este comportamento pode ser habilitado para uma construção por
especificando, no nível superior Construir arquivo:

Conscrito_chdir 1;

Quando habilitado, Cons mudará para a subsidiária Recruta arquivo que contém o diretório
durante a leitura desse arquivo e, em seguida, mude de volta para o diretório de nível superior assim que o arquivo
foi processado.

Espera-se que esse comportamento se torne o padrão em alguma versão futura do Cons.
Para se preparar para essa transição, os builds que esperam que os Contras permaneçam no topo do build
enquanto lê em uma subsidiária Recruta arquivo deve desabilitar explicitamente este recurso como
segue:

Conscrito_chdir 0;

Relativo, parente superior, e absoluto lima nomes

Você deve ter notado que os nomes dos arquivos especificados para o comando Build são relativos a
a localização do script a partir do qual ele é invocado. Isso geralmente é verdade para outro nome de arquivo
argumentos para outros comandos, também, embora possamos também mencionar aqui que se você começar
um nome de arquivo com uma marca de hash, `` # '', então esse arquivo é interpretado em relação ao
diretório de nível (onde o Construir arquivo reside). E, não surpreendentemente, se você começar
com `` / '', então é considerado um nome de caminho absoluto. Isso é verdade mesmo em sistemas
que usam uma barra invertida em vez de uma barra normal para nomear caminhos absolutos.

utilização módulos in construir Scripts

Você pode colocar módulos em cada Recruta arquivo usando o Perl normal `use 'ou` require'
afirmações:

use inglês;
require My :: Module;

Cada `usar 'ou` exigir' afeta apenas aquele Recruta arquivo em que aparece. Para usar um
módulo em múltiplos Recruta arquivos, você deve colocar uma instrução `use 'ou` require' em cada
aquele que precisa do módulo.

Objetivo of variáveis

O nível superior Construir arquivo e tudo Recruta os arquivos começam a vida em um Perl comum e separado
pacote. Desvantagens controla a tabela de símbolos para o pacote de modo que, a tabela de símbolos para
cada script está vazio, exceto para o Construir arquivo, que obtém parte da linha de comando
argumentos. Todas as variáveis ​​que são definidas ou usadas, portanto, são definidas pelo script
em si - não por algum script externo.

Variáveis ​​podem ser explicitamente importados por um script de seu script pai. Para importar um
variável, deve ter sido exportado pelo pai e inicializado (caso contrário, um erro
Vai acontecer).

A Exportações comando

O comando `Exportar 'é usado como no exemplo a seguir:

$ env = novos cons ();
$ INCLUDE = "# exportar / incluir";
$ LIB = "# export / lib";
Exportar qw (env INCLUDE LIB);
Compilar qw (util / Conscript);

Os valores das variáveis ​​simples mencionadas na lista `Exportar 'serão esquecidos
por quaisquer comandos `Build 'subsequentes. O comando `Exportar 'irá apenas exportar Perl escalar
variáveis, isto é, variáveis ​​cujo nome começa com `$ '. Outras variáveis, objetos, etc.
podem ser exportados por referência - mas todos os scripts irão se referir ao mesmo objeto, e este
objeto deve ser considerado somente leitura pelos scripts subsidiários e pelo original
exportando script. É aceitável, no entanto, atribuir um novo valor ao escalar exportado
variável - isso não mudará a variável subjacente referenciada. Esta sequência, para
exemplo, está OK:

$ env = novos cons ();
Exportar qw (env INCLUDE LIB);
Compilar qw (util / Conscript);
$ env = novos contras (CFLAGS => '-O');
Compilar qw (outro / Conscrito);

Não importa se a variável é definida antes ou depois do comando `Exportar '. O
importante é o valor da variável no momento em que o comando `Build 'é executado.
Isso é o que é esquecido. Quaisquer comandos `Export 'subsequentes, a propósito,
invalidar o primeiro: você deve mencionar todas as variáveis ​​que deseja exportar em cada
Comando `Exportar '.

A importação comando

Variáveis ​​exportadas pelo comando `Exportar 'podem ser importadas em scripts subsidiários pelo
Comando `Importar '. O script subsidiário sempre importa variáveis ​​diretamente do
script superior. Considere este exemplo:

Importar qw (env INCLUIR);

Isso só é válido se o script pai exportou `$ env 'e` $ INCLUDE'. Também deve
deram a cada uma dessas variáveis ​​valores. É normal que o script subsidiário apenas
importar um subconjunto das variáveis ​​exportadas (neste exemplo, `$ LIB ', que foi exportado por
o exemplo anterior não é importado).

Todas as variáveis ​​importadas são reexportadas automaticamente, então a sequência:

Importar qw (env INCLUIR);
Build qw (under-me / Conscript);

fornecerá `$ env 'e` $ INCLUDE' para o arquivo subsidiário. Se apenas `$ env 'for
exportado, então o seguinte será suficiente:

Importar qw (env INCLUIR);
Exportar qw (env);
Build qw (under-me / Conscript);

Desnecessário dizer que as variáveis ​​podem ser modificadas localmente antes de invocar `Build 'no
script subsidiário.

Construa escrita avaliação ordem

A única restrição na ordem dos scripts de construção é que os scripts superiores são
avaliados antes de seus scripts inferiores. O nível superior Construir arquivo, por exemplo, é
avaliado primeiro, seguido por quaisquer scripts inferiores. Isso é tudo que você realmente precisa saber
sobre a ordem de avaliação, uma vez que a ordem geralmente é irrelevante. Considere o seguinte
Comando `Build ':

Build qw (
drivers / display / Conscript
drivers / mouse / Conscript
analisador / conscrito
utilitários / Conscript
);

Optamos por colocar os nomes dos scripts em ordem alfabética, simplesmente porque é o mais
conveniente para fins de manutenção. Alterar o pedido não fará diferença para o
construir.

A Modelo para compartilhando arquivos


Alguns simples convenções

Em qualquer sistema de software complexo, um método para compartilhar produtos de construção deve ser
estabelecido. Propomos um conjunto simples de convenções que são triviais de implementar com
Contras, mas muito eficaz.

A regra básica é exigir que todos os produtos de construção que precisam ser compartilhados entre
os diretórios são compartilhados por meio de um diretório intermediário. Normalmente chamamos isso de
exportar, e, em um ambiente C, fornecido subdiretórios convencionais deste diretório,
tais como incluir, lib, caixa, etc.

Esses diretórios são definidos pelo nível superior Construir Arquivo. Um simples Construir arquivo para
a Olá, Mundo! aplicativo, organizado usando vários diretórios, pode ter a seguinte aparência:

# Construir arquivo para Hello, World!

# Onde colocar todos os nossos produtos compartilhados.
$ EXPORT = '#exportar';

Exportar qw (CONS INCLUDE LIB BIN);

# Diretórios padrão para compartilhar produtos.
$ INCLUDE = "$ EXPORT / include";
$ LIB = "$ EXPORT / lib";
$ BIN = "$ EXPORT / bin";

# Um ambiente de construção padrão.
$ CONS = novos contras (
CPPPATH => $ INCLUDE, # Incluir caminho para compilações C
LIBPATH => $ LIB, # Caminho da biblioteca para vincular programas
LIBS => '-lworld', # Lista de bibliotecas padrão
);

Build qw (
Olá / Conscrito
mundo / conscrito
);

A mundo do diretório Recruta arquivo se parece com este:

# Arquivo conscript para diretório world
Importar qw (CONS INCLUDE LIB);

# Instale os produtos deste diretório
Instale $ CONS $ LIB, 'libworld.a';
Instale $ CONS $ INCLUDE, 'world.h';

# Produtos internos
Biblioteca $ CONS 'libworld.a', 'world.c';

e os votos de Olá do diretório Recruta arquivo se parece com este:

# Arquivo conscript para o diretório hello
Importar qw (CONS BIN);

# Produtos exportados
Instale $ CONS $ BIN, 'olá';

# Produtos internos
Programa $ CONS 'hello', 'hello.c';

Para construir um Olá, Mundo! programa com esta estrutura de diretório, vá para o nível superior
e invoque `cons 'com os argumentos apropriados. No exemplo a seguir, nós
diga ao Cons para construir o diretório exportar. Para construir um diretório, Cons cria recursivamente todos
produtos conhecidos dentro desse diretório (apenas se precisarem de reconstrução, é claro). Se algum de
esses produtos dependem de outros produtos em outros diretórios, então eles serão construídos,
demasiado.

% contras exportação
Instale world / world.h como export / include / world.h
cc -Iexportar / incluir -c hello / hello.c -o hello / hello.o
cc -Iexport / include -c world / world.c -o world / world.o
ar r world / libworld.a world / world.o
ar: criando mundo / libworld.a
ranlib world / libworld.a
Instale world / libworld.a como export / lib / libworld.a
cc -o hello / hello hello / hello.o -Lexport / lib -lworld
Instale hello / hello como export / bin / hello

Limpar, compreensível, independente de localização Scripts

Você notará que os dois Recruta os arquivos são muito limpos e diretos. Eles simplesmente
especificar produtos do diretório e como construir esses produtos. As instruções de construção
são mínimos: eles especificam qual ambiente de construção usar, o nome do produto,
e o nome das entradas. Observe também que os scripts são independentes do local: se você
deseja reorganizar sua árvore de origem, você é livre para fazê-lo: você só precisa alterar o
Construir arquivo (neste exemplo), para especificar os novos locais do Recruta arquivos. o
o uso de uma árvore de exportação facilita esse objetivo.

Observe também como o Cons cuida dos pequenos detalhes para você. Todos exportar diretórios, para
exemplo, foram feitas automaticamente. E os arquivos instalados eram realmente vinculados ao
respectivos diretórios de exportação, para economizar espaço e tempo. Essa atenção aos detalhes economiza
trabalho considerável e torna ainda mais fácil produzir scripts simples e fáceis de manter.

Separando fonte e construir árvores


Muitas vezes, é desejável manter todos os arquivos derivados da construção completamente separados do
Arquivos Fonte. Isso torna muito mais fácil acompanhar o que é um arquivo de origem, e
também torna mais simples de manusear variante compilações, especialmente se você quiser as compilações variantes
para coexistir.

Separando construir e fonte diretórios utilização que o Ligação comando

O Cons fornece um mecanismo simples que lida com todos esses requisitos. O `Link '
comando é invocado como neste exemplo:

Link 'build' => 'src';

Os diretórios especificados são `` vinculados '' ao diretório de origem especificado. Vamos supor
que você configure um diretório de origem, src, com os subdiretórios mundo e Olá abaixo dele,
como no exemplo anterior. Você pode então substituir as linhas de construção originais pelo
A seguir:

Build qw (
build / world / Conscript
build / hello / Conscript
);

Observe que você trata o Recruta arquivo como se existisse no diretório de construção. Agora se
você digitar o mesmo comando de antes, obterá os seguintes resultados:

% contras exportação
Instale build / world / world.h como export / include / world.h
cc -Iexportar / incluir -c build / hello / hello.c -o build / hello / hello.o
cc -Iexportar / incluir -c build / world / world.c -o build / world / world.o
ar r build / world / libworld.a build / world / world.o
ar: criando build / world / libworld.a
ranlib build / world / libworld.a
Instale build / world / libworld.a como export / lib / libworld.a
cc -o build / hello / hello build / hello / hello.o -Lexport / lib -lworld
Instale build / hello / hello como export / bin / hello

Mais uma vez, a Cons cuidou dos detalhes para você. Em particular, você notará que todos
as compilações são feitas usando arquivos de origem e arquivos de objeto do diretório de compilação. Por
exemplo, build / world / world.o é compilado de construir / mundo / mundo.c e
export / include / world.h é instalado a partir de construir / mundo / mundo.h. Isso é realizado na maioria
sistemas pelo simples expediente de "hard" ligando os arquivos necessários de cada fonte
diretório para o diretório de construção apropriado.

Os links são mantidos corretamente pelo Cons, não importa o que você faça no diretório de origem.
Se você modificar um arquivo fonte, seu editor pode fazer isso `` no local '' ou pode renomeá-lo
primeiro e crie um novo arquivo. No último caso, qualquer link físico será perdido. Contras vão
detecte essa condição na próxima vez que o arquivo de origem for necessário e o vinculará novamente
adequadamente.

Você também notará, a propósito, que não mudanças foram necessárias para o subjacente Recruta
arquivos. E podemos ir mais longe, como veremos na próxima seção.

Variante Constrói


Olá, Mundo! para banana e pêssego sistemas operacionais

As compilações de variantes requerem apenas outra extensão simples. Vamos tomar como exemplo um
requisito para permitir construções para os sistemas operacionais baNaNa e peAcH. Nesse caso,
estamos usando um sistema de arquivos distribuído, como NFS para acessar o sistema específico, e
apenas um ou outro dos sistemas deve ser compilado para qualquer chamada de
`contras '. Esta é uma maneira de configurar o Construir arquivo para o nosso Olá, Mundo!
aplicação:

# Construir arquivo para Hello, World!

die qq (OS deve ser especificado) a menos que $ OS = $ ARG {OS};
die qq (o sistema operacional deve ser "pêssego" ou "banana")
if $ OS ne "pêssego" && $ OS ne "banana";

# Onde colocar todos os nossos produtos compartilhados.
$ EXPORT = "# export / $ OS";

Exportar qw (CONS INCLUDE LIB BIN);

# Diretórios padrão para compartilhar produtos.
$ INCLUDE = "$ EXPORT / include";
$ LIB = "$ EXPORT / lib";
$ BIN = "$ EXPORT / bin";

# Um ambiente de construção padrão.
$ CONS = novos contras (
CPPPATH => $ INCLUDE, # Incluir caminho para compilações C
LIBPATH => $ LIB, # Caminho da biblioteca para vincular programas
LIBS => '-lworld', # Lista de bibliotecas padrão
);

# $ BUILD é de onde derivaremos tudo.
$ BUILD = "# build / $ OS";

# Diga aos contras onde estão os arquivos-fonte de $ BUILD.
Link $ BUILD => 'src';

Construir (
"$ BUILD / hello / Conscript",
"$ BUILD / world / Conscript",
);

Agora, se fizermos login em um sistema peAcH, podemos construir nosso Olá, Mundo! aplicação para isso
plataforma:

% cons export OS = pêssego
Instale build / peach / world / world.h como export / peach / include / world.h
cc -Iexportar / pêssego / incluir -c build / pêssego / hello / hello.c -o build / pêssego / hello / hello.o
cc -Iexport / peach / include -c build / peach / world / world.c -o build / peach / world / world.o
ar r build / peach / world / libworld.a build / peach / world / world.o
ar: criando build / peach / world / libworld.a
ranlib build / peach / world / libworld.a
Instale build / peach / world / libworld.a como export / peach / lib / libworld.a
cc -o build / peach / hello / hello build / peach / hello / hello.o -Lexport / peach / lib -lworld
Instale build / peach / hello / hello como export / peach / bin / hello

Variações on a tema

Outras variações deste modelo são possíveis. Por exemplo, você pode decidir que deseja
para separar seus arquivos de inclusão em arquivos dependentes da plataforma e arquivos independentes da plataforma.
Neste caso, você teria que definir uma alternativa para `$ INCLUDE 'para dependentes de plataforma
arquivos. A maioria Recruta arquivos, gerando arquivos de inclusão puramente independentes da plataforma,
não tem que mudar.

Você também pode querer compilar todo o seu sistema com depuração ou criação de perfil,
por exemplo, habilitado. Você pode fazer isso com opções de linha de comando apropriadas, como
`DEBUG = on '. Isso seria então traduzido em uma plataforma específica apropriada
requisitos para habilitar a depuração (isso pode incluir desligar a otimização, para
exemplo). Você pode, opcionalmente, variar o espaço de nome para esses diferentes tipos de sistemas,
mas, como veremos na próxima seção, não é essencial para fazer isso, uma vez que Cons é bonito
inteligente sobre reconstruir coisas quando você muda as opções.

Assinaturas


MD5 criptografia assinaturas

Sempre que o Cons cria um arquivo derivado, ele armazena um assinatura para esse arquivo. A assinatura
é armazenado em um arquivo separado, um por diretório. Depois que o exemplo anterior foi compilado,
que o .consignar arquivo no construir / pêssego / mundo diretório parecia com este:

world.o:834179303 23844c0b102ecdc0b4548d1cd1cbd8c6
libworld.a:834179304 9bf6587fa06ec49d864811a105222c00

O primeiro número é um carimbo de data / hora - para sistemas UNIX, normalmente é o número de
segundos desde 1º de janeiro de 1970. O segundo valor é uma soma de verificação MD5. O Mensagem Digerir
Algoritmo é um algoritmo que, dada uma string de entrada, calcula uma forte criptografia
assinatura para essa string. A soma de verificação MD5 armazenada no .consignar arquivo é, na verdade, um
resumo de todas as informações de dependência do arquivo especificado. Então, por exemplo, para o
mundo.o arquivo, isso inclui pelo menos o mundo.c arquivo, e também quaisquer arquivos de cabeçalho que Cons
sabe sobre que estão incluídos, direta ou indiretamente por mundo.c. Não apenas isso, mas o
linha de comando real que foi usada para gerar mundo.o também é alimentado no cálculo de
a assinatura. Similarmente, libworld.a obtém uma assinatura que `` inclui '' todos os
assinaturas de seus constituintes (e, portanto, transitivamente, as assinaturas de deles
constituintes), bem como a linha de comando que criou o arquivo.

A assinatura de um arquivo não derivado é calculada, por padrão, tomando o atual
hora de modificação do arquivo e o nome de entrada do arquivo (a menos que haja um
atual .consignar para esse arquivo, caso em que essa assinatura é usada).

Observe que não há necessidade de um arquivo derivado depender de qualquer Construir or
Recruta arquivo - se as alterações nesses arquivos afetarem o arquivo em questão, isso será
refletido automaticamente em sua assinatura, uma vez que as partes relevantes da linha de comando são
incluído na assinatura. Mudanças não relacionadas não terão efeito.

Quando o Cons considera se deve derivar um arquivo específico, então, ele primeiro calcula o
assinatura esperada do arquivo. Em seguida, compara a hora da última modificação do arquivo com
o tempo registrado no .consignar entrada, se houver. Se esses horários corresponderem, então o
assinatura armazenada no .consignar arquivo é considerado preciso. Se o arquivo for anterior
a assinatura não corresponde à nova assinatura esperada, então o arquivo deve ser reenviado.

Observe que um arquivo será redirecionado sempre que algo sobre um arquivo dependente for alterado. Dentro
particular, observe que qualquer mudar para a hora de modificação de um dependente (encaminhar ou
para trás no tempo) forçará a recompilação do arquivo derivado.

O uso dessas assinaturas é um método extremamente simples, eficiente e eficaz de
melhorando - dramaticamente - a reprodutibilidade de um sistema.

Vamos demonstrar isso com um exemplo simples:

# Simples "Olá, Mundo!" Construir arquivo
$ CFLAGS = '-g' se $ ARG {DEBUG} eq 'on';
$ CONS = novos contras (CFLAGS => $ CFLAGS);
Programa $ CONS 'hello', 'hello.c';

Observe como Cons recompila nos momentos apropriados:

% cons olá
cc -c olá.c -o olá.o
cc -o olá olá.
% cons olá
contras: "hello" está atualizado.
% cons DEBUG = em olá
cc -g -c olá.c -o olá.o
cc -o olá olá.
% cons DEBUG = em olá
contras: "hello" está atualizado.
% cons olá
cc -c olá.c -o olá.o
cc -o olá olá.

Code Repositórios


Muitas organizações de desenvolvimento de software terão um ou mais diretório de repositório central
árvores contendo o código-fonte atual para um ou mais projetos, bem como os derivados
arquivos de objeto, bibliotecas e executáveis. Para reduzir a recompilação desnecessária,
é útil usar arquivos do repositório para construir software de desenvolvimento - assumindo, de
claro, que nenhum arquivo de dependência mais recente existe na árvore de construção local.

Repositório

Cons fornece um mecanismo para especificar uma lista de repositórios de código que serão pesquisados,
na ordem, para arquivos de origem e arquivos derivados não encontrados na árvore de diretório de compilação local.

As seguintes linhas em um Construir arquivo instruirá Cons para olhar primeiro sob o
/ usr / experiment / repository diretório e, em seguida, sob o / usr / product / repository diretório:

Repositório qw (
/ usr / experiment / repository
/ usr / product / repository
);

Os diretórios de repositório especificados podem conter arquivos de origem, arquivos derivados (objetos,
bibliotecas e executáveis), ou ambos. Se não houver nenhum arquivo local (fonte ou derivado) em
o diretório no qual Cons é executado, então a primeira cópia de um arquivo com o mesmo nome encontrada
sob um diretório de repositório será usado para construir quaisquer arquivos derivados locais.

Cons mantém uma lista global de diretórios de repositórios. Contras irão eliminar o
diretório atual e quaisquer diretórios não existentes da lista.

Descoberta que o Construir lima in a Repositório

Os contras também procurarão por Construir e Recruta arquivos na árvore ou árvores do repositório.
Porém, isso leva a uma situação do ovo e da galinha: como você se parece em uma árvore de repositório
para uma Construir arquivo se o Construir arquivo informa onde está o repositório? Para obter
em torno disso, os repositórios podem ser especificados via opções `-R 'na linha de comando:

% cons -R / usr / experiment / repository -R / usr / product / repository.

Quaisquer diretórios de repositório especificados no Construir or Recruta arquivos serão anexados
para os diretórios do repositório especificados pelas opções `-R 'da linha de comando.

Repositório fonte arquivos

Se o código-fonte (inclua o Recruta arquivo) para a versão da biblioteca do Olá,
Mundo! O aplicativo C está em um repositório (sem arquivos derivados), o Cons usará o
arquivos de origem do repositório para criar os arquivos de objeto locais e o arquivo executável:

% cons -R / usr / src_only / repositório olá
gcc -c /usr/src_only/repository/hello.c -o olá.o
gcc -c /usr/src_only/repository/world.c -o mundo.o
ar r libworld.a mundo.o
ar: criando libworld.a
ranlib libworld.a
gcc -o olá olá.o libworld.a

Criar um arquivo de origem local fará com que o Cons reconstrua o arquivo derivado apropriado ou
arquivos:

% pico mundo.c
[EDIT]
% cons -R / usr / src_only / repositório olá
gcc -c mundo.c -o mundo.o
ar r libworld.a mundo.o
ar: criando libworld.a
ranlib libworld.a
gcc -o olá olá.o libworld.a

E remover o arquivo de origem local fará com que o Cons volte para a construção do arquivo derivado
arquivos da fonte do repositório:

% rm mundo.c
% cons -R / usr / src_only / repositório olá
gcc -c /usr/src_only/repository/world.c -o mundo.o
ar r libworld.a mundo.o
ar: criando libworld.a
ranlib libworld.a
gcc -o olá olá.o libworld.a

Repositório derivada arquivos

Se uma árvore de repositório contém arquivos derivados (geralmente arquivos de objetos, bibliotecas ou
executáveis), o Cons realizará seu cálculo de assinatura normal para decidir se o
o arquivo do repositório está atualizado ou um arquivo derivado deve ser criado localmente. Isso significa que,
a fim de garantir o cálculo correto da assinatura, uma árvore do repositório também deve conter o
.consignar arquivos que foram criados pelo Cons ao gerar os arquivos derivados.

Isso geralmente seria realizado através da construção do software no repositório (ou,
alternativamente, em um diretório de construção e, em seguida, copiando o resultado para o repositório):

% cd / usr / all / repository
% cons olá
gcc -c olá.c -o olá.o
gcc -c mundo.c -o mundo.o
ar r libworld.a mundo.o
ar: criando libworld.a
ranlib libworld.a
gcc -o olá olá.o libworld.a

(Isso é seguro, mesmo se o Construir arquivo lista o / usr / all / repository diretório em um
Comando `Repositório 'porque Cons removerá o diretório atual do repositório
Lista.)

Agora, se quisermos construir uma cópia do aplicativo com o nosso ola.c arquivo, nós só precisamos
para criar o arquivo fonte necessário, e usar a opção `-R 'para que o Cons use outro
arquivos do repositório:

% mkdir $ HOME / build1
% cd $ HOME / build1
% ed olá.c
[EDIT]
% cons -R / usr / all / repositório olá
gcc -c olá.c -o olá.o
gcc -o olá olá.o /usr/all/repository/libworld.a

Observe que Cons não se preocupou em recriar um local libworld.a biblioteca (ou recompile o
mundo.o módulo), mas em vez disso usa a versão já compilada do repositório.

Porque as assinaturas MD5 que Cons coloca no .consignar arquivo contém carimbos de data / hora para o
arquivos derivados, os carimbos de data / hora da assinatura devem corresponder aos carimbos de data / hora do arquivo para uma assinatura
ser considerado válido.

Alguns sistemas de software podem alterar os carimbos de data / hora em arquivos de repositório (copiando-os,
por exemplo), caso em que o Cons irá, por padrão, assumir que as assinaturas do repositório são inválidas
e reconstruir arquivos desnecessariamente. Este comportamento pode ser alterado especificando:

Repositório_Sig_Times_OK 0;

Isso diz ao Cons para ignorar os carimbos de data / hora ao decidir se uma assinatura é válida. (Observação
que evitar esta verificação de integridade significa que deve haver controle adequado sobre o repositório
árvore para garantir que os arquivos derivados não possam ser modificados sem atualizar o .consignar
assinatura.)

Locais de cópias of arquivos

Se a árvore do repositório contém os resultados completos de uma construção, e tentamos construir a partir
o repositório sem nenhum arquivo em nossa árvore local, algo moderadamente surpreendente
acontece:

% mkdir $ HOME / build2
% cd $ HOME / build2
% cons -R / usr / all / repositório olá
contras: "hello" está atualizado.

Por que Cons diz que o Olá programa está atualizado quando não há Olá programa em
o diretório de compilação local? Porque o repositório (não o diretório local) contém o
que vai mais à frente Olá programa, e Cons determina corretamente que nada precisa ser feito para
reconstrua esta cópia atualizada do arquivo.

Existem, no entanto, muitas vezes em que é apropriado garantir que uma cópia local de um
arquivo sempre existe. Um empacotamento ou script de teste, por exemplo, pode assumir que certos
os arquivos gerados existem localmente. Em vez de tornar esses scripts subsidiários cientes do
diretório do repositório, o comando `Local 'pode ser adicionado a um Construir or Recruta arquivo para
especificar que um determinado arquivo ou arquivos devem aparecer no diretório de compilação local:

Qw local (
Olá
);

Então, se executarmos novamente o mesmo comando, o Cons fará uma cópia local do programa do
cópia do repositório (informando que está fazendo isso):

% cons -R / usr / all / repositório olá
Cópia local de hello de / usr / all / repository / hello
contras: "hello" está atualizado.

Observe que, porque o ato de fazer a cópia local não é considerado uma "construção" do
Olá arquivo, Cons ainda relata que está atualizado.

Criar cópias locais é mais útil para arquivos que estão sendo instalados em um
diretório intermediário (para compartilhar com outros diretórios) através do comando `Instalar '.
Acompanhar o comando `Instalar 'para um arquivo com um comando` Local' é tão
comum que o Cons fornece um comando `Install_Local 'como uma maneira conveniente de fazer ambos:

Install_Local $ env, '#export', 'hello';

é exatamente equivalente a:

Instale $ env '#export', 'hello';
'# Export / hello' local;

Ambos os comandos `Local 'e` Install_Local' atualizam o local .consignar arquivo com o
assinaturas de arquivo apropriadas, para que futuras compilações sejam executadas corretamente.

Repositório dependência análise

Devido à sua varredura embutida, o Cons irá pesquisar as árvores de repositório especificadas por
.h arquivos. A menos que o compilador também saiba sobre as árvores de repositório, porém, será
incapaz de achar .h arquivos que existem apenas em um repositório. Se, por exemplo, o ola.c
arquivo inclui o ola.h arquivo em seu diretório atual:

% cons -R / usr / all / repositório olá
gcc -c /usr/all/repository/hello.c -o olá.o
/usr/all/repository/hello.c:1: hello.h: Esse arquivo ou diretório não existe

Resolver este problema força alguns requisitos sobre a forma como os ambientes de construção são
definido e na forma como a diretiva de pré-processador C `#include 'é usada para incluir arquivos.

A fim de informar o compilador sobre as árvores de repositório, o Cons adicionará o `-I 'apropriado
sinalizadores para os comandos de compilação. Isso significa que a variável `CPPPATH 'no
o ambiente de construção deve especificar explicitamente todos os subdiretórios que devem ser pesquisados
para arquivos incluídos, incluindo o diretório atual. Consequentemente, podemos corrigir o acima
exemplo, alterando a criação do ambiente no Construir arquivo da seguinte maneira:

$ env = novos contras (
CC => 'gcc',
CPPPATH => '.',
LIBS => 'libworld.a',
);

Devido à definição da variável `CPPPATH ', isso resulta, quando reexecutamos o
comando:

% cons -R / usr / all / repositório olá
gcc -c -I. -I / usr / all / repository /usr/all/repository/hello.c -o hello.o
gcc -o olá olá.o /usr/all/repository/libworld.a

A ordem dos sinalizadores `-I 'replica, para o pré-processador C, o mesmo repositório-
caminho de pesquisa de diretório que Cons usa para sua própria análise de dependência. Se houver
vários repositórios e vários diretórios `CPPPATH ', Cons irá anexar o repositório
diretórios para o início de cada diretório `CPPPATH ', multiplicando rapidamente o número
de sinalizadores `-I '. Como um exemplo extremo, um Construir arquivo contendo:

Repositório qw (
/ u1
/ u2
);

$ env = novos contras (
CPPPATH => 'a: b: c',
);

Geraria um comando de compilação de:

cc -Ia -I / u1 / a -I / u2 / a -Ib -I / u1 / b -I / u2 / b -Ic -I / u1 / c -I / u2 / c -c olá.c -o olá.

Porque Cons depende dos sinalizadores `-I 'do compilador para comunicar a ordem em que
os diretórios do repositório devem ser pesquisados, o manuseio dos diretórios do repositório em Contras é
fundamentalmente incompatível com o uso de aspas duplas nas diretivas `#include 'em seu C
Código fonte:

#include "file.h" / * NÃO USE CITAÇÕES DUPLAS ASSIM * /

Isso ocorre porque a maioria dos pré-processadores C, quando confrontados com tal diretiva, sempre primeiro
pesquise o diretório que contém o arquivo de origem. Isso prejudica o elaborado `-I '
opções que o Cons constrói para fazer o pré-processador estar em conformidade com a sua pesquisa preferida
caminho.

Consequentemente, ao usar árvores de repositório em Cons, sempre use colchetes angulares para incluídos
arquivos:

#incluir / * USE ANGLE-BRACKETS EM VEZ * /

Lista_Repositórios

Cons fornece um comando `Repository_List 'para retornar uma lista de todos os diretórios do repositório
em sua ordem de pesquisa atual. Isso pode ser usado para depuração ou para fazer Perl mais complexo
coisa:

@lista = Repository_List;
imprimir junção ('', @list), "\ n";

Repositório interação com de outros Desvantagens características

O tratamento dos contras das árvores de repositório interage corretamente com outros recursos do Cons - que é
para dizer, geralmente faz o que você esperaria.

Mais notavelmente, as árvores de repositório interagem corretamente, e bastante poderosamente, com o 'Link'
comando. Uma árvore de repositório pode conter um ou mais subdiretórios para compilações de versão
estabelecido via `Link 'para um subdiretório de origem. Contras irão procurar por arquivos derivados em
os subdiretórios de construção apropriados na árvore do repositório.

Padrão tem como alvo


Até agora, demonstramos como invocar Cons com um destino explícito para construir:

% cons olá

Normalmente, Cons não constrói nada a menos que um alvo seja especificado, mas especificando '.'
(o diretório atual) irá construir tudo:

% cons # não constrói nada

% cons. # constrói tudo no diretório de nível superior

Adicionando o método `Padrão 'a qualquer Construir or Recruta arquivo irá adicionar o especificado
alvos a uma lista de alvos padrão. Contras construirão esses padrões se não houver
destinos especificados na linha de comando. Portanto, adicionando a seguinte linha ao nível superior
Construir arquivo irá imitar o comportamento típico do Make de construir tudo por padrão:

Padrão '.';

O seguinte adicionaria o Olá e adeus comandos (no mesmo diretório que o
Construir or Recruta arquivo) para a lista padrão:

Qw padrão (
Olá
adeus
);

O método `Padrão 'pode ser usado mais de uma vez para adicionar alvos à lista padrão.

Seletivo Constrói


Cons fornece dois métodos para reduzir o tamanho de determinada construção. O primeiro é especificando
alvos na linha de comando, e o segundo é um método para podar a árvore de construção. Bem
considere a especificação do alvo primeiro.

Seletivo alvejando

Como o make, Cons permite a especificação de `` alvos '' na linha de comando. Metas contras
podem ser arquivos ou diretórios. Quando um diretório é especificado, isso é simplesmente um curto
notação manual para cada produto derivável - que Cons conhece - no especificado
diretório e abaixo. Por exemplo:

% cons build / hello / hello.o

significa construir olá. e tudo que olá. pode precisar. Isto é de um anterior
versão do Olá, Mundo! programa no qual olá. dependia de
export / include / world.h. Se esse arquivo não estiver atualizado (porque alguém modificou
src / world / world.h), então ele será reconstruído, mesmo que esteja em um diretório remoto de
construir / olá.

Neste exemplo:

% contras construir

Tudo no construir diretório é construído, se necessário. Novamente, isso pode causar mais arquivos
ser construido. Em particular, ambos export / include / world.h e export / lib / libworld.a e guarante que os mesmos estão
requerido pelo construir / olá diretório, e assim eles serão construídos se estiverem desatualizados.

Se o fizermos, em vez disso:

% contras exportação

então apenas os arquivos que devem ser instalados no diretório de exportação serão reconstruídos, se
necessário e, em seguida, instalado lá. Note que `contras build 'pode construir arquivos que` contras
export 'não constrói e vice-versa.

Não `` especial '' tem como alvo

Com o Cons, os destinos `` especiais '' do make-style não são necessários. O analógico mais simples com Cons
é usar especial exportar diretórios, em vez disso. Vamos supor, por exemplo, que você tenha um
toda a série de testes de unidade associados ao seu código. Os testes ao vivo no
diretório de origem próximo ao código. Normalmente, no entanto, você não deseja construir esses testes.
Uma solução é fornecer todas as instruções de construção para criar os testes e, em seguida,
instale os testes em uma parte separada da árvore. Se instalarmos os testes em um nível superior
diretório chamado testes, então:

% contra testes

irá construir todos os testes.

% contras exportação

irá construir a versão de produção do sistema (mas não os testes), e:

% contras construir

provavelmente deve ser evitado (uma vez que irá compilar testes desnecessariamente).

Se você quiser construir apenas um único teste, você pode nomear explicitamente o teste (em
quer o testes diretório ou o construir diretório). Você também pode agregar os testes
em uma hierarquia conveniente dentro do diretório de testes. Esta hierarquia não precisa
necessariamente correspondem à hierarquia de origem, da mesma maneira que a hierarquia de inclusão
provavelmente não corresponde à hierarquia de origem (a hierarquia de inclusão é improvável que seja mais
mais de dois níveis de profundidade, para programas C).

Se você quiser construir absolutamente tudo na árvore (sujeito a quaisquer opções que você
selecionar), você pode usar:

% cons.

Isso não é particularmente eficiente, uma vez que irá percorrer todas as árvores de forma redundante,
incluindo a árvore de origem. A árvore de origem, é claro, pode ter objetos edificáveis ​​em
isso - nada o impede de fazer isso, mesmo se você normalmente compilar em uma compilação separada
árvore.

Construa Poda


Em conjunto com a seleção do alvo, construir poda pode ser usado para reduzir o escopo do
Construir. No exemplo anterior peAcH e baNaNa, já vimos como orientado por script
a poda de construção pode ser usada para disponibilizar apenas metade do potencial de construção para qualquer
invocação de `cons '. Cons também fornece, por conveniência, uma convenção de linha de comando que
permite que você especifique qual Recruta arquivos realmente são `` construídos '' - isto é, incorporados
na árvore de construção. Por exemplo:

% contras construir + mundo

O argumento `+ 'introduz uma expressão regular Perl. Isso deve, é claro, ser citado em
o nível de shell se houver metacaracteres de shell na expressão. O
expressão é comparada com cada Recruta arquivo que foi mencionado em um `Build '
declaração, e apenas os scripts com nomes correspondentes são realmente incorporados ao
construir árvore. Vários desses argumentos são permitidos, caso em que uma correspondência com qualquer um deles
é suficiente para fazer com que um script seja incluído.

No exemplo acima, o Olá programa não será construído, uma vez que Cons não terá
conhecimento do roteiro Olá / Conscrito. O libworld.a arquivo será construído, no entanto, se
precisa ser.

Existem alguns usos para a remoção de compilação por meio da linha de comando. Talvez o mais útil
é a capacidade de fazer mudanças locais, e então, com conhecimento suficiente do
consequências dessas mudanças, restringir o tamanho da árvore de construção para acelerar
o tempo de reconstrução. Um segundo uso para a remoção de compilação é prevenir ativamente a recompilação
de certos arquivos que você sabe que irão recompilar devido a, por exemplo, um arquivo de cabeçalho modificado.
Você pode saber que as alterações no arquivo de cabeçalho são imateriais ou que o
as alterações podem ser ignoradas com segurança para a maior parte da árvore, para fins de teste.
visão é que é pragmático admitir este tipo de comportamento, por entender que
na próxima compilação completa, tudo o que precisa ser reconstruído será. Não há equivalente
a um comando `` make touch '', para marcar os arquivos como permanentemente atualizados. Portanto, qualquer risco que seja
incorrido pela poda de construção é mitigado. Para um trabalho de qualidade de lançamento, obviamente, recomendamos
que você não usa remoção de compilação (é perfeitamente normal usar durante a integração, no entanto,
para verificar a compilação, etc. Apenas certifique-se de fazer uma compilação irrestrita antes de comprometer
a integração).

temporário Substitui


Cons fornece um mecanismo muito simples para substituir os aspectos de uma construção. A essência é
que você escreva um arquivo de substituição contendo um ou mais comandos `Substituir ', e você
especifique isso na linha de comando, ao executar `cons ':

% cons -o sobre exportação

vai construir o exportar diretório, com todos os arquivos derivados sujeitos às substituições presentes
no Acima de Arquivo. Se você deixar a opção `-o ', então tudo que é necessário para remover
todas as substituições serão reconstruídas.

Substituindo meio Ambiente variáveis

O arquivo de substituição pode conter dois tipos de substituições. O primeiro é o ambiente de entrada
variáveis. Estes são normalmente acessíveis pelo Construir arquivo do hash `% ENV '
variável. Eles podem ser substituídos trivialmente no arquivo de substituição, definindo o
elementos apropriados de `% ENV '(estes também podem ser substituídos no ambiente do usuário,
claro).

A Ultrapassar comando

O segundo tipo de substituição é realizado com o comando `Substituir ', que se parece com
esta:

Sobrepor , => , => , ...;

A expressão regular regexp é comparado com cada arquivo derivado que é um candidato
para a construção. Se o arquivo derivado corresponder, então os pares de variável / valor são usados ​​para
sobrescrever os valores no ambiente de construção associado ao arquivo derivado.

Vamos supor que temos um ambiente de construção como este:

$ CONS = novos contras (
COPT => '',
CDBG => '-g',
CFLAGS => '% COPT% CDBG',
);

Então, se tivermos um arquivo de substituição Acima de contendo este comando:

Substituir '\ .o $', COPT => '-O', CDBG => '';

então qualquer invocação de `contras 'com` -o over' que cria .o arquivos através deste ambiente irão
fazer com que sejam compilados com `-O 'e sem` -g'. A substituição pode, é claro, ser
restrito a um único diretório pela seleção apropriada de uma expressão regular.

Aqui está a versão original do Hello, World! programa, construído com este ambiente.
Observe que Cons reconstrói as peças apropriadas quando a substituição é aplicada ou removida:

% cons olá
cc -g -c olá.c -o olá.o
cc -o olá olá.
% cons -o sobre olá
cc -O -c olá.c -o olá.o
cc -o olá olá.
% cons -o sobre olá
contras: "hello" está atualizado.
% cons olá
cc -g -c olá.c -o olá.o
cc -o olá olá.

É importante que o comando `Override 'seja usado apenas para uso temporário e rápido
substituições necessárias para o desenvolvimento porque as substituições não são independentes da plataforma e
porque confiam demais no conhecimento íntimo do funcionamento dos scripts. Por
uso temporário, porém, são exatamente o que você deseja.

Observe que ainda é útil fornecer, digamos, a capacidade de criar um totalmente otimizado
versão de um sistema para uso em produção - do Construir e Recruta arquivos. Por aqui
você pode adaptar o sistema otimizado à plataforma. Onde as compensações do otimizador precisam estar
feito (arquivos específicos não podem ser compilados com otimização total, por exemplo), então
estes podem ser registrados para a posteridade (e reprodutibilidade) diretamente nos scripts.

Mais on formação ambientes


Padrão formação variáveis

Mencionamos e usamos o conceito de um formação meio Ambiente, muitas vezes no
páginas anteriores. Agora é hora de tornar isso um pouco mais concreto. Com o seguinte
declaração:

$ env = novos cons ();

uma referência a um novo ambiente de construção padrão é criada. Este contém um número
de variáveis ​​de construção e alguns métodos. No momento, a lista padrão de
variáveis ​​de construção são definidas da seguinte forma:

CC => 'cc',
CFLAGS => '',
CCCOM => '% CC% CFLAGS% _IFLAGS -c% <-o%>',
INCDIRPREFIX => '-I',
CXX => '% CC',
CXXFLAGS => '% CFLAGS',
CXXCOM => '% CXX% CXXFLAGS% _IFLAGS -c% <-o%>',
LINK => '% CXX',
LINKCOM => '% LINK% LDFLAGS -o%>% <% _LDIRS% LIBS',
LINKMODULECOM => '% LD -r -o%>% <',
LIBDIRPREFIX => '-L',
AR => 'ar',
ARFLAGS => 'r',
ARCOM => "% AR% ARFLAGS%>% <\ n% RANLIB%>",
RANLIB => 'ranlib',
AS => 'como',
ASFLAGS => '',
ASCOM => '% AS% ASFLAGS% <-o%>',
LD => 'ld',
LDFLAGS => '',
PREFLIB => 'lib',
SUFLIB => '.a',
SUFLIBS => '.so: .a',
SUFOBJ => '.o',
ENV => {'PATH' => '/ bin:/ usr / bin'},

Em sistemas Win32 (Windows NT), as seguintes variáveis ​​de construção são substituídas no
default:

CC => 'cl',
CFLAGS => '/ nologo',
CCCOM => '% CC% CFLAGS% _IFLAGS / c% </ Fo%>',
CXXCOM => '% CXX% CXXFLAGS% _IFLAGS / c% </ Fo%>',
INCDIRPREFIX => '/ I',
LINK => 'link',
LINKCOM => '% LINK% LDFLAGS / out:%>% <% _LDIRS% LIBS',
LINKMODULECOM => '% LD / r / o%>% <',
LIBDIRPREFIX => '/ LIBPATH:',
AR => 'lib',
ARFLAGS => '/ nologo',
ARCOM => "% AR% ARFLAGS / out:%>% <",
RANLIB => '',
LD => 'link',
LDFLAGS => '/ nologo',
PREFLIB => '',
SUFEXE => '.exe',
SUFLIB => '.lib',
SUFLIBS => '.dll: .lib',
SUFOBJ => '.obj',

Essas variáveis ​​são utilizadas pelos vários métodos associados ao ambiente, em
particular, qualquer método que invoque um comando externo irá substituí-los
variáveis ​​no comando final, conforme apropriado. Por exemplo, o método 'Objetos' leva
uma série de arquivos de origem e organiza para derivar, se necessário, o objeto correspondente
arquivos. Por exemplo:

Objetos $ env 'foo.c', 'bar.c';

Isso providenciará a produção, se necessário, foo.o e bar.o. O comando invocado é simplesmente
`% CCCOM ', que se expande por meio de substituição, para o comando externo apropriado necessário
para construir cada objeto. Exploraremos as regras de substituição mais detalhadamente no 'Comando'
método, abaixo.

As variáveis ​​de construção também são utilizadas para outros fins. Por exemplo, `CPPPATH 'é
usado para especificar um caminho separado por dois pontos de diretórios de inclusão. Estes são destinados a ser
passados ​​para o pré-processador C e também são usados ​​pela máquina de digitalização de arquivos C para
determinar as dependências envolvidas em uma compilação C. Variáveis ​​começando com
sublinhado, são criados por vários métodos e normalmente devem ser considerados `` internos ''
variáveis. Por exemplo, quando um método é chamado que chama para a criação de um objeto
de uma fonte C, a variável `_IFLAGS 'é criada: isto corresponde às opções` -I'
requerido pelo compilador C para representar os diretórios especificados por `CPPPATH '.

Observe que, para qualquer ambiente específico, o valor de uma variável é definido uma vez e, em seguida,
nunca redefinir (para alterar uma variável, você deve criar um novo ambiente. Métodos são fornecidos
para copiar ambientes existentes para este propósito). Algumas variáveis ​​internas, como
`_IFLAGS 'são criados sob demanda, mas uma vez definidos, eles permanecem fixos para a vida do
ambiente.

As variáveis ​​`CFLAGS ',` LDFLAGS' e `ARFLAGS 'fornecem um lugar para passar opções para
o compilador, carregador e arquivador, respectivamente. Menos obviamente, o `INCDIRPREFIX '
variável especifica a string de opção a ser anexada ao início de cada inclusão
diretório para que o compilador saiba onde encontrar .h arquivos. Da mesma forma, o
A variável `LIBDIRPREFIX 'especifica a string de opção a ser acrescentada ao início de
cada diretório que o vinculador deve pesquisar para bibliotecas.

Outra variável, `ENV ', é usada para determinar o ambiente do sistema durante a execução
de um comando externo. Por padrão, a única variável de ambiente definida é `PATH ',
que é o caminho de execução para um comando UNIX. Para a máxima reprodutibilidade, você deve
realmente organize para definir seu próprio caminho de execução, em seu nível superior Construir arquivo (ou
talvez importando um pacote de construção apropriado com o comando Perl `use '). O
as variáveis ​​padrão têm o objetivo de ajudá-lo a decolar.

Interpolando formação variáveis

As variáveis ​​do ambiente de construção podem ser interpoladas nos nomes dos arquivos de origem e destino
prefixando o nome da variável de construção com `% '.

$ env = novos contras (
DESTDIR => 'programas',
SRCDIR => 'src',
);
Programa $ env '% DESTDIR / hello', '% SRCDIR / hello.c';

A expansão das variáveis ​​de construção é recursiva - ou seja, o arquivo nome(s) serão re-
expandido até que mais substituições não possam ser feitas. Se uma variável de construção não é
definido no ambiente, a string nula será substituída.

Padrão formação métodos


A lista de métodos de construção padrão inclui o seguinte:

A `novo ' construtor

O método `novo 'é um construtor de objeto Perl. Ou seja, não é invocado por meio de uma referência
para um ambiente de construção existente referência, mas, bastante estaticamente, usando o nome
do Perl pacote onde o construtor é definido. O método é invocado assim:

$ env = novos contras ( );

O ambiente que você recebe de volta é abençoado no pacote `contras ', o que significa que ele irá
associaram a ele os métodos padrão descritos abaixo. Construção individual
variáveis ​​podem ser substituídas fornecendo pares de nome / valor em uma lista de substituição. Observe que
para substituir qualquer variável de ambiente de comando (ou seja, qualquer coisa sob `ENV '), você terá que
substituir todos eles. Você pode contornar esta dificuldade usando o método `copy 'em um
ambiente de construção existente.

A `clone ' método

O método `clone 'cria um clone de um ambiente de construção existente, e pode ser
chamado como no exemplo a seguir:

$ env2 = $ env1-> clone ( );

Você pode fornecer substituições da maneira usual para criar um ambiente diferente do
original. Se você quiser apenas um novo nome para o mesmo ambiente (o que pode ser útil quando
exportando ambientes para componentes existentes), você pode apenas usar uma atribuição simples.

A `copiar ' método

O método `copy 'extrai as variáveis ​​de construção definidas externamente de um
ambiente e os retorna como uma lista de pares nome / valor. Substituições também podem ser
desde que, nesse caso, os valores substituídos serão retornados, conforme apropriado. O
a lista retornada pode ser atribuída a um hash, conforme mostrado no protótipo abaixo, mas também pode
ser manipulado de outras maneiras:

% env = $ env1-> copiar ( );

O valor de `ENV ', que é um hash, também é copiado para um novo hash, então pode ser
mudou sem medo de afetar o ambiente original. Então, por exemplo, se você realmente
deseja substituir apenas a variável `PATH 'no ambiente padrão, você pode fazer o
A seguir:

% cons = novos cons () -> copiar ();
$ contr {ENV} {PATH} = " ";
$ cons = novos contras (% cons);

Isso deixará qualquer outra coisa que possa estar no ambiente de execução padrão
imperturbável.

A `Instalar ' método

O método `Install 'faz com que os arquivos especificados sejam instalados no
diretório. A instalação é otimizada: o arquivo não é copiado se puder ser vinculado. Se
este não é o comportamento desejado, você precisará usar um método diferente para instalar o
Arquivo. É chamado da seguinte forma:

Instale $ env , ;

Observe que, embora os arquivos a serem instalados possam ser nomeados arbitrariamente, apenas o último
componente de cada nome é usado para o nome do destino instalado. Então, por exemplo, se você
organizar para instalar foo / bar in baz, isso criará um Barra arquivo no baz diretório (não
foo / bar).

A `Instalar como ' método

O método `InstallAs 'organiza para a fonte especificada lima(s) a ser instalado como o
alvo especificado lima(s). Vários arquivos devem ser especificados como uma lista de arquivos. O
a instalação é otimizada: o arquivo não é copiado se puder ser vinculado. Se este não é o
comportamento desejado, você precisará usar um método diferente para instalar o arquivo. Isto é
chamado da seguinte forma:

`Instalar como 'funciona de duas maneiras:

Instalação de arquivo único:

InstallAs $ env TgtFile, SrcFile;

Instalação de vários arquivos:

InstallAs $ env ['tgt1', 'tgt2'], ['src1', 'src2'];

Ou mesmo como:

@srcs = qw (src1 src2 src3);
@tgts = qw (tgt1 tgt2 tgt3);
InstallAs $ env [@tgts], [@srcs];

As listas de destino e de origem devem ter o mesmo comprimento.

A `Precioso ' método

O método `Precious 'pede aos contras para não excluir o arquivo especificado ou a lista de arquivos antes
construí-los novamente. É invocado como:

Precioso ;

Isso é especialmente útil para permitir atualizações incrementais para bibliotecas ou depuração
arquivos de informações que são atualizados em vez de reconstruídos novamente a cada vez. Contras ainda vão
exclua os arquivos quando o sinalizador `-r 'for especificado.

A `Comando ' método

O método `Command 'é um método abrangente que pode ser usado para organizar qualquer
comando a ser chamado para atualizar o destino. Para este comando, um arquivo de destino e uma lista de
entradas são fornecidas. Além disso, uma linha de comando de construção, ou linhas, é fornecida como um
string (esta string pode ter vários comandos embutidos, separados por novos
linhas). `Command 'é chamado da seguinte forma:

Comando $ env , , ;

O destino torna-se dependente da lista de arquivos de entrada especificados e as entradas devem
ser construído com sucesso ou o Cons não tentará construir o alvo.

Dentro do comando de construção, qualquer variável do ambiente de construção pode ser
introduzido prefixando o nome da variável de construção com `% '. Isso é recursivo:
o comando é expandido até que mais substituições não possam ser feitas. Se uma construção
variável não é definida no ambiente, então a string nula será substituída. UMA
`%% 'dobrado será substituído por um único`%' no comando de construção.

Existem várias pseudo variáveis ​​que também serão expandidas:

%> O nome do arquivo de destino (em um comando multi-destino, este é sempre o primeiro destino
mencionado).

% 0 Igual a `%> '.

% 1,% 2, ...,% 9
Eles se referem ao primeiro ao nono arquivo de entrada, respectivamente.

% <O conjunto completo de entradas. Se algum destes tiver sido usado em qualquer outro lugar no
linha de comando atual (via `% 1 ',`% 2', etc.), então aqueles serão excluídos do
lista fornecida por `% <'. Considere o seguinte comando encontrado em um Recruta lima
no teste diretório:

Comando $ env 'tgt', qw (foo bar baz), qq (
echo% <-i% 1>%>
echo% <-i% 2 >>%>
echo% <-i% 3 >>%>
);

If tgt precisava ser atualizado, então isso resultaria na execução do
seguintes comandos, assumindo que nenhum remapeamento foi estabelecido para o teste
diretório:

teste de eco / teste de barra / baz -i teste / foo> teste / tgt
echo test / foo test / baz -i test / bar >> test / tgt
echo test / foo test / bar -i test / baz >> test / tgt

Qualquer uma das pseudo variáveis ​​acima pode ser seguida imediatamente por uma das seguintes
sufixos para selecionar uma parte do nome do caminho expandido:

: o caminho absoluto para o nome do arquivo
: b o diretório mais o nome do arquivo sem qualquer sufixo
: d o diretório
: f o nome do arquivo
: é o sufixo do nome do arquivo
: F o nome do arquivo sem qualquer sufixo

Continuando com o exemplo acima, `% <: f 'se expandiria para` foo bar baz', e `% ': d>
expandir para `testar '.

É possível reescrever programaticamente parte do comando incluindo parte dele
entre `% ['e`%]'. Isso irá chamar a variável de construção nomeada como a primeira palavra
colocado entre colchetes como uma referência de código Perl; os resultados desta chamada serão usados
para substituir o conteúdo dos colchetes na linha de comando. Por exemplo, dado um
arquivo de entrada existente denominado tgt.in:

@keywords = qw (foo bar baz);
$ env = novos contras (X_COMMA => sub {join (",", @_)});
Comando $ env 'tgt', 'tgt.in', qq (
echo '# Keywords:% [X_COMMA @keywords%]'>%>
gato% <>>%>
);

Isso irá executar:

echo '# Palavras-chave: foo, bar, baz'> tgt
cat tgt.in >> tgt

Após a substituição, as sequências de espaço em branco são convertidas em espaços em branco simples e
o espaço em branco à esquerda e à direita é eliminado. Portanto, não é possível introduzir
espaço em branco de comprimento variável em strings passadas em um comando, sem recorrer a algum
tipo de citação de shell.

Se uma cadeia de comandos de várias linhas for fornecida, os comandos serão executados sequencialmente. Caso existam
dos comandos falhar, nenhum dos outros será executado e o destino não será marcado como
atualizado, ou seja, uma nova assinatura não é armazenada para o destino.

Normalmente, se todos os comandos forem bem-sucedidos e retornarem um status zero (ou qualquer plataforma,
é necessária uma indicação específica de sucesso), então uma nova assinatura é armazenada para o
alvo. Se um comando relatar erroneamente o sucesso mesmo após uma falha, o Cons será
suponha que o arquivo de destino criado por esse comando seja preciso e atualizado.

A primeira palavra de cada string de comando, após a expansão, é considerada um executável
comando procurou na variável de ambiente 'PATH' (que é, por sua vez, especificada pelo
variável de construção 'ENV'). Se este comando for encontrado no caminho, o destino
dependem dele: o comando será, portanto, construído automaticamente, conforme necessário. Isso é
possível escrever comandos de várias partes em alguns shells, separados por ponto e vírgula. Apenas o
a primeira palavra de comando será dependente, no entanto, se você escrever suas strings de comando
desta forma, você deve configurar explicitamente uma dependência (com o método `Depends'), ou
certifique-se de que o comando que você está usando é um comando do sistema que deve ser
acessível. Se não estiver disponível, é claro que você receberá um erro.

Se algum comando (mesmo um dentro de um comando de várias linhas) começar com `[perl]', o restante
dessa linha de comando será avaliada pelo Perl em execução em vez de ser bifurcada pelo
Concha. Se ocorrer um erro ao analisar o Perl ou se a expressão Perl retornar 0 ou
undef, o comando será considerado como tendo falhado. Por exemplo, aqui está um simples
comando que cria um arquivo `foo' diretamente do Perl:

$ env = novos cons ();
Comando $env 'foo',
qq([perl] open(FOO,'>foo'); print FOO "hi\\n"; close(FOO); 1);

Observe que quando o comando é executado, você está no mesmo pacote de quando o comando Construir
or Recruta arquivo foi lido, então você pode chamar as funções Perl que você definiu no mesmo
Construir or Recruta arquivo no qual o 'Comando' aparece:

$ env = novos cons ();
sub criar_arquivo {
meu $arquivo = deslocamento;
open(ARQUIVO, ">$arquivo");
print ARQUIVO "oi\n";
fechar(ARQUIVO);
1 voltar;
}
Comando $env 'foo', "[perl] &create_file('%>')";

A string Perl será usada para gerar a assinatura para o arquivo derivado, então se você
alterar a string, o arquivo será reconstruído. O conteúdo de qualquer sub-rotina que você chamar,
no entanto, não fazem parte da assinatura, portanto, se você modificar uma sub-rotina chamada, como
`create_file' acima, o destino irá não ser reconstruída. Alerta usuário.

Contras normalmente imprime um comando antes de executá-lo. Este comportamento é suprimido se o
primeiro caractere do comando é `@'. Observe que você pode precisar separar o `@' de
o nome do comando ou escape para evitar que `@cmd' pareça um array para aspas Perl
operadores que realizam interpolação:

# A primeira linha de comando está incorreta,
# porque "@cp" se parece com um array
# para a função Perl qq//.
# Em vez disso, use o segundo formulário.
Comando $env 'foo', 'foo.in', qq(
@cp %< arquivo temporário
@cp tempfile %>
);

Se houver metacaracteres de shell em qualquer lugar na linha de comando expandida, como `<',
`>', aspas ou ponto e vírgula, então o comando será realmente executado invocando um
Concha. Isso significa que um comando como:

cd foo

sozinho normalmente falhará, pois não há comando 'cd' no caminho. Mas o comando
corda:

cd$<:d; tar cf $>:f $<:f

quando expandido ainda conterá o ponto-e-vírgula do metacaractere do shell, e um shell será
invocado para interpretar o comando. Como `cd' é interpretado por este sub-shell, o comando
será executado conforme o esperado.

Para especificar um comando com vários destinos, você pode especificar uma referência a uma lista de
alvos. Em Perl, uma referência de lista pode ser criada colocando uma lista entre colchetes.
Daí o seguinte comando:

Comando $env ['foo.h', 'foo.c'], 'foo.template', q(
geração % 1
);

pode ser usado em um caso onde o comando `gen' cria dois arquivos, ambos foo.h e foo.c.

A 'Objetos' método

O método `Objects' organiza para criar os arquivos de objeto que correspondem ao especificado
Arquivos Fonte. Ele é invocado como mostrado abaixo:

@files = Objetos $env ;

No Unix, os arquivos de origem terminando em .s e .c são atualmente suportados e serão compilados
em um nome do mesmo arquivo que termina em .o. Por padrão, todos os arquivos são criados invocando
o comando externo que resulta da expansão da variável de construção `CCCOM', com
`%<' e `%>' definidos para os arquivos de origem e objeto, respectivamente (veja o método `Command'
para detalhes de expansão). A variável `CPPPATH' também é usada ao verificar arquivos de origem
para dependências. Esta é uma lista de nomes de caminhos separados por dois pontos, e também é usada para criar
a variável de construção `_IFLAGS,' que conterá a lista apropriada de -`I'
opções para a compilação. Quaisquer caminhos relativos em `CPPPATH' são interpretados relativos
para o diretório no qual o ambiente de construção associado foi criado (absoluto
e nomes relativos superiores também podem ser usados). Esta variável é usada pelo `CCCOM'. O comportamento
deste comando pode ser modificado alterando qualquer uma das variáveis ​​que são interpoladas
em 'CCCOM', como 'CC', 'CFLAGS' e, indiretamente, 'CPPPATH'. Também é possível
substituir o valor do próprio `CCCOM'. Por conveniência, este arquivo retorna a lista de
nomes de arquivos de objetos.

A `Programa' método

O método 'Program' organiza para vincular o programa especificado com o objeto especificado
arquivos. É invocado da seguinte maneira:

Programa $env , ;

O nome do programa terá o valor da variável de construção `SUFEXE' anexada (por
padrão, `.exe' em sistemas Win32, nada em sistemas Unix) se o sufixo ainda não estiver
presente.

Arquivos de origem podem ser especificados no lugar de arquivos de objetos - o método 'Objetos' será
invocado para organizar a conversão de todos os arquivos em arquivos de objeto e, portanto, todos os
observações sobre o método 'Objetos', acima, também se aplicam a este método.

A vinculação real do programa será tratada por um comando externo que resulta
de expandir a variável de construção `LINKCOM', com `%<' definido para os arquivos de objeto para
ser vinculado (na ordem apresentada) e `%>' definido para o destino (consulte o método `Command'
para detalhes de expansão). O usuário pode definir variáveis ​​adicionais na construção
ambiente, incluindo `LINK', para definir qual programa usar para vincular, `LIBPATH', um
lista separada por dois pontos de caminhos de pesquisa de biblioteca, para uso com especificações de biblioteca do
formulário -lib, e `LIBS', especificando a lista de bibliotecas para vincular (em qualquer -lib
formulário ou apenas como nomes de caminho. Caminhos relativos em `LIBPATH' e `LIBS' são interpretados
em relação ao diretório no qual o ambiente de construção associado é criado
(nomes absolutos e relativos ao topo também podem ser usados). Contras configura automaticamente
dependências em quaisquer bibliotecas mencionadas em `LIBS': essas bibliotecas serão construídas antes
o comando está vinculado.

A "Biblioteca" método

O método `Library' organiza para criar a biblioteca especificada a partir do objeto especificado
arquivos. É invocado da seguinte forma:

Biblioteca $env , ;

O nome da biblioteca terá o valor da variável de construção `SUFLIB' anexada (por
default, `.lib' em sistemas Win32, `.a' em sistemas Unix) se o sufixo ainda não estiver
presente.

Arquivos de origem podem ser especificados no lugar de arquivos de objetos - o método 'Objetos' será
invocado para organizar a conversão de todos os arquivos em arquivos de objeto e, portanto, todos os
observações sobre o método 'Objetos', acima, também se aplicam a este método.

A criação real da biblioteca será tratada por um comando externo que resulta
de expandir a variável de construção `ARCOM', com `%<' definido para os membros da biblioteca (em
a ordem apresentada), e `%>' para a biblioteca a ser criada (veja o método `Command' para
detalhes da expansão). O usuário pode definir variáveis ​​no ambiente de construção que irão
afetar o funcionamento do comando. Estes incluem `AR', o programa de arquivamento a ser usado,
`ARFLAGS', que pode ser usado para modificar os sinalizadores dados ao programa especificado por `AR',
e `RANLIB', o nome de um programa de geração de índice de arquivo, se necessário (se o
necessidade não requer esta última funcionalidade, então o `ARCOM' deve ser redefinido para não
referência `RANLIB').

O método `Library' permite que a mesma biblioteca seja especificada em vários métodos
invocações. Todos os objetos contribuintes de todas as invocações (que podem ser de
diretórios diferentes) são combinados e gerados por um único comando de arquivo. Observação,
no entanto, se você remover uma compilação para que apenas parte de uma biblioteca seja especificada, somente
essa parte da biblioteca será gerada (o resto desaparecerá!).

A 'Módulo' método

O método 'Módulo' é uma combinação dos métodos 'Programa' e 'Comando'. Ao invés de
gerando um programa executável diretamente, este comando permite que você especifique seu próprio
comando para realmente gerar um módulo. O método é invocado da seguinte forma:

Módulo $env , , ;

Este comando é útil em instâncias onde você deseja criar, por exemplo, dinamicamente
módulos carregados ou bibliotecas de código vinculadas estaticamente.

A 'Depende' método

O método `Depends' permite especificar dependências adicionais para um destino. Isto é
invocado da seguinte forma:

Depende $env , ;

Isso pode ser útil ocasionalmente, especialmente nos casos em que não existe scanner (ou é
gravável) para tipos específicos de arquivos. Normalmente, as dependências são calculadas
automaticamente a partir de uma combinação das dependências explícitas configuradas pelo método
invocação ou varrendo os arquivos de origem.

Um conjunto de dependências idênticas para vários destinos pode ser especificado usando uma referência a
uma lista de alvos. Em Perl, uma referência de lista pode ser criada colocando uma lista no quadrado
colchetes. Daí o seguinte comando:

Depende $env ['foo', 'bar'], 'input_file_1', 'input_file_2';

especifica que tanto o Foo e Barra arquivos dependem dos arquivos de entrada listados.

A 'Ignorar' método

O método 'Ignore' permite que você ignore explicitamente as dependências que Cons infere em seu
ter. É invocado da seguinte forma:

Ignorar ;

Isso pode ser usado para evitar recompilações devido a alterações nos arquivos de cabeçalho do sistema ou
utilitários que são conhecidos por não afetarem os destinos gerados.

Se, por exemplo, um programa for criado em um diretório montado em NFS em vários sistemas que
tem cópias diferentes de estúdio.h, as diferenças afetarão as assinaturas de todos
alvos derivados criados a partir de arquivos de origem que `#include '. Isso fará com que todos
esses alvos sejam reconstruídos ao mudar os sistemas. Se este não for um comportamento desejável,
então a linha a seguir removerá as dependências no estúdio.h arquivo:

Ignore '^/usr/include/stdio\.h$';

Observe que os argumentos para o método 'Ignore' são expressões regulares, então
caracteres devem ser escapados e você pode querer ancorar o início ou o fim do
expressão com caracteres `^' ou `$'.

A 'Sal' método

O método 'Sal' adiciona um valor constante ao cálculo de assinatura para cada
Arquivo. É invocado da seguinte forma:

Sal $string;

Alterar o valor Salt forçará uma reconstrução completa de cada arquivo derivado. Isso pode ser
usado para forçar reconstruções em certas circunstâncias desejadas. Por exemplo,

Sal `uname -s`;

Forçaria uma reconstrução completa de cada arquivo derivado sempre que o sistema operacional em
qual a construção é executada (conforme relatado por `uname -s').

A `UseCache' método

O método `UseCache' instrui o Cons a manter um cache de arquivos derivados, a serem compartilhados
entre árvores de construção separadas do mesmo projeto.

UseCache("cache/ ") ⎪⎪ warn("diretório de cache não encontrado");

A `SourcePath' método

O método `SourcePath' retorna o nome do caminho de origem real de um arquivo, em oposição ao
nome do caminho dentro de um diretório de compilação. É invocado da seguinte forma:

$path = SourcePath ;

A `ConsPath' método

O método `ConsPath' retorna true se o caminho fornecido for um arquivo derivável e retorna
undef (falso) caso contrário. É invocado da seguinte forma:

$resultado = ConsPath ;

A `SplitPath' método

O método `SplitPath' procura vários nomes de caminho em uma string separada pelo padrão
separador de caminho para o sistema operacional (':' em sistemas UNIX, ';' no Windows NT) e
retorna os nomes totalmente qualificados. É invocado da seguinte forma:

@paths = SplitPath ;

O método `SplitPath' converterá nomes prefixados '#' para a compilação de nível superior apropriada
name (sem o '#') e converterá nomes relativos em nomes de nível superior.

A `DirPath' método

O método `DirPath' retorna o caminho de compilação nome(s) de um diretório ou lista de diretórios.
É invocado da seguinte forma:

$cwd = DirPath ;

O uso mais comum para o método `DirPath' é:

$cwd = DirPath '.';

para buscar o caminho para o diretório atual de uma subsidiária Recruta arquivo.

A `FilePath' método

O método `FilePath' retorna o caminho de compilação nome(s) de um arquivo ou lista de arquivos. Isto é
invocado da seguinte forma:

$arquivo = Caminho do Arquivo ;

A 'Ajuda' método

O método `Help' especifica o texto de ajuda que será exibido quando o usuário invocar `cons
-h'. Isso pode ser usado para fornecer documentação de alvos específicos, valores, construção
opções, etc. para a árvore de construção. É invocado da seguinte forma:

Ajuda ;

O método 'Help' pode ser chamado apenas uma vez, e normalmente deve ser especificado no top-
nível Construir arquivo.

Estendendo Desvantagens


Substituindo formação variáveis

Existem várias maneiras de estender Cons, que variam em grau de dificuldade. O mais simples
método é definir seu próprio ambiente de construção, com base no ambiente padrão,
mas modificado para refletir suas necessidades particulares. Isso geralmente será suficiente para sistemas baseados em C
formulários. Você pode usar o construtor `new' e os métodos `clone' e `copy' para
criar ambientes híbridos. Essas mudanças podem ser totalmente transparentes para o
Recruta arquivos.

Adicionando novo métodos

Para mudanças um pouco mais exigentes, você pode querer adicionar novos métodos aos `cons'
pacote. Aqui está um exemplo de uma extensão muito simples, `InstallScript', que instala um
tcl em um local solicitado, mas edita o script primeiro para refletir uma plataforma-
caminho dependente que precisa ser instalado no script:

# contras::InstallScript - Cria uma versão dependente de plataforma de um shell
# script substituindo a string ``#!your-path-here'' por uma plataforma específica
# caminho $BIN_DIR.

contras::InstallScript {
meu ($env, $dst, $src) = @_;
Comando $env $dst, $src, qq(
sed s+seu-caminho-aqui+$BIN_DIR+ %< > %>
chmod oug+x %>
);
}

Observe que este método é definido diretamente no pacote `cons' (prefixando o nome
com `cons::'). Uma mudança feita dessa maneira será globalmente visível para todos os ambientes,
e poderia ser chamado como no exemplo a seguir:

InstallScript $env "$BIN/foo", "foo.tcl";

Para uma pequena melhoria na generalidade, a variável 'BINDIR' pode ser passada como um
argumento ou retirado do ambiente de construção--como `%BINDIR'.

Substituindo métodos

Em vez de adicionar o método ao espaço de nomes `cons', você pode definir um novo pacote
que herda os métodos existentes do pacote `cons' e substitui ou adiciona outros. Isto
pode ser feito usando os mecanismos de herança do Perl.

O exemplo a seguir define um novo pacote `cons::switch' que substitui o padrão
método 'Biblioteca'. O método substituído cria módulos de biblioteca vinculados, em vez de biblioteca
arquivos. Um novo construtor é fornecido. Ambientes criados com este construtor irão
ter o novo método de biblioteca; outros não.

contras do pacote::switch;
BEGIN {@ISA = 'cons'}

sub-novo {
mudança;
abençoe novos contras(@_);
}

subbiblioteca {
meu($env) = deslocamento;
meu($lib) = deslocamento;
my(@objs) = Objetos $env @_;
Comando $env $lib, @objs, q(
%LD -r %LDFLAGS %< -o %>
);
}

Essa funcionalidade pode ser invocada como no exemplo a seguir:

$env = new contras::switch(@overrides);
...
Biblioteca $env 'lib.o', 'foo.c', 'bar.c';

Invocando Desvantagens


O comando `cons' geralmente é invocado a partir da raiz da árvore de construção. UMA Construir lima
deve existir nesse diretório. Se o argumento `-f' for usado, então uma alternativa Construir
arquivo pode ser usado (e, possivelmente, uma raiz alternativa, já que `cons' irá cd para Construir
diretório que contém o arquivo).

Se `cons' for invocado de um filho da raiz da árvore de construção com o argumento `-t', ele
percorrerá a hierarquia de diretórios procurando por um Construir Arquivo. (Um nome alternativo pode
ainda será especificado com `-f'.) Os alvos fornecidos na linha de comando serão modificados
ser relativo ao descoberto Construir Arquivo. Por exemplo, de um diretório contendo
um nível superior Construir arquivo, a seguinte invocação:

% cd libfoo/subdiretório
% contras -t alvo

é exatamente equivalente a:

% contras libfoo/subdir/target

Se houver algum destino 'Padrão' especificado na hierarquia de diretórios Construir or
Recruta arquivos, apenas os alvos padrão no diretório ou abaixo do qual `cons -t'
foi invocado será construído.

O comando é invocado da seguinte forma:

contras --

onde argumentos pode ser qualquer um dos seguintes, em qualquer ordem:

alvo Crie o destino especificado. Se alvo é um diretório, então construa recursivamente
tudo dentro desse diretório.

+padrão Limite o Recruta arquivos considerados apenas aqueles que correspondem de cinto de segurança, o que é
uma expressão regular Perl. Vários argumentos `+' são aceitos.

nome=
Conjuntos nome dar valor onda no hash 'ARG' passado para o nível superior Construir arquivo.

`-cc' Mostra o comando que teria sido executado, ao recuperar do cache. Não
é fornecida a indicação de que o arquivo foi recuperado; isso é útil para
gerando logs de compilação que podem ser comparados com logs de compilação reais.

`-cd' Desativa todo o cache. Não recupere do cache nem libere para o cache.

`-cr' Cria dependências em ordem aleatória. Isso é útil ao construir vários
árvores semelhantes com cache habilitado.

`-cs' Sincroniza os destinos de compilação existentes que estão atualizados com o cache.
Isso é útil se o cache foi desabilitado com -cc ou habilitado recentemente
com UseCache.

`-d' Habilita a depuração de dependência.

`-f'
Use o arquivo especificado em vez de Construir (mas primeiro mude para conter
diretório de lima).

`-h' Mostra uma mensagem de ajuda local para a compilação atual se uma estiver definida e sai.

`-k' Continue indo o mais longe possível após os erros.

`-o'
Ler arquivo de substituição lima.

`-p' Mostra produtos de construção em árvores especificadas. Nenhuma construção é tentada.

`-pa' Mostra produtos de construção e ações associadas. Nenhuma construção é tentada.

`-pw' Mostra os produtos e onde eles são definidos. Nenhuma construção é tentada.

`-q' Não seja prolixo sobre a instalação e remoção de alvos.

`-r' Remove produtos de construção associados a . Nenhuma construção é tentada.

`-R'
Pesquisar arquivos em repos. Múltiplo -R repos diretórios são pesquisados ​​no
pedido especificado.

`-t' Percorre a hierarquia de diretórios procurando por um Construir arquivo, se não existir
no diretório atual. Os alvos serão modificados para serem relativos ao
Construir arquivo.

`-v' Mostra a versão dos `cons' e continua o processamento.

`-V' Mostra a versão dos `cons' e sai.

`-wf'
Escreva todos os nomes de arquivos considerados em lima.

`-x' Mostra uma mensagem de ajuda semelhante a esta e sai.

E argumentos de construção podem ser quaisquer argumentos que você deseja processar no Construir arquivo.
Observe que deve haver uma -- separando os argumentos para contras e os argumentos que você
deseja processar no Construir arquivo.

Processamento de argumentos de construção pode ser feito por qualquer pacote padrão como Obter opção ou do seu
variantes ou qualquer pacote definido pelo usuário. contras vai passar no argumentos de construção as @ARGV e
não tentará interpretar nada após o --.

% cons -R /usr/local/repositório -d os=solaris +driver -- -c test -f DEBUG

passaria o seguinte para os contras

-R /usr/local/repositório -d os=solaris +driver

e o seguinte, para o nível superior Construir arquivo como @ARGV

-c teste -f DEBUG

Observe que `cons -r .' é equivalente a um 'make clean' recursivo completo, mas não requer
apoio no Construir arquivo ou qualquer Recruta arquivos. Isso é mais útil se você estiver
compilar arquivos em diretórios de origem (se você separar o construir e exportar diretórios,
então você pode simplesmente remover os diretórios).

As opções `-p', `-pa' e `-pw' são extremamente úteis para uso como auxílio na leitura
scripts ou depurá-los. Se você quiser saber qual script instala exportar/incluir/foo.h,
por exemplo, basta digitar:

% contras -pw export/include/foo.h

utilização e escrita dependência scanners


O QuickScan permite que simples scanners independentes de destino sejam configurados para arquivos de origem. Somente
um scanner QuickScan pode ser associado a qualquer arquivo de origem e ambiente.

O QuickScan é invocado da seguinte forma:

QuickScan CONSENV CODEREF, NOME DO ARQUIVO [, CAMINHO]

Espera-se que a sub-rotina referenciada pelo CODEREF retorne uma lista de nomes de arquivos incluídos
diretamente pelo FILE. Esses nomes de arquivo, por sua vez, serão verificados. O argumento PATH opcional
fornece um caminho de pesquisa para localizar FILENAME e/ou arquivos retornados pelo usuário fornecido
sub-rotina. O PATH pode ser uma referência a uma matriz de nomes de diretórios de pesquisa ou um
seqüência de nomes separados pelo caractere separador do sistema (':' em sistemas UNIX, ';' em
WindowsNT).

A sub-rotina é chamada uma vez para cada linha do arquivo, com $_ definido para a linha atual.
Se a sub-rotina precisar examinar linhas adicionais ou, nesse caso, todo o arquivo,
então ele pode lê-los por si mesmo, a partir do arquivo SCAN. Ele também pode encerrar o loop, se
ele sabe que nenhuma informação de inclusão adicional está disponível, fechando o filehandle.

Seja ou não fornecido um caminho de pesquisa, o QuickScan primeiro tenta pesquisar o arquivo
em relação ao diretório atual (para o arquivo de nível superior fornecido diretamente ao QuickScan),
ou do diretório que contém o arquivo que fez referência ao arquivo. Isso não é muito
geral, mas parece bom o suficiente - especialmente se você tem o luxo de escrever seu próprio
utilitários e pode controlar o uso do caminho de pesquisa de maneira padrão. finalmente, o
o caminho de pesquisa é, atualmente, separado por dois pontos. Isso pode não deixar o acampamento do NT feliz.

Aqui está um exemplo real, tirado de um Construir arquivo aqui:

contras::SMFgen {
meu($env, @tables) = @_;
foreach $t (@tabelas) {
$env->QuickScan(sub { /\b\S*?\.smf\b/g }, "$t.smf",
$env->{SMF_INCLUDE_PATH});
$env->Comando(
["$t.smdb.cc","$t.smdb.h","$t.snmp.cc","$t.ami.cc", "$t.http.cc"],
"$t.smf",
q(
smfgen %( %SMF_INCLUDE_OPT %) %
)
);
}
}

[OBSERVE que o formulário `$env->QuickScan ...' e `$env->Command ...' não deve ser
necessário, mas, por algum motivo, é necessário para essa invocação específica. Isso aparece
ser um bug em Perl ou um mal-entendido da minha parte; este estilo de invocação não
sempre parece ser necessário.]

Isso encontra todos os nomes do formulário .smf no arquivo. Ele retornará os nomes mesmo se
eles são encontrados nos comentários, mas tudo bem (o mecanismo perdoa arquivos extras;
eles são apenas ignorados na suposição de que o arquivo ausente será notado quando o
programa, neste exemplo, smfgen, é realmente invocado).

Um scanner só é invocado para um determinado arquivo de origem se for necessário para algum destino no
árvore. Ele só é invocado uma vez para um determinado arquivo de origem.

Aqui está outra maneira de construir o mesmo scanner. Este usa uma referência de código explícita,
e também (desnecessariamente, neste caso) lê o próprio arquivo inteiro:

sub myscan {
meu(@inclui);
fazer {
push(@inclui, /\b\S*?\.smf\b/g);
} enquanto ;
@inclui
}

Observe que a ordem do loop é invertida, com o teste de loop no final. Isto é
porque a primeira linha já está lida para você. Este scanner pode ser conectado a uma fonte
arquivo por:

QuickScan $env \myscan, "$_.smf";

SUPPORT E SUGESTÕES


Cons é mantido pela comunidade de usuários. Para se inscrever, envie um e-mail para contras-discutir-
[email protegido] com corpo Inscreva-se.

Por favor, relate quaisquer sugestões através do [email protegido] lista de discussão.

Use contras online usando os serviços onworks.net


Servidores e estações de trabalho gratuitos

Baixar aplicativos Windows e Linux

  • 1
    turcodevops
    turcodevops
    TurkDevOps a ? K kaynak yaz? L? M
    geli? tirici topluluklar? DevTurks-Team
    Tarafāndan desteklenmektedir..
    Recursos: https://github.com/turkdevops https://turkdevops.g...
    Baixar turkdevops
  • 2
    asammdf
    asammdf
    * asammdf * é um analisador Python rápido e
    editor para ASAM (Associação para
    Padronização da Automação e
    Sistemas de Medição) MDF / MF4
    (Formato de dados de medição ...
    Baixar asammdf
  • 3
    LAME (codificador Lame Aint an MP3)
    LAME (codificador Lame Aint an MP3)
    LAME é uma ferramenta educacional para ser usada
    para aprender sobre a codificação de MP3. o
    objetivo do projeto LAME é melhorar
    a psicoacústica, qualidade e rapidez
    de deputado...
    Baixar LAME (Lame não é um codificador de MP3)
  • 4
    wxPython
    wxPython
    Um conjunto de módulos de extensão Python que
    envolva as classes GUI multiplataforma de
    wxWidgets.. Público: Desenvolvedores. Do utilizador
    interface: Sistema X Window (X11), Win32 ...
    Baixar wxPython
  • 5
    gerenciador de arquivos de pacote
    gerenciador de arquivos de pacote
    Este é o gerenciador de arquivos do pacote Total War
    projeto, a partir da versão 1.7. UMA
    breve introdução ao Warscape
    Modificação: ...
    Baixar packfilemanager
  • 6
    IPerf2
    IPerf2
    Uma ferramenta de tráfego de rede para medir
    Desempenho de TCP e UDP com métricas
    em torno da taxa de transferência e da latência. o
    objetivos incluem manter um ativo
    iperf cod ...
    Baixar IPerf2
  • Mais "

Comandos Linux

Ad