IngleseFranceseSpagnolo

Ad


Favicon di OnWorks

contro - Online nel cloud

Esegui contro nel provider di hosting gratuito OnWorks su Ubuntu Online, Fedora Online, emulatore online di Windows o emulatore online di MAC OS

Questo è il contro del comando che può essere eseguito nel provider di hosting gratuito OnWorks utilizzando una delle nostre molteplici workstation online gratuite come Ubuntu Online, Fedora Online, emulatore online Windows o emulatore online MAC OS

PROGRAMMA:

NOME


Contro - Un sistema di costruzione del software

DESCRIZIONE


Una guida e un riferimento per la versione 2.2.0

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

Questo programma è un software gratuito; puoi ridistribuirlo e/o modificarlo secondo i termini di
la GNU General Public License come pubblicata dalla Free Software Foundation; o
versione 2 della Licenza o (a tua scelta) qualsiasi versione successiva.

Questo programma è distribuito nella speranza che possa essere utile, ma SENZA ALCUNA GARANZIA;
senza nemmeno la garanzia implicita di COMMERCIABILITÀ o IDONEITÀ PER UN PARTICOLARE SCOPO.
Vedere la GNU General Public License per maggiori dettagli.

Dovresti aver ricevuto una copia della GNU General Public License insieme a questo programma;
vedere il file COPIA. In caso contrario, scrivi alla Free Software Foundation, Inc., 59 Temple
Luogo - Suite 330, Boston, MA 02111-1307, USA.

Introduzione


Svantaggi è un sistema per costruire, principalmente, software, ma è abbastanza diverso da
precedenti sistemi di costruzione del software. Contro è stato progettato da zero per affrontare
facilmente con la costruzione di software distribuito su più directory di origine. contro
semplifica la creazione di script di compilazione semplici, comprensibili e gestibili.
Contro garantisce che il software complesso sia facilmente e accuratamente riproducibile.

Contro utilizza una serie di tecniche per ottenere tutto questo. Gli script di costruzione sono giusti
script Perl, che li rendono facili da comprendere e molto flessibili. Scopo globale di
viene sostituita con un meccanismo di importazione/esportazione per la condivisione delle informazioni tra
script, migliorando notevolmente la leggibilità e la manutenibilità di ogni script.
Costruzione ambienti vengono introdotti: si tratta di oggetti Perl che catturano il file
informazioni necessarie per controllare il processo di compilazione. Vengono utilizzati più ambienti
quando è richiesta una semantica diversa per generare prodotti nell'albero di build. contro
implementa l'analisi delle dipendenze automatica e la usa per sequenziare globalmente l'intero
costruire. Le build delle varianti sono facilmente prodotte da un unico albero di origine. Costruzione intelligente
il sottoinsieme è possibile, quando si lavora su modifiche localizzate. È possibile impostare le sostituzioni
sovrascrivere facilmente le istruzioni di compilazione senza modificare alcuno script. Crittografico MD5
firme sono associati a file derivati ​​e vengono utilizzati per determinare con precisione se
un determinato file deve essere ricostruito.

Pur offrendo tutto quanto sopra e altro, Cons rimane semplice e facile da usare. Questo sarà,
si spera, diventi chiaro mentre leggi il resto di questo documento.

Perché Contro? Perché non Rendere?


Contro è un make sostituzione. Nei paragrafi seguenti, esaminiamo alcuni dei
caratteristiche indesiderabili di make - e tipici ambienti di build basati su make - that
motivato lo sviluppo della Cons.

Costruire complessità

I tradizionali sistemi basati su make di qualsiasi dimensione tendono a diventare piuttosto complessi. La marca originale
l'utilità ei suoi derivati ​​hanno contribuito a questa tendenza in diversi modi. Fare è
non è bravo a gestire sistemi distribuiti su più directory. Vari lavori-
i giri sono usati per superare questa difficoltà; la scelta abituale è quella di far invocare
stesso in modo ricorsivo per ogni sottodirectory di una build. Questo porta a codice complicato, in
che spesso non è chiaro come viene impostata una variabile o quale effetto sull'impostazione di una variabile
avrà sulla build nel suo insieme. Il linguaggio di scripting make è stato gradualmente esteso
per fornire più possibilità, ma queste sono servite in gran parte a ingombrare già
linguaggio sovraesteso. Spesso, le build vengono eseguite in più passaggi per fornire
prodotti appropriati da una directory a un'altra directory. Questo rappresenta un ulteriore
aumento della complessità costruttiva.

Costruire riproducibilità

La rovina di tutte le marche è sempre stata la corretta gestione delle dipendenze. Molto spesso, un
si tenta di eseguire un lavoro ragionevole di dipendenze all'interno di una singola directory, ma no
viene fatto un serio tentativo di eseguire il lavoro tra le directory. Anche quando le dipendenze lo sono
funzionando correttamente, fare affidamento su un semplice confronto di timestamp per determinare se
un file non è aggiornato rispetto ai suoi dipendenti non è, in generale, adeguato per
determinare quando un file deve essere riconvertito. Se una libreria esterna, ad esempio, lo è
ricostruito e poi ``scattato'' in posizione, i timestamp sui suoi file appena creati potrebbero
ben prima dell'ultima costruzione locale, poiché fu costruita prima che diventasse visibile.

Variante costruisce

Make fornisce solo funzionalità limitate per la gestione delle build di varianti. Con la proliferazione
di piattaforme hardware e la necessità di codice di cui è possibile eseguire il debug rispetto a codice ottimizzato, la capacità di
creare facilmente queste varianti è essenziale. Ancora più importante, se vengono create varianti, esso
è importante poter separare le varianti o essere in grado di riprodurle
originale o variante a piacimento. Con make è molto difficile separare le build in
più directory di build, separate dalla sorgente. E se questa tecnica non viene utilizzata,
è anche praticamente impossibile garantire in qualsiasi momento in quale variante sia presente
l'albero, senza ricorrere a una ricostruzione completa.

repository

Make fornisce solo un supporto limitato per la creazione di software dal codice esistente in a
struttura di directory del repository centrale. La funzionalità VPATH di GNU make (e altri
make implementazioni) ha lo scopo di fornire questo, ma non funziona come previsto: it
cambia il percorso del file di destinazione nel nome VPATH troppo presto nella sua analisi, e quindi
cerca tutte le dipendenze nella directory VPATH. Per garantire un corretto sviluppo
builds, è importante essere in grado di creare un file in una directory di build locale e avere
qualsiasi file in un repository di codice (una directory VPATH, in termini make) che dipende dal locale
il file viene ricostruito correttamente. Questo non è possibile con VPATH, senza codificare molto
conoscenza complessa del repository direttamente nei makefile.

conservazione it semplice


Alcune delle difficoltà con make sono state citate sopra. In questo e nei successivi
sezioni, introdurremo i contro e mostreremo come vengono affrontati questi problemi.

Perl script

Contro è basato su Perl. Cioè, gli script Contro...coscritto ed Costruire file, l'equivalente
a Makefile or makefile--sono tutti scritti in Perl. Ciò fornisce un vantaggio immediato: il
il linguaggio per scrivere gli script è familiare. Anche se non sei un Perl
programmatore, aiuta sapere che Perl è fondamentalmente solo un semplice linguaggio dichiarativo,
con un flusso di controllo ben definito e una semantica familiare. Ha variabili che si comportano
fondamentalmente nel modo in cui ti aspetteresti che lo facessero, subroutine, flusso di controllo e così via. Là
non è stata introdotta una sintassi speciale per Cons. L'uso di Perl come linguaggio di scripting
semplifica il compito di esprimere la soluzione adeguata a ciò che spesso è complesso
requisiti di una build.

Ciao, Mondo!

Per fondare la seguente discussione, ecco come potresti costruire il Ciao, Mondo! C
applicazione con Contro:

$env = nuovo cons();
Programma $env 'ciao', 'ciao.c';

Se installi questo script in una directory, dai un nome allo script Costruiree crea il file
Ciao C sorgente nella stessa directory, quindi puoi digitare `cons hello' per creare il file
applicazione:

% contro ciao
cc -c ciao.c -o ciao.o
cc -o ciao ciao.o

Costruzione ambienti

Una semplificazione chiave di Contro è l'idea di a costruzione ambiente. Una costruzione
l'ambiente è un oggetto caratterizzato da un insieme di coppie chiave/valore e da un insieme di metodi.
Per dire a Cons come costruire qualcosa, invochi il metodo appropriato tramite un
ambiente di costruzione appropriato. Considera il seguente esempio:

$env = nuovi contro(
CC => 'gcc',
LIBS => 'libworld.a'
);

Programma $env 'ciao', 'ciao.c';

In questo caso, invece di utilizzare l'ambiente di costruzione predefinito, come è, abbiamo
sovrascritto il valore di `CC' in modo da utilizzare invece l'equivalente GNU C Compiler. Da quando
questa versione di Ciao, Mondo! richiede una biblioteca, libworld.a, abbiamo specificato che qualsiasi
il programma collegato in questo ambiente dovrebbe essere collegato a quella libreria. Se la biblioteca
esiste già, bene e bene, ma in caso contrario, dovremo includere anche l'affermazione:

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

Ora se digiti `cons ciao', la libreria verrà creata prima che il programma sia collegato e,
ovviamente, `gcc' verrà utilizzato per compilare entrambi i moduli:

% contro ciao
gcc -c ciao.c -o ciao.o
gcc -c mondo.c -o mondo.o
ar libworld.a world.o
ar: creazione di libworld.a
ranliblibworld.a
gcc -o ciao ciao.o libworld.a

Automatico ed completamento di una dipendenza .

Con Contro, le dipendenze vengono gestite automaticamente. Continuando l'esempio precedente, nota
che quando modifichiamo mondo.c, mondo.o viene ricompilato, libworld.a ricreato, e Ciao
ricollegato:

% vi mondo.c
[MODIFICARE]
% contro ciao
gcc -c mondo.c -o mondo.o
ar libworld.a world.o
ar: creazione di libworld.a
ranliblibworld.a
gcc -o ciao ciao.o libworld.a

Questo è un esempio relativamente semplice: Contro ``sa'' mondo.o dipende da mondo.c, perché
la dipendenza è esplicitamente impostata dal metodo `Library'. Lo sa anche libworld.a
dipende da mondo.o e che Ciao dipende da libworld.a, tutto per ragioni simili.

Ora si scopre che Ciao C include anche il file di definizione dell'interfaccia, mondo.h:

% emacs mondo.h
[MODIFICARE]
% contro ciao
gcc -c ciao.c -o ciao.o
gcc -o ciao ciao.o libworld.a

Come fa Cons a saperlo Ciao C inclusi mondo.h, e quello ciao.o deve quindi essere
ricompilato? Per ora, basti dire che quando si considera se o meno ciao.o è su-
ad oggi, Cons invoca uno scanner per la sua dipendenza, Ciao C. Questo scanner enumera il
file inclusi da Ciao C per elaborare un elenco di ulteriori dipendenze, oltre a quelle
esplicitato dal copione Cons. Questo processo è ricorsivo: tutti i file inclusi da
anche i file inclusi verranno scansionati.

Non è costoso? La risposta è, dipende. Se si esegue una build completa di un sistema di grandi dimensioni,
il tempo di scansione è insignificante. Se esegui una ricostruzione di un sistema di grandi dimensioni, lo farà Cons
passa una buona quantità di tempo a pensarci prima che decida che nulla deve essere
fatto (anche se non necessariamente più tempo che fare!). La buona notizia è che Cons ce la fa
molto facile sottoimpostare in modo intelligente la tua build, quando stai lavorando su modifiche localizzate.

Automatico globale costruire sequenziamento

Perché Cons esegue un'analisi delle dipendenze completa e accurata e lo fa a livello globale, per il
intera build, Cons è in grado di utilizzare queste informazioni per assumere il pieno controllo del file sequenziamento
della costruzione. Questa sequenza è evidente negli esempi precedenti ed è equivalente a cosa
ti aspetteresti da make, dato un set completo di dipendenze. Con Contro, questo si estende
banalmente a build più grandi e multi-directory. Di conseguenza, tutta la complessità coinvolta
nell'assicurarsi che una build sia organizzata correttamente, inclusa la gerarchia multi-pass
builds: viene eliminato. Ne discuteremo ulteriormente nelle prossime sezioni.

Costruzione grandi alberi: fermi ad appena as semplice


A gerarchia of costruire script

Una build più grande, in Cons, è organizzata creando una gerarchia di costruire script. In cima
dell'albero è uno script chiamato Costruire. Il resto degli script, per convenzione, sono ciascuno
detto coscritto. Questi script sono collegati tra loro, molto semplicemente, da `Build',
Comandi "Esporta" e "Importa".

