EnglezăFrancezăSpaniolă

Ad


Favicon OnWorks

contra - Online în cloud

Rulați contra în furnizorul de găzduire gratuit OnWorks peste Ubuntu Online, Fedora Online, emulator online Windows sau emulator online MAC OS

Acesta este dezavantajele comenzii care pot fi executate în furnizorul de găzduire gratuit OnWorks folosind una dintre multiplele noastre stații de lucru online gratuite, cum ar fi Ubuntu Online, Fedora Online, emulator online Windows sau emulator online MAC OS

PROGRAM:

NUME


Contra - Un sistem de construcție software

DESCRIERE


Un ghid și referință pentru versiunea 2.2.0

Drepturi de autor (c) 1996-2000 Free Software Foundation, Inc.

Acest program este software gratuit; îl puteți redistribui și/sau modifica în conformitate cu termenii
Licența publică generală GNU publicată de Free Software Foundation; fie
versiunea 2 a Licenței sau (la alegerea dvs.) orice versiune ulterioară.

Acest program este distribuit in speranta ca va fi de folos, dar FARA NICIO GARANTIE;
fără nici măcar garanția implicită de VANTABILITATE sau ADECVARE PENTRU UN ANUMIT SCOP.
Consultați Licența publică generală GNU pentru mai multe detalii.

Ar fi trebuit să primiți o copie a licenței publice generale GNU împreună cu acest program;
vezi fisierul COPIERE. Dacă nu, scrieți la Free Software Foundation, Inc., 59 Temple
Locație - Suite 330, Boston, MA 02111-1307, SUA.

Introducere


Contra este un sistem pentru construirea, în primul rând, de software, dar este destul de diferit de
sisteme de construcție software anterioare. Contra a fost conceput de la zero pentru a face față
cu ușurință cu construcția de software răspândit în mai multe directoare surse. Contra
facilitează crearea de scripturi de compilare care sunt simple, de înțeles și de întreținut.
Dezavantajele asigură că software-ul complex este ușor și precis reproductibil.

Cons folosește o serie de tehnici pentru a realiza toate acestea. Scripturile de construcție sunt doar
Scripturi Perl, făcându-le atât ușor de înțeles, cât și foarte flexibile. Scoping global al
variabile este înlocuit cu un mecanism de import/export pentru partajarea informațiilor între
scripturi, îmbunătățind semnificativ lizibilitatea și mentenabilitatea fiecărui script.
Construcţie medii sunt introduse: acestea sunt obiecte Perl care captează
informațiile necesare pentru controlul procesului de construcție. Sunt utilizate mai multe medii
când este necesară o semantică diferită pentru generarea de produse în arborele de construcție. Contra
implementează analiza automată a dependenței și o folosește pentru a ordona global întregul
construi. Variantele sunt produse cu ușurință dintr-un singur arbore sursă. Construcție inteligentă
subsetarea este posibilă atunci când lucrați la modificări localizate. Modificarile pot fi setate la
înlocuiți cu ușurință instrucțiunile de construcție fără a modifica niciun script. criptografic MD5
semnături sunt asociate cu fișiere derivate și sunt utilizate pentru a determina cu precizie dacă
un anumit fișier trebuie reconstruit.

Deși oferă toate cele de mai sus și multe altele, Cons rămâne simplu și ușor de utilizat. Asta va,
sperăm că deveniți clar pe măsură ce citiți restul acestui document.

De ce Contra? De ce nu Face?


Contra este a face înlocuire. În paragrafele următoare, ne uităm la câteva dintre ele
caracteristicile nedorite ale mărcii - și mediile tipice de construcție bazate pe marca - care
a motivat dezvoltarea Cons.

Construi complexitate

Sistemele tradiționale bazate pe marcă de orice dimensiune tind să devină destul de complexe. Marca originală
utilitatea și derivatele sale au contribuit la această tendință în mai multe moduri. Face este
nu este bun la a face cu sisteme care sunt răspândite în mai multe directoare. diverse lucrari-
împrejurimile sunt folosite pentru a depăși această dificultate; alegerea obișnuită este ca make să invoce
în sine recursiv pentru fiecare subdirector al unei build. Acest lucru duce la un cod complicat, în
care este adesea neclar cum este setată o variabilă sau ce efect are setarea unei variabile
va avea asupra construcției în ansamblu. Limbajul make scripting a fost extins treptat
pentru a oferi mai multe posibilități, dar acestea au servit în mare măsură la aglomerarea unui deja
limbaj supraextins. Adesea, construcțiile se fac în mai multe treceri pentru a furniza
produse adecvate dintr-un director în altul. Aceasta reprezintă o altă
creșterea complexității construcției.

Construi reproductibilitate

Nenorocirea tuturor mărcilor a fost întotdeauna gestionarea corectă a dependențelor. Cel mai adesea, an
se încearcă să facă o treabă rezonabilă de dependențe într-un singur director, dar nu
se face o încercare serioasă de a face treaba între directoare. Chiar și atunci când dependențele sunt
funcționând corect, te bazezi pe o comparație simplă a ștampilei de timp pentru a determina dacă
un dosar este depășit în ceea ce privește persoanele aflate în întreținerea acestuia nu este, în general, adecvat pentru
stabilirea când un fișier trebuie rederivat. Dacă o bibliotecă externă, de exemplu, este
reconstruit și apoi „prins” la locul său, marcajele de timp de pe fișierele sale nou create pot
bine să fie mai devreme decât ultima construcție locală, deoarece a fost construită înainte să devină vizibilă.

Variantă construiește

Make oferă doar facilități limitate pentru gestionarea variantelor de construcție. Odată cu proliferarea
a platformelor hardware și nevoia de cod depanabil vs. optimizat, capacitatea de a
a crea cu ușurință aceste variante este esențială. Mai important, dacă sunt create variante, aceasta
este important fie pentru a putea separa variantele, fie pentru a putea reproduce
original sau variantă după bunul plac. Cu make este foarte dificil să separați construcțiile în
mai multe directoare de compilare, separate de sursă. Și dacă această tehnică nu este folosită,
de asemenea, este practic imposibil să se garanteze la un moment dat în ce variantă este prezentă
arborele, fără a recurge la o reconstrucție completă.

Repozitorii

Make oferă doar suport limitat pentru crearea de software din codul care există în a
structura directorului depozitului central. Caracteristica VPATH a GNU make (și altele
make implementations) are scopul de a oferi acest lucru, dar nu funcționează așa cum era de așteptat: it
schimbă calea fișierului țintă la numele VPATH prea devreme în analiza sa și, prin urmare
caută toate dependențele din directorul VPATH. Pentru a asigura o dezvoltare corectă
build-uri, este important să puteți crea un fișier într-un director de build local și să aveți
orice fișiere dintr-un depozit de cod (un director VPATH, în termeni de make) care depind de local
fișierul este reconstruit corect. Acest lucru nu este posibil cu VPATH, fără a codifica mult
cunoștințe complexe de depozit direct în fișierele make.

păstrare it simplu


Câteva dintre dificultățile legate de make au fost citate mai sus. În aceasta și în cele ulterioare
secțiunile, vom introduce Contra și vom arăta cum sunt abordate aceste probleme.

Perl script-uri

Contra este bazat pe Perl. Adică, scripturile contra...recrut și construi fișiere, echivalentul
la makefile or makefile--sunt toate scrise în Perl. Acest lucru oferă un beneficiu imediat: the
limbajul de scriere a scenariilor este unul familiar. Chiar dacă nu se întâmplă să fii Perl
programator, te ajută să știi că Perl este, practic, doar un simplu limbaj declarativ,
cu un flux de control bine definit și o semantică familiară. Are variabile care se comportă
practic, așa cum v-ați aștepta, subrutine, flux de control și așa mai departe. Acolo
nu este introdusă o sintaxă specială pentru Cons. Utilizarea Perl ca limbaj de scripting
simplifică sarcina de a exprima soluția adecvată la cele adesea complexe
cerințele unei construcții.

Buna, Lume!

Pentru a fundamenta următoarea discuție, iată cum ați putea construi Buna, Lume! C
aplicație cu contra:

$env = new contra();
Program $env 'hello', 'hello.c';

Dacă instalați acest script într-un director, denumind scriptul construi, și creați
buna fișier sursă în același director, apoi puteți tasta „cons hello” pentru a construi fișierul
aplicare:

% contra salut
cc -c salut.c -o salut.o
cc -o salut salut.o

Construcţie medii

O simplificare cheie a Cons este ideea de a construcţie mediu inconjurator. O construcție
mediul este o obiect caracterizată printr-un set de perechi cheie/valoare și un set de metode.
Pentru a-i spune lui Cons cum să construiască ceva, invocați metoda corespunzătoare printr-un
mediu de construcție adecvat. Luați în considerare următorul exemplu:

$env = noi contra(
CC => 'gcc',
LIBS => 'libworld.a'
);

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

În acest caz, mai degrabă decât să folosim mediul de construcție implicit, așa cum este, avem
a suprascris valoarea lui `CC' astfel încât să fie folosit echivalentul GNU C Compiler. De cand
această versiune a Buna, Lume! necesită o bibliotecă, libworld.a, am precizat că orice
programul legat în acest mediu ar trebui să fie legat de acea bibliotecă. Dacă biblioteca
există deja, bine și bine, dar dacă nu, atunci va trebui să includem și declarația:

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

Acum, dacă tastați „cons hello”, biblioteca va fi construită înainte ca programul să fie conectat și,
desigur, `gcc' va fi folosit pentru a compila ambele module:

% contra salut
gcc -c salut.c -o salut.o
gcc -c lume.c -o lume.o
ar r libworld.o lume.o
ar: crearea libworld.a
ranlib libworld.a
gcc -o salut salut.o libworld.a

Automat și Completă dependenţă analiză

Cu Contra, dependențele sunt gestionate automat. Continuând exemplul anterior, rețineți
că atunci când modificăm lume.c, lume.o este recompilat, libworld.a recreat, și Alo
reconectat:

% vi lume.c
[EDIT]
% contra salut
gcc -c lume.c -o lume.o
ar r libworld.o lume.o
ar: crearea libworld.a
ranlib libworld.a
gcc -o salut salut.o libworld.a

Acesta este un exemplu relativ simplu: Cons ``knows'' lume.o depinde de lume.c, Deoarece
dependența este configurată în mod explicit prin metoda „Bibliotecă”. Știe și asta libworld.a
depinde de lume.o şi că Alo depinde de libworld.a, toate din motive similare.

Acum se dovedește că buna include, de asemenea, fișierul de definire a interfeței, lume.h:

% emacs world.h
[EDIT]
% contra salut
gcc -c salut.c -o salut.o
gcc -o salut salut.o libworld.a

De unde știe Cons asta buna include lume.h, și asta salut.o trebuie deci să fie
recompilat? Deocamdată, este suficient să spunem asta atunci când ne gândim dacă sau nu salut.o este sus-
până în prezent, Cons invocă un scanner pentru dependența sa, buna. Acest scaner enumeră
fișiere incluse de buna pentru a veni cu o listă de dependențe suplimentare, dincolo de acestea
făcut explicit de scenariul Cons. Acest proces este recursiv: orice fișiere incluse de
fișierele incluse vor fi, de asemenea, scanate.

Nu este scump? Răspunsul este - depinde. Dacă faceți o construcție completă a unui sistem mare,
timpul de scanare este nesemnificativ. Dacă faceți o reconstrucție a unui sistem mare, atunci contra va face
petrec destul de mult timp gândindu-se la asta înainte de a decide că nimic nu trebuie să fie
gata (deși nu neapărat mai mult timp decât face!). Vestea bună este că Cons o face
foarte ușor de subsetat în mod inteligent construcția, atunci când lucrați la modificări localizate.

Automat global construi secvențiere

Deoarece Cons face o analiză completă și precisă a dependenței și face acest lucru la nivel global, pentru
întreaga construcție, Cons poate folosi aceste informații pentru a prelua controlul deplin asupra secvențiere
a construcției. Această secvențiere este evidentă în exemplele de mai sus și este echivalentă cu ce
v-ați aștepta pentru make, având în vedere un set complet de dependențe. Cu Contra, acest lucru se extinde
trivial la versiuni mai mari, cu mai multe directoare. Ca rezultat, toată complexitatea implicată
pentru a vă asigura că o construcție este organizată corect - inclusiv ierarhic cu mai multe treceri
construiește--este eliminat. Vom discuta acest lucru în continuare în secțiunile următoare.

