2012-06-15 3 views
9

Abbiamo la libreria Boost nella nostra parte. Consiste in un numero enorme di file che non cambiano mai e viene utilizzata solo una piccola parte di esso. Scambiamo l'intera directory di boost se stiamo cambiando le versioni. Attualmente abbiamo le fonti Boost nel nostro SVN, file per file che rende le operazioni di checkout molto lente, specialmente su Windows.g ++: Usa i file ZIP come input

Sarebbe bello se ci fosse una notazione/plugin per affrontare i file C++ all'interno di file ZIP, qualcosa di simile:

// @ZIPFS ASSIGN 'boost' 'boost.zip/boost' 
#include <boost/smart_ptr/shared_ptr.hpp> 

ci sono eventuali supporto per i ganci del compilatore in g ++? Ci sono degli sforzi per quanto riguarda il supporto ZIP? Altre idee?

+0

Se si utilizza 'g ++', perché non utilizzare 'gzip' per la corrispondenza? Haha brutto scherzo, +1. –

+6

Spostarsi da SVN a un moderno sistema SCM? Oppure è possibile comprimere la directory boost in alto per inserirla in SVN per velocizzare il checkout e quindi fare in modo che parte del processo di compilazione venga decompresso dal file, se necessario. – bames53

+0

@ bames53 Ci ho pensato. Non risparmia molto tempo su Windows, a causa dell'estrazione di molti piccoli file. Sicuramente, sarebbe un po 'meglio. – Notinlist

risposta

9

Suppongo che make o un simile sistema di build sia coinvolto nel processo di creazione del software. Inserisco il file zip nel repository e aggiungo una regola al Makefile per estrarlo prima che inizi la generazione effettiva.

Ad esempio, supponiamo che il file zip si trovi nell'albero dei sorgenti in "external/boost.zip" e che venga estratto in "external/boost" e contenga al suo livello un file "boost_version.h". .

# external/Makefile 
unpack_boost: boost/boost_version.h 

boost/boost_version.h: boost.zip 
    unzip $< 

non so l'esatta sintassi della chiamata unzip, chiedete al vostro pagina di manuale su questo.

Quindi in altri Makefile, è possibile consentire ai file di origine di dipendere dal target unpack_boost in modo da avere make decomprimere Boost prima che un file di origine sia compilato.

# src/Makefile (excerpt) 
unpack_boost: 
    make -C ../external unpack_boost 

source_file.cpp: unpack_boost 

Se stai usando un generatore di Makefile (o un sistema di generazione completamente diversa), si prega di consultare la documentazione per questi programmi per come creare qualcosa come il target personalizzato unpack_boost. Ad esempio, in CMake, è possibile utilizzare la direttiva add_custom_command.

L'ammenda di stampa: Il file boost/boost_version.h non è strettamente necessaria per il Makefile per lavorare. Si potrebbe semplicemente inserire il comando unzip nella destinazione unpack_boost, ma la destinazione sarebbe effettivamente fasulla, ovvero: sarebbe eseguita durante ogni generazione. Il file tra parentesi (che ovviamente è necessario sostituire con un file effettivamente presente nell'archivio zip) assicura che unzip venga eseguito solo se necessario.

2

Questo è qualcosa che non si dovrebbe fare in g ++, perché qualsiasi altra applicazione che vuole farlo dovrebbe anche essere modificata.

Archiviare i file su un file system compresso. Quindi ogni applicazione ottiene automaticamente il vantaggio.

+0

Se un g ++ non è "agganciato" come quello allora l'annotazione verrà ignorata e lo zip può essere estratto manualmente (come fallback). Boost non ha bisogno di sapere tutto questo. Al secondo: il filesystem compresso non velocizza il checkout. – Notinlist

2

Dovrebbe essere possibile in un sistema operativo consentire l'accesso trasparente ai file all'interno di un file ZIP. So che l'ho inserito nel design del mio sistema operativo molto tempo fa (2004 o giù di lì), ma non l'ho mai portato a un punto in cui era utilizzabile. Il rovescio della medaglia è che cercare indietro in un file all'interno di un ZIP è più lento in quanto è compresso (e non è possibile riavvolgere lo stato del compressore, quindi è necessario cercare dall'inizio invece). Questo rende anche l'uso di una zip-inside-a-zip slow per riavvolgere e leggere. Fortunatamente, la maggior parte dei casi legge solo un file in sequenza.

Dovrebbe anche essere compatibile con i sistemi operativi correnti, almeno nello spazio client. È possibile agganciare le funzioni di accesso al filesystem utilizzate (fopen, open, ...) e aggiungere un set di descrittori di file virtuali che il proprio software restituirebbe per un determinato nome file.Se si tratta di un file reale, basta passarlo, se non è aperto il file sottostante (possibilmente nuovamente tramite questa stessa funzione) e passare un handle virtuale. Quando si accede ai contenuti del file, leggere direttamente dal file zip senza cache.