I Costruire command

Il comando `Build' prende un elenco di coscritto nomi di file e fa in modo che siano
incluso nella build. Per esempio:

Costruisci qw(
autisti/display/coscritto
driver/mouse/coscritto
parser/coscritto
servizi di pubblica utilità/coscritto
);

Questa è una semplice gerarchia a due livelli di script di compilazione: tutti i sussidiari coscritto file
sono menzionati nel livello superiore Costruire file. Si noti che non tutte le directory nell'albero
necessariamente avere script di build ad essi associati.

Questo potrebbe anche essere scritto come uno script multi-livello. Ad esempio, il Costruire file potrebbe
contengono questo comando:

Costruisci qw(
parser/coscritto
autisti/coscritto
servizi di pubblica utilità/coscritto
);

e la coscritto file nella driver la directory potrebbe contenere questo:

Costruisci qw(
display/coscritto
topo/coscritto
);

L'esperienza ha dimostrato che il modello precedente è un po' più facile da capire, poiché il
l'intero albero da costruzione è disposto di fronte a te, al livello più alto. Gli schemi ibridi sono
anche possibile. Un componente gestito separatamente che deve essere incorporato in a
build tree, ad esempio, potrebbe agganciarsi all'albero build in un punto, ma definirne uno proprio
gerarchia costruttiva.

Per impostazione predefinita, Cons non cambia la sua directory di lavoro nella directory contenente a
filiale coscritto file è incluso. Questo comportamento può essere abilitato per una build da
specificando, nel livello superiore Costruire file:

Coscript_chdir 1;

Quando abilitato, Cons passerà alla sussidiaria coscritto la directory contenente il file
durante la lettura in quel file, quindi tornare alla directory di livello superiore una volta che il file
è stato processato.

Si prevede che questo comportamento diventi l'impostazione predefinita in alcune versioni future di Cons.
Per prepararsi a questa transizione, le build che prevedono che i Cons rimangano in cima alla build
mentre si legge in una sussidiaria coscritto file dovrebbe disabilitare esplicitamente questa funzione come
segue:

Coscript_chdir 0;

Parente, parente superiore, ed assoluto filetto nomi

Potresti aver notato che i nomi dei file specificati nel comando Build sono relativi a
la posizione dello script da cui viene richiamato. Questo è generalmente vero per altri nomi di file
argomenti anche per altri comandi, anche se potremmo anche menzionarlo qui se inizi
un nome di file con un cancelletto, ``#'', quindi quel file viene interpretato rispetto al top-
directory di livello (dove il file Costruire risiede il file). E, non sorprendentemente, se lo inizi
con ``/'', allora è considerato un percorso assoluto. Questo vale anche sui sistemi
che utilizzano una barra rovesciata anziché una barra in avanti per nominare percorsi assoluti.

utilizzando moduli in costruire script

Puoi inserire moduli in ciascuno coscritto file usando il normale Perl 'usa' o 'richiedi'
dichiarazioni:

Usa l'inglese;
richiedono My::Modulo;

Ogni 'uso' o 'richiede' riguarda solo quello coscritto file in cui appare. Per usare un
modulo in più coscritto file, è necessario inserire un'istruzione "use" o "require" in ciascuno
uno che ha bisogno del modulo.

Obbiettivo of variabili

Il livello più alto Costruire file e tutto coscritto i file iniziano la vita in un Perl comune e separato
pacchetto. Svantaggi controlla la tabella dei simboli per il pacchetto in modo che, la tabella dei simboli per
ogni script è vuoto, ad eccezione di Costruire file, che ottiene parte della riga di comando
argomenti. Tutte le variabili impostate o utilizzate, quindi, sono impostate dallo script
stesso--non da qualche script esterno.

Le variabili possono essere esplicitamente importati da uno script dal suo script padre. Per importare un
variabile, dev'essere stato esportati dal genitore e inizializzato (altrimenti un errore
si verificherà).

I Esportare command

Il comando 'Esporta' viene utilizzato come nell'esempio seguente:

$env = nuovo cons();
$INCLUDE = "#esporta/includi";
$LIB = "#esportazione/libreria";
Esporta qw( env INCLUDE LIB );
Build qw(util/Conscript);

I valori delle variabili semplici menzionate nell'elenco 'Esporta' verranno eliminati
da qualsiasi successivo comando "Build". Il comando 'Esporta' esporterà solo Perl scalare
variabili, ovvero variabili il cui nome inizia con `$'. Altre variabili, oggetti, ecc.
può essere esportato per riferimento, ma tutti gli script faranno riferimento allo stesso oggetto e questo
l'oggetto dovrebbe essere considerato di sola lettura dagli script sussidiari e dall'originale
script di esportazione. È tuttavia accettabile assegnare un nuovo valore allo scalare esportato
variabile--che non cambierà la variabile sottostante a cui si fa riferimento. Questa sequenza, per
esempio, va bene:

$env = nuovo cons();
Esporta qw( env INCLUDE LIB );
Build qw(util/Conscript);
$env = new cons(CFLAGS => '-O');
Build qw(altro/Coscritto);

Non importa se la variabile è impostata prima o dopo il comando 'Esporta'. Il
l'importante è il valore della variabile nel momento in cui viene eseguito il comando 'Build'.
Questo è ciò che viene scoiattolo via. Qualsiasi successivo comando "Esporta", a proposito,
invalida la prima: devi menzionare tutte le variabili che desideri esportare su ciascuna
comando 'Esporta'.

I Importare command

Le variabili esportate dal comando 'Esporta' possono essere importate in script sussidiari dal
Comando 'Importa'. Lo script sussidiario importa sempre le variabili direttamente da
sceneggiatura superiore. Considera questo esempio:

Importa qw( env INCLUDE );