Clădire mare copaci — încă doar as simplu


A ierarhie of construi script-uri

O construcție mai mare, în Cons, este organizată prin crearea unei ierarhii de construi script-uri. În vârf
al arborelui este un script numit construi. Restul scenariilor, prin convenție, sunt fiecare
denumit recrut. Aceste scripturi sunt conectate între ele, foarte simplu, prin „Build”,
Comenzile „Export” și „Import”.

Construi comandă

Comanda „Build” preia o listă de recrut nume de fișiere și aranjează ca acestea să fie
incluse în construcție. De exemplu:

Build qw(
drivere/display/Conscript
drivere/mouse/Conscript
parser/Conscript
utilitati/Conscript
);

Aceasta este o ierarhie simplă pe două niveluri de scripturi de compilare: toate subsidiarele recrut fișiere
sunt menționate la nivelul superior construi fişier. Observați că nu toate directoarele din arbore
au neapărat scripturi de compilare asociate acestora.

Acest lucru ar putea fi scris și ca un script cu mai multe niveluri. De exemplu, cel construi fișierul ar putea
conține această comandă:

Build qw(
parser/Conscript
șoferi/Conscript
utilitati/Conscript
);

si recrut de fișier în drivere directorul ar putea conține:

Build qw(
afişare/Conscript
şoarece/Conscript
);

Experiența a arătat că fostul model este puțin mai ușor de înțeles, din moment ce
întreg arborele de construcție este așezat în fața ta, la nivelul superior. Schemele hibride sunt
de asemenea posibil. O componentă întreținută separat care trebuie încorporată în a
build tree, de exemplu, s-ar putea conecta la build tree într-un singur loc, dar își definește propriul
ierarhia construcției.

În mod implicit, Cons nu își schimbă directorul de lucru în directorul care conține a
filială recrut fișierul pe care îl include. Acest comportament poate fi activat pentru un build by
specificând, la nivelul superior construi fișier:

Conscript_chdir 1;

Când este activat, Contra se va schimba în subsidiar recrut directorul care conține fișierul
în timp ce citiți fișierul respectiv, apoi treceți înapoi la directorul de nivel superior odată ce fișierul a ajuns
s-a procesat.

Este de așteptat ca acest comportament să devină implicit într-o versiune viitoare a Cons.
Pentru a se pregăti pentru această tranziție, versiunile care se așteaptă ca Cons să rămână în partea de sus a versiunii
în timp ce se citește într-o filială recrut fișierul ar trebui să dezactiveze în mod explicit această caracteristică ca
urmează:

Conscript_chdir 0;

Relativ, ruda de top, și absolut fişier nume

Este posibil să fi observat că numele fișierelor specificate pentru comanda Build sunt relative la
locația scriptului din care este invocat. Acest lucru este valabil în general pentru alte nume de fișier
argumente și la alte comenzi, deși am putea la fel de bine să menționăm aici că dacă începeți
un nume de fișier cu un semn hash, ``#'', apoi acel fișier este interpretat în raport cu partea de sus-
directorul de nivel (unde construi rezidă fișierul). Și, nu este surprinzător, dacă o începi
cu ``/'', atunci este considerat a fi un nume de cale absolut. Acest lucru este valabil chiar și pentru sisteme
care folosesc o bară oblică inversă mai degrabă decât o oblică înainte pentru a denumi căile absolute.

Utilizarea module in construi script-uri

Puteți trage module în fiecare recrut fișier folosind Perl normal „utilizare” sau „require”
declarații:

foloseste engleza;
necesită Modulul meu::;

Fiecare „utilizare” sau „necesită” îl afectează doar pe aceea recrut fisierul in care apare. Pentru a folosi a
modul în multiple recrut fișiere, trebuie să puneți o declarație „use” sau „require” în fiecare
unul care are nevoie de modul.

domeniu of variabile

Nivelul superior construi dosar și tot recrut fișierele încep viața într-un Perl comun, separat
pachet. Contra controlează tabelul de simboluri pentru pachet, astfel încât, tabelul de simboluri pentru
fiecare script este gol, cu excepția construi fișier, care primește o parte din linia de comandă
argumente. Prin urmare, toate variabilele care sunt setate sau utilizate sunt stabilite de script
în sine — nu printr-un script extern.

Variabilele pot fi explicit importate printr-un script din scriptul părinte. Pentru a importa a
variabilă, trebuie să fi fost exportat de către părinte și inițializat (altfel o eroare
o să se întâmple).

Export comandă

Comanda „Export” este folosită ca în exemplul următor:

$env = new contra();
$INCLUDE = "#export/include";
$LIB = "#export/lib";
Export qw( env INCLUDE LIB );
Build qw(util/Conscript);

Valorile variabilelor simple menționate în lista „Export” vor fi eliminate
prin orice comenzi `Build' ulterioare. Comanda „Export” va exporta doar Perl mărime scalară
variabile, adică variabile al căror nume începe cu `$'. Alte variabile, obiecte etc.
poate fi exportat prin referință - dar toate scripturile se vor referi la același obiect și asta
obiectul ar trebui să fie considerat doar pentru citire de către scripturile subsidiare și de către original
exportarea scriptului. Este acceptabil, totuși, să atribuiți o nouă valoare scalarului exportat
variabilă - care nu va schimba variabila de bază la care se face referire. Această secvență, pentru
exemplu, este OK:

$env = new contra();
Export qw( env INCLUDE LIB );
Build qw(util/Conscript);
$env = new cons(CFLAGS => '-O');
Build qw(altul/Conscript);

Nu contează dacă variabila este setată înainte sau după comanda „Export”. The
lucru important este valoarea variabilei în momentul în care comanda `Build' este executată.
Aceasta este ceea ce se îndepărtează. Apropo, orice comenzi „Export” ulterioare,
invalidați primul: trebuie să menționați toate variabilele pe care doriți să le exportați pentru fiecare
Comanda „Export”.

Import comandă

Variabilele exportate prin comanda „Export” pot fi importate în scripturi subsidiare de către
Comanda „Import”. Scriptul subsidiar importă întotdeauna variabile direct din
scenariu superior. Luați în considerare acest exemplu:

Import qw( env INCLUDE );

Acest lucru este legal numai dacă scriptul părinte a exportat atât „$env” cât și „$INCLUDE”. De asemenea, trebuie
au dat fiecăreia dintre aceste variabile valori. Este OK doar pentru scriptul subsidiar
importați un subset de variabile exportate (în acest exemplu, `$LIB', care a fost exportat de
exemplul anterior, nu este importat).

Toate variabilele importate sunt reexportate automat, astfel încât secvența:

Import qw ( env INCLUDE );
Construiți qw (sub-me/Conscript);

va furniza atât `$env' cât și `$INCLUDE' fișierului subsidiar. Dacă doar `$env' trebuie să fie
exportate, atunci vor fi suficiente următoarele:

Import qw ( env INCLUDE );
Export qw ( env );
Construiți qw (sub-me/Conscript);