Su Linux si utilizzerà LD_PRELOAD per iniettarlo nel software esistente (al momento dell'utilizzo), su Windows è possibile agganciare le chiamate di sistema o iniettare una DLL nello spazio del software per agganciare le stesse funzioni.

Qualcuno sa se questo esiste già? Non vedo alcun motivo chiaro per cui non ...

+1

Su LINUX c'è il modulo del kernel FUSE (Spazio utente file system E-qualsiasi). –

4

Abbiamo riscontrato problemi simili nella nostra azienda. Gestire le versioni di boost negli ambienti di compilazione non sarà mai facile. Con oltre 10 sviluppatori, tutti in codice sui propri sistemi, è necessario un qualche tipo di automazione.

In primo luogo, non penso che sia una buona idea conservare copie di grandi librerie come boost in SVN o qualsiasi sistema SCM del resto, non è quello che sono progettati per quei sistemi, tranne se si prevede di modificare il codice in boost te stesso. Ma supponiamo che tu non lo stia facendo.

Ecco come lo gestiamo ora, dopo aver provato un sacco di metodi diversi, questo funziona meglio per noi.

Per ogni versione di boost che usiamo, mettiamo l'intero albero (decompresso) su un file server e aggiungiamo sottodirectory aggiuntive, una per ogni combinazione di architettura/compilatore, dove inseriamo le librerie compilate. Manteniamo le copie di questi alberi su ogni sistema di generazione e nell'ambiente del sistema globale che aggiungere le variabili come:

BOOST_1_48=C:\boost\1.48 # Windows environment var 

o

BOOST_1_48=/usr/local/boost/1.48 # Linux environment var, e.g. in /etc/profile.d/boost.sh 

questa directory contiene l'albero di spinta (. Boost/* HPP) e le librerie precompilate aggiunte (es. lib/win/x64/msvc2010/libboost_system * .lib, ...)

Tutte le configurazioni di build (vs soluzioni, file di proprietà, file di configurazione di gnu, ...) definiscono una variabile interna , importando i vars dell'ambiente, come:

BOOSTROOT=$(BOOST_1_48) # e.g. in a Makefile, or an included Makefile 

e ulteriori regole di compilazione utilizzano tutte l'impostazione BOOSTROOT per definire i percorsi di inclusione e i percorsi di ricerca della libreria, ad es.

CXXFLAGS += -I$(BOOSTROOT) 
LFLAGS += -L$(BOOSTROOT)/lib/linux/x64/ubuntu/precise 
LFLAGS += -lboost_date_time 

La ragione per mantenere copie locali di boost è la velocità di compilazione. Ci vuole un bel po 'di spazio su disco, in particolare le librerie compilate, ma lo stoccaggio è a buon mercato e uno sviluppatore di perdere un sacco di codice di tempo compilazione non è. Inoltre, questo deve essere copiato solo una volta.

Il motivo dell'utilizzo di vars ambiente globale è che le configurazioni di generazione sono trasferibili da un sistema a un altro e possono quindi essere archiviate in sicurezza nel sistema SCM.

Per semplificare un po ', abbiamo sviluppato un piccolo strumento che si occupa della copia e dell'impostazione dell'ambiente globale. Con una CLI, questo può anche essere incluso nel processo di compilazione.

Diversi ambienti di lavoro significano regole e culture diverse, ma credetemi, abbiamo provato un sacco di cose e alla fine abbiamo deciso di definire una sorta di convenzione. Forse il nostro può ispirarti ...

+0

Questo è simile al modo in cui lo facciamo, ad eccezione del potenziamento link simbolico/a una delle varie versioni di boost esistenti. – KitsuneYMG

+0

Questo va bene, a condizione che il file system supporti i collegamenti simbolici. Avevamo bisogno di un metodo che funzioni sia su Windows che su sistemi * nix. – Pat

7

Un anno fa ero nella tua stessa posizione.Abbiamo mantenuto la nostra fonte in SVN e, peggio ancora, incluso l'aumento nello stesso repository (stesso ramo) del nostro codice. Cercare di lavorare su più filiali era impossibile, poiché ci sarebbe voluta quasi tutta la giornata per controllare una nuova copia di lavoro. Spostare la spinta in un repository separato del fornitore ha aiutato, ma ci vorranno ancora ore per il check-out.

Ho passato la squadra a git. Per darti un'idea di quanto sia migliore di SVN, ho appena creato un repository contenente la release 1.45.0 di boost, quindi clonato sulla rete. (La clonazione copia tutta la cronologia del repository, che in questo caso è un singolo commit e crea una copia funzionante.)

Questo clone impiegava sei minuti.

Nei primi sei secondi una copia compressa del repository è stata copiata sul mio computer. Il resto del tempo è stato dedicato alla scrittura di tutti quei piccoli file.

Raccomando vivamente di provare git. La curva di apprendimento è ripida, ma dubito che farai molto hacking pre-compilatore nel tempo che occorrerebbe per clonare una copia di boost.