Questo è legale solo se lo script padre ha esportato sia `$env' che `$INCLUDE'. Deve anche
hanno dato valori a ciascuna di queste variabili. Va bene solo per lo script sussidiario
importare un sottoinsieme delle variabili esportate (in questo esempio, `$LIB', che è stato esportato da
l'esempio precedente non è importato).

Tutte le variabili importate vengono riesportate automaticamente, quindi la sequenza:

Importa qw ( env INCLUDE );
Build qw (under-me/Coscript);

fornirà sia `$env' che `$INCLUDE' al file sussidiario. Se solo `$env' dovesse essere
esportato, sarà sufficiente quanto segue:

Importa qw ( env INCLUDE );
Esporta qw ( ambiente );
Build qw (under-me/Coscript);

Inutile dire che le variabili possono essere modificate localmente prima di invocare "Build" sul file
sceneggiatura sussidiaria.

Costruire copione valutazione minimo

L'unico vincolo sull'ordine degli script di compilazione è che lo sono gli script superiori
valutati prima dei loro script inferiori. Il livello superiore Costruire il file, ad esempio, è
valutato per primo, seguito da eventuali script inferiori. Questo è tutto ciò che devi davvero sapere
sull'ordine di valutazione, poiché l'ordine è generalmente irrilevante. Considera quanto segue
Comando 'Costruisci':

Costruisci qw(
autisti/display/coscritto
driver/mouse/coscritto
parser/coscritto
servizi di pubblica utilità/coscritto
);

Abbiamo scelto di mettere i nomi degli script in ordine alfabetico, semplicemente perché è il massimo
conveniente per la manutenzione. La modifica dell'ordine non farà alcuna differenza per il
costruire.

A Modello per compartecipazione file


Alcuni semplice convenzioni

In qualsiasi sistema software complesso, deve esistere un metodo per condividere i prodotti di build
stabilito. Proponiamo un semplice insieme di convenzioni con cui è banale implementare
Contro, ma molto efficace.

La regola di base è richiedere che tutti costruiscano prodotti che devono essere condivisi tra
le directory sono condivise tramite una directory intermedia. In genere abbiamo chiamato questo
exporte, in un ambiente C, fornite le sottodirectory convenzionali di questa directory,
ad esempio includere, lib, bidone, ecc.

Queste directory sono definite dal livello superiore Costruire file. Un semplice Costruire file per
a Ciao, Mondo! l'applicazione, organizzata utilizzando più directory, potrebbe apparire così:

# Costruisci file per Hello, World!

# Dove mettere tutti i nostri prodotti condivisi.
$ESPORTA = '#esporta';

Esporta qw( CONS INCLUDE LIB BIN );

# Directory standard per la condivisione dei prodotti.
$INCLUDE = "$ESPORTA/includi";
$LIB = "$ESPORTA/libreria";
$BIN = "$ESPORTA/bin";

# Un ambiente di costruzione standard.
$CONS = nuovi svantaggi (
CPPPATH => $INCLUDE, # Include il percorso per le compilazioni C
LIBPATH => $LIB, # Percorso della libreria per il collegamento dei programmi
LIBS => '-lworld', # Elenco di librerie standard
);

Costruisci qw(
ciao/coscritto
mondo/coscritto
);

I mondo directory coscritto il file ha questo aspetto:

# File di coscrizione per il mondo delle directory
Importa qw( CONS INCLUDE LIB );

# Installa i prodotti di questa directory
Installa $CONS $LIB, 'libworld.a';
Installa $CONS $INCLUDE, 'world.h';

# Prodotti interni
Libreria $CONS 'libworld.a', 'world.c';

e la Ciao directory coscritto il file ha questo aspetto:

# File di coscrizione per la directory ciao
Importa qw( CONS BIN );

# Prodotti esportati
Installa $CONS $BIN, 'ciao';

# Prodotti interni
Programma $CONS 'ciao', 'ciao.c';

Per costruire un file Ciao, Mondo! programma con questa struttura di directory, vai al livello superiore
directory e invocare `cons' con gli argomenti appropriati. Nel seguente esempio, noi
di' a Cons di creare la directory export. Per creare una directory, Cons compila ricorsivamente tutto
prodotti conosciuti all'interno di quella directory (solo se devono essere ricostruiti, ovviamente). Se qualcuno di
quei prodotti dipendono da altri prodotti in altre directory, quindi verranno creati,
troppo.

% contro esportazione
Installa world/world.h come export/include/world.h
cc -Iexport/include -c ciao/ciao.c -o ciao/ciao.o
cc -Iexport/include -c mondo/mondo.c -o mondo/mondo.o
ar r mondo/libworld.a mondo/world.o
ar: creazione del mondo/libworld.a
mondo ranlib/libworld.a
Installa world/libworld.a come export/lib/libworld.a
cc -o ciao/ciao ciao/ciao.o -Lexport/lib -lworld
Installa ciao/ciao come export/bin/ciao

Pulito, comprensibile, indipendente dalla posizione script

Noterai che i due coscritto i file sono molto puliti e al punto. Semplicemente
specificare i prodotti della directory e come creare tali prodotti. Le istruzioni per la costruzione
sono minimi: specificano quale ambiente di costruzione utilizzare, il nome del prodotto,
e il nome degli ingressi. Nota anche che gli script sono indipendenti dalla posizione: se tu
desideri riorganizzare il tuo albero dei sorgenti, sei libero di farlo: devi solo cambiare il
Costruire (in questo esempio), per specificare le nuove posizioni del file coscritto File. Il
l'uso di un albero di esportazione rende facile questo obiettivo.

Nota anche come Cons si prende cura dei piccoli dettagli per te. Tutti i export directory, per
esempio, sono stati realizzati automaticamente. E i file installati erano davvero hard-linkati nel file
rispettive directory di esportazione, per risparmiare spazio e tempo. Questa attenzione ai dettagli salva
notevole lavoro e rende ancora più semplice la produzione di script semplici e gestibili.

Separare source ed costruire alberi


È spesso desiderabile mantenere tutti i file derivati ​​dalla build completamente separati dal file
file sorgenti. Ciò rende molto più semplice tenere traccia di ciò che è un file sorgente e
lo rende anche più semplice da maneggiare variante build, specialmente se vuoi le build varianti
di coesistere.

Separare costruire ed source directory utilizzando , il Link command

Contro fornisce un meccanismo semplice che gestisce tutti questi requisiti. Il "collegamento"
il comando viene invocato come in questo esempio:

Link 'build' => 'src';

Le directory specificate sono ``collegate'' alla directory sorgente specificata. Supponiamo
che hai impostato una directory di origine, src, con le sottodirectory mondo ed Ciao sotto di esso,
come nell'esempio precedente. È quindi possibile sostituire le linee di costruzione originali con il file
seguenti:

Costruisci qw(
build/mondo/coscritto
build/ciao/coscritto
);

Nota che tratti il coscritto file come se esistesse nella directory build. Ora se
digiti lo stesso comando di prima, otterrai i seguenti risultati:

% contro esportazione
Installa build/world/world.h come export/include/world.h
cc -Iexport/include -c build/ciao/ciao.c -o build/ciao/ciao.o
cc -Iexport/include -c build/mondo/mondo.c -o build/mondo/mondo.o
ar r build/world/libworld.a build/world/world.o
ar: creazione di build/world/libworld.a
ranlib build/world/libworld.a
Installa build/world/libworld.a come export/lib/libworld.a
cc -o build/ciao/ciao build/ciao/ciao.o -Lexport/lib -lworld
Installa build/hello/hello come export/bin/hello

Ancora una volta, Cons si è preso cura dei dettagli per te. In particolare, noterai che tutto
le build vengono eseguite utilizzando i file sorgente e i file oggetto dalla directory build. Per
esempio, costruire/mondo/mondo.o è compilato da build/mondo/mondo.ce
esporta/includi/mondo.h è installato da build/mondo/mondo.h. Questo è realizzato sulla maggior parte
sistemi con il semplice espediente di collegare ``hard'' i file richiesti da ogni sorgente
directory nella directory di build appropriata.

I collegamenti sono gestiti correttamente da Cons, indipendentemente da ciò che fai nella directory di origine.
Se modifichi un file sorgente, il tuo editor può farlo "sul posto" o può rinominarlo
prima e creare un nuovo file. In quest'ultimo caso, qualsiasi hard link andrà perso. I contro lo faranno
rileva questa condizione la prossima volta che è necessario il file di origine e lo ricollegherà
appropriatamente.

Noterai anche, tra l'altro, che no erano necessarie modifiche al sottostante coscritto
File. E possiamo andare oltre, come vedremo nella prossima sezione.

Variante costruisce


Ciao, Mondo! per Banana ed pesca OS

Le build di varianti richiedono solo un'altra semplice estensione. Prendiamo come esempio a
requisito per consentire build per entrambi i sistemi operativi baNaNa e peAcH. In questo caso,
stiamo usando un file system distribuito, come NFS per accedere a un particolare sistema, e
solo l'uno o l'altro dei sistemi deve essere compilato per ogni data invocazione di
`contro'. Ecco un modo in cui potremmo impostare il Costruire file per il nostro Ciao, Mondo!
applicazione:

# Costruisci file per Hello, World!

die qq(è necessario specificare il sistema operativo) a meno che $OS = $ARG{OS};
die qq(il sistema operativo deve essere "pesca" o "banana")
se $OS ne "pesca" && $OS ne "banana";

# Dove mettere tutti i nostri prodotti condivisi.
$ESPORTA = "#esporta/$OS";

Esporta qw( CONS INCLUDE LIB BIN );

# Directory standard per la condivisione dei prodotti.
$INCLUDE = "$ESPORTA/includi";
$LIB = "$ESPORTA/libreria";
$BIN = "$ESPORTA/bin";

# Un ambiente di costruzione standard.
$CONS = nuovi svantaggi (
CPPPATH => $INCLUDE, # Include il percorso per le compilazioni C
LIBPATH => $LIB, # Percorso della libreria per il collegamento dei programmi
LIBS => '-lworld', # Elenco di librerie standard
);

# $BUILD è dove trarremo tutto.
$BUILD = "#build/$OS";

# Indica ai contro dove si trovano i file di origine per $BUILD.
Collegamento $BUILD => 'src';

Costruire (
"$BUILD/ciao/Coscritto",
"$BUILD/mondo/Coscritto",
);

Ora, se accediamo a un sistema peAcH, possiamo costruire il nostro Ciao, Mondo! domanda per quello
piattaforma:

% contro export OS=pesca
Installa build/peach/world/world.h come export/peach/include/world.h
cc -Iexport/peach/include -c build/peach/ciao/ciao.c -o build/peach/ciao/ciao.o
cc -Iexport/peach/include -c build/peach/mondo/mondo.c -o build/peach/mondo/mondo.o
ar r build/peach/world/libworld.a build/peach/world/world.o
ar: creazione di build/peach/world/libworld.a
ranlib build/peach/world/libworld.a
Installa build/peach/world/libworld.a come export/peach/lib/libworld.a
cc -o build/peach/ciao/ciao build/peach/ciao/ciao.o -Lexport/peach/lib -lworld
Installa build/peach/hello/hello come export/peach/bin/hello

Variazioni on a tema

Sono possibili altre varianti di questo modello. Ad esempio, potresti decidere di volerlo
per separare i file di inclusione in file dipendenti dalla piattaforma e file indipendenti dalla piattaforma.
In questo caso, dovresti definire un'alternativa a `$INCLUDE' per dipendente dalla piattaforma
File. Più coscritto i file, generando file di inclusione puramente indipendenti dalla piattaforma, lo farebbero
non devi cambiare.

Potresti anche voler essere in grado di compilare l'intero sistema con il debug o la profilazione,
ad esempio, abilitato. Puoi farlo con le opzioni della riga di comando appropriate, come
`DEBUG=attivo'. Questo verrebbe quindi tradotto nell'appropriato specifico della piattaforma
requisiti per abilitare il debug (questo potrebbe includere la disattivazione dell'ottimizzazione, per
esempio). È possibile facoltativamente variare lo spazio dei nomi per questi diversi tipi di sistemi,
ma, come vedremo nella prossima sezione, non lo è essential per fare questo, dal momento che Cons è carino
intelligente nel ricostruire le cose quando cambi le opzioni.

firme


MD5 crittografico firme

Ogni volta che Cons crea un file derivato, memorizza a firma per quel file. La firma
è memorizzato in un file separato, uno per directory. Dopo aver compilato l'esempio precedente,
, il .consegnare file nella costruire/pesca/mondo la directory era simile a questa:

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

Il primo numero è un timestamp: per un sistema UNIX, questo è in genere il numero di
secondi dal 1 gennaio 1970. Il secondo valore è un checksum MD5. Il Messaggio digerire
Algoritmo è un algoritmo che, data una stringa di input, calcola una crittografia forte
firma per quella stringa. Il checksum MD5 memorizzato nel file .consegnare il file è, in effetti, a
digest di tutte le informazioni sulle dipendenze per il file specificato. Quindi, ad esempio, per il
mondo.o file, questo include almeno il mondo.c file, e anche eventuali file di intestazione che Cons
sa che sono inclusi, direttamente o indirettamente da mondo.c. Non solo quello, ma il
riga di comando effettiva che è stata utilizzata per generare mondo.o viene inserito anche nel calcolo di
la firma. Allo stesso modo, libworld.a ottiene una firma che ``include'' tutti i
firme dei suoi costituenti (e quindi, transitivamente, le firme di loro
costituenti), nonché la riga di comando che ha creato il file.

La firma di un file non derivato viene calcolata, di default, prendendo la corrente
l'ora di modifica del file e il nome della voce del file (a meno che non ci sia a
corrente .consegnare voce per quel file, nel qual caso viene utilizzata quella firma).

Si noti che non è necessario che un file derivato dipenda da alcun particolare Costruire or
coscritto file: se le modifiche a questi file influiscono sul file in questione, lo sarà
riflesso automaticamente nella sua firma, poiché le parti rilevanti della riga di comando lo sono
incluso nella firma. Le modifiche non correlate non avranno effetto.

Quando Cons valuta se derivare un file particolare, calcola prima il
firma prevista del file. Quindi confronta l'ora dell'ultima modifica del file con
il tempo registrato nel .consegnare voce, se ne esiste una. Se questi tempi corrispondono, allora il
firma conservata nel .consegnare file è considerato accurato. Se il file è precedente
la firma non corrisponde alla nuova firma prevista, quindi il file deve essere riconvertito.

Si noti che un file verrà riconvertito ogni volta che cambia qualcosa su un file dipendente. In
particolare, notalo in qualsiasi passare all'ora di modifica di un dipendente (avanti o
indietro nel tempo) forzerà la ricompilazione del file derivato.

L'uso di queste firme è un metodo estremamente semplice, efficiente ed efficace
migliorare – drasticamente – la riproducibilità di un sistema.

Lo dimostreremo con un semplice esempio:

# Semplice "Ciao mondo!" Costruisci file
$CFLAGS = '-g' se $ARG{DEBUG} eq 'on';
$CONS = nuovi contro(CFLAGS => $CFLAGS);
Programma $CONS 'ciao', 'ciao.c';

Nota come Cons si ricompila al momento opportuno:

% contro ciao
cc -c ciao.c -o ciao.o
cc -o ciao ciao.o
% contro ciao
contro: "ciao" è aggiornato.
% contro DEBUG=on ciao
cc -g -c ciao.c -o ciao.o
cc -o ciao ciao.o
% contro DEBUG=on ciao
contro: "ciao" è aggiornato.
% contro ciao
cc -c ciao.c -o ciao.o
cc -o ciao ciao.o

Code repository


Molte organizzazioni di sviluppo software avranno una o più directory di repository centrali
alberi contenenti il ​​codice sorgente corrente per uno o più progetti, nonché il derivato
file oggetto, librerie ed eseguibili. Al fine di ridurre la ricompilazione non necessaria,
è utile utilizzare i file del repository per creare software di sviluppo, supponendo, di
ovviamente, che nessun file di dipendenza più recente esiste nell'albero di build locale.

Repository

Contro fornisce un meccanismo per specificare un elenco di repository di codice che verranno cercati,
in ordine, per i file di origine e i file derivati ​​non trovati nell'albero della directory di build locale.

Le righe seguenti in a Costruire il file indicherà a Cons di guardare prima sotto il file
/usr/esperimento/repository directory e quindi sotto il /usr/prodotto/repository directory:

Archivio qw (
/usr/esperimento/repository
/usr/prodotto/repository
);

Le directory del repository specificate possono contenere file di origine, file derivati ​​(oggetti,
librerie ed eseguibili), o entrambi. Se non è presente alcun file locale (sorgente o derivato) in
la directory in cui viene eseguito Cons, quindi la prima copia di un file omonimo trovato
in una directory di repository verrà utilizzato per creare qualsiasi file derivato locale.

Contro mantiene un elenco globale di directory di repository. I contro elimineranno il
directory corrente e tutte le directory inesistenti dall'elenco.

Trovare , il Costruire filetto in a Repository

Anche i contro cercheranno Costruire ed coscritto file nell'albero o negli alberi del repository.
Questo porta a una situazione di pollo e uova, però: come si guarda in un albero di repository
per Costruire file se il Costruire il file ti dice dove si trova il repository? Ottenere
intorno a questo, i repository possono essere specificati tramite le opzioni `-R' sulla riga di comando:

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

Qualsiasi directory di repository specificata in Costruire or coscritto i file verranno aggiunti
alle directory del repository specificate dalle opzioni `-R' della riga di comando.

Repository source file

Se il codice sorgente (includere il coscritto file) per la versione libreria di Ciao,
Mondo! L'applicazione C si trova in un repository (senza file derivati), Contro utilizzerà il file
file di origine del repository per creare i file oggetto locali e il file eseguibile:

% contro -R /usr/src_only/repository ciao
gcc -c /usr/src_only/repository/ciao.c -o ciao.o
gcc -c /usr/src_only/repository/world.c -o world.o
ar libworld.a world.o
ar: creazione di libworld.a
ranliblibworld.a
gcc -o ciao ciao.o libworld.a

La creazione di un file di origine locale farà sì che Cons ricostruisca il file derivato appropriato o
File:

% pico mondo.c
[MODIFICARE]
% contro -R /usr/src_only/repository ciao
gcc -c mondo.c -o mondo.o
ar libworld.a world.o
ar: creazione di libworld.a
ranliblibworld.a
gcc -o ciao ciao.o libworld.a

E la rimozione del file di origine locale farà sì che Cons torni a creare il derivato
file dalla fonte del repository:

% rm mondo.c
% contro -R /usr/src_only/repository ciao
gcc -c /usr/src_only/repository/world.c -o world.o
ar libworld.a world.o
ar: creazione di libworld.a
ranliblibworld.a
gcc -o ciao ciao.o libworld.a

Repository derivati file

Se un albero del repository contiene file derivati ​​(in genere file oggetto, librerie o
eseguibili), Cons eseguirà il suo normale calcolo della firma per decidere se il
il file repository è aggiornato oppure è necessario creare un file derivato in locale. Ciò significa che,
per garantire un corretto calcolo della firma, un albero di repository deve contenere anche il file
.consegnare file che sono stati creati da Cons durante la generazione dei file derivati.

Questo di solito sarebbe ottenuto costruendo il software nel repository (o,
in alternativa, in una directory build e quindi copiando il risultato nel repository):

% cd /usr/all/repository
% contro ciao
gcc -c ciao.c -o ciao.o
gcc -c mondo.c -o mondo.o
ar libworld.a world.o
ar: creazione di libworld.a
ranliblibworld.a
gcc -o ciao ciao.o libworld.a

(Questo è sicuro anche se il Costruire file elenca il /usr/tutti/repository directory in a
Comando `Repository' perché Cons rimuoverà la directory corrente dal repository
elenco.)

