2009-12-10 13 views
5

J'ai récemment récupéré des scons pour implémenter un framework de construction multiplateforme pour un projet C++ de taille moyenne. La construction génère un tas de tests unitaires qui devraient être invoqués à la fin de tout. Comment obtient-on ce genre de chose?scons - comment exécuter quelque chose/après/toutes les cibles ont été construites

Par exemple, dans mon haut niveau sconstruct, je

subdirs=['list', 'of', 'my', 'subprojects'] 
for subdir in subdirs: 
    SConscript(dirs=subdir, exports='env', name='sconscript', 
     variant_dir=subdir+os.sep+'build'+os.sep+mode, duplicate=0) 

Chacun des subdir a ses tests unitaires, cependant, car il y a des dépendances entre les dll et executables construites à l'intérieur eux - je veux tenir l'exécution de tests jusqu'à ce que tous les sous-répertoires aient été construits et installés (je veux dire, en utilisant env.Install).

Où dois-je écrire la boucle pour parcourir les tests intégrés et les exécuter? J'ai essayé de le mettre juste après cette boucle - mais puisque Scons ne vous permet pas de contrôler l'ordre d'exécution - il est exécuté bien avant que je ne le souhaite.

S'il vous plaît aider un newbie scons. :)

merci,

Répondre

0

En termes de dépendances, ce que vous voulez est pour toutes les actions de test pour dépendent de toutes les actions construites programme. Pour ce faire, créez et exportez une cible factice dans tous les fichiers sconscript des sous-répertoires et, dans les fichiers sconscript, placez la cible fictive Depends sur les cibles principales et placez les cibles de test Depends sur la cible fictive. .

Je vais avoir un peu de mal à comprendre comment mettre en place la cible factice, mais cela fonctionne essentiellement:

(en SConstruct haut niveau)

dummy = env.Command('.all_built', 'SConstruct', 'echo Targets built. > $TARGET') 
Export('dummy') 

(dans chaque sous- SConscript du répertoire)

Import('dummy') 
for target in target_list: 
    Depends(dummy, targe) 
for test in test_list: 
    Depends(test, dummy) 

Je suis sûr que d'autres améliorations sont possibles, mais peut-être que cela vous aidera à démarrer.

EDIT: il vaut également la peine de signaler this page sur le sujet.

5

SCons, comme Make, utilise une méthode déclarative pour résoudre le problème de construction. Vous ne voulez pas dire aux SCons comment faire leur travail. Vous voulez documenter toutes les dépendances, puis laisser SCons résoudre comment il construit tout.

Si quelque chose est en cours d'exécution avant quelque chose d'autre, vous devez créer et raccorder les dépendances.

Si vous souhaitez créer des fichiers tactiles jma, vous pouvez créer un constructeur personnalisé comme:

import time 

def action(target, source, env): 
    os.system('echo here I am running other build') 
    dmy_fh = open('dmy_file','w') 
    dmy_fh.write('Dummy dependency file created at %4d.%02d.%02d %02dh%02dm%02ds\n'%time.localtime()[0:6]) 
    dmy_fh.close() 

bldr = Builder(action=action) 
env.Append(BUILDERS = {'SubBuild' : bldr }) 

env.SubBuild(srcs,tgts) 

Il est très important de mettre l'horodatage dans le fichier fictif, parce que scons utilise hash md5. Si vous avez un fichier vide, le md5 sera toujours le même et il peut décider de ne pas faire les étapes de construction suivantes. Si vous devez générer différents réglages sur une commande de base, vous pouvez utiliser des fabriques de fonctions pour modifier un modèle. par exemple.

def gen_a_echo_cmd_func(echo_str): 
    def cmd_func(target,source,env): 
     cmd = 'echo %s'%echo_str 
     print cmd 
     os.system(cmd) 
    return cmd_fun 

bldr = Builder(action = gen_a_echo_cmd_func('hi')) 
env.Append(BUILDERS = {'Hi': bldr}) 
env.Hi(srcs,tgts) 

bldr = Builder(action = gen_a_echo_cmd_func('bye')) 
env.Append(BUILDERS = {'Bye': bldr}) 
env.Bye(srcs,tgts) 

Si vous avez quelque chose que vous voulez injecter automatiquement dans les flux scons construire (par exemple quelque chose qui compresse tous vos fichiers journaux build après tout a couru d'autre), voir my question here.

2

La solution devrait être aussi simple que cela.

Faire le résultat des constructeurs d'essai dépendent du résultat du constructeur installation

En pseudo:

test = Test(dlls) 
result = Install(dlls) 
Depends(test,result) 

La meilleure façon serait si le constructeur de test a effectivement travaillé sur les dépendances de dll pour vous , mais il peut y avoir toutes sortes de raisons, il ne le fait pas.

0

Il suffit que chaque SConscript renvoie une valeur sur laquelle vous allez créer des dépendances.

fichier SConscript:

test = debug_environment.Program('myTest', src_files) 
Return('test') 

fichier SConstruct:

dep1 = SConscript([...]) 
dep2 = SConscript([...]) 
Depends(dep1, dep2) 

Maintenant dep1 build complètera après dep2 construction terminée.