Inutil să spunem că variabilele pot fi modificate local înainte de a invoca `Build' pe
script subsidiar.

Construi scenariu evaluare comandă

Singura constrângere privind ordonarea scripturilor de compilare este aceea că scripturile superioare sunt
evaluate înaintea scenariilor lor inferioare. Nivelul superior construi fișier, de exemplu, este
evaluat mai întâi, urmat de orice scripturi inferioare. Acesta este tot ce trebuie să știți cu adevărat
despre ordinea de evaluare, deoarece ordinea este în general irelevantă. Luați în considerare următoarele
Comanda „Build”:

Build qw(
drivere/display/Conscript
drivere/mouse/Conscript
parser/Conscript
utilitati/Conscript
);

Am ales să punem numele scripturilor în ordine alfabetică, pur și simplu pentru că asta este cel mai mult
convenabil pentru scopuri de întreținere. Schimbarea ordinii nu va face nicio diferență pentru
construi.

A Model pentru partajarea fișiere


niste simplu Convenții

În orice sistem software complex, trebuie să existe o metodă de partajare a produselor de construcție
stabilit. Vă propunem un set simplu de convenții cu care sunt simple de implementat
Contra, dar foarte eficient.

Regula de bază este să ceri ca toți să construiască produse care trebuie să fie partajate între ele
directoarele sunt partajate printr-un director intermediar. De obicei am numit asta
exporturileși, într-un mediu C, au furnizat subdirectoare convenționale ale acestui director,
precum include, lib, bin, Etc

Aceste directoare sunt definite de nivelul superior construi fişier. Un simplu construi fisier pentru
a Buna, Lume! aplicația, organizată folosind mai multe directoare, ar putea arăta astfel:

# Construiți fișierul pentru Hello, World!

# Unde să punem toate produsele noastre comune.
$EXPORT = '#export';

Export qw( CONTRAS INCLUDE LIB BIN );

# Directoare standard pentru partajarea produselor.
$INCLUDE = "$EXPORT/include";
$LIB = "$EXPORT/lib";
$BIN = "$EXPORT/bin";

# Un mediu de construcție standard.
$CONS = noi contra (
CPPPATH => $INCLUDE, # Include calea pentru compilațiile C
LIBPATH => $LIB, # Calea bibliotecii pentru conectarea programelor
LIBS => '-lworld', # Listă de biblioteci standard
);

Build qw(
salut/Conscript
lume/Conscript
);

lume directorului recrut fișierul arată astfel:

# Fișier conscript pentru lumea directorului
Import qw( CONS INCLUDE LIB );

# Instalați produsele din acest director
Instalați $CONS $LIB, 'libworld.a';
Instalați $CONS $INCLUDE, 'world.h';

# Produse interne
Biblioteca $CONS 'libworld.a', 'world.c';

si Alo directorului recrut fișierul arată astfel:

# Fișier conscript pentru directorul salut
Import qw( CONS BIN );

# Produse exportate
Instalați $CONS $BIN, „bună ziua”;

# Produse interne
Program $CONS 'hello', 'hello.c';

Pentru a construi un Buna, Lume! program cu această structură de directoare, mergeți la nivelul superior
director și invocați „cons” cu argumentele corespunzătoare. În exemplul următor, noi
spune-i lui Cons să construiască directorul exporturile. Pentru a construi un director, Cons le construiește recursiv pe toate
produse cunoscute din acel director (numai dacă au nevoie de reconstrucție, desigur). Dacă vreuna dintre
acele produse depind de alte produse din alte directoare, apoi acestea vor fi construite,
prea.

% contra export
Instalați world/world.h ca export/include/world.h
cc -Iexport/include -c hello/hello.c -o hello/hello.o
cc -Iexport/include -c world/world.c -o world/world.o
ar r lume/libworld.a lume/lume.o
ar: crearea lumii/libworld.a
ranlib world/libworld.a
Instalați world/libworld.a ca export/lib/libworld.a
cc -o hello/hello hello/hello.o -Lexport/lib -lworld
Instalați hello/hello ca export/bin/hello

Curat, de inteles, independent de locație script-uri

Veți observa că cei doi recrut fișierele sunt foarte curate și la obiect. Ei pur și simplu
specificați produsele din director și cum să construiți acele produse. Instrucțiunile de construire
sunt minime: ele specifică ce mediu de construcție să folosească, numele produsului,
și numele intrărilor. Rețineți, de asemenea, că scripturile sunt independente de locație: dacă dvs
Doriți să vă reorganizați arborele sursă, sunteți liber să faceți acest lucru: trebuie doar să schimbați
construi (în acest exemplu), pentru a specifica noile locații ale fișierului recrut fișiere.
utilizarea unui arbore de export face acest obiectiv ușor.

Observați, de asemenea, cum Cons are grijă de micile detalii pentru dvs. Toate exporturile directoare, pentru
de exemplu, au fost realizate automat. Și fișierele instalate au fost într-adevăr conectate direct în
directoarele de export respective, pentru a economisi spațiu și timp. Această atenție la detalii salvează
muncă considerabilă și face și mai ușoară producerea de scripturi simple, care pot fi întreținute.

separare sursă și construi copaci


Este adesea de dorit să păstrați orice fișiere derivate din build complet separat de fișierul
fișiere sursă. Acest lucru face mult mai ușor să urmăriți ceea ce este un fișier sursă și
de asemenea, face mai ușor de manevrat variantă builds, mai ales dacă vrei varianta builds
a coexista.

separare construi și sursă directoare folosind il Link comandă

Contra oferă un mecanism simplu care se ocupă de toate aceste cerințe. „Legătura”
comanda este invocată ca în acest exemplu:

Link 'build' => 'src';

Directoarele specificate sunt „legate” la directorul sursă specificat. Să presupunem
că ai configurat un director sursă, src, cu subdirectoarele lume și Alo sub acesta,
ca în exemplul precedent. Apoi, puteți înlocui liniile de construcție originale
Următor:

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

Observați că tratați recrut fișier ca și cum ar fi existat în directorul de compilare. Acum dacă
tastați aceeași comandă ca înainte, veți obține următoarele rezultate:

% contra export
Instalați build/world/world.h ca export/include/world.h
cc -Iexport/include -c build/hello/hello.c -o build/hello/hello.o
cc -Iexport/include -c build/world/world.c -o build/world/world.o
ar r build/world/libworld.a build/world/world.o
ar: crearea build/world/libworld.a
ranlib build/world/libworld.a
Instalați build/world/libworld.a ca export/lib/libworld.a
cc -o build/hello/hello build/hello/hello.o -Lexport/lib -lworld
Instalați build/hello/hello ca export/bin/hello

Din nou, Cons s-a ocupat de detalii pentru tine. În special, veți observa că toate
build-urile se fac folosind fișiere sursă și fișiere obiect din directorul de build. Pentru
exemplu, construi/lumea/lumea.o este compilat din construi/lumea/lumea.c, și
export/include/world.h este instalat de la construi/lumea/lumea.h. Acest lucru este realizat la majoritatea
sisteme prin simplul expedient de a lega „hard” fișierele necesare din fiecare sursă
directorul în directorul de compilare corespunzător.

Legăturile sunt întreținute corect de Cons, indiferent de ceea ce faci cu directorul sursă.
Dacă modificați un fișier sursă, editorul dumneavoastră poate face acest lucru „la loc” sau îl poate redenumi
mai întâi și creați un fișier nou. În acest din urmă caz, orice legătură rigidă va fi pierdută. Contra vor
detectează această condiție data viitoare când este nevoie de fișierul sursă și îl va reconecta
în mod corespunzător.

De asemenea, veți observa, apropo, că Nu. au fost necesare modificări ale suportului recrut
fișiere. Și putem merge mai departe, așa cum vom vedea în secțiunea următoare.

Variantă construiește


Buna, Lume! pentru banană și piersică OS-uri

Variantele necesită doar o altă extensie simplă. Să luăm ca exemplu a
cerința de a permite versiuni atât pentru sistemele de operare baNaNa, cât și pentru Peach. În acest caz,
folosim un sistem de fișiere distribuit, cum ar fi NFS pentru a accesa un anumit sistem și
numai unul sau altul dintre sisteme trebuie să fie compilat pentru orice invocare dată a
„contra”. Iată o modalitate prin care am putea configura construi dosar pentru nostru Buna, Lume!
aplicare:

# Construiți fișierul pentru Hello, World!

die qq (OS trebuie specificat) cu excepția cazului în care $OS = $ARG{OS};
die qq (OS trebuie să fie „piersică” sau „banană”)
if $OS ne "piersică" && $OS ne "banana";

# Unde să punem toate produsele noastre comune.
$EXPORT = "#export/$OS";

Export qw( CONTRAS INCLUDE LIB BIN );

# Directoare standard pentru partajarea produselor.
$INCLUDE = "$EXPORT/include";
$LIB = "$EXPORT/lib";
$BIN = "$EXPORT/bin";

# Un mediu de construcție standard.
$CONS = noi contra (
CPPPATH => $INCLUDE, # Include calea pentru compilațiile C
LIBPATH => $LIB, # Calea bibliotecii pentru conectarea programelor
LIBS => '-lworld', # Listă de biblioteci standard
);

# $BUILD este locul unde vom deriva totul.
$BUILD = "#build/$OS";

# Spuneți contra unde sunt fișierele sursă pentru $BUILD.
Link $BUILD => 'src';

Construi (
„$BUILD/hello/Conscript”,
„$BUILD/world/Conscript”,
);

Acum, dacă ne conectăm la un sistem Peach, ne putem construi Buna, Lume! cerere pentru asta
platformă:

% contra export OS=piersică
Instalați build/peach/world/world.h ca export/peach/include/world.h
cc -Iexport/piersică/include -c build/peach/hello/hello.c -o build/peach/hello/hello.o
cc -Iexport/piersică/include -c build/peach/world/world.c -o build/peach/world/world.o
ar r build/peach/world/libworld.a build/peach/world/world.o
ar: crearea build/peach/world/libworld.a
ranlib build/peach/world/libworld.a
Instalați build/peach/world/libworld.a ca export/peach/lib/libworld.a
cc -o build/peach/hello/hello build/peach/hello/hello.o -Lexport/peach/lib -lworld
Instalați build/peach/hello/hello ca export/peach/bin/hello

Variaţii on a temă

Alte variante ale acestui model sunt posibile. De exemplu, ați putea decide că doriți
pentru a separa fișierele incluse în fișiere dependente de platformă și fișiere independente de platformă.
În acest caz, ar trebui să definiți o alternativă la `$INCLUDE' pentru platformă dependentă
fișiere. Cel mai recrut fișiere, care generează fișiere include pur independente de platformă, ar
nu trebuie să se schimbe.

De asemenea, poate doriți să puteți compila întregul sistem cu depanare sau profilare,
de exemplu, activat. Puteți face acest lucru cu opțiunile de linie de comandă adecvate, cum ar fi
`DEBUG=on'. Acest lucru ar fi apoi tradus în platforma corespunzătoare specifică
cerințe pentru a activa depanarea (aceasta ar putea include dezactivarea optimizării, pentru
exemplu). Puteți varia opțional spațiul de nume pentru aceste tipuri diferite de sisteme,
dar, după cum vom vedea în secțiunea următoare, nu este esenţial pentru a face asta, deoarece Cons este drăguț
inteligent în ceea ce privește reconstruirea lucrurilor atunci când schimbați opțiunile.

Semnături


MD5 criptografic semnături

Ori de câte ori Cons creează un fișier derivat, acesta stochează un semnătură pentru acel dosar. Semnatura
este stocat într-un fișier separat, unul pentru fiecare director. După ce exemplul anterior a fost compilat,
il .consemn de fișier în construi/piersică/lume directorul arăta astfel:

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

Primul număr este un marcaj de timp - pentru un sistem UNIX, acesta este de obicei numărul de
secunde de la 1 ianuarie 1970. A doua valoare este o sumă de control MD5. The Mesaj rezumat
Algoritm este un algoritm care, având în vedere un șir de intrare, calculează un criptografic puternic
semnătura pentru acel șir. Suma de control MD5 stocată în .consemn dosarul este, de fapt, a
rezumați toate informațiile de dependență pentru fișierul specificat. Deci, de exemplu, pentru
lume.o fișier, acesta include cel puțin fișierul lume.c fișier, precum și orice fișiere antet care Cons
știe despre care sunt incluse, direct sau indirect de lume.c. Nu numai asta, ci și
linia de comandă reală care a fost folosită pentru a genera lume.o este, de asemenea, alimentat în calculul
semnatura. În mod similar, libworld.a primește o semnătură care „include” toate
semnăturile constituenților săi (și, prin urmare, tranzitiv, semnăturile lui lor
constituenți), precum și linia de comandă care a creat fișierul.

Semnătura unui fișier nederivat este calculată, implicit, luând curentul
ora de modificare a fișierului și numele intrării fișierului (cu excepția cazului în care se întâmplă să existe un
curent .consemn intrare pentru acel dosar, caz în care se utilizează semnătura respectivă).

Observați că nu este nevoie ca un fișier derivat să depindă de niciun anume construi or
recrut fișier -- dacă modificările aduse acestor fișiere afectează fișierul în cauză, atunci acesta va fi
reflectată automat în semnătura sa, deoarece părțile relevante ale liniei de comandă sunt
incluse în semnătură. Modificările fără legătură nu vor avea niciun efect.

Când Cons ia în considerare dacă să derive un anumit fișier, atunci mai întâi calculează
semnătura așteptată a dosarului. Apoi compară ultima oră de modificare a fișierului cu
timpul înregistrat în .consemn intrare, dacă există. Dacă aceste timpuri se potrivesc, atunci
semnătura stocată în .consemn fișierul este considerat a fi corect. Dacă fișierul este anterior
semnătura nu se potrivește cu semnătura nouă, așteptată, atunci fișierul trebuie rederivat.

Observați că un fișier va fi rederivat ori de câte ori se schimbă ceva despre un fișier dependent. În
în special, observați că Orice modificarea timpului de modificare a unei persoane dependente (înainte sau
înapoi în timp) va forța recompilarea fișierului derivat.

Utilizarea acestor semnături este o metodă extrem de simplă, eficientă și eficientă
imbunatatirea -- in mod dramatic -- reproductibilitatea unui sistem.

Vom demonstra acest lucru cu un exemplu simplu:

# Simplu „Bună, lume!” Construiți fișierul
$CFLAGS = '-g' dacă $ARG{DEBUG} eq 'on';
$CONS = noi contra(CFLAGS => $CFLAGS);
Program $CONS 'hello', 'hello.c';

Observați cum se recompilează Cons la momentele potrivite:

% contra salut
cc -c salut.c -o salut.o
cc -o salut salut.o
% contra salut
contra: „bună ziua” este la zi.
% contra DEBUG=on salut
cc -g -c salut.c -o salut.o
cc -o salut salut.o
% contra DEBUG=on salut
contra: „bună ziua” este la zi.
% contra salut
cc -c salut.c -o salut.o
cc -o salut salut.o

Cod Repozitorii


Multe organizații de dezvoltare de software vor avea unul sau mai multe directoare de depozite centrale
arbori care conțin codul sursă curent pentru unul sau mai multe proiecte, precum și codul derivat
fișiere obiect, biblioteci și executabile. Pentru a reduce recompilările inutile,
este util să folosiți fișiere din depozit pentru a construi software de dezvoltare - presupunând, de
desigur, că nu există un fișier de dependență mai nou în arborele de construcție local.

Repertoriu

Contra oferă un mecanism pentru a specifica o listă de depozite de coduri care vor fi căutate,
în ordine, pentru fișierele sursă și fișierele derivate care nu se găsesc în arborele directorului de compilare local.

Următoarele rânduri în a construi fișierul va instrui Cons să caute mai întâi sub
/usr/experiment/repository director și apoi sub /usr/product/repository director:

Depozitul qw (
/usr/experiment/repository
/usr/product/repository
);

Directoarele de depozit specificate pot conține fișiere sursă, fișiere derivate (obiecte,
biblioteci și executabile), sau ambele. Dacă nu există niciun fișier local (sursă sau derivat) sub
directorul în care se execută Cons, apoi prima copie a unui fișier cu același nume găsită
sub un director de depozit va fi folosit pentru a construi orice fișiere derivate locale.

Cons menține o listă globală de directoare de depozite. Contra vor elimina
directorul curent și orice directoare inexistente din listă.

Găsire il construi fişier in a Repertoriu

Contra vor căuta, de asemenea construi și recrut fișierele din arborele sau arborii depozitului.
Totuși, acest lucru duce la o situație de pui și ou: cum arăți într-un arbore de depozit
pentru o construi dosar dacă construi fișierul vă spune unde este depozitul? A obține
în jurul acestui lucru, depozitele pot fi specificate prin opțiunile „-R” de pe linia de comandă:

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

Orice directoare de depozit specificate în construi or recrut fișierele vor fi atașate
către directoarele de depozit specificate de opțiunile `-R' din linia de comandă.