Ora, se vogliamo creare una copia dell'applicazione con la nostra Ciao C file, abbiamo solo bisogno
per creare l'unico file sorgente necessario e utilizzare l'opzione `-R' per fare in modo che i Cons ne usino altri
file dal repository:

% mkdir $HOME/build1
% cd $HOME/build1
% ed ciao.c
[MODIFICARE]
% contro -R /usr/all/repository ciao
gcc -c ciao.c -o ciao.o
gcc -o ciao ciao.o /usr/all/repository/libworld.a

Si noti che Cons non si è preoccupato di ricreare un locale libworld.a libreria (o ricompilare il file
mondo.o module), ma usa invece la versione già compilata dal repository.

Perché le firme MD5 che Cons inserisce nel file .consegnare il file contiene timestamp per il
file derivati, i timestamp della firma devono corrispondere ai timestamp del file per una firma
essere considerato valido.

Alcuni sistemi software possono alterare i timestamp sui file di repository (copiandoli,
es), nel qual caso Cons, per impostazione predefinita, presumerà che le firme del repository non siano valide
e ricostruire i file inutilmente. Questo comportamento può essere modificato specificando:

Repository_Sig_Times_OK 0;

Questo dice a Cons di ignorare i timestamp quando si decide se una firma è valida. (Nota
che evitare questo controllo di integrità significa che ci deve essere un controllo adeguato sul repository
tree per garantire che i file derivati ​​non possano essere modificati senza aggiornare il file .consegnare
firma.)

Locali copie of file

Se l'albero del repository contiene i risultati completi di una build, e proviamo a costruire da
il repository senza alcun file nel nostro albero locale, qualcosa di moderatamente sorprendente
succede:

% mkdir $HOME/build2
% cd $HOME/build2
% contro -R /usr/all/repository ciao
contro: "ciao" è aggiornato.

Perché Contro dice che il Ciao il programma è aggiornato quando non ci sono Ciao programma in
la directory di build locale? Poiché il repository (non la directory locale) contiene il file
up-to-date Ciao programma e Cons determina correttamente che non è necessario eseguire alcuna operazione
ricostruire questa copia aggiornata del file.

Ci sono, tuttavia, molte volte in cui è opportuno garantire che una copia locale di a
il file esiste sempre. Uno script di confezionamento o test, ad esempio, può presupporre che sia certo
i file generati esistono localmente. Invece di rendere consapevoli questi script sussidiari del
repository, il comando `Local' può essere aggiunto a a Costruire or coscritto file per
specificare che un determinato file o file devono apparire nella directory di build locale:

qw locale(
Ciao
);

Quindi, se eseguiamo nuovamente lo stesso comando, Cons eseguirà una copia locale del programma dal file
copia del repository (dicendoti che lo sta facendo):

% contro -R /usr/all/repository ciao
Copia locale di ciao da /usr/all/repository/hello
contro: "ciao" è aggiornato.

Si noti che, poiché l'atto di fare la copia locale non è considerato una "costruzione" del file
Ciao file, Contro segnala ancora che è aggiornato.

La creazione di copie locali è molto utile per i file che vengono installati in un
directory intermedia (per la condivisione con altre directory) tramite il comando 'Installa'.
Accompagnare il comando "Installa" per un file con un comando complementare "Locale" è così
comune che Cons fornisca un comando `Install_Local' come un modo conveniente per fare entrambe le cose:

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

è esattamente equivalente a:

Installa $env '#export', 'hello';
Locale '#esporta/ciao';

Entrambi i comandi `Local' e `Install_Local' aggiornano il local .consegnare depositare presso la
firme di file appropriate, in modo che le build future vengano eseguite correttamente.

Repository dipendenza .

Grazie alla sua scansione integrata, Cons cercherà gli alberi del repository specificati per inclusi
.h File. A meno che il compilatore non conosca anche gli alberi del repository, lo sarà
incapace di trovare .h file che esistono solo in un repository. Se, ad esempio, il Ciao C
il file include il Ciao h file nella sua directory corrente:

% contro -R /usr/all/repository ciao
gcc -c /usr/all/repository/ciao.c -o ciao.o
/usr/all/repository/hello.c:1: hello.h: nessun file o directory di questo tipo

Risolvere questo problema impone alcuni requisiti sul modo in cui sono gli ambienti di costruzione
definito e sul modo in cui la direttiva del preprocessore C `#include' viene utilizzata per includere i file.

Per informare il compilatore sugli alberi del repository, Cons aggiungerà l'appropriato `-I'
flag ai comandi di compilazione. Ciò significa che la variabile `CPPPATH' nel file
costruire l'ambiente deve specificare in modo esplicito tutte le sottodirectory in cui eseguire la ricerca
per i file inclusi, inclusa la directory corrente. Di conseguenza, possiamo correggere quanto sopra
esempio modificando la creazione dell'ambiente in Costruire file come segue:

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

A causa della definizione della variabile 'CPPPATH', questo produce, quando eseguiamo nuovamente il file
comando:

% contro -R /usr/all/repository ciao
gcc -c -I. -I/usr/all/repository /usr/all/repository/ciao.c -o ciao.o
gcc -o ciao ciao.o /usr/all/repository/libworld.a

L'ordine dei flag `-I' replica, per il preprocessore C, lo stesso repository-
percorso di ricerca della directory che Cons utilizza per la propria analisi delle dipendenze. Se ci sono
più repository e più directory `CPPPATH', Cons aggiungerà il repository
directory all'inizio di ogni directory `CPPPATH', moltiplicando rapidamente il numero
di flag `-I'. Come esempio estremo, a Costruire file contenente:

Archivio qw(
/u1
/u2
);

$env = nuovi contro(
CPPPATH => 'a:b:c',
);

Darebbe un comando di compilazione di:

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

Perché Cons si basa sui flag `-I' del compilatore per comunicare l'ordine in cui
le directory del repository devono essere cercate, la gestione delle directory del repository da parte di Contro lo è
fondamentalmente incompatibile con l'uso di doppie virgolette sulle direttive `#include' nel tuo C
codice sorgente:

#include "file.h" /* NON UTILIZZARE DOPPIE CITAZIONI COME QUESTE */

Questo perché la maggior parte dei preprocessori C, di fronte a una tale direttiva, sarà sempre per prima
cercare nella directory contenente il file di origine. Questo mina l'elaborato `-I'
opzioni che Cons costruisce per rendere il preprocessore conforme alla sua ricerca preferita
sentiero.

Di conseguenza, quando si utilizzano alberi di repository in Cons, sempre utilizzare staffe angolari per incluso
File:

#includere /* UTILIZZA INVECE STAFFE ANGOLARI */

Elenco_repository

Contro fornisce un comando `Repository_List' per restituire un elenco di tutte le directory del repository
nel loro attuale ordine di ricerca. Questo può essere utilizzato per il debug o per eseguire Perl più complessi
cose:

@lista = Elenco_repository;
print join(' ', @list), "\n";

Repository interazione con Altro Svantaggi Caratteristiche

La gestione degli alberi del repository da parte dei contro interagisce correttamente con altre funzionalità dei contro, il che è
per dire, generalmente fa quello che ti aspetteresti.

In particolare, gli alberi dei repository interagiscono correttamente e in modo piuttosto potente con il "Link"
comando. Un albero di repository può contenere una o più sottodirectory per le build delle versioni
stabilito tramite `Link' a una sottodirectory di origine. I contro cercheranno i file derivati ​​in
le sottodirectory di build appropriate sotto l'albero del repository.

Predefinito obiettivi


Fino ad ora, abbiamo dimostrato di invocare i contro con un obiettivo esplicito da costruire:

% contro ciao

Normalmente, Cons non compila nulla a meno che non venga specificato un target, ma specificando '.'
(la directory corrente) costruirà tutto:

% cons # non crea nulla

% contro. # costruisce tutto nella directory di primo livello

Aggiunta del metodo 'Predefinito' a qualsiasi Costruire or coscritto il file aggiungerà il specificato
destinazioni a un elenco di destinazioni predefinite. I contro costruiranno queste impostazioni predefinite se non ci sono
obiettivi specificati nella riga di comando. Quindi aggiungendo la seguente riga al livello superiore
Costruire il file imiterà il comportamento tipico di Make di creare tutto per impostazione predefinita:

Predefinito '.';

Quanto segue aggiungerebbe il Ciao ed addio comandi (nella stessa directory di
Costruire or coscritto file) nell'elenco predefinito:

qw predefinito(
Ciao
addio
);

Il metodo 'Predefinito' può essere utilizzato più di una volta per aggiungere destinazioni all'elenco predefinito.

Selettivo costruisce


Contro fornisce due metodi per ridurre le dimensioni di una data build. Il primo è specificando
target sulla riga di comando e il secondo è un metodo per sfoltire l'albero di compilazione. Bene
considerare prima la specifica del target.

Selettivo mira

Come make, Cons consente la specifica di ``target'' sulla riga di comando. Contro obiettivi
possono essere file o directory. Quando viene specificata una directory, questo è semplicemente un breve
notazione a mano per ogni prodotto derivabile - di cui Cons è a conoscenza - nello specificato
directory e sotto. Per esempio:

% contro build/ciao/ciao.o

significa costruire ciao.o e tutto ciò che ciao.o potrebbe aver bisogno. Questo è di un precedente
versione del Ciao, Mondo! programma in cui ciao.o dipendeva da
esporta/includi/mondo.h. Se quel file non è aggiornato (perché qualcuno ha modificato
sorgente/mondo/mondo.h), verrà ricostruito, anche se si trova in una directory remota da
costruire/ciao.

In questo esempio:

% contro build

Tutto in costruire viene creata la directory, se necessario. Anche in questo caso, ciò potrebbe causare più file
essere costruito. In particolare, entrambi esporta/includi/mondo.h ed export/lib/libworld.a sono
richiesto da costruire/ciao directory, e quindi verranno compilati se non sono aggiornati.

Se invece lo facciamo:

% contro esportazione

quindi verranno ricostruiti solo i file che dovrebbero essere installati nella directory di esportazione, se
necessario e quindi installato lì. Nota che `cons build' potrebbe creare file che `cons
export' non viene compilato e viceversa.

Non ``speciale'' obiettivi

