VCProj simplifiés
Comme je l'ai dit dans un post précédent, j'ai mis en place une version simplifiée de vcproj pour compiler mes projets C/C++ sous Linux dont voici un exemple :<?xml version="1.0" encoding="utf-8"?>
<CodeProject Name="LLE" Version="0.0.1" xmlns="http://XSDServer/Tools/Project" xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance" xsi:schemaLocation="http://XSDServer:1050/Tools/Project/ProjectConfig.xsd">
<GeneralOptions>
<FilePathManagement>
<EnvironmentVar Var="RAGE_DEV" />
</FilePathManagement>
<ProjectType Type="StaticLib"/>
<Filters FolderFilterList=".svn"/>
</GeneralOptions>
<DependencyList>
</DependencyList>
<TargetList>
<Target Name="Debug" Platform="Linux" OutputDir="{RAGE_TEMP}/Libs/Linux/{TargetName}/{ProjectName}" Builder="SCONS">
<ToolList>
<SconsBuilder ToolChain="gcc"/>
<GCCCompiler IncludePathList="{RAGE_DEV}/Engine/Components;{RAGE_DEV}/ThirdParty/boost" PreprocessorList="LINUX;DEBUG" CFlags="" CXXFlags="-Wall -g"/>
<GCCLinker OutputFile="LLE" LibPathList="" LibList="" Flags="-g"/>
</ToolList>
</Target>
<Target Name="Release" Platform="Linux" OutputDir="{RAGE_TEMP}/Libs/Linux/{TargetName}/{ProjectName}" Builder="SCONS">
<ToolList>
<SconsBuilder ToolChain="gcc"/>
<GCCCompiler IncludePathList="{RAGE_DEV}/Engine/Components;{RAGE_DEV}/ThirdParty/boost" PreprocessorList="LINUX;RELEASE" CFlags="" CXXFlags="-Wall -O2"/>
<GCCLinker OutputFile="LLE" LibPathList="" LibList="" Flags=""/>
</ToolList>
</Target>
</TargetList>
<EntryList>
<DirEntry DirPath="Engine/Components/LLE/Sources/Common" FilterList="c;cpp;cxx"/>
<DirEntry DirPath="Engine/Components/LLE/Sources/PlatformSpecific/Linux" FilterList="c;cpp;cxx"/>
</EntryList>
<Deployment>
</Deployment>
</CodeProject>
Il n'y a pas vraiment de quoi s'exclamer mais voici les caractéristiques principales de ce format de fichier :
- L'option générale la plus intéressante est FilePathManagement qui permet de savoir comment sont gérés les paths vers les fichiers. Les valeurs possibles sont : EnvironmentVar, ProjectFile (paths relatifs par rapport au fichier du projet) et Absolute (paths absolus ... depreciated pour avoir un code source relocalisable).
- Dans la section DependencyList on spécifie les autres projets dont celui-ci dépend,
- La liste des Targets est assez standard i.e. on indique pour chacune où il faut mettre les fichiers finaux et intermédiaires, la plateforme, le nom de la configuration et le type de builder (SCons dans mon cas). Ensuite, en fonction du builder et de la plateforme cible, on sait à quoi s'attendre dans la liste des tools. Dans l'exemple ci-dessus, sous Linux et avec Scons j'utilise les Tools GCCCompiler et GCCLinker.
- Ce format utilise comme Visual Studio un système de variables. Il y a des variales définies par le format de fichier lui même (ProjectName, OutPutDir, etc.) et il est également possible d'utiliser dans variables d'environnement. je vais peut être étendre cela à un système de variables définies par l'utilisateur.
- Le système d'Entry est assez standard i.e. on peut spécifier soit une Entry par fichier ou une Entry par répertoire (récurcif ou pas). Il est également possible de spécifier des fichiers à ne pas inclure à la compilation ou des options de compilation spécifiques.
- La dernière section est le déploiement i.e. les différentes opérations à effectuer après avoir compiler un projet pour qu'il soit utilisable e.g. copier des xml de configuration, des dlls, etc. Je ferai un autre post pour vous montrer comment j'ai géré le déploiement des outils.
Pour chacun de mes projets j'ai 4 scripts de travail :
- Clean du projet (SCons -c ... c'est simple non :)),
- Génération du fichier scons à partir du xml de projet,
- Lancement de la compilation i.e. lancement de SCons sur le fichier généré,
- Génération du fichier Scons + lancement de la compilation.
Pour faire cela, j'ai plusieurs modules Python qui me génèrent le fichier SCons par rapport à un xml de projet et qui me lancent la compilation. Voici un exemple de fichier SCons généré :
FileList =[u'/usr/local/share/Dev/Rage/Engine/Components/LLE/Sources/Common/Stdafx.cpp', u'/usr/local/share/Dev/Rage/Engine/Components/LLE/Sources/Common/Types.cpp', u'/usr/local/share/Dev/Rage/Engine/Components/LLE/Sources/Common/Engine.cpp', u'/usr/local/share/Dev/Rage/Engine/Components/LLE/Sources/Common/Patterns/Creational/FactoryGenerator.cpp', u'/usr/local/share/Dev/Rage/Engine/Components/LLE/Sources/Common/Patterns/Creational/Factory.cpp', u'/usr/local/share/Dev/Rage/Engine/Components/LLE/Sources/Common/STL/StdAlgorithms.cpp', u'/usr/local/share/Dev/Rage/Engine/Components/LLE/Sources/Common/System/Service.cpp', u'/usr/local/share/Dev/Rage/Engine/Components/LLE/Sources/Common/System/CRC32.cpp', u'/usr/local/share/Dev/Rage/Engine/Components/LLE/Sources/Common/System/Assert.cpp', u'/usr/local/share/Dev/Rage/Engine/Components/LLE/Sources/Common/System/BaseObject.cpp', u'/usr/local/share/Dev/Rage/Engine/Components/LLE/Sources/Common/System/IO/LoggerStdOut.cpp', u'/usr/local/share/Dev/Rage/Engine/Components/LLE/Sources/Common/System/IO/Logger.cpp', u'/usr/local/share/Dev/Rage/Engine/Components/LLE/Sources/Common/System/Error/ErrorManager.cpp']
ObjFileList =[u'Stdafx', u'Types', u'Engine', u'FactoryGenerator', u'Factory', u'StdAlgorithms', u'Service', u'CRC32', u'Assert', u'BaseObject', u'LoggerStdOut', u'Logger', u'ErrorManager']
Env = Environment(CFLAGS=" -DLINUX -DDEBUG",CXXFLAGS="-Wall -g -DLINUX -DDEBUG",CPPPATH=[u'/usr/local/share/Dev/Rage/Engine/Components', u'/usr/local/share/Dev/Rage/ThirdParty/boost'],LINKFLAGS="-g");
EnvDict = Env.Dictionary();
TargetObjList = [];
FileIter = 0;
for ObjIter in ObjFileList :
TargetObjList = TargetObjList + Env.Object(ObjIter, FileList[FileIter]);
FileIter = FileIter + 1;
Env.StaticLibrary("LLE", TargetObjList)
La génération de ce fichier représente à peu près 10 lignes de code Python.
En ce qui concerne mon retour sur SCons, je trouve cet outil de build très bon pour le moment
et cela pour plusieurs raisons :
- Il a des performances totalement satisfaisantes par rapport à la complexité de sur quoi je travaille (je ne sais pas ce qu'il peut valoir sur des projets professionnels de grande envergure ... je pense qu'elles ne sont pas mauvaises car ils l'ont utilisé sur Doom 3 :)),
- Il gère correctement les dépendances,
- Les scripts de build sont compréhensibles par n'importe quel codeur,
- On peut déboguer les scripts de build facilement,
- On peut compiler son projet C/C++ from scratch en quelques dizaines de minutes sans avoir à passer des heures au préalable dans le mans ou sur le web (c.f. make),
- Pour le moment je n'ai fait qu'effleurer ses fonctionnalités et je crois qu'il en a encore pas mal dans le bide :)
PS:
Je schématise toutes mes données xml grâce à des XSD mais je n'ai pas encore trouvé d'éditeur XML libre me permettant de les valider ... si quelqu'un en connait un bon, je suis preneur ! :)

Commentaires