Repertoriu sursă fișiere

Dacă codul sursă (include recrut fișier) pentru versiunea de bibliotecă a fișierului Buna,
Lume! Aplicația C este într-un depozit (fără fișiere derivate), Contra va folosi
fișiere sursă de depozit pentru a crea fișierele obiect local și fișierul executabil:

% contra -R /usr/src_only/repository salut
gcc -c /usr/src_only/repository/hello.c -o hello.o
gcc -c /usr/src_only/repository/world.c -o world.o
ar r libworld.o lume.o
ar: crearea libworld.a
ranlib libworld.a
gcc -o salut salut.o libworld.a

Crearea unui fișier sursă local va determina Cons să reconstruiască fișierul derivat corespunzător sau
fișiere:

% pico lume.c
[EDIT]
% contra -R /usr/src_only/repository salut
gcc -c lume.c -o lume.o
ar r libworld.o lume.o
ar: crearea libworld.a
ranlib libworld.a
gcc -o salut salut.o libworld.a

Și eliminarea fișierului sursă local va face ca Cons să revină la construirea derivatului
fișiere din sursa depozitului:

% rm lume.c
% contra -R /usr/src_only/repository salut
gcc -c /usr/src_only/repository/world.c -o world.o
ar r libworld.o lume.o
ar: crearea libworld.a
ranlib libworld.a
gcc -o salut salut.o libworld.a

Repertoriu derivat fișiere

Dacă un arbore de depozit conține fișiere derivate (de obicei fișiere obiect, biblioteci sau
executabile), Cons va efectua calculul normal al semnăturii pentru a decide dacă
fișierul de depozit este actualizat sau un fișier derivat trebuie să fie construit local. Aceasta înseamnă că,
pentru a asigura calcularea corectă a semnăturii, un arbore de depozit trebuie să conțină și codul
.consemn fișiere care au fost create de Cons la generarea fișierelor derivate.

Acest lucru ar fi de obicei realizat prin construirea software-ului în depozit (sau,
alternativ, într-un director de compilare și apoi copierea rezultatului în depozit):

% cd /usr/all/repository
% contra salut
gcc -c salut.c -o salut.o
gcc -c lume.c -o lume.o
ar r libworld.o lume.o
ar: crearea libworld.a
ranlib libworld.a
gcc -o salut salut.o libworld.a

(Acest lucru este sigur chiar dacă construi fișierul listează /usr/all/repository director într-un
Comanda „Repository” deoarece Cons va elimina directorul curent din depozit
listă.)

Acum, dacă vrem să construim o copie a aplicației cu propria noastră buna dosar, avem nevoie doar
pentru a crea singurul fișier sursă necesar și utilizați opțiunea `-R' pentru ca Cons să folosească altul
fișiere din depozit:

% mkdir $HOME/build1
% cd $HOME/build1
% ed salut.c
[EDIT]
% contra -R /usr/all/repository salut
gcc -c salut.c -o salut.o
gcc -o salut hello.o /usr/all/repository/libworld.a

Observați că Cons nu s-a deranjat să recreeze un local libworld.a biblioteca (sau recompilați
lume.o module), dar în schimb folosește versiunea deja compilată din depozit.

Pentru că semnăturile MD5 pe care le pune Cons în .consemn fișierul conține marcaje de timp pentru
fișiere derivate, marcajele de timp ale semnăturii trebuie să se potrivească cu marcajele de timp ale fișierului pentru o semnătură
fi considerat valabil.

Unele sisteme software pot modifica marcajele de timp ale fișierelor de depozit (prin copierea acestora,
de exemplu), caz în care Cons va presupune, în mod implicit, că semnăturile din depozit sunt nevalide
și reconstruiți fișierele în mod inutil. Acest comportament poate fi modificat prin specificarea:

Repository_Sig_Times_OK 0;

Acest lucru îi spune lui Cons să ignore marcajele de timp atunci când decide dacă o semnătură este validă. (Notă
faptul că evitarea acestei verificări de sănătate înseamnă că trebuie să existe un control adecvat asupra depozitului
arbore pentru a vă asigura că fișierele derivate nu pot fi modificate fără actualizarea .consemn
semnătură.)

Local copii of fișiere

Dacă arborele depozitului conține rezultatele complete ale unei build, și încercăm să construim din
depozitul fără fișiere în arborele nostru local, ceva moderat surprinzător
se intampla:

% mkdir $HOME/build2
% cd $HOME/build2
% contra -R /usr/all/repository salut
contra: „bună ziua” este la zi.

De ce spune Cons că Alo programul este actualizat atunci când nu există Alo program în
directorul de compilare local? Deoarece depozitul (nu directorul local) conține fișierul
up-to-data Alo program, iar Cons stabilește corect că nu trebuie făcut nimic
reconstruiți această copie actualizată a fișierului.

Există, totuși, de multe ori în care este oportun să se asigure că o copie locală a a
fișierul există întotdeauna. Un script de ambalare sau de testare, de exemplu, poate presupune că este sigur
fișierele generate există local. În loc să facă aceste scripturi subsidiare conștiente de
directorul de depozit, comanda `Local' poate fi adăugată la a construi or recrut fișier de
specificați că un anumit fișier sau fișiere trebuie să apară în directorul de compilare local:

qw local(
Alo
);

Apoi, dacă rulăm din nou aceeași comandă, Cons va face o copie locală a programului din
copie din depozit (să vă spună că face acest lucru):

% contra -R /usr/all/repository salut
Copie locală a hello din /usr/all/repository/hello
contra: „bună ziua” este la zi.

Observați că, deoarece acțiunea de a face copie locală nu este considerată o „build” a fișierului
Alo fișier, Cons încă raportează că este actualizat.

Crearea de copii locale este cea mai utilă pentru fișierele care sunt instalate într-un
director intermediar (pentru partajarea cu alte directoare) prin comanda „Instalare”.
Însoțirea comenzii „Instalare” pentru un fișier cu o comandă „Local” însoțitoare este așa
este comun faptul că Cons oferă o comandă „Install_Local” ca o modalitate convenabilă de a face ambele:

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

este exact echivalent cu:

Instalați $env '#export', 'hello';
Local „#export/hello”;

Atât comenzile `Local' cât și `Install_Local' actualizează local .consemn fișier cu
semnăturile de fișiere adecvate, astfel încât versiunile viitoare să fie efectuate corect.

Repertoriu dependenţă analiză

Datorită scanării sale încorporate, Cons va căuta în arborii de depozit specificati
.h fișiere. Cu toate acestea, cu excepția cazului în care compilatorul știe și despre arborii depozitului, va fi
de negasit .h fișiere care există doar într-un depozit. Dacă, de exemplu, buna
fișierul include fișierul bună h fișier în directorul său curent:

% contra -R /usr/all/repository salut
gcc -c /usr/all/repository/hello.c -o hello.o
/usr/all/repository/hello.c:1: hello.h: Nu există un astfel de fișier sau director

Rezolvarea acestei probleme impune anumite cerințe asupra modului în care sunt mediile de construcție
definite și în modul în care este utilizată directiva de preprocesor C `#include' pentru a include fișiere.

Pentru a informa compilatorul despre arborii depozitului, Cons va adăuga „-I” corespunzător
flags la comenzile de compilare. Aceasta înseamnă că variabila `CPPPATH' din fișierul
mediul de construcție trebuie să specifice în mod explicit toate subdirectoarele care urmează să fie căutate
pentru fișierele incluse, inclusiv directorul curent. În consecință, putem remedia cele de mai sus
exemplu prin schimbarea mediului crearea în construi fișier după cum urmează:

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

Datorită definiției variabilei `CPPPATH', aceasta rezultă, atunci când re-executăm
comanda:

% contra -R /usr/all/repository salut
gcc -c -I. -I/usr/all/repository /usr/all/repository/hello.c -o hello.o
gcc -o salut hello.o /usr/all/repository/libworld.a

Ordinea steagurilor „-I” reproduce, pentru preprocesorul C, același depozit-
calea de căutare a directorului pe care Cons o folosește pentru propria analiză a dependenței. Dacă există
mai multe depozite și mai multe directoare `CPPPATH', Cons va adăuga depozitul
directoare la începutul fiecărui director `CPPPATH', înmulțind rapid numărul
de steaguri `-I'. Ca exemplu extrem, a construi fisier care contine:

Depozitul qw(
/u1
/u2
);

$env = noi contra(
CPPPATH => 'a:b:c',
);

Ar produce o comandă de compilare a:

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

Deoarece Cons se bazează pe steagurile `-I' ale compilatorului pentru a comunica ordinea în care
directoarele depozitului trebuie căutate, manevrarea de către Cons a directoarelor depozitului este
fundamental incompatibil cu utilizarea ghilimelelor duble pe directivele `#include' din C
cod sursa:

#include „fișier.h” /* NU UTILIZA CITELE DUBLE CA ASTA */

Acest lucru se datorează faptului că majoritatea preprocesoarelor C, atunci când se confruntă cu o astfel de directivă, vor fi întotdeauna pe primul loc
căutați în directorul care conține fișierul sursă. Acest lucru subminează elaboratul „-eu”
opțiunile pe care Cons le construiește pentru a face ca preprocesorul să se conformeze căutării preferate
cale.

În consecință, atunci când utilizați arbori de depozit în Cons, mereu utilizați unghiuri pentru inclus
fișiere:

#include /* UTILIZAȚI ANGULARE ÎN LOC */

Lista_depozite

Contra oferă o comandă „Repository_List” pentru a returna o listă a tuturor directoarelor depozitului
în ordinea lor curentă de căutare. Acesta poate fi folosit pentru depanare sau pentru a face Perl mai complex
chestie:

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

Repertoriu interacţiune cu alte Contra caracteristici

Manevrarea de către Cons a arborilor depozitului interacționează corect cu alte caracteristici Cons - ceea ce este
să spun, în general, face ceea ce te-ai aștepta.

În special, arborii de depozit interacționează corect și destul de puternic cu „Link”
comanda. Un arbore de depozit poate conține unul sau mai multe subdirectoare pentru versiuni
stabilit prin „Link” către un subdirector sursă. Contra vor căuta fișiere derivate în
subdirectoarele de compilare adecvate sub arborele depozitului.

Mod implicit obiective


Până acum, am demonstrat că invocăm Cons cu o țintă explicită de construit:

% contra salut

În mod normal, Cons nu construiește nimic decât dacă este specificată o țintă, dar specificând '.'
(directorul curent) va construi totul:

% contra # nu construiește nimic

% contra . # construiește totul sub directorul de nivel superior

Adăugarea metodei „Default” la oricare construi or recrut fișierul va adăuga cele specificate
ținte la o listă de ținte implicite. Contra vor crea aceste valori implicite dacă nu există
ținte specificate pe linia de comandă. Deci, adăugarea următoarei linii la nivelul superior
construi fișierul va imita comportamentul tipic al lui Make de a construi totul în mod implicit:

Mod implicit '.';

Următoarele ar adăuga Alo și la revedere comenzi (în același director ca și
construi or recrut fișier) în lista implicită:

Qw implicit(
Alo
la revedere
);

Metoda „Default” poate fi folosită de mai multe ori pentru a adăuga ținte la lista implicită.

Selectiv construiește


Contra oferă două metode pentru a reduce dimensiunea construcției date. Prima este prin precizare
ținte pe linia de comandă, iar a doua este o metodă de tăiere a arborelui de construcție. Bine
luați în considerare mai întâi specificația țintei.

Selectiv direcționare

La fel ca make, Cons permite specificarea „țintelor” pe linia de comandă. Țintele contra
pot fi fie fișiere, fie directoare. Când este specificat un director, acesta este pur și simplu un scurt-
notație manuală pentru fiecare produs derivat - despre care Cons știe - în specificația
director și mai jos. De exemplu:

% contra build/hello/hello.o

înseamnă a construi salut.o si tot ceea ce salut.o ar putea avea nevoie. Acesta este dintr-un precedent
Versiunea Buna, Lume! program în care salut.o depindea de
export/include/world.h. Dacă acel fișier nu este actualizat (pentru că cineva a modificat
src/world/world.h), apoi va fi reconstruit, chiar dacă se află într-un director aflat la distanță de la
construi/saluta.