Con Cons, non sono richiesti obiettivi "speciali" in stile make. L'analogo più semplice con Cons
è usare speciale export directory, invece. Supponiamo, ad esempio, di avere a
intera serie di unit test associati al tuo codice. Le prove vivono nel
directory sorgente vicino al codice. Normalmente, tuttavia, non si desidera creare questi test.
Una soluzione consiste nel fornire tutte le istruzioni di compilazione per la creazione dei test e quindi per
installare i test in una parte separata dell'albero. Se installiamo i test in un livello superiore
directory chiamata test, Allora:

% contro test

costruirà tutti i test.

% contro esportazione

creerà la versione di produzione del sistema (ma non i test) e:

% contro build

dovrebbe probabilmente essere evitato (poiché compilerà test inutilmente).

Se vuoi creare un solo test, puoi nominare esplicitamente il test (in
sia la test directory o il costruire directory). Potresti anche aggregare i test
in una comoda gerarchia all'interno della directory test. Questa gerarchia non è necessaria
corrisponde necessariamente alla gerarchia di origine, più o meno allo stesso modo della gerarchia di inclusione
probabilmente non corrisponde alla gerarchia di origine (è improbabile che la gerarchia di inclusione sia maggiore
di due livelli di profondità, per i programmi C).

Se vuoi costruire assolutamente tutto nell'albero (soggetto a qualsiasi opzione tu
seleziona), puoi utilizzare:

% contro.

Questo non è particolarmente efficiente, dal momento che camminerà in modo ridondante su tutti gli alberi,
compreso l'albero di origine. L'albero dei sorgenti, ovviamente, potrebbe contenere oggetti costruibili
it--niente ti impedisce di farlo, anche se normalmente costruisci in una build separata
albero.

Costruire Potatura


Insieme alla selezione del target, costruire potatura può essere utilizzato per ridurre la portata del
costruire. Nel precedente esempio di peAcH e baNaNa, abbiamo già visto come sia guidato da script
l'eliminazione delle build può essere utilizzata per rendere disponibile solo la metà della build potenziale per qualsiasi dato
invocazione di `cons'. Contro fornisce anche, per comodità, una convenzione da riga di comando che
permette di specificare quale coscritto i file vengono effettivamente ``costruiti'', cioè incorporati
nell'albero di costruzione. Per esempio:

% contro build + mondo

L'argomento `+' introduce un'espressione regolare Perl. Questo deve, ovviamente, essere citato a
il livello della shell se sono presenti metacaratteri della shell all'interno dell'espressione. Il
l'espressione viene confrontata con ciascuna coscritto file che è stato menzionato in una `Build'
e solo gli script con nomi corrispondenti sono effettivamente incorporati in
costruire albero. Sono consentiti più argomenti di questo tipo, nel qual caso una corrispondenza contro uno qualsiasi di essi
è sufficiente per includere uno script.

Nell'esempio sopra, il Ciao programma non verrà costruito, poiché i Cons avranno n
conoscenza della sceneggiatura ciao/coscritto. libworld.a l'archivio verrà costruito, tuttavia, se
bisogno di essere.

Ci sono un paio di usi per l'eliminazione delle build tramite la riga di comando. Forse il più utile
è la capacità di apportare modifiche locali e quindi, con sufficiente conoscenza del
conseguenze di tali modifiche, limitare le dimensioni dell'albero di compilazione per accelerare
il tempo di ricostruzione. Un secondo utilizzo per la potatura di build è prevenire attivamente la ricompilazione
di alcuni file che sai verranno ricompilati a causa, ad esempio, di un file di intestazione modificato.
Potresti sapere che le modifiche al file di intestazione sono irrilevanti o che il file
le modifiche possono essere tranquillamente ignorate per la maggior parte dell'albero, a scopo di test. Con Contro, il
Il punto di vista è che è pragmatico ammettere questo tipo di comportamento, con la consapevolezza che
nella prossima build completa sarà tutto ciò che deve essere ricostruito. Non esiste un equivalente
a un comando ``make touch'', per contrassegnare i file come costantemente aggiornati. Quindi qualsiasi rischio che sia
sostenute dalla potatura di build è mitigata. Per lavori di qualità di rilascio, ovviamente, consigliamo
che non utilizzi l'eliminazione della build (è perfettamente OK da usare durante l'integrazione, tuttavia,
per controllare la compilazione, ecc. Assicurati solo di eseguire una build non vincolata prima di eseguire il commit
l'integrazione).

Temporaneo sostituisce


Contro fornisce un meccanismo molto semplice per ignorare gli aspetti di una build. L'essenza è
che scrivi un file di override contenente uno o più comandi "Override" e tu
specificalo sulla riga di comando, quando esegui `cons':

% contro -o sull'esportazione

costruirà il export directory, con tutti i file derivati ​​soggetti alle sostituzioni presenti
nel ancora file. Se si omette l'opzione `-o', allora tutto il necessario per rimuovere
tutte le sostituzioni verranno ricostruite.

Override ambiente variabili

Il file di sostituzione può contenere due tipi di sostituzione. Il primo è l'ambiente in entrata
variabili. Questi sono normalmente accessibili dal Costruire file dall'hash `%ENV'
variabile. Questi possono essere banalmente sovrascritti nel file di override impostando il
elementi appropriati di `%ENV' (questi potrebbero anche essere sovrascritti nell'ambiente dell'utente,
ovviamente).

I Override command

Il secondo tipo di override viene eseguito con il comando 'Override', che sembra
Questo:

Oltrepassare , => , => , ...;

L'espressione regolare regexp viene confrontato con ogni file derivato che è un candidato
per la costruzione. Se il file derivato corrisponde, vengono utilizzate le coppie variabile/valore
sovrascrivere i valori nell'ambiente di costruzione associati al file derivato.

Supponiamo di avere un ambiente di costruzione come questo:

$CONS = nuovi contro(
COPT => '',
CDBG => '-g',
CFLAGS => '%COPT %CDBG',
);

Quindi se abbiamo un file di override ancora contenente questo comando:

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

quindi qualsiasi chiamata `cons' con `-o over' che crea .o i file tramite questo ambiente lo faranno
farli compilare con `-O 'e senza `-g'. L'override potrebbe, ovviamente, essere
limitato a una singola directory dalla selezione appropriata di un'espressione regolare.

Ecco la versione originale di Hello, World! programma, costruito con questo ambiente.
Si noti che Cons ricostruisce i pezzi appropriati quando viene applicata o rimossa la sostituzione:

% contro ciao
cc -g -c ciao.c -o ciao.o
cc -o ciao ciao.o
% contro -o ciao
cc -O -c ciao.c -o ciao.o
cc -o ciao ciao.o
% contro -o ciao
contro: "ciao" è aggiornato.
% contro ciao
cc -g -c ciao.c -o ciao.o
cc -o ciao ciao.o

È importante che il comando 'Sostituisci' venga utilizzato solo per operazioni temporanee, al volo
sostituzioni necessarie per lo sviluppo perché le sostituzioni non sono indipendenti dalla piattaforma e
perché si basano troppo sulla conoscenza intima del funzionamento delle sceneggiature. Per
uso temporaneo, tuttavia, sono esattamente quello che vuoi.

