Source code for gdeps.project

#!python3

# Copyright 2007-2017 Gemr. All Rights Reserved.
# Licensed to MIT see LICENSE.txt

import glob
import os
import warnings
from zipfile import ZipFile

import gdeps as GDeps

__author__ = 'Suryavarman (http://sourceforge.net/u/suryavarman/profile/)'


[docs]class Listener:
[docs] def afterInit(self, inProjects): """ Or before update """ pass
[docs] def afterUpdate(self, inProjects): """ Or before the repository list update """ pass
[docs] def afterRepoListUpdate(self, inProjects, inRepositoryCloningPath): pass
[docs] def afterAllRepoListUpdate(self, inProjects): """ Or before extract archive """ pass
[docs] def afterExtractArchive(self, inProjects): """ Or before Make and build """ pass
[docs] def afterMakeAndBuild(self, inProjects): """Before the build of Ide list""" pass
[docs] def afterEachIdeListBuild(self, inProjects, inIdeBuilder): pass
[docs] def afterAllIdeListBuild(self, inProjects): """Last action""" pass
[docs]class Projects: def __init__(self, inParams, inListeners=[], inMakeArchive=True): self.m_Params = inParams self.m_Listeners = inListeners self.m_MakeArchive = inMakeArchive self.m_ArchiveIgnore = [] """ Array to store the files and folder to be exclude in the archive function. Use glob syntax. """ self.m_CurrentMacroReporting = None self.initArchiveIgnore() assert GDeps.Keys.ms_FolderDir in self.m_Params, "There no folder dir : use the GDeps.Keys.ms_FolderDir or directly the value : " + GDeps.Keys.ms_FolderDir + " to setup the working folder." self.m_FolderDir = self.m_Params[GDeps.Keys.ms_FolderDir] self.buildConfig() self.buildRepository() self.buildRepositoryList() self.buildArchive() self.buildCompilers() self.m_TargetsArgs = self.getTargets(self.m_Params) self.buildIdes() self.buildIdeBuilder() self.buildIdeBuilders() self.buildMaker() for aListener in self.m_Listeners: aListener.afterInit(self)
[docs] def buildConfig(self): aConfigFilePath = self.m_Params[GDeps.Keys.ms_ConfigFilePath] if GDeps.Keys.ms_ConfigFilePath in self.m_Params else "" aConfigFilePathIsDefine = len(aConfigFilePath) > 0 if not aConfigFilePathIsDefine: warnings.warn("You haven't set a config file path. Use GDeps.Keys.ms_ConfigFilePath or its value " + GDeps.Keys.ms_ConfigFilePath + " to define it.", ResourceWarning) if aConfigFilePathIsDefine: self.m_ConfigFile = GDeps.ConfigFile(aConfigFilePath)
[docs] def buildRepository(self): aRepoAliasName = self.m_Params[GDeps.Keys.ms_RepoAlias] if GDeps.Keys.ms_RepoAlias in self.m_Params else "" if aRepoAliasName: aRepoAlias = GDeps.Alias(self.m_ConfigFile, aRepoAliasName) aCloneParams = self.m_Params[GDeps.Keys.ms_RepoCloneArgs] if GDeps.Keys.ms_RepoCloneArgs in self.m_Params else "" aUpdateParams = self.m_Params[GDeps.Keys.ms_RepoUpdateArgs] if GDeps.Keys.ms_RepoUpdateArgs in self.m_Params else "" aRepoUrl = self.m_Params[GDeps.Keys.ms_RepoUrl] if GDeps.Keys.ms_RepoUrl in self.m_Params else "" assert aRepoUrl, "You need to set a path to clone the repository. Use GDeps.Keys.ms_RepoUrl or its value " + GDeps.Keys.ms_RepoUrl + " ." aLogDirectory = self.m_FolderDir self.m_Repository = getattr(GDeps, aRepoAlias.m_Type)(self.m_ConfigFile, self.m_FolderDir, aLogDirectory, aRepoUrl, aCloneParams, aUpdateParams, aRepoAlias.m_Name)
[docs] def buildRepositoryList(self): self.m_Repositories = [] repository_config_list = self.m_Params[GDeps.Keys.ms_RepoList] if GDeps.Keys.ms_RepoList in self.m_Params else [] for repo_config in repository_config_list: aRepoAliasName = repo_config[GDeps.Keys.ms_RepoAlias] if GDeps.Keys.ms_RepoAlias in self.m_Params else "" if aRepoAliasName: aRepoAlias = GDeps.Alias(self.m_ConfigFile, aRepoAliasName) aCloneParams = repo_config[GDeps.Keys.ms_RepoCloneArgs] if GDeps.Keys.ms_RepoCloneArgs in self.m_Params else "" aUpdateParams = repo_config[GDeps.Keys.ms_RepoUpdateArgs] if GDeps.Keys.ms_RepoUpdateArgs in self.m_Params else "" aRepoUrl = repo_config[GDeps.Keys.ms_RepoUrl] if GDeps.Keys.ms_RepoUrl in self.m_Params else "" aDirectory = os.path.normpath(self.m_FolderDir + r'\\' + repo_config[GDeps.Keys.ms_RepoDir]) if GDeps.Keys.ms_RepoUrl in self.m_Params else self.m_FolderDir assert aRepoUrl, "Also for list of repository you need to set a path to clone a repository. Use GDeps.Keys.ms_RepoUrl or its value " + GDeps.Keys.ms_RepoUrl + " ." aLogDirectory = aDirectory self.m_Repositories.append(getattr(GDeps, aRepoAlias.m_Type)(self.m_ConfigFile, aDirectory, aLogDirectory, aRepoUrl, aCloneParams, aUpdateParams, aRepoAlias.m_Name))
[docs] def buildArchive(self): aFileArchiverAliasName = self.m_Params[GDeps.Keys.ms_ArchiverAlias] if GDeps.Keys.ms_ArchiverAlias in self.m_Params else "" if aFileArchiverAliasName: aFileArchiverAlias = GDeps.Alias(self.m_ConfigFile, aFileArchiverAliasName) aArchiveUrl = self.m_Params[GDeps.Keys.ms_ArchiveUrl] if GDeps.Keys.ms_ArchiveUrl in self.m_Params else "" assert aArchiveUrl, "You need to set a path to download the archive. Use GDeps.Keys.ms_ArchiveUrl or its value " + GDeps.Keys.ms_ArchiveUrl + " ." aLogDirectory = self.m_Params[GDeps.Keys.ms_ArchiveFolder] if GDeps.Keys.ms_ArchiveFolder in self.m_Params else self.m_FolderDir self.m_Archiver = getattr(GDeps, aFileArchiverAlias.m_Type)(inConfigFile=self.m_ConfigFile, inFolderPath=self.m_FolderDir, inLogFileDirectory=aLogDirectory, inArchiveUrl=aArchiveUrl, inSectionName=aFileArchiverAlias.m_Name)
@staticmethod
[docs] def getCompilers(inSectionNames, inConfigFile): return GDeps.getCompilers(inConfigFile, inSectionNames)
[docs] def buildCompilers(self): self.m_Compilers = GDeps.getCompilers(self.m_ConfigFile, self.m_ConfigFile.sections())
@staticmethod
[docs] def getIde(inAliasName, inConfigFile): aIdeAlias = GDeps.Alias(inConfigFile, inAliasName) aCompilers = GDeps.getCompilers(inConfigFile, aIdeAlias.m_SubAlias) return getattr(GDeps, aIdeAlias.m_Type)(inConfigFile=inConfigFile, inSectionName=aIdeAlias.m_Name, inCompilers=aCompilers, inCompilersAlias=[])
@staticmethod
[docs] def getIdes(inConfigFile): ides = [] aIdeSections = [aSectionName for aSectionName in inConfigFile.sections() if GDeps.Keys.ms_IdeAliasPrefix in aSectionName] for sectionName in aIdeSections: ides.append(Projects.getIde(sectionName, inConfigFile)) return ides
[docs] def buildIdes(self): self.m_Ides = Projects.getIdes(self.m_ConfigFile)
[docs] def buildIdeBuilder(self): if GDeps.Keys.ms_IdeAlias in self.m_Params and GDeps.Keys.ms_IdeSolutionName in self.m_Params: aIde = self.getIde(self.m_Params[GDeps.Keys.ms_IdeAlias], self.m_ConfigFile) aArgs = self.m_Params[GDeps.Keys.ms_IdeArgs] if GDeps.Keys.ms_IdeArgs in self.m_Params else {} aWildCard = self.m_Params[GDeps.Keys.ms_IdeWildcard] if GDeps.Keys.ms_IdeWildcard in self.m_Params else "" aSolutionSubDir = self.m_Params[GDeps.Keys.ms_IdeSolutionSubDir] if GDeps.Keys.ms_IdeSolutionSubDir in self.m_Params else "" aTargetName = self.m_Params[GDeps.Keys.ms_IdeTargetName] if GDeps.Keys.ms_IdeTargetName in self.m_Params else "" if not aWildCard: assert False, "ERROR : You haven't define a wildcard for the ide : " + aIde self.m_IdeBuilder = GDeps.IdeBuilder(inIde=aIde, inSolutionName=self.m_Params[GDeps.Keys.ms_IdeSolutionName], inWildCard=aWildCard, inTargets=self.m_TargetsArgs, inFolderDir=self.m_FolderDir + r"\\" + aSolutionSubDir, inArgs=aArgs, inLogFileOutPutDir='', inOverrideBuildType=aTargetName)
[docs] def buildIdeBuilders(self): self.m_IdeBuilders = [] ide_config_list = self.m_Params[GDeps.Keys.ms_IdeAliasList] if GDeps.Keys.ms_IdeAliasList in self.m_Params else [] for ide_config in ide_config_list: if GDeps.Keys.ms_IdeAlias in ide_config and GDeps.Keys.ms_IdeSolutionName in ide_config: ide_section = ide_config[GDeps.Keys.ms_IdeAlias] if self.m_ConfigFile.getSection(ide_section): aIde = self.getIde(ide_config[GDeps.Keys.ms_IdeAlias]) aArgs = ide_config[GDeps.Keys.ms_IdeArgs] if GDeps.Keys.ms_IdeArgs in ide_config else {} aWildCard = ide_config[GDeps.Keys.ms_IdeWildcard] if GDeps.Keys.ms_IdeWildcard in ide_config else "" aSolutionSubDir = ide_config[GDeps.Keys.ms_IdeSolutionSubDir] if GDeps.Keys.ms_IdeSolutionSubDir in ide_config else "" aTargetName = ide_config[GDeps.Keys.ms_IdeTargetName] if GDeps.Keys.ms_IdeTargetName in ide_config else "" targets_args = self.getTargets(ide_config) if not aWildCard: assert False, "ERROR : You haven't define a wildcard for the ide : " + aIde self.m_IdeBuilders.append(GDeps.IdeBuilder(inIde=aIde, inSolutionName=ide_config[GDeps.Keys.ms_IdeSolutionName], inWildCard=aWildCard, inTargets=targets_args, inFolderDir=self.m_FolderDir + r"\\" + aSolutionSubDir, inArgs=aArgs, inLogFileOutPutDir='', inOverrideBuildType=aTargetName)) else: if GDeps.Keys.ms_IdeAlias not in ide_config: warnings.warn('In the ide alias list a item the parameter GDeps.Keys.ms_IdeAlias is missing.') if GDeps.Keys.ms_IdeSolutionName not in ide_config: warnings.warn('In the ide alias list a item the parameter GDeps.Keys.ms_IdeSolutionName is missing.')
@staticmethod
[docs] def getTargets(inParams): """ by default a Project build the dynamic release and dynamic debug targets """ result = [] if GDeps.Keys.ms_Targets in inParams: result = inParams[GDeps.Keys.ms_Targets] else: result.append(GDeps.TargetArgs(GDeps.Target.release_dynamic, {}, {}, {}, {})) result.append(GDeps.TargetArgs(GDeps.Target.debug_dynamic, {}, {}, {}, {})) return result
[docs] def buildMaker(self): self.buildMakerNew()
# aMakerArgs = self.m_Params[GDeps.Keys.ms_MakerArgs] if GDeps.Keys.ms_MakerArgs in self.m_Params else {} # # if( GDeps.Keys.ms_MakerAlias in self.m_Params ): # # aMakerAlias = GDeps.Alias( self.m_ConfigFile, self.m_Params[GDeps.Keys.ms_MakerAlias] ) # self.m_Maker = getattr( GDeps, aMakerAlias.m_Type )( self.m_ConfigFile, aMakerAlias.m_Name, self.m_FolderDir, self.m_Params[GDeps.Keys.ms_MakerSolutionName], aMakerArgs, self.m_TargetsArgs, self.m_Compilers, self.m_Ides ) # # else: # # if( GDeps.Keys.ms_MakerType in self.m_Params ): # # aSolutionName = self.m_Params[GDeps.Keys.ms_MakerSolutionName] if GDeps.Keys.ms_MakerSolutionName in self.m_Params else "" # aSubdirMakeFile = self.m_Params[GDeps.Keys.ms_MakerSubDir] if GDeps.Keys.ms_MakerSubDir in self.m_Params else "" # self.m_Maker = getattr( GDeps, self.m_Params[GDeps.Keys.ms_MakerType] )( aMakerArgs, self.m_FolderDir + aSubdirMakeFile, aSolutionName, self.m_TargetsArgs, self.m_Compilers ) # # else: # pass
[docs] def buildMakerNew(self): aMakerArgs = self.m_Params[GDeps.Keys.ms_MakerArgs] if GDeps.Keys.ms_MakerArgs in self.m_Params else {} aIsAlias = GDeps.Keys.ms_MakerAlias in self.m_Params aIsLocal = GDeps.Keys.ms_MakerType in self.m_Params if aIsAlias or aIsLocal: aMarkerTypeName = "" aMakerSectionName = "" aSolutionName = self.m_Params[GDeps.Keys.ms_MakerSolutionName] if GDeps.Keys.ms_MakerSolutionName in self.m_Params else "" aSubdirMakeFile = self.m_Params[GDeps.Keys.ms_MakerSubDir] if GDeps.Keys.ms_MakerSubDir in self.m_Params else "" aHasMakerExePath = GDeps.Keys.ms_MakerExePath in self.m_Params """ If it's empty the config value can be use by the maker """ aIdes = [] if aIsAlias: aMakerAlias = GDeps.Alias(self.m_ConfigFile, self.m_Params[GDeps.Keys.ms_MakerAlias]) aMarkerTypeName = aMakerAlias.m_Type aMakerSectionName = aMakerAlias.m_Name aIdes = self.m_Ides # assert aSolutionName, "The solution name is empty." if aIsLocal: aMarkerTypeName = self.m_Params[GDeps.Keys.ms_MakerType] aMakerSectionName = "" if aHasMakerExePath or aIsAlias: """ The maker exe path config will be read only if it's the inExePath is empty. And if an alias we haven't to use the maker inExePath default value, because thi one can be not empty. aHasMakerExePath has the priority above aIsAlias. """ self.m_Maker = getattr(GDeps, aMarkerTypeName)(inConfigFile = self.m_ConfigFile, inSectionName = aMakerSectionName, inFolderDir = os.path.normpath(self.m_FolderDir + aSubdirMakeFile), inSolutionName= aSolutionName, inArgs = aMakerArgs, inTargetsArgs = self.m_TargetsArgs, inCompilers = self.m_Compilers, inIdes = aIdes, inExePath = self.m_Params[GDeps.Keys.ms_MakerExePath] if aHasMakerExePath else "") else: """ We use the default makerExePath define by the maker. """ self.m_Maker = getattr(GDeps, aMarkerTypeName)(inConfigFile = self.m_ConfigFile, inSectionName = aMakerSectionName, inFolderDir = os.path.normpath(self.m_FolderDir + aSubdirMakeFile), inSolutionName= aSolutionName, inArgs = aMakerArgs, inTargetsArgs = self.m_TargetsArgs, inCompilers = self.m_Compilers, inIdes = aIdes)
[docs] def go(self): self.m_CurrentMacroReporting = GDeps.MacroReporting() if 'm_Repository' in self.__dict__: if self.m_Repository.exist(): # if it's not a repo clean can be crash self.m_CurrentMacroReporting.append2(self.m_Repository.clean()) self.m_CurrentMacroReporting.append2(self.m_Repository.update()) else: self.m_CurrentMacroReporting.append2(self.m_Repository.clone()) else: warnings.warn("There are no repository defined. If the source already exist GDeps will try to build it. Use GDeps.Keys.ms_RepoAlias or " + GDeps.Keys.ms_RepoAlias + " to define a repository.") for aListener in self.m_Listeners: aListener.afterUpdate(self) if 'm_Repositories' in self.__dict__: for repository in self.m_Repositories: if repository.exist(): # if it's not a repo clean can be crash self.m_CurrentMacroReporting.append2(repository.clean()) self.m_CurrentMacroReporting.append2(repository.update()) else: self.m_CurrentMacroReporting.append2(repository.clone()) for aListener in self.m_Listeners: aListener.afterRepoListUpdate(self, repository.m_FolderPath) for aListener in self.m_Listeners: aListener.afterAllRepoListUpdate(self) if 'm_Archiver' in self.__dict__: self.m_CurrentMacroReporting.append2(self.m_Archiver.download()) self.m_CurrentMacroReporting.append2(self.m_Archiver.extract()) for aListener in self.m_Listeners: aListener.afterExtractArchive(self) if 'm_Maker' in self.__dict__: self.m_CurrentMacroReporting.append2(self.m_Maker.make()) for aListener in self.m_Listeners: aListener.afterMakeAndBuild(self) elif 'm_IdeBuilder' in self.__dict__ or 'm_IdeBuilders' in self.__dict__: if 'm_IdeBuilder' in self.__dict__: self.m_CurrentMacroReporting.append2(self.m_IdeBuilder.go()) for aListener in self.m_Listeners: aListener.afterMakeAndBuild(self) if 'm_IdeBuilders' in self.__dict__: for ide in self.m_IdeBuilders: self.m_CurrentMacroReporting.append2(ide.go()) for aListener in self.m_Listeners: aListener.afterEachIdeListBuild(self, ide) for aListener in self.m_Listeners: aListener.afterAllIdeListBuild(self) else: warnings.warn("There are no maker or ide defined. Use GDeps.Keys.ms_MakerAlias or GDeps.Keys.ms_MakerType ( " + GDeps.Keys.ms_MakerAlias + " or " + GDeps.Keys.ms_MakerType + " ) to define one of them.") if self.m_MakeArchive: self.makeArchive() return self.m_CurrentMacroReporting
[docs] def initArchiveIgnore(self): """ Init the ignore list to the m_ArchiveIgnore array. Use glob syntax. """ if len(self.m_ArchiveIgnore) > 0: warnings.warn("The archive ignore list is not empty.") self.m_ArchiveIgnore = [] # Generale self.m_ArchiveIgnore += ['*.obj', '*.pch', '*.log', 'INSTALL', 'MAKEFILE', '*.m4', '*.mk', '*.o', '*.0.d', 'BUILD', '*am', 'configure', '*.in.org', '.gdeps_tmp', '.travis.yml'] # git, svn, mercurial, CVS self.m_ArchiveIgnore += ['.svn', '.git', '.hg', 'CVS', '.gitignore', '.hgignore', '.cvsignore', '.gitattributes', '.gitmodules', '.hgsub', '.hgsubstate'] # visual self.m_ArchiveIgnore += ['*.vcproj', '*.sln', '*.suo', '*.vcxproj', '*.vcxproj.filters', '*.dsp', '*.dsw', '*.obj.rsp', '*.lib.rsp', '*.dll.rsp', '*.vcxproj.user', '*.iobj', '*.ipdb', '*.ilk', '*.idb', '*.sdf', '.ncb', '*.opensdf'] # Codeblocks self.m_ArchiveIgnore += ['*.cbp', '*.layout', '*.workspace', '*.depend'] # boost self.m_ArchiveIgnore += ['*.jam', 'Jamroot', 'Jamfile.v2', 'b2.exe', 'bjam.exe'] # bakefile self.m_ArchiveIgnore += ['*.gcc', '*.bcc', '*.vc', '*.wat', '*.in', '*.unx', '*.va', '*.mms'] # cmake self.m_ArchiveIgnore += ['*.cmake', 'CMakeCache.txt', 'CMakeFiles', 'CMakeLists.txt', '.lastbuildstate', '*.tlog'] # Os Generated self.m_ArchiveIgnore += ['.DS_Store', '.DS_Store?', '._ *', '.Spotlight - V100', '.Trashes', 'ehthumbs.db', 'Thumbs.db', '* ~', '*.swp']
[docs] def makeArchive(self): """ After to call go you can create a archive with the output binaries, sources, resources and headers. :return: the archive file name. :rtype: str """ aPaths = GDeps.getPaths(self.m_FolderDir) aIgnoreList = self.listIgnoredPaths() aPathsToTheArchive = [] aCurrentDir = os.getcwd() aArchiveFolder = os.path.normpath(self.m_FolderDir) os.chdir(os.path.normpath(self.m_FolderDir + r'\\..')) aIgnoreFiles = set() # add every files and directories child or equal of a directory in the ignore directory. for aIgnoreDirectory in aIgnoreList[0]: for aPath in aPaths: if os.path.normpath(aIgnoreDirectory) == os.path.normpath(aPath[0:len(aIgnoreDirectory)]) or aPath in aIgnoreList[0] or aPath in aIgnoreList[1]: aIgnoreFiles.add(os.path.normpath(aPath)) for aPath in aPaths: if aPath not in aIgnoreList[0] and aPath not in aIgnoreList[1] and aPath not in aIgnoreFiles: aPathsToTheArchive.append(aPath) aArchiveFileName = os.path.basename(self.m_FolderDir) + '.zip' if os.path.isfile(aArchiveFileName): os.remove(aArchiveFileName) with ZipFile(aArchiveFileName, 'w') as aCompressedFile: os.chdir(self.m_FolderDir) for aPath in aPathsToTheArchive: aRealPath = r'.\\' + aPath[len(aArchiveFolder):] aCompressedFile.write(aRealPath) os.chdir(aCurrentDir) return aArchiveFileName
[docs] def listIgnoredPaths(self): """ Function to return all the ignored paths. We look for every directories inside inDirectory the glob result. The glob result is append to the ignore list. :return: the list of ignored paths. :rtype: array of set of str [0] set of directories [1] set of full file names """ aDirectories = GDeps.getDirectories(self.m_FolderDir) aIgnoreList = [set(), set()] def addIgnoreItem(inDirectory, inLocalPath): aNormPath = os.path.normpath(inDirectory + r'\\' + inLocalPath) if os.path.isdir(aNormPath): aIgnoreList[0].add(aNormPath) elif os.path.isfile(aNormPath): aIgnoreList[1].add(aNormPath) for aGlobExp in self.m_ArchiveIgnore: for aDirectory in aDirectories: aGlobResult = glob.glob1(aDirectory, aGlobExp) for aLocalPath in aGlobResult: addIgnoreItem(aDirectory, aLocalPath) if aGlobExp in os.listdir(aDirectory): addIgnoreItem(aDirectory, aGlobExp) return aIgnoreList