În acest exemplu:

% contra construi

Totul în construi directorul este construit, dacă este necesar. Din nou, acest lucru poate cauza mai multe fișiere
a fi construit. În special, ambele export/include/world.h și export/lib/libworld.a sunt
cerute de construi/saluta director și astfel vor fi construite dacă sunt învechite.

Dacă facem, în schimb:

% contra export

atunci numai fișierele care ar trebui să fie instalate în directorul de export vor fi reconstruite, dacă
necesar și apoi instalat acolo. Rețineți că „cons build” ar putea construi fișiere care „cons
export' nu se construiește și invers.

Nu „special” obiective

Cu Contra, nu sunt necesare ținte „speciale” de tip make-style. Cel mai simplu analog cu Cons
este de a folosi special exporturile directoare, în schimb. Să presupunem, de exemplu, că aveți un
întreaga serie de teste unitare care sunt asociate cu codul dvs. Testele trăiesc în
directorul sursă lângă cod. În mod normal, totuși, nu doriți să construiți aceste teste.
O soluție este să oferiți toate instrucțiunile de construire pentru crearea testelor și apoi să
instalați testele într-o parte separată a arborelui. Dacă instalăm testele într-un nivel superior
director numit teste, atunci:

% teste contra

va construi toate testele.

% contra export

va construi versiunea de producție a sistemului (dar nu și testele) și:

% contra construi

ar trebui probabil evitată (deoarece va compila teste în mod inutil).

Dacă doriți să construiți doar un singur test, atunci puteți denumi în mod explicit testul (în
fie teste directorul sau construi director). De asemenea, puteți agrega testele
într-o ierarhie convenabilă în directorul de teste. Această ierarhie nu trebuie
se potrivesc neapărat cu ierarhia sursă, aproape în același mod în care ierarhia include
probabil că nu se potrivește cu ierarhia sursă (ierarhia de includere este puțin probabil să fie mai mare
adâncime de peste două niveluri, pentru programele C).

Dacă doriți să construiți absolut totul în arbore (sub rezerva oricăror opțiuni pe care le aveți
selectați), puteți utiliza:

% contra .

Acest lucru nu este deosebit de eficient, deoarece va plimba în mod redundant toți copacii,
inclusiv arborele sursă. Arborele sursă, desigur, poate conține obiecte construibile
ea--nimic nu te împiedică să faci asta, chiar dacă în mod normal construiești într-o versiune separată
copac.

Construi Tunderea


În legătură cu selecția țintei, construi tăiere poate fi folosit pentru a reduce domeniul de aplicare al
construi. În exemplul anterior Peach și baNaNa, am văzut deja modul în care este condus de script
tăierea de construcție poate fi utilizată pentru a face disponibilă doar jumătate din construcția potențială pentru orice dată
invocarea „contra”. Contra oferă, de asemenea, ca comoditate, o convenție de linie de comandă care
vă permite să specificați care recrut fișierele sunt de fapt „construite” – adică încorporate
în arborele de construcție. De exemplu:

% contra build +world

Argumentul „+” introduce o expresie regulată Perl. Acest lucru trebuie, desigur, citat la
nivelul shell dacă există meta-caractere shell în expresie. The
expresia este corelată cu fiecare recrut fișier care a fost menționat într-un „Build”
declarație și numai acele scripturi cu nume care se potrivesc sunt de fapt încorporate în
construi un copac. Sunt permise mai multe astfel de argumente, caz în care o potrivire împotriva oricăruia dintre ele
este suficient pentru a determina includerea unui script.

În exemplul de mai sus, Alo programul nu va fi construit, deoarece Cons va avea nr
cunoașterea scenariului salut/Conscript. libworld.a arhiva va fi construita insa daca
trebuie să fie.

Există câteva utilizări pentru tăierea construcției prin linia de comandă. Poate cel mai util
este capacitatea de a face schimbări locale și apoi, cu cunoștințe suficiente despre
consecințele acestor modificări, restrângeți dimensiunea arborelui de construcție pentru a accelera
timpul de reconstrucție. O a doua utilizare pentru tăierea de construcție este prevenirea activă a recompilării
a anumitor fișiere despre care știți că se vor recompila datorită, de exemplu, unui fișier antet modificat.
Poate știți că fie modificările aduse fișierului antet sunt neimportante, fie că
modificările pot fi ignorate în siguranță pentru cea mai mare parte a arborelui, în scopuri de testare. Cu contra,
opinia este că este pragmatic să admitem acest tip de comportament, înțelegând că
la următoarea construcție completă va fi tot ceea ce trebuie reconstruit. Nu există echivalent
la o comandă ``make touch'', pentru a marca fișierele ca fiind permanent actualizate. Deci orice risc care este
cauzate de tăierea construcției este atenuată. Pentru munca de calitate a lansării, evident, vă recomandăm
pe care nu îl utilizați build tuning (este perfect OK să îl utilizați în timpul integrării, totuși,
pentru a verifica compilarea, etc. Doar asigurați-vă că faceți o construcție neconstrânsă înainte de a comite
integrarea).

Temporar suprascrie


Contra oferă un mecanism foarte simplu pentru suprascrierea aspectelor unei build. Esența este
că scrieți un fișier de suprascriere care conține una sau mai multe comenzi „Override” și dvs
specificați acest lucru pe linia de comandă, când rulați „cons”:

% contra -o peste export

va construi exporturile director, cu toate fișierele derivate supuse înlocuirilor prezente
în peste fişier. Dacă omiteți opțiunea „-o”, atunci tot ce este necesar pentru a elimina
toate suprareglarile vor fi reconstruite.

Supracomandarea mediu inconjurator variabile

Fișierul de înlocuire poate conține două tipuri de suprascrieri. Primul este mediul de intrare
variabile. Acestea sunt în mod normal accesibile de către construi fișier din hash-ul „%ENV”.
variabil. Acestea pot fi înlocuite în mod trivial în fișierul de suprascriere prin setarea
elementele adecvate ale lui `%ENV' (acestea pot fi, de asemenea, suprascrise în mediul utilizatorului,
desigur).

Trece peste comandă

Al doilea tip de suprascriere este realizat cu comanda „Override”, care arată ca
acest:

Trece peste , => , => , ...;

Expresia regulată expresie regulată este corelat cu fiecare fișier derivat care este candidat
pentru construirea. Dacă fișierul derivat se potrivește, atunci perechile variabilă/valoare sunt folosite pentru
suprascrie valorile din mediul de construcție asociat fișierului derivat.

Să presupunem că avem un mediu de construcție ca acesta:

$CONS = noi contra(
COPT => '',
CDBG => '-g',
CFLAGS => '%COPT %CDBG',
);

Apoi, dacă avem un fișier de suprascriere peste care contine aceasta comanda:

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

apoi orice invocare „contra” cu „-o peste” care creează .o fișierele prin acest mediu vor
determinați-le să fie compilate cu `-O 'și nu `-g'. Desigur, anularea ar putea fi
limitat la un singur director prin selectarea adecvată a unei expresii regulate.

Iată versiunea originală a Hello, World! program, construit cu acest mediu.
Rețineți că Cons reconstruiește piesele corespunzătoare atunci când anularea este aplicată sau eliminată:

% contra salut
cc -g -c salut.c -o salut.o
cc -o salut salut.o
% contra -o peste salut
cc -O -c salut.c -o salut.o
cc -o salut salut.o
% contra -o peste salut
contra: „bună ziua” este la zi.
% contra salut
cc -g -c salut.c -o salut.o
cc -o salut salut.o

Este important ca comanda „Override” să fie folosită numai pentru temporar, din mers
suprascrieri necesare dezvoltării deoarece suprascrierile nu sunt independente de platformă și
deoarece se bazează prea mult pe cunoașterea intimă a modului de funcționare a scenariilor. Pentru
utilizarea temporară, totuși, sunt exact ceea ce îți dorești.

Rețineți că este încă util să oferiți, să zicem, capacitatea de a crea o imagine complet optimizată
versiunea unui sistem pentru utilizare în producție - din construi și recrut fișiere. Pe aici
puteți adapta sistemul optimizat la platformă. Acolo unde trebuie să existe compromisuri ale optimizatorului
realizate (fișierele anume pot să nu fie compilate cu optimizare completă, de exemplu), atunci
acestea pot fi înregistrate pentru posteritate (și reproductibilitate) direct în scenarii.

Mai Mult on construcţie medii


Mod implicit construcţie variabile

Am menționat și am folosit conceptul de a construcţie mediu inconjurator, de multe ori în
paginile precedente. Acum este timpul să facem acest lucru puțin mai concret. Cu următoarele
afirmație:

$env = new contra();

este creată o referință la un mediu de construcție nou, implicit. Acesta conține un număr
a variabilelor de construcţie şi a unor metode. În prezent, lista implicită a
variabilele de construcție sunt definite după cum urmează:

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

Pe sistemele Win32 (Windows NT), următoarele variabile de construcție sunt suprascrise în
implicit:

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

Aceste variabile sunt utilizate de diferitele metode asociate mediului, în
în special orice metodă care în cele din urmă invocă o comandă externă le va înlocui pe acestea
variabile în comanda finală, după caz. De exemplu, metoda „Obiecte” ia
un număr de fișiere sursă și aranjează pentru a deriva, dacă este necesar, obiectul corespunzător
fișiere. De exemplu:

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

Aceasta va aranja să producă, dacă este necesar, foo.o și bar.o. Comanda invocată este simplă
`%CCCOM', care se extinde prin substituire, la comanda externă corespunzătoare necesară
pentru a construi fiecare obiect. Vom explora regulile de substituție în continuare sub „Comandă”
metoda, mai jos.

Variabilele de construcție sunt utilizate și în alte scopuri. De exemplu, `CPPPATH' este
folosit pentru a specifica o cale separată de două puncte pentru directoarele include. Acestea sunt menite să fie
transmis la preprocesorul C și sunt, de asemenea, utilizate de mașina de scanare a fișierelor C pentru
determina dependențele implicate într-o compilație C. Variabile care încep cu
sublinierea, sunt create prin diverse metode și, în mod normal, ar trebui să fie considerate „interne”
variabile. De exemplu, când este apelată o metodă care necesită crearea unui obiect
dintr-o sursă C, este creată variabila `_IFLAGS': aceasta corespunde comutatoarelor `-I'
cerut de compilatorul C pentru a reprezenta directoarele specificate de `CPPPATH'.

Rețineți că, pentru orice mediu particular, valoarea unei variabile este setată o dată, apoi
nu resetați niciodată (pentru a schimba o variabilă, trebuie să creați un mediu nou. Sunt furnizate metode
pentru copierea mediilor existente în acest scop). Unele variabile interne, cum ar fi
`_IFLAGS' sunt create la cerere, dar odată setate, ele rămân fixate pe toată durata de viață
mediu. (envrironment)

Variabilele „CFLAGS”, „LDFLAGS” și „ARFLAGS” oferă toate un loc pentru trecerea opțiunilor către
compilatorul, încărcătorul și, respectiv, arhivatorul. Mai puțin evident, „INCDIRPREFIX”
variabila specifică șirul de opțiuni care trebuie adăugat la începutul fiecărei includeri
director, astfel încât compilatorul să știe unde să găsească .h fișiere. În mod similar, cel
Variabila `LIBDIRPREFIX' specifică șirul de opțiuni care trebuie adăugat la începutul lui
fiecare director pe care linkerul ar trebui să-l caute pentru biblioteci.

O altă variabilă, `ENV', este utilizată pentru a determina mediul sistemului în timpul execuției
a unei comenzi externe. În mod implicit, singura variabilă de mediu care este setată este `PATH',
care este calea de execuție pentru o comandă UNIX. Pentru cea mai mare reproductibilitate, ar trebui
aranjați-vă cu adevărat să vă setați propria cale de execuție, la nivelul superior construi dosar (sau
poate prin importul unui pachet de construcție adecvat cu comanda Perl `use'). The
variabilele implicite sunt menite să vă scoată la iveală.

Interpolând construcţie variabile