Si noti che è comunque utile fornire, ad esempio, la possibilità di creare un file completamente ottimizzato
versione di un sistema per uso di produzione--dal Costruire ed coscritto File. Per di qua
puoi adattare il sistema ottimizzato alla piattaforma. Dove devono esserci i compromessi dell'ottimizzatore
made (ad esempio file particolari potrebbero non essere compilati con l'ottimizzazione completa), quindi
questi possono essere registrati per i posteri (e riproducibilità) direttamente negli script.

Più on costruzione ambienti


Predefinito costruzione variabili

Abbiamo menzionato, e utilizzato, il concetto di a costruzione ambiente, molte volte nel
pagine precedenti. Ora è il momento di renderlo un po' più concreto. Con quanto segue
dichiarazione:

$env = nuovo cons();

viene creato un riferimento a un nuovo ambiente di costruzione predefinito. Questo contiene un numero
delle variabili di costruzione e di alcuni metodi. Allo stato attuale, l'elenco predefinito di
le variabili di costruzione sono definite come segue:

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',
COME => 'come',
ASFLAGS => '',
ASCOM => '%AS %ASFLAGS %< -o %>',
LD => 'ld',
LDFLAGS => '',
PREFLIB => 'lib',
SUFLIB => '.a',
SUFLIBS => '.so:.a',
SUFOJ => '.o',
ENV => { 'PERCORSO' => '/bidone:/ Usr / bin' },

Sui sistemi Win32 (Windows NT), le seguenti variabili di costruzione vengono sovrascritte nel file
di 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 => 'collegamento',
LDFLAGS => '/nologo ',
PREFISSO => '',
SUFEXE => '.exe',
SUFLIB => '.lib',
SUFLIBS => '.dll:.lib',
SUFOJ => '.obj',

Queste variabili sono utilizzate dai vari metodi associati all'ambiente, in
in particolare qualsiasi metodo che alla fine invochi un comando esterno li sostituirà
variabili nel comando finale, a seconda dei casi. Ad esempio, il metodo 'Oggetti' accetta
un certo numero di file sorgente e provvede a ricavare, se necessario, l'oggetto corrispondente
File. Per esempio:

Oggetti $env 'pippo.c', 'bar.c';

Questo provvederà a produrre, se necessario, foo.o ed bar.o. Il comando invocato è semplicemente
`%CCCOM', che si espande tramite la sostituzione, al comando esterno appropriato richiesto
per costruire ogni oggetto. Esploreremo ulteriormente le regole di sostituzione sotto il "Comando"
metodo, di seguito.

Le variabili di costruzione vengono utilizzate anche per altri scopi. Ad esempio, `CPPPATH' è
utilizzato per specificare un percorso separato da due punti delle directory di inclusione. Questi sono destinati ad essere
passato al preprocessore C e sono utilizzati anche dal macchinario di scansione di file C
determinare le dipendenze coinvolte in una compilazione C. Variabili che iniziano con
underscore, sono creati con vari metodi e dovrebbero normalmente essere considerati ``interni''
variabili. Ad esempio, quando viene chiamato un metodo che richiede la creazione di un oggetto
da un sorgente C viene creata la variabile `_IFLAGS': questa corrisponde agli switch `-I'
richiesto dal compilatore C per rappresentare le directory specificate da `CPPPATH'.

Si noti che, per qualsiasi ambiente particolare, il valore di una variabile viene impostato una volta, quindi
non reimpostare mai (per modificare una variabile, è necessario creare un nuovo ambiente. I metodi sono forniti
per copiare ambienti esistenti a questo scopo). Alcune variabili interne, come
Gli `_IFLAGS' vengono creati su richiesta, ma una volta impostati rimangono fissi per tutta la vita del
ambiente.

Le variabili 'CFLAGS', 'LDFLAGS' e 'ARFLAGS' forniscono tutte un posto per passare le opzioni a
rispettivamente il compilatore, il caricatore e l'archiviatore. Meno ovviamente, l'"INCDIRPREFIX"
variabile specifica la stringa di opzione da aggiungere all'inizio di ogni inclusione
directory in modo che il compilatore sappia dove trovare .h File. Allo stesso modo, il
La variabile `LIBDIRPREFIX' specifica la stringa di opzione da aggiungere all'inizio di
ogni directory in cui il linker dovrebbe cercare le librerie.

Un'altra variabile, `ENV', viene utilizzata per determinare l'ambiente del sistema durante l'esecuzione
di un comando esterno. Per impostazione predefinita, l'unica variabile di ambiente impostata è "PATH",
che è il percorso di esecuzione di un comando UNIX. Per la massima riproducibilità, dovresti
organizza davvero per impostare il tuo percorso di esecuzione, nel tuo livello superiore Costruire file (o
magari importando un pacchetto di costruzione appropriato con il comando Perl `use'). Il
le variabili predefinite hanno lo scopo di farti decollare.

Interpolazione costruzione variabili

Le variabili dell'ambiente di costruzione possono essere interpolate nei nomi dei file di origine e di destinazione
anteponendo il nome della variabile di costruzione a `%'.

$env = nuovi contro(
DESTDIR => 'programmi',
SRCDIR => 'src',
);
Programma $env '%DESTDIR/hello', '%SRCDIR/hello.c';

L'espansione delle variabili di costruzione è ricorsiva, ovvero il file Nome(s) sarà ri-
ampliato fino a non poter più effettuare sostituzioni. Se una variabile di costruzione non lo è
definita nell'ambiente, verrà sostituita la stringa nulla.

Predefinito costruzione metodi


L'elenco dei metodi di costruzione predefiniti include quanto segue:

I nuovo costruttore

Il metodo `new' è un costruttore di oggetti Perl. Cioè, non viene invocato tramite un riferimento
ad un ambiente di costruzione esistente riferimento, ma, in modo piuttosto statico, usando il nome
del Perl pacchetto dove è definito il costruttore. Il metodo viene invocato in questo modo:

$env = nuovi contro( );

L'ambiente che ottieni è benedetto nel pacchetto "cons", il che significa che lo farà
hanno associato ad esso i metodi predefiniti descritti di seguito. Costruzione individuale
le variabili possono essere sostituite fornendo coppie nome/valore in un elenco di sostituzioni. Notare che
per sovrascrivere qualsiasi variabile d'ambiente di comando (cioè qualsiasi cosa sotto 'ENV'), dovrai farlo
ignorarli tutti. Puoi aggirare questa difficoltà usando il metodo `copy' su un
ambiente di costruzione esistente.

I 'clone' metodo

Il metodo `clone' crea un clone di un ambiente di costruzione esistente e può esserlo
chiamato come nell'esempio seguente:

$env2 = $env1->clona( );

È possibile fornire sostituzioni nel solito modo per creare un ambiente diverso da
originale. Se vuoi solo un nuovo nome per lo stesso ambiente (che potrebbe essere utile quando
esportazione di ambienti in componenti esistenti), puoi semplicemente utilizzare una semplice assegnazione.

I `copia' metodo

Il metodo `copy' estrae le variabili di costruzione definite esternamente da un file
ambiente e li restituisce come un elenco di coppie nome/valore. Possono anche essere sostituzioni
a condizione, in tal caso, i valori sovrascritti verranno restituiti, a seconda dei casi. Il
l'elenco restituito può essere assegnato a un hash, come mostrato nel prototipo, di seguito, ma può anche farlo
essere manipolato in altri modi:

%env = $env1->copia( );

Anche il valore di "ENV", che è esso stesso un hash, viene copiato in un nuovo hash, quindi potrebbe essere
cambiato senza timore di intaccare l'ambiente originario. Quindi, per esempio, se davvero
vuoi sovrascrivere solo la variabile 'PATH' nell'ambiente predefinito, potresti fare il
seguenti:

%cons = new cons()->copy();
$cons{ENV}{PERCORSO} = " ";
$cons = nuovi contro(%cons);

Ciò lascerà qualsiasi altra cosa che potrebbe trovarsi nell'ambiente di esecuzione predefinito
indisturbato.

I `Installa' metodo

Il metodo `Installa' fa in modo che i file specificati vengano installati nel file specificato
directory. L'installazione è ottimizzata: il file non viene copiato se può essere collegato. Se
questo non è il comportamento desiderato, sarà necessario utilizzare un metodo diverso per installare il
file. Si chiama così:

Installa $env , ;

Si noti che, mentre i file da installare possono essere nominati arbitrariamente, solo l'ultimo
componente di ogni nome viene utilizzato per il nome di destinazione installato. Quindi, per esempio, se tu
organizzare l'installazione foo/bar in baz, questo creerà un bar file nella baz directory (non
foo/bar).

I `Installa come' metodo

Il metodo `InstallAs' organizza l'origine specificata filetto(s) da installare come il
destinazione specificata filetto(S). È necessario specificare più file come elenco di file. Il
l'installazione è ottimizzata: il file non viene copiato se può essere collegato. Se questo non è il
comportamento desiderato, sarà necessario utilizzare un metodo diverso per installare il file. è
chiamato come segue:

`InstallAs' funziona in due modi:

Installazione file singolo:

InstallAs $env TgtFile, SrcFile;

Installazione di più file:

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

Oppure, anche come:

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

Sia l'elenco di destinazione che quello di origine devono essere della stessa lunghezza.

I `Prezioso' metodo

Il metodo "Precious" chiede ai contro di non eliminare prima il file specificato o l'elenco di file
costruendoli di nuovo. Viene invocato come:

Prezioso ;

Ciò è particolarmente utile per consentire aggiornamenti incrementali alle librerie o eseguire il debug
file di informazioni che vengono aggiornati anziché ricostruiti di nuovo ogni volta. I contro continueranno
eliminare i file quando è specificato il flag `-r'.

I 'Comando' metodo

Il metodo 'Comando' è un metodo catchall che può essere utilizzato per organizzare qualsiasi esterno
comando da chiamare per aggiornare la destinazione. Per questo comando, un file di destinazione e un elenco di
gli input sono forniti. Inoltre viene fornita una o più righe di comando di costruzione come a
string (questa stringa può avere più comandi incorporati, separati da new
Linee). 'Comando' è chiamato come segue:

Comando $ambiente , , ;

La destinazione dipende dall'elenco di file di input specificato e gli input devono
essere compilato correttamente o Contro non tenterà di costruire la destinazione.

All'interno del comando di costruzione, può essere presente qualsiasi variabile dell'ambiente di costruzione
introdotto anteponendo il nome della variabile di costruzione a `%'. Questo è ricorsivo:
il comando viene ampliato fino a quando non è possibile effettuare più sostituzioni. Se una costruzione
variabile non è definita nell'ambiente, la stringa nulla verrà sostituita. UN
raddoppiato `%%' sarà sostituito da un singolo `%' nel comando di costruzione.

Ci sono diverse pseudo variabili che verranno anche ampliate:

%> Il nome del file di destinazione (in un comando multi-target, questo è sempre il primo target
menzionato).

%0 Come `%>'.

%1, %2, ..., %9
Questi si riferiscono rispettivamente al primo e al nono file di input.

%< Il set completo di input. Se qualcuno di questi è stato utilizzato altrove nel
riga di comando corrente (tramite `%1', `%2', ecc.), quindi quelli verranno eliminati dal file
elenco fornito da `%<'. Considera il seguente comando trovato in a coscritto filetto
nel test directory:

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

If TGT necessario aggiornare, ciò comporterebbe l'esecuzione del
seguenti comandi, supponendo che non sia stata stabilita alcuna rimappatura per il test
directory:

echo test/bar test/baz -i test/foo > test/tgt
echo test/foo test/baz -i test/bar >> test/tgt
echo test/foo test/bar -i test/baz >> test/tgt

Ciascuna delle pseudo variabili di cui sopra può essere seguita immediatamente da una delle seguenti
suffissi per selezionare una parte del nome del percorso espanso:

:a il percorso assoluto del nome del file
:b la directory più il nome del file privato di qualsiasi suffisso
:d la directory
:f il nome del file
:s il suffisso del nome del file
:F il nome del file privato di qualsiasi suffisso

Continuando con l'esempio precedente, `%<:f' si espande in `foo bar baz' e `%':d>
espandere a `test'.

È possibile riscrivere a livello di codice parte del comando racchiudendone parte
tra `%[' e `%]'. Questo chiamerà la variabile di costruzione denominata come prima parola
racchiuso tra parentesi come riferimento al codice Perl; verranno utilizzati i risultati di questa chiamata
per sostituire il contenuto delle parentesi nella riga di comando. Ad esempio, dato un
file di input esistente denominato tgt.in:

@keywords = qw(pippo bar baz);
$env = new cons(X_COMMA => sub { join(",", @_) });
Comando $env 'tgt', 'tgt.in', qq(
echo '# Parole chiave: %[X_COMMA @keywords %]' > %>
gatto %< >> %>
);

Questo verrà eseguito:

echo '# Parole chiave: foo,bar,baz' > tgt
gatto tgt.in >> tgt

Dopo che si è verificata la sostituzione, le stringhe di spazio bianco vengono convertite in singoli spazi vuoti e
lo spazio bianco iniziale e finale viene eliminato. Non è quindi possibile introdurre
spazio bianco di lunghezza variabile nelle stringhe passate in un comando, senza ricorrere ad alcuni
una sorta di citazione della shell.

Se viene fornita una stringa di comando su più righe, i comandi vengono eseguiti in sequenza. Se c'è
dei comandi fallisce, quindi nessuno degli altri viene eseguito e la destinazione non viene contrassegnata come
aggiornato, ovvero non viene memorizzata una nuova firma per la destinazione.

Normalmente, se tutti i comandi hanno esito positivo e restituiscono uno stato zero (o qualsiasi altra piattaforma-
è richiesta specifica indicazione di successo), quindi viene memorizzata una nuova firma per il
obbiettivo. Se un comando segnala erroneamente il successo anche dopo un errore, lo farà Contro
presupporre che il file di destinazione creato da quel comando sia accurato e aggiornato.