Variabilele de mediu de construcție pot fi interpolate în numele fișierelor sursă și țintă
prin prefixarea numelui variabilei de construcție cu `%'.

$env = noi contra(
DESTDIR => 'programe',
SRCDIR => 'src',
);
Program $env '%DESTDIR/hello', '%SRCDIR/hello.c';

Extinderea variabilelor de construcție este recursivă - adică fișierul nume(s) vor fi re-
extins până când nu mai pot fi făcute înlocuiri. Dacă o variabilă de construcție nu este
definit în mediu, atunci șirul nul va fi înlocuit.

Mod implicit construcţie Metode


Lista metodelor implicite de construcție include următoarele:

"nou" constructor

Metoda „nouă” este un constructor de obiecte Perl. Adică nu este invocat printr-o referință
la un mediu de construcție existent referință, ci, mai degrabă static, folosind numele
din Perl pachet unde este definit constructorul. Metoda este invocată astfel:

$env = noi contra( );

Mediul pe care îl primiți înapoi este binecuvântat în pachetul „contra”, ceea ce înseamnă că va fi
au asociat cu acesta metodele implicite descrise mai jos. Constructie individuala
variabilele pot fi suprascrise prin furnizarea de perechi nume/valoare într-o listă de înlocuire. Rețineți că
pentru a suprascrie orice variabilă de mediu de comandă (adică orice sub `ENV'), va trebui
depășește-le pe toate. Puteți ocoli această dificultate folosind metoda „copiere” pe un
mediul de construcție existent.

"clona" metodă

Metoda „clone” creează o clonă a unui mediu de construcție existent și poate fi
numită ca în exemplul următor:

$env2 = $env1->clona( );

Puteți oferi modificări în mod obișnuit pentru a crea un mediu diferit de cel al
original. Dacă doriți doar un nume nou pentru același mediu (care poate fi util când
exportând medii în componente existente), puteți utiliza doar o atribuire simplă.

"copie" metodă

Metoda „copiere” extrage variabilele de construcție definite extern dintr-un
mediu și le returnează ca o listă de perechi nume/valoare. De asemenea, pot fi înlocuite
cu condiția, în acest caz, valorile suprascrise vor fi returnate, după caz. The
lista returnată poate fi atribuită unui hash, așa cum se arată în prototipul de mai jos, dar poate și
fi manipulat în alte moduri:

%env = $env1->copiere( );

Valoarea lui „ENV”, care este ea însăși un hash, este de asemenea copiată într-un nou hash, deci aceasta poate fi
schimbat fără teama de a afecta mediul inițial. Deci, de exemplu, dacă într-adevăr
doriți să suprascrieți doar variabila `PATH' în mediul implicit, puteți face acest lucru
Următor:

%cons = new cons()->copy();
$cons{ENV}{PATH} = " ";
$cons = new contra(%cons);

Acest lucru va lăsa orice altceva care ar putea fi în mediul de execuție implicit
netulburat.

„Instalare” metodă

Metoda „Instalare” aranjează ca fișierele specificate să fie instalate în locația specificată
director. Instalarea este optimizată: fișierul nu este copiat dacă poate fi legat. Dacă
acesta nu este comportamentul dorit, va trebui să utilizați o metodă diferită pentru a instala
fişier. Se numește astfel:

Instalați $env , ;

Rețineți că, în timp ce fișierele care urmează să fie instalate pot fi denumite în mod arbitrar, numai ultimul
componenta fiecărui nume este utilizată pentru numele țintă instalat. Deci, de exemplu, dacă tu
aranjați instalarea foo/bar in Baz, aceasta va crea un bar de fișier în Baz director (nu
foo/bar).

„InstallAs” metodă

Metoda `InstallAs' aranjează sursa specificată fişier(s) să fie instalat ca
ținta specificată fişier(s). Mai multe fișiere ar trebui să fie specificate ca o listă de fișiere. The
instalarea este optimizată: fișierul nu este copiat dacă poate fi legat. Dacă acesta nu este
comportamentul dorit, va trebui să utilizați o metodă diferită pentru a instala fișierul. Este
numit astfel:

`InstallAs' funcționează în două moduri:

Instalare un singur fișier:

InstallAs $env TgtFile, SrcFile;

Instalare mai multe fișiere:

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

Sau chiar ca:

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

Atât lista țintă, cât și lista surselor ar trebui să fie de aceeași lungime.

„Prețios” metodă

Metoda `Precious' cere contra să nu ștergă fișierul specificat sau lista de fișiere înainte
construindu-le din nou. Este invocat ca:

Prețios ;

Acest lucru este util în special pentru a permite actualizări incrementale ale bibliotecilor sau depanare
fișiere de informații care sunt actualizate mai degrabă decât reconstruite de fiecare dată. Contra vor încă
ștergeți fișierele când este specificat steag-ul „-r”.

"Comandă" metodă

Metoda „Comandă” este o metodă catchall care poate fi folosită pentru a aranja orice extern
comanda care urmează să fie apelată pentru a actualiza ținta. Pentru această comandă, un fișier țintă și o listă de
sunt furnizate intrări. În plus, o linie de comandă de construcție, sau linii, este furnizată ca a
șir (acest șir poate avea mai multe comenzi încorporate în el, separate prin new
linii). „Comandă” este numită după cum urmează:

Comanda $env , , ;

Ținta este făcută dependentă de lista de fișiere de intrare specificată, iar intrările trebuie
să fie construit cu succes sau Contra nu va încerca să construiască ținta.

În cadrul comenzii de construcție, orice variabilă din mediul de construcție poate fi
introdus prin prefixarea numelui variabilei de construcție cu `%'. Acesta este recursiv:
comanda este extinsă până când nu mai pot fi făcute înlocuiri. Dacă o construcţie
variabila nu este definită în mediu, atunci șirul nul va fi înlocuit. A
„%%” dublat va fi înlocuit cu un singur „%” în comanda de construcție.

Există mai multe pseudo variabile care vor fi, de asemenea, extinse:

%> Numele fișierului țintă (într-o comandă multi-țintă, aceasta este întotdeauna prima țintă
menționat).

%0 La fel ca `%>'.

%1, %2, ..., %9
Acestea se referă la primul până la al nouălea fișier de intrare, respectiv.

%< Setul complet de intrări. Dacă oricare dintre acestea a fost folosit oriunde altundeva în
linia de comandă curentă (prin „%1”, „%2” etc.), atunci acestea vor fi șterse din
lista oferită de `%<'. Luați în considerare următoarea comandă găsită în a recrut fişier
în test director:

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

If TGT trebuiau actualizate, atunci aceasta ar avea ca rezultat executarea
următoarele comenzi, presupunând că nu a fost stabilită nicio remapare pentru test
director:

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

Oricare dintre pseudovariabilele de mai sus poate fi urmată imediat de una dintre următoarele
sufixe pentru a selecta o parte din numele căii extinse:

:a calea absolută către numele fișierului
:b directorul plus numele fișierului fără orice sufix
:d directorul
:f numele fișierului
: este sufixul numelui fișierului
:F numele fișierului fără orice sufix

Continuând cu exemplul de mai sus, `%<:f' s-ar extinde la `foo bar baz', iar `%':d> ar
extinde la „test”.

Este posibil să rescrieți programatic o parte a comenzii prin includerea unei părți a acesteia
între `%[' și `%]'. Aceasta va apela variabila de construcție numită ca prim cuvânt
inclusă între paranteze ca referință de cod Perl; vor fi utilizate rezultatele acestui apel
pentru a înlocui conținutul parantezelor din linia de comandă. De exemplu, având în vedere un
fișier de intrare existent numit tgt.in:

@keywords = qw(foo bar baz);
$env = new cons(X_COMMA => sub { join(",", @_) });
Comanda $env 'tgt', 'tgt.in', qq(
echo „# Cuvinte cheie: %[X_COMMA @keywords %]” > %>
pisica %< >> %>
);

Aceasta va executa:

echo „# Cuvinte cheie: foo,bar,baz” > tgt
cat tgt.in >> tgt

După ce are loc înlocuirea, șirurile de spațiu alb sunt convertite în spații unice și
spațiul alb de început și de final este eliminat. Prin urmare, nu este posibil să se introducă
spații albe de lungime variabilă în șiruri de caractere trecute într-o comandă, fără a recurge la unele
un fel de citare a cochiliei.

Dacă este furnizat un șir de comandă cu mai multe linii, comenzile sunt executate secvenţial. Dacă există
dintre comenzi eșuează, apoi niciuna dintre celelalte nu este executată și ținta nu este marcată ca
actualizat, adică o nouă semnătură nu este stocată pentru țintă.

În mod normal, dacă toate comenzile reușesc și returnează o stare zero (sau orice platformă-
este necesară o indicație specifică de succes), apoi o nouă semnătură este stocată pentru
ţintă. Dacă o comandă raportează în mod eronat succes chiar și după un eșec, atunci contra va face
presupunem că fișierul țintă creat de acea comandă este exact și actualizat.

Primul cuvânt al fiecărui șir de comandă, după extindere, se presupune a fi un executabil
comanda a căutat pe variabila de mediu `PATH' (care este, la rândul ei, specificată de
Variabila de construcție `ENV'). Dacă această comandă este găsită pe cale, atunci ținta o va face
depinde de asta: comanda va fi astfel construită automat, după cum este necesar. este
este posibil să scrieți comenzi cu mai multe părți în unele shell-uri, separate prin punct și virgulă. Doar
Cu toate acestea, se va depinde primul cuvânt de comandă, deci dacă scrieți șirurile de comandă
în acest fel, trebuie fie să configurați în mod explicit o dependență (cu metoda „Depend”), fie
asigurați-vă că comanda pe care o utilizați este o comandă de sistem care se așteaptă să fie
disponibil. Dacă nu este disponibil, veți primi, desigur, o eroare.

Dacă orice comandă (chiar și una dintr-o comandă cu mai multe linii) începe cu „[perl]”, restul
din acea linie de comandă va fi evaluată de Perl care rulează în loc să fie bifurcată de către
coajă. Dacă apare o eroare la analizarea Perl sau dacă expresia Perl returnează 0 sau
undef, comanda va fi considerată a eșuat. De exemplu, aici este un simplu
comandă care creează un fișier „foo” direct din Perl:

$env = new contra();
Comanda $env „foo”,
qq([perl] deschide(FOO,'>foo');printează FOO "bună\\n"; închide(FOO); 1);

Rețineți că atunci când comanda este executată, vă aflați în același pachet ca și atunci când comanda construi
or recrut fișierul a fost citit, astfel încât să puteți apela funcțiile Perl pe care le-ați definit în același
construi or recrut fișier în care apare „Comandă”:

$env = new contra();
sub create_file {
my $file = shift;
deschide(FIȘIER, ">$fișier");
tipăriți FIȘIER „bună ziua\n”;
close(FIȘIER);
1 reveni;
}
Comanda $env 'foo', "[perl] &create_file('%>')";

Șirul Perl va fi folosit pentru a genera semnătura pentru fișierul derivat, deci dacă dvs
schimbați șirul, fișierul va fi reconstruit. Conținutul oricăror subrutine pe care le apelați,
totuși, nu fac parte din semnătură, deci dacă modificați o subrutină numită, cum ar fi
`create_file' de mai sus, ținta va nu fi reconstruit. Avertisment utilizator.

Contra, în mod normal, imprimă o comandă înainte de a o executa. Acest comportament este suprimat dacă
primul caracter al comenzii este „@”. Rețineți că poate fi necesar să separați „@” de
numele comenzii sau evadați-l pentru a preveni `@cmd' să arate ca o matrice pentru citatul Perl
operatori care efectuează interpolarea:

# Prima linie de comandă este incorectă,
# deoarece „@cp” arată ca o matrice
# la funcția Perl qq//.
# Utilizați în schimb a doua formă.
Comanda $env „foo”, „foo.in”, qq(
@cp %< tempfile
@ cp tempfile %>
);

Dacă există meta caractere shell oriunde în linia de comandă extinsă, cum ar fi „<”,
`>', ghilimele sau punct și virgulă, atunci comanda va fi de fapt executată prin invocarea unui
coajă. Aceasta înseamnă că o comandă precum:

cd foo

singur va eșua de obicei, deoarece nu există nicio comandă „cd” pe cale. Dar comanda
şir:

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

atunci când este extins, va conține în continuare meta caracterul shell punct și virgulă, iar un shell va fi
invocat pentru a interpreta comanda. Deoarece `cd' este interpretat de acest sub-shell, comanda
se va executa conform așteptărilor.

Pentru a specifica o comandă cu mai multe ținte, puteți specifica o referință la o listă de
tinte. În Perl, o listă de referință poate fi creată prin includerea unei liste între paranteze drepte.
De aici următoarea comandă:

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

ar putea fi folosit într-un caz în care comanda `gen' creează două fișiere, ambele foo.h și foo.c.

„Obiecte” metodă

Metoda „Obiecte” aranjează să creeze fișierele obiect care corespund celor specificate
fișiere sursă. Este invocat după cum se arată mai jos:

@files = Obiecte $env ;

Sub Unix, fișierele sursă care se termină în .s și .c sunt acceptate în prezent și vor fi compilate
într-un nume al aceluiași fișier care se termină în .o. În mod implicit, toate fișierele sunt create prin invocare
comanda externă care rezultă din extinderea variabilei de construcție `CCCOM', cu
`%<' și `%>' setate la fișierele sursă și, respectiv, obiect (vezi metoda `Comandă'
pentru detalii de extindere). Variabila `CPPPATH' este de asemenea folosită la scanarea fișierelor sursă
pentru dependențe. Aceasta este o listă de căi separate prin puncte și este folosită și pentru a crea
variabila de construcție `_IFLAGS,' care va conține lista corespunzătoare de -`I'
opțiuni pentru compilare. Orice căi relative din „CPPPATH” este interpretată relativ
la directorul în care a fost creat mediul de construcție asociat (absolut
iar nume de rude de top pot fi, de asemenea, folosite). Această variabilă este folosită de „CCCOM”. Comportamentul
a acestei comenzi poate fi modificată prin modificarea oricăreia dintre variabilele care sunt interpolate
în „CCCOM”, cum ar fi „CC”, „CFLAGS” și, indirect, „CPPPATH”. De asemenea, este posibil să
înlocuiți valoarea lui „CCCOM” în sine. Pentru comoditate, acest fișier returnează lista de
nume de fișiere obiect.