Si presume che la prima parola di ogni stringa di comando, dopo l'espansione, sia un eseguibile
comando ha cercato la variabile d'ambiente `PATH' (che è, a sua volta, specificata dal file
variabile di costruzione `ENV'). Se questo comando viene trovato sul percorso, lo farà il target
dipende da esso: il comando verrà quindi compilato automaticamente, se necessario. È
possibile scrivere comandi in più parti su alcune shell, separati da punto e virgola. Solo il
la prima parola di comando dipenderà, tuttavia, quindi se scrivi le tue stringhe di comando
in questo modo, devi impostare esplicitamente una dipendenza (con il metodo `Depends'), oppure
assicurati che il comando che stai utilizzando sia un comando di sistema che dovrebbe essere
a disposizione. Se non è disponibile, ovviamente riceverai un errore.

Se un comando (anche uno all'interno di un comando multi-riga) inizia con `[perl]', il resto
di quella riga di comando sarà valutata dal Perl in esecuzione invece di essere biforcata dal
guscio. Se si verifica un errore durante l'analisi del Perl o se l'espressione Perl restituisce 0 o
undef, il comando sarà considerato fallito. Ad esempio, ecco un semplice
comando che crea un file `foo' direttamente da Perl:

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

Nota che quando il comando viene eseguito, ti trovi nello stesso pacchetto di quando il Costruire
or coscritto il file è stato letto, quindi puoi chiamare le funzioni Perl che hai definito nello stesso
Costruire or coscritto file in cui compare il 'Comando':

$env = nuovo cons();
sub crea_file {
il mio $file = turno;
open(FILE, ">$file");
stampa FILE "ciao\n";
chiudi(FILE);
1 ritorno;
}
Comando $env 'pippo', "[perl] &create_file('%>')";

La stringa Perl verrà utilizzata per generare la firma per il file derivato, quindi se tu
cambia la stringa, il file verrà ricostruito. Il contenuto di qualsiasi subroutine che chiami,
tuttavia, non fanno parte della firma, quindi se si modifica una subroutine chiamata come
`create_file' sopra, il target lo farà non essere ricostruito. Avvertimento utente.

Contro normalmente stampa un comando prima di eseguirlo. Questo comportamento viene soppresso se il
il primo carattere del comando è `@'. Nota che potrebbe essere necessario separare "@" da
il nome del comando o esegui l'escape per evitare che `@cmd' assomigli a un array di virgolette Perl
operatori che eseguono l'interpolazione:

# La prima riga di comando non è corretta,
# perché "@cp" sembra un array
# alla funzione Perl qq//.
# Utilizzare invece il secondo modulo.
Comando $env 'pippo', 'pippo.in', qq(
@cp %< file temporaneo
@cp file temporaneo %>
);

Se sono presenti meta caratteri della shell in qualsiasi punto della riga di comando espansa, come `<',
`>', virgolette o punto e virgola, il comando verrà effettivamente eseguito invocando a
guscio. Ciò significa che un comando come:

cd pippo

da solo in genere fallirà, poiché non c'è nessun comando `cd' nel percorso. Ma il comando
stringa:

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

quando espanso conterrà ancora il punto e virgola del meta carattere della shell e lo sarà una shell
invocato per interpretare il comando. Poiché `cd' è interpretato da questa sub-shell, il comando
verrà eseguito come previsto.

Per specificare un comando con più destinazioni, è possibile specificare un riferimento a un elenco di
obiettivi. In Perl, un riferimento a un elenco può essere creato racchiudendo un elenco tra parentesi quadre.
Da qui il seguente comando:

Comando $env ['foo.h', 'foo.c'], 'foo.template', q(
generazione %1
);

potrebbe essere usato nel caso in cui il comando `gen' crei due file, entrambi foo.h ed foo.c.

I `Oggetti' metodo

Il metodo `Oggetti' provvede a creare i file oggetto che corrispondono a quello specificato
file sorgenti. Viene invocato come mostrato di seguito:

@files = Oggetti $env ;

In Unix, i file di origine che terminano con .s ed .c sono attualmente supportati e verranno compilati
in un nome dello stesso file che termina con .o. Per impostazione predefinita, tutti i file vengono creati invocando
il comando esterno che risulta dall'espansione della variabile di costruzione `CCCOM', con
`%<' e `%>' impostati rispettivamente sui file sorgente e oggetto (vedi il metodo `Comando'
per i dettagli sull'espansione). La variabile `CPPPATH' viene utilizzata anche durante la scansione dei file sorgente
per le dipendenze. Questo è un elenco di percorsi separati da due punti e viene utilizzato anche per creare
la variabile di costruzione `_IFLAGS', che conterrà l'elenco appropriato di -`I'
opzioni per la compilazione. Qualsiasi percorso relativo in `CPPPATH' viene interpretato relativo
nella directory in cui è stato creato l'ambiente di costruzione associato (assoluto
e possono essere utilizzati anche nomi di parentela superiore). Questa variabile è usata da `CCCOM'. Il comportamento
di questo comando può essere modificato cambiando una qualsiasi delle variabili che vengono interpolate
in "CCCOM", come "CC", "CFLAGS" e, indirettamente, "CPPPATH". È anche possibile
sostituire il valore di 'CCCOM' stesso. Per comodità, questo file restituisce l'elenco di
nomi file oggetto.

I `Programma' metodo

Il metodo `Programma' provvede a collegare il programma specificato con l'oggetto specificato
File. Si invoca nel modo seguente:

Programma $ambient , ;

Il nome del programma avrà il valore della variabile di costruzione `SUFEXE' aggiunta (da
predefinito, `.exe' sui sistemi Win32, niente sui sistemi Unix) se il suffisso non è già
presente.

I file di origine possono essere specificati al posto dei file di oggetti: lo sarà il metodo 'Oggetti'
invocato per organizzare la conversione di tutti i file in file oggetto, e quindi tutti i
le osservazioni sul metodo 'Oggetti', sopra, si applicano anche a questo metodo.

Il collegamento effettivo del programma sarà gestito da un comando esterno che ne risulta
dall'espansione della variabile di costruzione `LINKCOM', con `%<' impostato sui file oggetto a
essere collegato (nell'ordine presentato) e `%>' impostato sull'obiettivo (vedere il metodo `Comando'
per i dettagli sull'espansione). L'utente può impostare variabili aggiuntive nella costruzione
ambiente, incluso `LINK', per definire quale programma usare per il collegamento, `LIBPATH', a
elenco separato da due punti dei percorsi di ricerca della libreria, da utilizzare con le specifiche della libreria di
modulo -libe `LIBS', specificando l'elenco delle librerie a cui collegarsi (in entrambi -lib
form o semplicemente come nomi di percorso. Vengono interpretati i percorsi relativi sia in "LIBPATH" che in "LIBS".
relativo alla directory in cui viene creato l'ambiente di costruzione associato
(possono essere utilizzati anche nomi assoluti e top-relativi). Contro si imposta automaticamente
dipendenze da qualsiasi libreria menzionata in `LIBS': quelle librerie verranno create prima
il comando è collegato.

I "Biblioteca" metodo

Il metodo `Library' organizza la creazione della libreria specificata dall'oggetto specificato
File. Si invoca come segue:

Biblioteca $ambiente , ;

Il nome della libreria avrà il valore della variabile di costruzione `SUFLIB' aggiunta (da
predefinito, `.lib' su sistemi Win32, `.a' su sistemi Unix) se il suffisso non è già
presente.

I file di origine possono essere specificati al posto dei file di oggetti: lo sarà il metodo 'Oggetti'
invocato per organizzare la conversione di tutti i file in file oggetto, e quindi tutti i
le osservazioni sul metodo 'Oggetti', sopra, si applicano anche a questo metodo.

La creazione vera e propria della libreria sarà gestita da un comando esterno che ne risulta
dall'espansione della variabile di costruzione `ARCOM', con `%<' impostato sui membri della libreria (in
l'ordine presentato) e `%>' alla libreria da creare (vedere il metodo `Command' per
dettagli di espansione). L'utente può impostare variabili nell'ambiente di costruzione che lo farà
influenzare il funzionamento del comando. Questi includono `AR', il programma di archivio da utilizzare,
`ARFLAGS', che può essere usato per modificare i flag dati al programma specificato da `AR',
e `RANLIB', il nome di un programma di generazione dell'indice di archivio, se necessario (se il particolare
necessità non richiede quest'ultima funzionalità, allora `ARCOM' deve essere ridefinito in no
riferimento 'RANLIB').

Il metodo `Library' consente di specificare la stessa libreria in metodi multipli
invocazioni. Tutti gli oggetti che contribuiscono da tutte le invocazioni (che possono provenire da
directory diverse) sono combinati e generati da un unico comando di archivio. Nota,
tuttavia, se si elimina una build in modo che sia specificata solo una parte di una libreria, solo allora
quella parte della libreria verrà generata (il resto scomparirà!).

I `Modulo' metodo

Il metodo 'Modulo' è una combinazione dei metodi 'Programma' e 'Comando'. Piuttosto che
generando direttamente un programma eseguibile, questo comando consente di specificare il proprio
comando per generare effettivamente un modulo. Il metodo viene invocato come segue:

Modulo $ambiente , , ;

Questo comando è utile nei casi in cui desideri creare, ad esempio, in modo dinamico
moduli caricati o librerie di codice collegate staticamente.

I `Dipende' metodo

Il metodo `Depends' consente di specificare dipendenze aggiuntive per una destinazione. è
invocato come segue:

Dipende $ ambiente , ;

Questo può essere occasionalmente utile, specialmente nei casi in cui non esiste (o è
scrivibile) per particolari tipi di file. Normalmente, le dipendenze vengono calcolate
automaticamente da una combinazione delle dipendenze esplicite impostate dal metodo
chiamata o eseguendo la scansione dei file di origine.

È possibile specificare un insieme di dipendenze identiche per più destinazioni utilizzando un riferimento a
un elenco di obiettivi. In Perl, un riferimento a un elenco può essere creato racchiudendo un elenco in un quadrato
parentesi. Da qui il seguente comando:

Dipende $env ['pippo', 'barra'], 'file_input_1', 'file_input_2';

specifica che entrambi i foo ed bar i file dipendono dai file di input elencati.

I 'Ignora' metodo

Il metodo `Ignora' ti permette di ignorare esplicitamente le dipendenze che Cons inferisce su di esso
possedere. Si invoca come segue:

Ignorare ;

Questo può essere utilizzato per evitare ricompilazioni dovute a modifiche nei file di intestazione del sistema o
utilità note per non influire sui target generati.

Se, ad esempio, un programma è compilato in una directory montata su NFS su più sistemi che
avere copie diverse di stdio. h, le differenze influenzeranno le firme di tutti
target derivati ​​costruiti da file di origine che `#include '. Questo causerà tutto
quegli obiettivi da ricostruire quando si cambiano i sistemi. Se questo non è un comportamento desiderabile,
quindi la riga seguente rimuoverà le dipendenze da stdio. h file:

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

Nota che gli argomenti del metodo 'Ignora' sono espressioni regolari, quindi speciali
i caratteri devono essere sottoposti a escape e potresti voler ancorare l'inizio o la fine del
espressione con caratteri `^' o `$'.

I `Sale' metodo

Il metodo `Salt' aggiunge un valore costante al calcolo della firma per ogni derivato
file. Si invoca come segue:

$ spago di sale;

La modifica del valore Salt forzerà una ricostruzione completa di ogni file derivato. Questo può essere
usato per forzare le ricostruzioni in determinate circostanze desiderate. Per esempio,

Sale `uname -s`;

Forzerebbe una ricostruzione completa di ogni file derivato ogni volta che il sistema operativo è acceso
cui viene eseguita la build (come riportato da `uname -s') cambia.

I `Usa cache' metodo

Il metodo `UseCache' indica a Cons di mantenere una cache di file derivati, da condividere
tra alberi di costruzione separati dello stesso progetto.

UseCache("cache/ ") ⎪⎪ warn("cartella cache non trovata");

I `Percorso sorgente' metodo

Il metodo `SourcePath' restituisce il vero nome del percorso di origine di un file, in opposizione al
nome del percorso all'interno di una directory di build. Si invoca come segue:

$percorso = PercorsoSorgente ;

I `ConsPath' metodo

Il metodo `ConsPath' restituisce true se il percorso fornito è un file derivabile e restituisce
undef (falso) altrimenti. Si invoca come segue:

$risultato = PercorsoCons ;

I `Percorso diviso' metodo

Il metodo `SplitPath' cerca più nomi di percorsi in una stringa separata per impostazione predefinita
separatore di percorso per il sistema operativo (':' su sistemi UNIX, ';' su Windows NT) e
restituisce i nomi completi. Si invoca come segue:

@percorsi = SplitPath ;

Il metodo `SplitPath' converte i nomi con il prefisso '#' nella build di primo livello appropriata
name (senza '#') e convertirà i nomi relativi in ​​nomi di primo livello.

I `Percorso Dir' metodo

Il metodo `DirPath' restituisce il percorso di compilazione Nome(s) di una directory o di un elenco di directory.
Si invoca come segue:

$cwd = Percorso Dir ;

L'uso più comune per il metodo `DirPath' è:

$cwd = Percorso Dir '.';

per recuperare il percorso della directory corrente di una filiale coscritto file.

I `Percorso file' metodo

Il metodo `FilePath' restituisce il percorso di compilazione Nome(s) di un file o di un elenco di file. è
invocato come segue:

$file = PercorsoFile ;

I 'Aiuto' metodo

Il metodo `Help' specifica il testo della guida che verrà visualizzato quando l'utente invoca `cons
-h'. Questo può essere utilizzato per fornire la documentazione di obiettivi, valori, build specifici
opzioni, ecc. per l'albero di compilazione. Si invoca come segue:

Aiuto ;

Il metodo "Aiuto" può essere chiamato solo una volta e dovrebbe essere tipicamente specificato nella parte superiore-
livello Costruire file.

Estensione Svantaggi


Override costruzione variabili

Esistono diversi modi per estendere i contro, che variano in base al grado di difficoltà. Il più semplice
il metodo consiste nel definire il proprio ambiente di costruzione, basato sull'ambiente predefinito,
ma modificato per riflettere le tue esigenze particolari. Questo sarà spesso sufficiente per C-based
applicazioni. Puoi usare il costruttore "new" ei metodi "clone" e "copy" per
creare ambienti ibridi. Queste modifiche possono essere completamente trasparenti al sottostante
coscritto File.

Aggiunta nuovi metodi

Per modifiche leggermente più impegnative, potresti voler aggiungere nuovi metodi a `cons'
pacchetto. Ecco un esempio di un'estensione molto semplice, `InstallScript', che installa a
tcl in una posizione richiesta, ma prima modifica lo script per riflettere un platform-
percorso dipendente che deve essere installato nello script:

# contro::InstallScript - Crea una versione dipendente dalla piattaforma di una shell
# script sostituendo la stringa ``#!il-tuo-percorso-qui'' con specifica della piattaforma
# percorso $DIR_BIN.

sub contro::InstallScript {
mio ($env, $dst, $src) = @_;
Comando $env $dst, $src, qq(
sed s+il-tuo-percorso-qui+$BIN_DIR+ %< > %>
chmod oug+x %>
);
}

Si noti che questo metodo è definito direttamente nel pacchetto `cons' (premettendo il nome
con `contro::'). Una modifica apportata in questo modo sarà globalmente visibile a tutti gli ambienti,
e potrebbe essere chiamato come nel seguente esempio:

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

Per un piccolo miglioramento in generale, la variabile `BINDIR' potrebbe essere passata come an
argomento o preso dall'ambiente di costruzione, come `%BINDIR'.

Override metodi

Invece di aggiungere il metodo allo spazio dei nomi `cons', potresti definire un nuovo pacchetto
che eredita i metodi esistenti dal pacchetto `cons' e ne sovrascrive o ne aggiunge altri. Questo
può essere fatto usando i meccanismi di ereditarietà di Perl.

L'esempio seguente definisce un nuovo pacchetto `cons::switch' che sovrascrive lo standard
Metodo "Biblioteca". Il metodo sottoposto a override crea moduli di libreria collegati, anziché una libreria
archivi. Viene fornito un nuovo costruttore. Gli ambienti creati con questo costruttore lo faranno
avere il nuovo metodo di libreria; altri no.

contro del pacchetto::interruttore;
INIZIA {@ISA = 'contro'}

sottonuovo {
cambio;
benedici i nuovi contro(@_);
}

sottobiblioteca {
mio($env) = spostamento;
mio($lib) = spostamento;
mio(@objs) = Oggetti $env @_;
Comando $env $lib, @objs, q(
%LD -r %LDFLAGS %< -o %>
);
}

Questa funzionalità può essere invocata come nell'esempio seguente:

$env = nuovi contro::switch(@overrides);
...
Libreria $env 'lib.o', 'foo.c', 'bar.c';

Invocando Svantaggi


Il comando `cons' viene solitamente invocato dalla radice dell'albero di build. UN Costruire filetto
deve esistere in quella directory. Se viene utilizzato l'argomento `-f', allora un'alternativa Costruire
può essere utilizzato il file (e, possibilmente, una radice alternativa, poiché `cons' eseguirà il cd in Costruire
directory contenente il file).

Se `cons' viene invocato da un figlio della radice dell'albero di build con l'argomento `-t', esso
salirà nella gerarchia delle directory cercando a Costruire file. (Un nome alternativo può
essere ancora specificato con `-f'.) I target forniti sulla riga di comando verranno modificati
essere relativo allo scoperto Costruire file. Ad esempio, da una directory contenente
un livello superiore Costruire file, la seguente chiamata:

% cd libfoo/sottodir
% cons -t obiettivo

è esattamente equivalente a:

% contro libfoo/subdir/target

Se ci sono destinazioni "Predefinite" specificate nella gerarchia delle directory Costruire or
coscritto file, solo le destinazioni predefinite in corrispondenza o al di sotto della directory da cui `cons -t'
è stato invocato verrà compilato.

Il comando viene invocato come segue:

contro --

where argomenti può essere uno dei seguenti, in qualsiasi ordine:

bersaglio Costruisci la destinazione specificata. Se bersaglio è una directory, quindi compila in modo ricorsivo
tutto all'interno di quella directory.

+modello Limita il coscritto file considerati solo quelli che corrispondono modello, Che ha
un'espressione regolare Perl. Sono accettati più argomenti `+'.

Nome=
Set Nome valorizzare val nell'hash 'ARG' è passato al livello superiore Costruire file.

`-cc' Mostra il comando che sarebbe stato eseguito durante il recupero dalla cache. No
viene fornita l'indicazione che il file è stato recuperato; questo è utile per
generazione di log di build che possono essere confrontati con log di build reali.

`-cd' Disabilita tutta la memorizzazione nella cache. Non recuperare dalla cache né scaricare nella cache.

`-cr' Crea dipendenze in ordine casuale. Questo è utile quando si costruiscono multipli
alberi simili con memorizzazione nella cache abilitata.

`-cs' Sincronizza le destinazioni di build esistenti che risultano essere aggiornate con la cache.
Questo è utile se la memorizzazione nella cache è stata disabilitata con -cc o abilitata di recente
con UseCache.

`-d' Abilita il debug delle dipendenze.

`-f'
Utilizzare il file specificato invece di Costruire (ma prima cambia in contenente
directory di filetto).

`-h' Mostra un messaggio di aiuto locale alla build corrente se ne è definita una, ed esci.

`-k' Continua ad andare il più lontano possibile dopo gli errori.

`-o'
Leggi il file di sostituzione filetto.

`-p' Mostra i prodotti da costruzione negli alberi specificati. Non viene tentata alcuna build.

`-pa' Mostra i prodotti da costruzione e le azioni associate. Non viene tentata alcuna build.

`-pw' Mostra i prodotti e dove sono definiti. Non viene tentata alcuna build.

`-q' Non essere prolisso sull'installazione e la rimozione dei target.

`-r' Rimuove i prodotti da costruzione associati a . Non viene tentata alcuna build.

`-R'
Cerca file in pronti contro termine. multiplo -R pronti contro termine le directory vengono cercate in
ordine specificato.

`-t' Risalire la gerarchia delle directory cercando a Costruire file, se non esiste
nella directory corrente. Gli obiettivi verranno modificati per essere relativi al
Costruire file.

`-v' Mostra la versione `cons' e continua l'elaborazione.

`-V' Mostra la versione `cons' ed esci.

`-wf'
Scrivi tutti i nomi di file considerati filetto.

`-x' Mostra un messaggio di aiuto simile a questo ed esci.

E altre ancora… costruire-args può essere qualsiasi argomento che desideri elaborare in Costruire file.
Nota che dovrebbe esserci un -- separando gli argomenti in contro e gli argomenti che tu
desidera elaborare nel Costruire file.

Elaborazione di costruire-args può essere fatto da qualsiasi pacchetto standard come Ottieni o suo
varianti o qualsiasi pacchetto definito dall'utente. cons passerà nel costruire-args as @ARGV ed
non tenterà di interpretare nulla dopo il --.

% contro -R /usr/local/repository -d os=solaris +driver -- -c test -f DEBUG

passerebbe quanto segue a cons

-R /usr/local/repository -d os=solaris +driver

e quanto segue, al livello più alto Costruire file come @ARGV

-c prova -f DEBUG

Nota che `cons -r .' è equivalente a un completo ricorsivo `make clean', ma non richiede
supporto nel Costruire file o qualsiasi coscritto File. Questo è molto utile se lo sei
la compilazione di file nelle directory di origine (se si separa il file costruire ed export directory,
quindi puoi semplicemente rimuovere le directory).

Le opzioni `-p', `-pa' e `-pw' sono estremamente utili per l'uso come ausilio nella lettura
script o eseguirne il debug. Se vuoi sapere quale script installa esporta/includi/foo.h,
per esempio, basta digitare:

% contro -pw export/include/foo.h

utilizzando ed scrittura dipendenza scanner


QuickScan consente di impostare semplici scanner indipendenti dalla destinazione per i file di origine. Solo
uno scanner QuickScan può essere associato a qualsiasi file di origine e ambiente.

QuickScan viene richiamato come segue:

QuickScan CONSENV CODEREF, NOME FILE [, PERCORSO]

La subroutine a cui fa riferimento CODEREF dovrebbe restituire un elenco di nomi di file inclusi
direttamente da FILE. Questi nomi di file verranno, a loro volta, scansionati. L'argomento PATH facoltativo
fornisce un percorso di ricerca per trovare FILENAME e/o file restituiti dall'utente fornito
sottoprogramma. Il PERCORSO può essere un riferimento a un array di nomi di directory di ricerca o a
stringa di nomi separati dal carattere separatore del sistema (':' su sistemi UNIX, ';' su
WindowsNT).

La subroutine viene chiamata una volta per ogni riga nel file, con $_ impostato sulla riga corrente.
Se la subroutine ha bisogno di guardare righe aggiuntive, o, se è per questo, l'intero file,
quindi può leggerli da solo, dal filehandle SCAN. Può anche terminare il ciclo, se
sa che non sono disponibili ulteriori informazioni di inclusione, chiudendo il filehandle.

Indipendentemente dal fatto che venga fornito o meno un percorso di ricerca, QuickScan tenta innanzitutto di cercare il file
relativo alla directory corrente (per il file di primo livello fornito direttamente a QuickScan),
o dalla directory contenente il file che ha fatto riferimento al file. Questo non è molto
generale, ma sembra abbastanza buono, specialmente se hai il lusso di scriverne uno tuo
utility e può controllare l'uso del percorso di ricerca in modo standard. Infine, il
il percorso di ricerca è, attualmente, separato dai due punti. Questo potrebbe non rendere felice il campo del NT.

Ecco un esempio reale, tratto da a Costruire file qui:

sub contro::SMFgen {
mio($env, @tabelle) = @_;
foreach $t (@tabelle) {
$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 %) %
)
);
}
}

[NOTA che il modulo `$env->QuickScan ...' e `$env->Comando ...' non dovrebbe essere
necessario, ma, per qualche ragione, è richiesto per questa particolare invocazione. Questo appare
essere un bug in Perl o un malinteso da parte mia; questo stile di invocazione non lo fa
sembrano essere sempre necessari.]

Questo trova tutti i nomi del modulo .smf nel file. Restituirà i nomi anche se
si trovano nei commenti, ma va bene (il meccanismo consente di perdonare i file extra;
vengono semplicemente ignorati partendo dal presupposto che il file mancante verrà notato quando il file
programma, in questo esempio, smfgen, viene effettivamente invocato).

Uno scanner viene invocato solo per un determinato file di origine se è necessario per qualche destinazione nel file
albero. Viene invocato solo una volta per un determinato file di origine.

Ecco un altro modo per costruire lo stesso scanner. Questo utilizza un riferimento di codice esplicito,
e inoltre (inutilmente, in questo caso) legge l'intero file stesso:

scansione secondaria {
mio(@include);
fare {
push(@include, /\b\S*?\.smf\b/g);
} mentre ;
@include
}

Si noti che l'ordine del ciclo è invertito, con il test del ciclo alla fine. Questo è
perché la prima riga è già letta per te. Questo scanner può essere collegato a una fonte
file di:

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

SUPPORTO E SUGGERIMENTI


Contro è gestito dalla comunità di utenti. Per iscriversi, inviare una mail a contro-discutere-
[email protected] con il corpo sottoscrivi.

Si prega di segnalare eventuali suggerimenti tramite il [email protected] mailing list.

Usa i contro online utilizzando i servizi onworks.net


Server e workstation gratuiti

Scarica app per Windows e Linux

  • 1
    turchi
    turchi
    TurkDevOps a ?k kaynak yaz?l?m
    geli?tirici topluklar? DevTurks-Team
    Taraf?ndan desteklenmektedir..
    Caratteristiche:https://github.com/turkdevopshttps://turkdevops.g...
    Scarica turkdevops
  • 2
    asamdf
    asamdf
    *asammdf* è un parser Python veloce e
    redattore per ASAM (Associazione per
    Standardizzazione dell'automazione e
    Sistemi di misura) MDF / MF4
    (Formato dei dati di misurazione...
    Scarica asammdf
  • 3
    LAME (Lame non è un codificatore MP3)
    LAME (Lame non è un codificatore MP3)
    LAME è uno strumento educativo da utilizzare
    per conoscere la codifica MP3. Il
    L'obiettivo del progetto LAME è quello di migliorare
    la psicoacustica, qualità e velocità
    di deputato...
    Scarica LAME (Lame non è un codificatore MP3)
  • 4
    wxPython
    wxPython
    Un insieme di moduli di estensione Python che
    avvolgere le classi GUI multipiattaforma da
    wxWidgets.. Pubblico: sviluppatori. Utente
    interfaccia: X Window System (X11), Win32 ...
    Scarica wxPython
  • 5
    packfilemanager
    packfilemanager
    Questo è il file manager del pacchetto Total War
    progetto, a partire dalla versione 1.7. UN
    breve introduzione a Warscape
    mod:...
    Scarica packfilemanager
  • 6
    IPerf2
    IPerf2
    Uno strumento di misurazione del traffico di rete
    Prestazioni TCP e UDP con metriche
    intorno sia al throughput che alla latenza. Il
    gli obiettivi includono il mantenimento di un attivo
    merluzzo iperf...
    Scarica IPerf2
  • Di Più "

Comandi Linux

Ad