„Program” metodă

Metoda „Program” aranjează să lege programul specificat cu obiectul specificat
fișiere. Se invocă în felul următor:

Programul $env , ;

Numele programului va avea valoarea variabilei de construcție „SUFEXE” adăugată (de
implicit, `.exe' pe sistemele Win32, nimic pe sistemele Unix) dacă sufixul nu este deja
prezent.

Fișierele sursă pot fi specificate în locul fișierelor obiecte - metoda „Obiecte” va fi
invocat pentru a aranja conversia tuturor fișierelor în fișiere obiect și, prin urmare, a tuturor fișierelor
observațiile despre metoda „Obiecte”, de mai sus, se aplică și acestei metode.

Conectarea efectivă a programului va fi gestionată de o comandă externă care rezultă
de la extinderea variabilei de construcție `LINKCOM', cu `%<' setat la fișierele obiect la
să fie legat (în ordinea prezentată) și „%>” setat la țintă (vezi metoda „Comandă”
pentru detalii de extindere). Utilizatorul poate seta variabile suplimentare în construcție
mediu, inclusiv `LINK', pentru a defini ce program să folosească pentru a lega, `LIBPATH', a
listă de căi de căutare în biblioteci, separate prin două puncte, pentru utilizare cu specificațiile bibliotecii ale
formă -llib, și `LIBS', specificând lista bibliotecilor cu care să se conecteze (în fie -llib
formă sau doar ca nume de căi. Căile relative atât în ​​„LIBPATH” cât și în „LIBS” sunt interpretate
relativ la directorul în care este creat mediul de construcție asociat
(pot fi folosite, de asemenea, nume absolute și super-relative). Contra se configurează automat
dependențe de orice biblioteci menționate în `LIBS': acele biblioteci vor fi construite înainte
comanda este legată.

"Biblioteca" metodă

Metoda `Library' aranjează crearea bibliotecii specificate din obiectul specificat
fișiere. Se invocă astfel:

Biblioteca $env , ;

Numele bibliotecii va avea valoarea variabilei de construcție „SUFLIB” adăugată (de
implicit, `.lib' pe sistemele Win32, `.a' pe sistemele Unix) dacă sufixul nu este deja
prezent.

Fișierele sursă pot fi specificate în locul fișierelor obiecte - metoda „Obiecte” va fi
invocat pentru a aranja conversia tuturor fișierelor în fișiere obiect și, prin urmare, a tuturor fișierelor
observațiile despre metoda „Obiecte”, de mai sus, se aplică și acestei metode.

Crearea propriu-zisă a bibliotecii va fi gestionată de o comandă externă care rezultă
de la extinderea variabilei de construcție „ARCOM”, cu „%<” setat la membrii bibliotecii (în
ordinea prezentată) și `%>' la biblioteca care urmează să fie creată (vezi metoda `Comandă' pentru
detalii de extindere). Utilizatorul poate seta variabile în mediul de construcție care vor
afectează funcționarea comenzii. Acestea includ `AR', programul de arhivare de utilizat,
`ARFLAGS', care poate fi folosit pentru a modifica steaguri date programului specificat de `AR',
și `RANLIB', numele unui program de generare de index de arhivă, dacă este necesar (dacă anume
nevoia nu necesită această din urmă funcționalitate, atunci „ARCOM” trebuie redefinit la nu
referință `RANLIB').

Metoda „Library” permite ca aceeași bibliotecă să fie specificată în metode multiple
invocaţii. Toate obiectele care contribuie din toate invocarile (care pot fi de la
directoare diferite) sunt combinate și generate printr-o singură comandă de arhivă. Notă,
totuși, dacă tăiați o construcție astfel încât să fie specificată doar o parte a unei biblioteci, atunci numai
acea parte a bibliotecii va fi generată (restul va dispărea!).

„Modul” metodă

Metoda „Module” este o combinație a metodelor „Program” și „Comandă”. Decat
generând direct un program executabil, această comandă vă permite să specificați propriul program
comandă pentru a genera efectiv un modul. Metoda este invocată după cum urmează:

Modulul $env , , ;

Această comandă este utilă în cazurile în care doriți să creați, de exemplu, dinamic
module încărcate sau biblioteci de cod legate static.

"Depinde" metodă

Metoda „Depend” vă permite să specificați dependențe suplimentare pentru o țintă. Este
invocat astfel:

Depinde $env , ;

Acest lucru poate fi ocazional util, mai ales în cazurile în care nu există scaner (sau este
inscriptibil) pentru anumite tipuri de fișiere. În mod normal, dependențele sunt calculate
automat dintr-o combinație a dependențelor explicite stabilite de metodă
invocare sau prin scanarea fișierelor sursă.

Un set de dependențe identice pentru mai multe ținte poate fi specificat folosind o referință la
o listă de ținte. În Perl, o referință de listă poate fi creată prin includerea unei liste în pătrat
paranteze. De aici următoarea comandă:

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

precizează că atât cele foo și bar fișierele depind de fișierele de intrare listate.

"Ignora" metodă

Metoda „Ignorare” vă permite să ignorați în mod explicit dependențele pe care Cons le deduce
proprii. Se invocă astfel:

Ignora ;

Acest lucru poate fi folosit pentru a evita recompilările din cauza modificărilor în fișierele antet de sistem sau
utilități despre care se știe că nu afectează țintele generate.

Dacă, de exemplu, un program este construit într-un director montat pe NFS pe mai multe sisteme care
au copii diferite ale stdio.h, diferențele vor afecta semnăturile tuturor
ținte derivate construite din fișiere sursă care `#include '. Acest lucru va cauza totul
acele ținte să fie reconstruite la schimbarea sistemelor. Dacă acesta nu este un comportament de dorit,
apoi următoarea linie va elimina dependențele de pe stdio.h fișier:

Ignorați „^/usr/include/stdio\.h$”;

Rețineți că argumentele metodei „Ignorare” sunt expresii regulate, atât de speciale
caracterele trebuie să fie evadate și poate doriți să ancorați începutul sau sfârșitul
expresie cu caractere „^” sau „$”.

"Sare" metodă

Metoda „Sare” adaugă o valoare constantă la calculul semnăturii pentru fiecare derivat
fişier. Se invocă astfel:

Sare $șir;

Modificarea valorii Salt va forța o reconstrucție completă a fiecărui fișier derivat. Acesta poate fi
folosit pentru a forța reconstrucțiile în anumite circumstanțe dorite. De exemplu,

Sare `uname -s`;

Ar forța o reconstrucție completă a fiecărui fișier derivat ori de câte ori sistemul de operare este pornit
care se realizează construcția (așa cum este raportat de „uname -s”) se modifică.

„Utilizați Cache” metodă

Metoda „UseCache” îi instruiește pe Cons să mențină un cache de fișiere derivate, care urmează să fie partajate
printre arbori de construcție separati ai aceluiași proiect.

UseCache("cache/ ") ⎪⎪ warn("directorul cache nu a fost găsit");

„SourcePath” metodă

Metoda „SourcePath” returnează numele real al căii sursă a unui fișier, spre deosebire de
numele căii într-un director de compilare. Se invocă astfel:

$cale = SourcePath ;

„ConsPath” metodă

Metoda „ConsPath” returnează adevărat dacă calea furnizată este un fișier derivat și returnează
undef (fals) altfel. Se invocă astfel:

$rezultat = ConsPath ;

„SplitPath” metodă

Metoda „SplitPath” caută mai multe nume de căi într-un șir separat de valorile implicite
separator de cale pentru sistemul de operare (':' pe sisteme UNIX, ';' pe Windows NT) și
returnează numele complet calificate. Se invocă astfel:

@paths = SplitPath ;

Metoda „SplitPath” va converti numele cu prefixul „#” în versiunea corespunzătoare de nivel superior
nume (fără „#”) și va converti numele relative în nume de nivel superior.

„DirPath” metodă

Metoda „DirPath” returnează calea de construire nume(s) a unui director sau a unei liste de directoare.
Se invocă astfel:

$cwd = DirPath ;

Cea mai frecventă utilizare a metodei „DirPath” este:

$cwd = DirPath '.';

pentru a prelua calea către directorul curent al unei subsidiare recrut fișier.

„FilePath” metodă

Metoda `FilePath' returnează calea de construire nume(s) unui fișier sau a unei liste de fișiere. Este
invocat astfel:

$file = FilePath ;

"Ajutor" metodă

Metoda „Ajutor” specifică textul de ajutor care va fi afișat atunci când utilizatorul invocă „cons
-h'. Aceasta poate fi folosită pentru a furniza documentație privind obiectivele, valorile, construirea specifice
opțiuni, etc. pentru arborele de construcție. Se invocă astfel:

Ajutor ;

Metoda „Ajutor” poate fi apelată o singură dată și, de obicei, ar trebui să fie specificată în partea de sus
nivel construi fișier.

Extinderea Contra


Supracomandarea construcţie variabile

Există mai multe moduri de a extinde Contra, care variază în grad de dificultate. Cel mai simplu
metoda este să vă definiți propriul mediu de construcție, pe baza mediului implicit,
dar modificate pentru a reflecta nevoile dumneavoastră particulare. Acest lucru va fi adesea suficient pentru C-based
aplicatii. Puteți folosi constructorul `new' și metodele `clone' și `copy' la
creați medii hibride. Aceste modificări pot fi complet transparente pentru subiacent
recrut fișiere.

Adăugare nou Metode

Pentru modificări ceva mai solicitante, poate doriți să adăugați metode noi la „contra”
pachet. Iată un exemplu de extensie foarte simplă, `InstallScript', care instalează un
tcl într-o locație solicitată, dar editează mai întâi scriptul pentru a reflecta o platformă-
cale dependentă care trebuie instalată în script:

# contra::InstallScript - Creați o versiune dependentă de platformă a unui shell
# script prin înlocuirea șirului de caractere ``#!your-path-here'' cu specific platformei
# cale $BIN_DIR.

sub contra::InstallScript {
my ($env, $dst, $src) = @_;
Comanda $env $dst, $src, qq(
sed s+calea-voastra-aici+$BIN_DIR+ %< > %>
chmod oug+x %>
);
}

Observați că această metodă este definită direct în pachetul „cons” (prin prefixarea numelui
cu `contra::'). O schimbare realizată în acest mod va fi vizibilă la nivel global pentru toate mediile,
și ar putea fi numită ca în exemplul următor:

InstallScript $env „$BIN/foo”, „foo.tcl”;

Pentru o mică îmbunătățire în general, variabila „BINDIR” ar putea fi transmisă ca un
argument sau preluat din mediul de construcție - ca `%BINDIR'.

Supracomandarea Metode

În loc să adăugați metoda în spațiul de nume „contra”, ați putea defini un nou pachet
care moștenește metodele existente din pachetul „cons” și suprascrie sau adaugă altele. Acest
poate fi realizat folosind mecanismele de moștenire Perl.

Următorul exemplu definește un nou pachet `cons::switch' care suprascrie standardul
Metoda „Bibliotecă”. Metoda suprascrisă construiește module de bibliotecă legate, mai degrabă decât bibliotecă
arhive. Este oferit un nou constructor. Mediile create cu acest constructor vor
au noua metodă de bibliotecă; alții nu vor.

contra pachet::switch;
ÎNCEPE {@ISA = „contra”}

sub nou {
schimb;
binecuvântează noi contra (@_);
}

subbiblioteca {
my($env) = shift;
my($lib) = shift;
my(@objs) = Obiecte $env @_;
Comanda $env $lib, @objs, q(
%LD -r %LDFLAGS %< -o %>
);
}

Această funcționalitate poate fi invocată ca în exemplul următor:

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

Invocarea Contra


Comanda „cons” este de obicei invocată de la rădăcina arborelui de compilare. A construi fişier
trebuie să existe în acel director. Dacă se folosește argumentul „-f”, atunci o alternativă construi
poate fi folosit fișierul (și, eventual, o rădăcină alternativă, deoarece `cons' va cd la construi
directorul care conține fișierul).

Dacă „cons” este invocat dintr-un copil al rădăcinii arborelui de compilare cu argumentul „-t”, acesta
va urca în ierarhia directoarelor căutând a construi fişier. (Un nume alternativ poate
să fie specificate în continuare cu `-f'.) Țintele furnizate pe linia de comandă vor fi modificate
a fi relativ la descoperit construi fişier. De exemplu, dintr-un director care conține
un nivel superior construi fișier, următoarea invocare:

% cd libfoo/subdir
% cons -t țintă

este exact echivalent cu:

% contra libfoo/subdir/target

Dacă există ținte „Implicite” specificate în ierarhia directoarelor construi or
recrut fișiere, doar țintele implicite la sau sub directorul din care `cons -t'
a fost invocat va fi construit.

Comanda este invocată după cum urmează:

contra --

Unde argumente poate fi oricare dintre următoarele, în orice ordine:

ţintă Construiți ținta specificată. Dacă ţintă este un director, apoi construit recursiv
totul din acel director.

+model Limitați recrut fișierele considerate doar la cele care se potrivesc model, Care este
o expresie regulată Perl. Sunt acceptate mai multe argumente „+”.

nume=
Seturi nume a valorifica val în hash-ul „ARG” a trecut la nivelul superior construi fișier.

`-cc' Afișează comanda care ar fi fost executată, la preluarea din cache. Nu
se dă indicația că fișierul a fost preluat; acest lucru este util pentru
generând jurnalele de construcție care pot fi comparate cu jurnalele de construcție reale.

`-cd' Dezactivează toate stocarea în cache. Nu preluați din cache și nici nu goliți în cache.

`-cr' Construiește dependențe în ordine aleatorie. Acest lucru este util atunci când construiți mai multe
arbori similari cu memorarea în cache activată.

`-cs' Sincronizează țintele de construcție existente care se găsesc a fi actualizate cu memoria cache.
Acest lucru este util dacă memorarea în cache a fost dezactivată cu -cc sau doar recent activată
cu UseCache.

`-d' Activează depanarea dependenței.

`-f'
Utilizați fișierul specificat în loc de construi (dar mai întâi schimbați la care conține
directorul de fişier).

`-h' Afișează un mesaj de ajutor local pentru versiunea curentă dacă este definit un astfel de mesaj și ieși.

`-k' Continuați să mergeți cât mai departe posibil după erori.

`-o'
Citiți fișierul de înlocuire fişier.

`-p' Afișați produsele de construcție în arbori specificați. Nu se încearcă construcția.

`-pa' Afișează produsele de construcție și acțiunile asociate. Nu se încearcă construcția.

`-pw' Afișează produsele și unde sunt definite. Nu se încearcă construcția.

`-q' Nu vorbiți despre instalarea și eliminarea țintelor.

`-r' Eliminați produsele de construcție asociate cu . Nu se încearcă construcția.

`-R'
Căutați fișiere în odihnă. Multiplu -R odihnă directoarele sunt căutate în
comanda specificata.

`-t' Parcurgeți în sus ierarhia directoarelor căutând a construi fișier, dacă nu există
în directorul curent. Țintele vor fi modificate pentru a fi relativ la
construi fișier.

`-v' Afișează versiunea `cons' și continuă procesarea.

„-V” Afișează versiunea „contra” și ieși.

`-wf'
Scrieți toate numele fișierelor luate în considerare fişier.

`-x' Afișați un mesaj de ajutor similar cu acesta și ieșiți.

Și construct-args pot fi orice argumente pe care doriți să le procesați în construi fișier.
Rețineți că ar trebui să existe un -- separând argumentele de contra și argumentele pe care tu
doresc să proceseze în construi fișier.

Procesarea a construct-args se poate face cu orice pachet standard cum ar fi Getopt sau sa
variante sau orice pachet definit de utilizator. contra va trece în construct-args as @ARGV și
nu va încerca să interpreteze nimic după --.

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

ar trece următoarele la contra

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

și următoarele, la nivelul superior construi fișier ca @ARGV

-c test -f DEBUG

Rețineți că `cons -r .' este echivalent cu un „make clean” recursiv complet, dar necesită nu
sprijin în construi dosar sau oricare recrut fișiere. Acest lucru este cel mai util dacă sunteți
compilarea fișierelor în directoare sursă (dacă separați fișierul construi și exporturile directoare,
atunci puteți doar să eliminați directoarele).

Opțiunile „-p”, „-pa” și „-pw” sunt extrem de utile pentru utilizare ca ajutor în citire
scripturi sau depanarea acestora. Dacă vrei să știi ce script se instalează export/include/foo.h,
de exemplu, tastați:

% contra -pw export/include/foo.h

Utilizarea și scris dependenţă scanere


QuickScan permite configurarea unor scanere simple independente de țintă pentru fișierele sursă. Numai
un scaner QuickScan poate fi asociat cu orice fișier sursă și mediu dat.

QuickScan este invocat după cum urmează:

QuickScan CONSENV CODEREF, FILENAME [, PATH]

Se așteaptă ca subrutina la care face referire CODEREF să returneze o listă de nume de fișiere incluse
direct prin FIȘIER. Aceste nume de fișiere vor fi, la rândul lor, scanate. Argumentul opțional PATH
furnizează o cale de căutare pentru găsirea FILENAME și/sau fișierele returnate de utilizatorul furnizat
subrutină. PATH poate fi o referință la o serie de nume de director de căutare sau a
șir de nume separate prin caracterul separator al sistemului (':' pe sisteme UNIX, ';' pe
Windows NT).

Subrutina este apelată o dată pentru fiecare linie din fișier, cu $_ setat la linia curentă.
Dacă subrutina trebuie să se uite la linii suplimentare sau, de altfel, întregul fișier,
apoi le poate citi singur, din manerul de fișiere SCAN. De asemenea, poate termina bucla, dacă
știe că nu sunt disponibile alte informații de includere, prin închiderea filehandle-ului.

Indiferent dacă este furnizată sau nu o cale de căutare, QuickScan încearcă mai întâi să caute fișierul
raportat la directorul curent (pentru fișierul de nivel superior furnizat direct către QuickScan),
sau din directorul care conține fișierul care face referire la fișier. Acest lucru nu este foarte
general, dar pare destul de bun - mai ales dacă ai luxul de a-l scrie pe al tău
utilitare și poate controla utilizarea căii de căutare într-un mod standard. În cele din urmă, cel
calea de căutare este, în prezent, separată prin două puncte. Acest lucru poate să nu facă fericită tabăra NT.

Iată un exemplu real, luat din a construi fisier aici:

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

[REȚINATĂ că forma `$env->QuickScan ...' și `$env->Command ...' nu ar trebui să fie
necesar, dar, din anumite motive, este necesar pentru această invocare specială. Aceasta apare
a fi o eroare în Perl sau o neînțelegere din partea mea; acest stil de invocare nu
întotdeauna par a fi necesar.]

Aceasta găsește toate numele formularului .smf în fișier. Va returna numele chiar dacă
se găsesc în comentarii, dar este în regulă (mecanismul scutește fișierele suplimentare;
sunt doar ignorați, presupunând că fișierul lipsă va fi observat atunci când
programul, în acest exemplu, smfgen, este de fapt invocat).

Un scanner este invocat doar pentru un anumit fișier sursă dacă este nevoie de o anumită țintă din
copac. Este invocat o singură dată pentru un anumit fișier sursă.

Iată o altă modalitate de a construi același scaner. Acesta folosește o referință de cod explicită,
și, de asemenea (inutil, în acest caz) citește întregul fișier în sine:

sub myscan {
meu(@include);
face {
push(@include, /\b\S*?\.smf\b/g);
} in timp ce ;
@include
}

Rețineți că ordinea buclei este inversată, cu testul buclei la sfârșit. Aceasta este
pentru că primul rând este deja citit pentru tine. Acest scaner poate fi atașat la o sursă
dosar de:

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

SUPORT AND SUGESTII


Contra este menținută de comunitatea de utilizatori. Pentru a vă abona, trimiteți e-mail la contra-discuta-
[e-mail protejat] cu trupul subscrie.

Vă rugăm să raportați orice sugestii prin intermediul [e-mail protejat] lista de discuții.

Utilizați contra online folosind serviciile onworks.net


Servere și stații de lucru gratuite

Descărcați aplicații Windows și Linux

  • 1
    turkdevops
    turkdevops
    TurkDevOps a ?k kaynak yaz?l?m
    geli?tirici topluluklar? Echipa DevTurks
    Taraf?ndan desteklenmektedir..
    Caracteristici:https://github.com/turkdevopshttps://turkdevops.g...
    Descărcați turkdevops
  • 2
    asammdf
    asammdf
    *asammdf* este un parser rapid Python și
    redactor pentru ASAM (Asociația pentru
    Standardizarea automatizării și
    Sisteme de măsurare) MDF / MF4
    (Format de date de măsurare...
    Descărcați asammdf
  • 3
    LAME (Lame nu este un codificator MP3)
    LAME (Lame nu este un codificator MP3)
    LAME este un instrument educațional de utilizat
    pentru a afla despre codificarea MP3. The
    Scopul proiectului LAME este îmbunătățirea
    psihoacustica, calitatea si viteza
    de deputat...
    Descărcați LAME (Lame Aint an MP3 Encoder)
  • 4
    wxPython
    wxPython
    Un set de module de extensie Python care
    împachetați clasele GUI multiplatformă din
    wxWidgets.. Public: Dezvoltatori. Utilizator
    interfață: X Window System (X11), Win32...
    Descărcați wxPython
  • 5
    packfilemanager
    packfilemanager
    Acesta este managerul de fișiere al pachetului Total War
    proiect, începând cu versiunea 1.7. A
    scurtă introducere în Warscape
    modding:...
    Descărcați packfilemanager
  • 6
    IPerf2
    IPerf2
    Un instrument de măsurare a traficului de rețea
    Performanță TCP și UDP cu metrici
    atât în ​​jurul debitului cât și al latenței. The
    obiectivele includ menținerea unui activ
    cod iperf...
    Descărcați IPerf2
  • Mai mult »

Comenzi Linux

Ad