Dear Gentoo Users, Developers!

I would like to share my little program.
Help in compiling programs.

See attached python files.

sincerely xbx.

Attachment: simplebuild.build
Description: Binary data

#!/usr/bin/env python


import os
import sys
import subprocess
import datetime
import shutil


class ConfigMain(object):
    def __init__(self):
        self.configDictKeyFileName = "FileName"
        self.configDictKeyFilePath = "FilePath"
        self.configDictKeyDirPath = "DirPath"
        self.configDictKeyObjectNameAndPath = "ObjectNamePath"
        self.configFileExtensionCCode = ".c"
        self.configFileExtensionObject = ".o"
        self.configObjectBinDir = "ObjectBinaryDir"
        self.configCompilerObjectBinaryDirectory = "CompileObjectBinDir"
        self.configSharedObjectBinaryDirectory = "SharedObjectBinDir"
        self.configLinkingReportDirectory = "LinkingReport"
        #
        self.configBinaryLinkingReportDirectory = "BinaryBuildLinkingReport"
        self.configAssemblyOutputDirectory = "AssemblyOutputDirectory"
        self.gccCompileCommand = "gcc -Wall -Werror "
        self.gccOptionCompile = " -c "
        self.gccOptionObject = " -o "
        self.gccOptionBinaryNameAfterLink = " -o "
        self.gccLinkCommand = "gcc "
        self.configCompileReportDirectory = "CompileReport"
        self.configBinaryCompileReportDirectory = "BinaryBuildCompileReport"
        self.commandPackageConfig = "pkg-config --libs "
        # highlight for remove
        self.configReportFileCompile =  "CompileReportFile"
        self.configReportFileLinker =   "LinkerReportFile" 
        # patch
        self.configReportOutputDirBinaryCompile = "DIR_Report_BinaryOutputCompile"
        self.configReportOutputDirBinaryLinker  = "DIR_Report_BinaryOutputLinker"
        self.configReportOutputDirSharedCompile = "DIR_Report_SharedOutputCompile"
        self.configReportOutputDirSharedLinker  = "DIR_Report_SharedOutputLinker"
        # end
        self.configReportFileBinaryCompile = "BinaryCompileReportFile"
        self.configReportFileBinaryLinking = "BinaryLinkingReportFile"
        self.configReportFileSharedCompile = "SharedCompileReportFile"
        self.configReportFileSharedLinking = "SharedLinkingReportFile"
        self.configReportFileExtension = ".log"
        #for shared object
        self.gccOptionSharedLibDynamic = " -shared "
        self.gccOptionSharedDynamicFileOutput = " -o "
        self.configSharedObjectDirPrePath = "SharedObjectDir"

class CreateDirList(object):
    def __init__(self):
        self.__objConfigMain = ConfigMain()
        self.__configDictKeyFileName = self.__objConfigMain.configDictKeyFileName
        self.__configDictKeyFilePath = self.__objConfigMain.configDictKeyFilePath
        self.__configDictKeyDirPath = self.__objConfigMain.configDictKeyDirPath
        self.__configFileExtensionCCode = self.__objConfigMain.configFileExtensionCCode
        self.__resultAllFileDirListDict = list()
        self.__resultCCodeFileListDict = list()
        self.__resultDifferentDirPathOnly = list()
        self.__listDirSource = None
        self.__prePath = None
    
    def setValuePrePath(self,prePath):
        self.__prePath = prePath

    """ Pass the SourceCode Directory Here """
    def listDirectory(self,listDirName):
        for rootDir,subDirectories,fileNameList in os.walk(listDirName):
            for fsFileName in fileNameList:
                fileDirNameDict = dict()
                fileDirNameDict[self.__configDictKeyFileName] = fsFileName
                fileDirNameDict[self.__configDictKeyDirPath] = rootDir
                fsFileAndPath = os.path.join(rootDir,fsFileName)
                fileDirNameDict[self.__configDictKeyFilePath] = fsFileAndPath
                #print("fileName: {0} FileAndPath: {1}".format(fsFileName,fsFileAndPath))
                self.__resultAllFileDirListDict.append(fileDirNameDict)

    def filterOnCCodeFile(self):
        for fileSystemObject in self.__resultAllFileDirListDict:
            fsFileName = fileSystemObject[self.__configDictKeyFileName]
            if fsFileName.endswith(self.__configFileExtensionCCode):
                #print("C Code fileName: {0}".format(fsFileName))
                self.__resultCCodeFileListDict.append(fileSystemObject)

    def __searchInListISTrue(self,directoryList,searchElement):
        for item in directoryList:
            if item == searchElement:
                #print("Item Dir found: {0}".format(item))
                return True
        return False

    """ Need to run the filterOnCCodeFile before this """
    def filterOnDifferentDir(self):
        sortedDirList = list()
        for fileSystemObject in self.__resultCCodeFileListDict:
            directoryOnly = fileSystemObject[self.__configDictKeyDirPath]
            if self.__searchInListISTrue(sortedDirList,directoryOnly) is False:
                sortedDirList.append(directoryOnly)
                self.__resultDifferentDirPathOnly.append(fileSystemObject)

    def debugListDirectory(self):
        for item in self.__resultAllFileDirListDict:
            print("Dirpath: {0}, FileName {1}, FilePath {2}".format(
                item[self.__configDictKeyDirPath],
                item[self.__configDictKeyFileName],
                item[self.__configDictKeyFilePath]))

    def debugListDifferentDirectory(self):
        for item in self.__resultDifferentDirPathOnly:
            print("Dirpath: {0}, FileName {1}, FilePath {2}".format(
                item[self.__configDictKeyDirPath],
                item[self.__configDictKeyFileName],
                item[self.__configDictKeyFilePath]))

    def getResultFileSystemList(self):
        if self.__resultAllFileDirListDict is not None:
            return self.__resultAllFileDirListDict

    def getResultFileSystemCCodeList(self):
        if self.__resultCCodeFileListDict is not None:
            return self.__resultCCodeFileListDict

    def getResultFileSystemDifferentDirOnlyList(self):
        if self.__resultDifferentDirPathOnly is not None:
            return self.__resultDifferentDirPathOnly

""" Patched setValue output dir name """
class ObjectDirCreator(object):
    def __init__(self):
        self.__objConfigMain = ConfigMain()
        self.__configDictionaryKeyDirOnly = self.__objConfigMain.configDictKeyDirPath
        self.__configObjectBinDir = self.__objConfigMain.configObjectBinDir
        self.__differentDirectoryList = list()
        self.__pathCreateDirectoryList = list()
        self.__prePath = None

    def setValueDifferentDirList(self,differentDirList):
        self.__differentDirectoryList = differentDirList

    def setValuePrePath(self,prePath):
        self.__prePath = prePath

    """ Patch OverRide the pre output dir in path"""
    def setValueOutputPreDirectory(self,outputDirectory):
        if outputDirectory is not None:
            self.__configObjectBinDir = outputDirectory

    def __generatePathCurrentDirAndObjectPath(self,objectBinaryPath):
        currentDir =  self.__prePath
        currentAndObjectMainDir = os.path.join(currentDir,self.__configObjectBinDir)
        currentAndObjectPath = os.path.join(currentAndObjectMainDir,objectBinaryPath)
        return currentAndObjectPath

    def __createObjectPathDirectory(self,objectDirectoryPath):
        try:
            if not os.path.exists(objectDirectoryPath):
                os.makedirs(objectDirectoryPath)
        except Exception as exc:
            print("Exception occured When Create Dir: {0}, Exception was: {1}".format(objectDirectoryPath,
                exc))
            sys.exit(1)

    def generateObjectDirOutput(self):
        for fileSystemDictionary in self.__differentDirectoryList:
            directoryOnly = fileSystemDictionary[self.__configDictionaryKeyDirOnly]
            print("Create Directory: {0}".format(directoryOnly))
            pathCurrentAndObject = self.__generatePathCurrentDirAndObjectPath(directoryOnly)
            self.__createObjectPathDirectory(pathCurrentAndObject)

class CommandRunner(object):
    def __init__(self):
        self.__objConfigMain = ConfigMain()
        self.__gccCompileCommand = self.__objConfigMain.gccCompileCommand
        self.__gccCompileOption = self.__objConfigMain.gccOptionCompile
        self.__gccObjectOption = self.__objConfigMain.gccOptionObject
        self.__configFileExtensionCCode = self.__objConfigMain.configFileExtensionCCode
        self.__configFileExtensionObject = self.__objConfigMain.configFileExtensionObject
        self.__objectOutputDirectory = self.__objConfigMain.configObjectBinDir
        self.__countCompilationErrorAll = 0
        self.__allCompilationErrorString = ""
        self.__cmdPackageConfig = self.__objConfigMain.commandPackageConfig
        self.__gccLinkCommand = self.__objConfigMain.gccLinkCommand
        self.__gccOptionBinaryNameAfterLink = self.__objConfigMain.gccOptionBinaryNameAfterLink
        self.__linkingErrorCounter = 0
        self.__gccLinkToLibraryList = list()
        self.__resultLinkingErrorString = ""
        #for holding the Link to library list strign
        self.__gccLinkAllLibraryString = ""


    def __converterCCodeToObjectFileNameAndPath(self,cCodeFileName,objectBinPath):
        objectFileName = self.__convertFromCToObjectFileName(cCodeFileName)
        objectOutputFileNameAndPath = self.__generateObjectOutputPath(objectBinPath,objectFileName)
        return objectOutputFileNameAndPath

    """ NEW methon to handle the library is a list """
    def commmandPackageConfigRunList(self,linkLibraryList):
        stringCommand = self.__cmdPackageConfig
        stringPackage = ""
        stringCmdAndLibrary = ""
        listPkgConfigLibs = list()
        retDataListToString = ""
        for singleLibrary in linkLibraryList:
            stringCmdAndLibrary = stringCommand + " " + singleLibrary
            print("Search For library: {0}. Command: {1}".format(singleLibrary,stringCmdAndLibrary))
            cmdProcess = subprocess.run([stringCmdAndLibrary],shell=True,capture_output=True)
            cmdReturnCode = cmdProcess.returncode
            if cmdReturnCode == 0:
                cmdReturnData = cmdProcess.stdout.decode("utf-8")
                if cmdReturnCode is not None:
                    gccLibraryLinkParameter = cmdReturnData.rstrip(os.linesep)
                    self.__gccLinkAllLibraryString += str(" ") + gccLibraryLinkParameter
        print("The Pkg config all library paramters: {0}".format(self.__gccLinkAllLibraryString))

    def commandGCCCompileRun(self,cCodeFileWithPath,objectFileWithPath):
        # gcc -Wall -Werror -c hello.c -o hello.o
        # gcc -Wall -Werror -c hello.c -o hello.o -lmariadb
        cmdToRun = [self.__gccCompileCommand]
        cmdToRun.append(self.__gccCompileOption)
        cmdToRun.append(cCodeFileWithPath)
        cmdToRun.append(self.__gccObjectOption)
        cmdToRun.append(objectFileWithPath)
        #print("Subprocess run: {0}".format(cmdToRun))
        cmdToRunString = " ".join(cmdToRun)
        cmdToRunString +=  self.__gccLinkAllLibraryString
        print("Subprocess GCC COMPILE run String: {0}".format(cmdToRunString))
        cmdProcess = subprocess.run([cmdToRunString],shell=True,capture_output=True)
        gccReturnCode = cmdProcess.returncode
        print("Return code: {0}".format(gccReturnCode))
        if gccReturnCode != 0:
            self.__countCompilationErrorAll += 1
            print("STDOUT: {0}".format(cmdProcess.stdout))
            errorOutput = cmdProcess.stderr
            printError = errorOutput.decode("utf-8")
            print(">>> ERROR IN FILE: {0}".format(cCodeFileWithPath))
            print("STDERR: {0}".format(printError))
            fullErrorString = self.createReportString(cmdProcess.stdout,printError,cCodeFileWithPath)
            self.__allCompilationErrorString += fullErrorString
        #print(stderr)

    def commandGCCObjectToBinary(self,objectFileNamePathString,binaryFileName):
        cmdLinkingList = list()
        self.__resultLinkingErrorString = ""
        #print("Object file list pass to gcc: {0}".format(objectFileNamePathString))
        cmdLinkingList.append(self.__gccLinkCommand)
        cmdLinkingList.append(objectFileNamePathString)
        parameterGCCLinkAllListToString = str(" ") + self.__gccLinkAllLibraryString
        cmdLinkingList.append(parameterGCCLinkAllListToString)
        cmdLinkingList.append(self.__gccOptionBinaryNameAfterLink)
        cmdLinkingList.append(binaryFileName)
        cmdLinkingStringAll = " ".join(cmdLinkingList)
        print("CMD TO LINK: {0}".format(cmdLinkingStringAll))
        cmdProcessLinkGCC = subprocess.run([cmdLinkingStringAll],shell=True,capture_output=True)
        if cmdProcessLinkGCC.returncode != 0 :
            self.__linkingErrorCounter += 1
            stdError = cmdProcessLinkGCC.stderr
            stdErrorPrintable = stdError.decode("utf-8")
            stdOut = cmdProcessLinkGCC.stdout
            stdOutPrintable = stdOut.decode("utf-8")
            print("Linking output StdError: \n {0} ".format(stdErrorPrintable))
            self.__resultLinkingErrorString += stdErrorPrintable
        else:
            print("Linking went OK.\n")


    def createReportString(self,stdout,stderror,fileName):
        stringReport = ""
        stringReport += os.linesep
        stringReport = "Error Compiling file {0}. Error Was: ".format(fileName)
        stringReport += os.linesep
        stringReport += ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
        stringReport += os.linesep
        stringReport += stderror
        stringReport += "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
        stringReport += os.linesep
        return stringReport

    def getResultCompilationErrorString(self):
        if self.__allCompilationErrorString is not None:
            return self.__allCompilationErrorString
        else:
            return None

    def getResultCompilationErrorCounter(self):
        if self.__countCompilationErrorAll is not None:
            return self.__countCompilationErrorAll
        else:
            return None

    def getResultLinkingErrorString(self):
        if self.__resultLinkingErrorString is not None:
            return self.__resultLinkingErrorString
        else:
            return None

class CommandSharedLibraryRunner(object):
    def __init__(self):
        self.__objConfigMain = ConfigMain()
        #gcc -shared  -o libmylib.so myobj.o
        self.__configGCCCompileCommand = self.__objConfigMain.gccCompileCommand
        # need object all object file list
        self.__configGCCSharedLibDynamic = self.__objConfigMain.gccOptionSharedLibDynamic
        self.__configGCCSharedDynamicFileOutput = self.__objConfigMain.gccOptionSharedDynamicFileOutput
        self.__resultLinkingErrorString = ""

    def compileWithGCCSharedLibrary(self,compiledObjectFileListString,sharedObjectFileName):
        #gcc -shared  -o libmylib.so myobj1.o myobj2.o
        cmdSharedList = list() 
        cmdSharedList.append(self.__configGCCCompileCommand) 
        cmdSharedList.append(self.__configGCCSharedLibDynamic)
        cmdSharedList.append(self.__configGCCSharedDynamicFileOutput)
        cmdSharedList.append(sharedObjectFileName)
        cmdSharedList.append(compiledObjectFileListString)
        cmdSharedLinkingStringAll =  " ".join(cmdSharedList)
        print("Shared Gcc String: {0}".format(cmdSharedLinkingStringAll))
        cmdProcessLinkGCCToShared = subprocess.run([cmdSharedLinkingStringAll],shell=True,capture_output=True)
        if cmdProcessLinkGCCToShared.returncode != 0:
            stdError = cmdProcessLinkGCCToShared.stderr
            if stdError is not None:
                stdErrorPrintable = stdError.decode("utf-8")
                print("Error When Linking Shared Object file: {0}. Error: {1}"\
                        .format(sharedObjectFileName,stdErrorPrintable))
                self.__resultLinkingErrorString = stdErrorPrintable
        else:
            print("Creating Shared Library: {0} went ok.".format(sharedObjectFileName))

    def getResultSharedDynamicLibraryLinkingString(self):
        if self.__resultLinkingErrorString:
            return self.__resultLinkingErrorString 

class ReportFileCreatorBase(object):
    def __init__(self):
        self.__fileNameReport = None
        self.__fileHandlerReport = None
        self.__EXIT_AFTER_EXCEPTION = True

    def openReportFile(self,fileNameReport):
        self.__fileNameReport = fileNameReport
        try:
            self.__fileHandlerReport = open(self.__fileNameReport,"w")
        except OSError as exc:
            print("Exception Occured: {0}.".format(exc))
            if self.__HALT_AFTER_EXC:
                sys.exit(1)
            
    def writeToReportFile(self,writeStringData):
        try:
            self.__fileHandlerReport.write(writeStringData)
            self.__fileHandlerReport.flush()
        except OSError as exc:
            print("Exception Occured: {0}.".format(exc))
            if self.__HALT_AFTER_EXC:
                sys.exit(1)

    def closeReportFile(self):
        try:
            if self.__fileHandlerReport is not None:
                self.__fileHandlerReport.flush()
                self.__fileHandlerReport.close()
                """ If the self.__fileHandlerReport is not set to null 
                    The destructor __del__ is try to flush a closed file handler"""
                self.__fileHandlerReport = None
        except OSError as exc:
            print("Exception Occured: {0}.".format(exc))

    def __del__(self):
        if self.__fileHandlerReport is not None:
            self.__fileHandlerReport.flush()
            self.__fileHandlerReport.close()

class ReportFileUtility(object):
    def __init__(self):
        pass

    def stampCurrentDataTime(self):
        currentDate = datetime.datetime.now()
        formattedCurrentDateTime = datetime.datetime.strftime(currentDate,"__%Y_%m_%d__%H_%M_%S")
        return formattedCurrentDateTime

class PrePathException(Exception):
    def __init__(self,message):
        self.__message = "Exception in class ReportFile." + os.linesep + \
                "Exception Was: The prePath variable is not set. " + os.linesep +\
                message
        super().__init__(self.__message)

class ReportFileCompilerExtended(object):
    def __init__(self):
        self.__objConfigMain = ConfigMain()
        self.__reportFileNameCompileStart =  self.__objConfigMain.configReportFileCompile
        self.__reportFileExtension = self.__objConfigMain.configReportFileExtension
        self.__objReportFileCreator =  ReportFileCreatorBase()
        self.__prePath = None
        #self.__configCompileReportDirectory = self.__objConfigMain.configCompileReportDirectory
        self.__objReportUtil = ReportFileUtility()
        self.__reportFileName = None
        self.__fullPathCompileDirAndFileName = None

    def setValuePrePath(self,prePath):
        self.__prePath = prePath

    def setValueReportDirectoryOutputDirName(self,outputDirectoryName):
        self.__configCompileReportDirectory = outputDirectoryName

    def createReportFileCompileName(self,reportFileNameCompile):
        fileNameDateTimeStamp = self.__objReportUtil.stampCurrentDataTime()
        self.__reportFileName = reportFileNameCompile + fileNameDateTimeStamp +\
                self.__reportFileExtension

    def __createPathWithOutputDir(self):
        self.__fullPathCompileDirAndFileName = os.path.join(self.__prePath,\
                self.__configCompileReportDirectory)
        if not os.path.exists(self.__fullPathCompileDirAndFileName):
            os.makedirs(self.__fullPathCompileDirAndFileName)

    def __addFileNameToOutputDirectoryPath(self):
        self.__fullPathCompileDirAndFileName = os.path.join(self.__fullPathCompileDirAndFileName,\
                self.__reportFileName)

    def __writeToReportFile(self,writeDataToReportFile):
        self.__objReportFileCreator.openReportFile(self.__fullPathCompileDirAndFileName)
        self.__objReportFileCreator.writeToReportFile(writeDataToReportFile)
        self.__objReportFileCreator.closeReportFile()

    def reportFileCompileProcess(self,writeDataToReportFile):
        if self.__prePath is None:
            raise PrePathException("")
        #self.createReportFileCompileName()
        self.__createPathWithOutputDir()
        self.__addFileNameToOutputDirectoryPath()
        self.__writeToReportFile(writeDataToReportFile)


class ReportFileLinkerExtended(object):
    def __init__(self):
        self.__objConfigMain = ConfigMain()
        #self.__reportFileNameLinkerStart = self.__objConfigMain.configReportFileLinker 
        self.__reportFileNameEnd = self.__objConfigMain.configReportFileExtension
        self.__objReportFileCreator =  ReportFileCreatorBase()
        self.__prePath = None
        #self.__configLinkingReportDirectory = self.__objConfigMain.configLinkingReportDirectory
        self.__objReportUtility = ReportFileUtility()
        self.__reportFileName = None
        self.__fullPathLinkerDirAndFileName = None
    
    def setValuePrePath(self,prePath):
        self.__prePath = prePath

    def setValueReportDirectoryOutputDirName(self,outputDirectoryName):
        self.__configLinkingReportDirectory = outputDirectoryName

    def createReportFileLinkerName(self,linkerReportFileName):
        fileNameLinkerDateTimeStamp = self.__objReportUtility.stampCurrentDataTime()
        self.__reportFileName = linkerReportFileName + fileNameLinkerDateTimeStamp + \
                self.__reportFileNameEnd

    def __createPathWithOutputDir(self,linkerReportDirectory):
        self.__fullPathLinkerDirAndFileName = os.path.join(self.__prePath,\
                self.__configLinkingReportDirectory)
        if not os.path.exists(self.__fullPathLinkerDirAndFileName):
            os.makedirs(self.__fullPathLinkerDirAndFileName)

    def __addFileNameToOutputDirectoryPath(self):
        self.__fullPathLinkerDirAndFileName = os.path.join(self.__fullPathLinkerDirAndFileName,\
                self.__reportFileName)

    def __writeToReportFile(self,writeDataToReportFile):
        self.__objReportFileCreator.openReportFile(self.__fullPathLinkerDirAndFileName)
        self.__objReportFileCreator.writeToReportFile(writeDataToReportFile)
        self.__objReportFileCreator.closeReportFile()

    def reportFileLinkerProcess(self,writeDataToReportFile):
        if self.__prePath is None:
            raise PrePathException("")
        #self.__createReportFileLinkerName()
        self.__createPathWithOutputDir()
        self.__addFileNameToOutputDirectoryPath()
        self.__writeToReportFile(writeDataToReportFile)


class DeleteObjectBinaryFiles(object):
    def __init__(self,prePath,configObjectBinDir):
        self.__objConfigMain = ConfigMain()
        self.__configObjectBinaryDirectory = configObjectBinDir
        self.__prePath = prePath

    def setValueAddPrePathToObjectBinDir(self,prePath):
        self.__prePath = prePath

    def removeObjectDirectoryContent(self):
        currentDirAndObjectFileDirectory = os.path.join(self.__prePath,self.__configObjectBinaryDirectory)
        if os.path.exists(currentDirAndObjectFileDirectory):
            print(">Delete Old Object files.")
            shutil.rmtree(currentDirAndObjectFileDirectory)

    def removeRunnableBinary(self,binaryName):
        currentDirAndBinaryFile =  os.path.join(self.__prePath,binaryName)
        if os.path.exists(currentDirAndBinaryFile):
            print("Delete binary file: {0}".format(currentDirAndBinaryFile))
            os.remove(currentDirAndBinaryFile)
        

class SimpleBuildCompileWorker(object):
    def __init__(self):
        self.__objConfigMain = ConfigMain()
        self.__objCommandRunner = CommandRunner()
        self.__configDictKeyFileName = self.__objConfigMain.configDictKeyFileName
        self.__configDictKeyFilePath = self.__objConfigMain.configDictKeyFilePath
        self.__configDictKeyDirPath = self.__objConfigMain.configDictKeyDirPath
        self.__configFileExtensionCCode =  self.__objConfigMain.configFileExtensionCCode
        self.__configFileExtensionObject =  self.__objConfigMain.configFileExtensionObject
        self.__configDictKeyObjectNameAndPath = self.__objConfigMain.configDictKeyObjectNameAndPath
        self.__fileSystemCCodeList = list()
        self.__fileSystemObjectBinPathAndFileName = list()
        self.__dataHolderObjectFileNameAndPath = list()
        self.__prePath = None
        self.__exitONCompileError = True
        self.__exitONLinkerError = True
        # SET Output Object Bin Directory
        self.__configOutputCompilerObjectDirectoryPrePath = self.__objConfigMain.\
                configCompilerObjectBinaryDirectory


    def setValuePrePath(self,prePath):
        self.__prePath = prePath

    def preInitializing(self,sourceCodePath):
        createDirList = CreateDirList()
        createDirList.setValuePrePath(self.__prePath)
        createDirList.listDirectory(sourceCodePath)
        createDirList.filterOnCCodeFile()
        createDirList.filterOnDifferentDir()
        #createDirList.debugListDirectory()
        #createDirList.debugListDifferentDirectory()
        onlyDifferentDirList = createDirList.getResultFileSystemDifferentDirOnlyList()
        self.__fileSystemCCodeList = createDirList.getResultFileSystemCCodeList()
        objectDirCreator = ObjectDirCreator()
        objectDirCreator.setValuePrePath(self.__prePath)
        objectDirCreator.setValueOutputPreDirectory(\
                self.__configOutputCompilerObjectDirectoryPrePath)
        objectDirCreator.setValueDifferentDirList(onlyDifferentDirList)
        objectDirCreator.generateObjectDirOutput()

    def __convertFromCToObjectFileName(self,cCodeFileName):
        fileNameOnly = cCodeFileName.rstrip(self.__configFileExtensionCCode)
        objectExtension = fileNameOnly + self.__configFileExtensionObject
        return objectExtension

    def __generateObjectOutputPath(self,objectBinPath,objectFileName):
        currentDir = self.__prePath
        objectCurrentAndDedicatedDir = os.path.join(currentDir,\
                self.__configOutputCompilerObjectDirectoryPrePath)

        currentAndBinPath = os.path.join(objectCurrentAndDedicatedDir,objectBinPath)
        objectOutputPathWithFileName = os.path.join(currentAndBinPath,objectFileName)
        return objectOutputPathWithFileName

    def __converterCCodeToObjectFileNameAndPath(self,cCodeFileName,objectBinPath):
        objectFileName = self.__convertFromCToObjectFileName(cCodeFileName)
        objectOutputFileNameAndPath = self.__generateObjectOutputPath(objectBinPath,objectFileName)
        return objectOutputFileNameAndPath

    def workRemovePreviousObjectFile(self):
        deleteObjectFiles = DeleteObjectBinaryFiles() 
        deleteObjectFiles.setValueAddPrePathToObjectBinDir(self.__prePath)
        deleteObjectFiles.removeObjectDirectoryContent()

    def workRemoveCompiledBinary(self,binaryName):
        deleteObjectFiles  = DeleteObjectBinaryFiles()
        deleteObjectFiles.setValueAddPrePathToObjectBinDir(self.__prePath)
        deleteObjectFiles.removeRunnableBinary(binaryName)

    def workOnCompileAllWithGCC(self,gccNeedToLinkLibrary):
        commandRunner = CommandRunner()
        self.__objCommandRunner.commmandPackageConfigRunList(gccNeedToLinkLibrary)
        for fileSystemDictionary in self.__fileSystemCCodeList:
            cCodeWithPath = fileSystemDictionary[self.__configDictKeyFilePath]
            objectCodePath = fileSystemDictionary[self.__configDictKeyDirPath]
            cCodeFileName = fileSystemDictionary[self.__configDictKeyFileName]
            normalObjectBinPath = objectCodePath.lstrip("./")
            #print("C Code: {0}".format(cCodeWithPath))
            #print("Object output Dir: {0}".format(normalObjectBinPath))
            # generate objec file name from C Code file name
            generatedObjetFileName = self.__convertFromCToObjectFileName(cCodeFileName)
            objectFileNameAndPath = self.__generateObjectOutputPath(normalObjectBinPath,\
                    generatedObjetFileName)
            self.__dataHolderObjectFileNameAndPath.append(objectFileNameAndPath)
            self.__objCommandRunner.commandGCCCompileRun(cCodeWithPath,objectFileNameAndPath)
        allCompilationErrorString = self.__objCommandRunner.getResultCompilationErrorString()
        allCompilationErrorCounter = self.__objCommandRunner.getResultCompilationErrorCounter()
        if allCompilationErrorCounter == 0:
            print("Compilation went OK.")
        else:
            print(">>> " + os.linesep)
            print("Compilation has errors. Error count: {0}".format(allCompilationErrorCounter))
            print("<<<" + os.linesep)
            if allCompilationErrorString is not None:
                reportFileCompileExtended = ReportFileCompilerExtended()
                reportFileCompileExtended.setValuePrePath(self.__prePath)
                # file name, output directory
                reportFileCompileExtended.setValueReportDirectoryOutputDirName(\
                        self.__objConfigMain.configReportOutputDirBinaryCompile)
                reportFileCompileExtended.createReportFileCompileName(\
                        self.__objConfigMain.configReportFileBinaryCompile)
                reportFileCompileExtended.reportFileCompileProcess(allCompilationErrorString)
            if self.__exitONCompileError == True:
                print("EXITING: Because Compilation has ERRORS.")
                sys.exit(10)

    def workCompileObjectFileToBinary(self,programNameBinaryName):
        objectBinaryPathAndFileNameCommandString = " ".join(\
                self.__dataHolderObjectFileNameAndPath)
        self.__objCommandRunner.commandGCCObjectToBinary(objectBinaryPathAndFileNameCommandString,\
                programNameBinaryName)

        allLinkerErrorString = self.__objCommandRunner.getResultLinkingErrorString()
        if allLinkerErrorString  == "":
            print("Linker reported no error.")
        else:
            print("Linker Error: {0}".format(allLinkerErrorString))
            reportFileLinkerExtended = ReportFileLinkerExtended()
            reportFileLinkerExtended.setValuePrePath(self.__prePath)
            reportFileLinkerExtended.setValueReportDirectoryOutputDirName(\
                    self.__objConfigMain.configReportOutputDirBinaryLinker)
            reportFileLinkerExtended.createReportFileLinkerName(\
                    self.__objConfigMain.configReportFileBinaryLinking)
            reportFileLinkerExtended.reportFileLinkerProcess(allLinkerErrorString)
            if self.__exitONLinkerError == True:
                print("EXITING: Because linking has ERRORS.")
                sys.exit(11)

class SimpleBuildSharedLibraryWorker(object):
    def __init__(self):
        self.__prePath = None
        self.__objConfigMain = ConfigMain()
        self.__objCommandRunner = CommandRunner()
        self.__objSharedDynamicLibraryRunner = CommandSharedLibraryRunner()
        # Configs Also in previous class
        self.__configDictKeyFileName = self.__objConfigMain.configDictKeyFileName
        self.__configDictKeyFilePath = self.__objConfigMain.configDictKeyFilePath
        self.__configDictKeyDirPath = self.__objConfigMain.configDictKeyDirPath
        self.__configFileExtensionCCode =  self.__objConfigMain.configFileExtensionCCode
        self.__configFileExtensionObject =  self.__objConfigMain.configFileExtensionObject
        # new class configs #
        self.__configObjectBinDir = self.__objConfigMain.configSharedObjectBinaryDirectory
        self.__configSharedObjectDirPrePath = self.__objConfigMain.configSharedObjectDirPrePath 
        # DATA HOLDERS #
        self.__fileSystemCCodeList = list()
        self.__dataHolderObjectFileNameAndPath = list()
        self.__exitONLinkerError = True
        self.__exitONCompileError = True

    def setValuePrePath(self,prePath):
        self.__prePath = prePath

    def preInitializing(self,sourceCodePath):
        # dir list 
        createDirList = CreateDirList()
        createDirList.setValuePrePath(self.__prePath)
        # ERROR
        createDirList.listDirectory(sourceCodePath)
        createDirList.filterOnCCodeFile()
        createDirList.filterOnDifferentDir()
        #createDirList.debugListDirectory()
        #createDirList.debugListDifferentDirectory()
        onlyDifferentDirList = createDirList.getResultFileSystemDifferentDirOnlyList()
        self.__fileSystemCCodeList = createDirList.getResultFileSystemCCodeList()
        # for object files need an Output Directory
        objectDirCreator = ObjectDirCreator()
        objectDirCreator.setValuePrePath(self.__prePath)
        objectDirCreator.setValueOutputPreDirectory(self.__configSharedObjectDirPrePath)
        objectDirCreator.setValueDifferentDirList(onlyDifferentDirList)
        objectDirCreator.generateObjectDirOutput()

    def __convertFromCToObjectFileName(self,cCodeFileName):
        fileNameOnly = cCodeFileName.rstrip(self.__configFileExtensionCCode)
        objectExtension = fileNameOnly + self.__configFileExtensionObject
        return objectExtension

    def __generateObjectOutputPath(self,objectBinPath,objectFileName):
        currentDir = self.__prePath
        objectCurrentAndDedicatedDir = os.path.join(currentDir,self.__configSharedObjectDirPrePath)

        currentAndBinPath = os.path.join(objectCurrentAndDedicatedDir,objectBinPath)
        objectOutputPathWithFileName = os.path.join(currentAndBinPath,objectFileName)
        return objectOutputPathWithFileName

    def __converterCCodeToObjectFileNameAndPath(self,cCodeFileName,objectBinPath):
        objectFileName = self.__convertFromCToObjectFileName(cCodeFileName)
        objectOutputFileNameAndPath = self.__generateObjectOutputPath(objectBinPath,objectFileName)
        return objectOutputFileNameAndPath

    def workRemovePreviousSharedLibraryDirectory(self):
        deleteObjectFiles = DeleteObjectBinaryFiles(self.__prePath,\
                self.__configSharedObjectDirPrePath) 
        deleteObjectFiles.removeObjectDirectoryContent()

    def workRemoveCompiledSharedObjectFile(self,sharedLibraryObjectName):
        deleteObjectFiles  = DeleteObjectBinaryFiles(self.__prePath,\
                self.__configSharedObjectDirPrePath)
        deleteObjectFiles.removeRunnableBinary(sharedLibraryObjectName)

    def workOnCompileCToObjectSharedLibraryWithGCC(self,gccNeedToLinkLibrary):
        self.__objCommandRunner.commmandPackageConfigRunList(gccNeedToLinkLibrary)
        for fileSystemDictionary in self.__fileSystemCCodeList:
            cCodeWithPath = fileSystemDictionary[self.__configDictKeyFilePath]
            objectCodePath = fileSystemDictionary[self.__configDictKeyDirPath]
            cCodeFileName = fileSystemDictionary[self.__configDictKeyFileName]
            normalObjectBinPath = objectCodePath.lstrip("./")
            #print("C Code: {0}".format(cCodeWithPath))
            #print("Object output Dir: {0}".format(normalObjectBinPath))
            # generate objec file name from C Code file name
            generatedObjetFileName = self.__convertFromCToObjectFileName(cCodeFileName)
            objectFileNameAndPath = self.__generateObjectOutputPath(normalObjectBinPath,\
                    generatedObjetFileName)
            self.__dataHolderObjectFileNameAndPath.append(objectFileNameAndPath)
            self.__objCommandRunner.commandGCCCompileRun(cCodeWithPath,objectFileNameAndPath)
        allCompilationErrorString = self.__objCommandRunner.getResultCompilationErrorString()
        allCompilationErrorCounter = self.__objCommandRunner.getResultCompilationErrorCounter()
        if allCompilationErrorCounter == 0:
            print("Compilation went OK.")
        else:
            print(">>> " + os.linesep)
            print("Compilation has errors. Error count: {0}".format(allCompilationErrorCounter))
            print("<<<" + os.linesep)
            if allCompilationErrorString is not None:
                reportFileSharedCompileExtended = ReportFileCompilerExtended()
                reportFileSharedCompileExtended.setValuePrePath(self.__prePath)
                reportFileSharedCompileExtended.setValueReportDirectoryOutputDirName(\
                        self.__objConfigMain.configReportOutputDirSharedCompile)
                reportFileSharedCompileExtended.createReportFileCompileName(\
                        self.__objConfigMain.configReportFileSharedCompile)
                reportFileSharedCompileExtended.reportFileCompileProcess(allCompilationErrorString)
            if self.__exitONCompileError == True:
                print("EXITING: Because Compilation has ERRORS.")
                sys.exit(12)

    def workCompileObjectFileToSharedDynamicLibrary(self,sharedDynamicLibraryName):
        objectBinaryPathAndFileNameCommandString = " ".join(\
                self.__dataHolderObjectFileNameAndPath)
        self.__objSharedDynamicLibraryRunner.compileWithGCCSharedLibrary(\
                objectBinaryPathAndFileNameCommandString,sharedDynamicLibraryName)
        allLinkerErrorString = self.__objSharedDynamicLibraryRunner.\
                getResultSharedDynamicLibraryLinkingString()
        if allLinkerErrorString  == "":
            print("Linker reported no error.")
        else:
            print("Linker Error: {0}".format(allLinkerErrorString))
            reportFileSharedLinkerExtended = ReportFileLinkerExtended()
            reportFileSharedLinkerExtended.setValuePrePath(self.__prePath)
        
            reportFileSharedLinkerExtended.setValueReportDirectoryOutputDirName(\
                    self.__objConfigMain.configReportOutputDirSharedLinker)
            reportFileSharedLinkerExtended.createReportFileLinkerName(\
                    self.__objConfigMain.configReportFileSharedLinking)

            reportFileSharedLinkerExtended.reportFileLinkerProcess(allLinkerErrorString)
            if self.__exitONLinkerError is True:
                print("EXITING: Because linking has ERRORS.")
                sys.exit(13)


class RunnerSimpleBuildCompile(object):
    def __init__(self):
        self.__programNeedToLinkLibraryList = list()
        self.__sourceDirectoryToCompile = None
        self.__generatedOutputBinaryName = None
        self.__projectName = None
        self.__prePath = None
        self.__sharedDynamicLibraryName = None

    def setValueLinkToLibraryList(self,needToLinkLibrary):
        self.__programNeedToLinkLibraryList = needToLinkLibrary

    def setValueSourceDirectoryToCompile(self,sourceDirectoryToCompile):
        self.__sourceDirectoryToCompile = sourceDirectoryToCompile

    def setValueOutputBinaryName(self,outputBinaryName):
        self.__generatedOutputBinaryName = outputBinaryName

    def setValueOutputSharedDynamicLibraryName(self,sharedDynamicLibraryName):
        self.__sharedDynamicLibraryName = sharedDynamicLibraryName 

    def setValueProjectName(self,projectName):
        self.__projectName = projectName

    def setValuePrePath(self,prePath):
        self.__prePath = prePath

    def runSimpleBuildCompile(self):
        workerSimpleBuildCompile = SimpleBuildCompileWorker()
        workerSimpleBuildCompile.setValuePrePath(self.__prePath)
        workerSimpleBuildCompile.workRemovePreviousObjectFile()
        workerSimpleBuildCompile.workRemoveCompiledBinary(self.__generatedOutputBinaryName)
        workerSimpleBuildCompile.preInitializing(self.__sourceDirectoryToCompile)
        workerSimpleBuildCompile.workOnCompileAllWithGCC(self.__programNeedToLinkLibraryList)
        workerSimpleBuildCompile.workCompileObjectFileToBinary(self.__generatedOutputBinaryName)

    def runSimpleBuildSharedLibraryLinking(self):
        workerSimpleBuildSharedLibrary =  SimpleBuildSharedLibraryWorker()
        workerSimpleBuildSharedLibrary.setValuePrePath(self.__prePath)
        workerSimpleBuildSharedLibrary.workRemovePreviousSharedLibraryDirectory()
        workerSimpleBuildSharedLibrary.workRemoveCompiledSharedObjectFile(self.__sharedDynamicLibraryName)
        workerSimpleBuildSharedLibrary.preInitializing(self.__sourceDirectoryToCompile)
        workerSimpleBuildSharedLibrary.workOnCompileCToObjectSharedLibraryWithGCC(\
                self.__programNeedToLinkLibraryList)
        workerSimpleBuildSharedLibrary.workCompileObjectFileToSharedDynamicLibrary(\
                self.__sharedDynamicLibraryName)

#!/usr/bin/env python


import os 
import sys

from simpleBuildParser import ConfigSimpleBuild
from simpleBuildCompile import RunnerSimpleBuildCompile 
from simpleBuildParser import RunnerSimpleBuildConfigParser
from simpleBuildParser import RunnerSectionBlockParser
from simpleBuildParser import ParseToDictionaryShared


class SimpleBuildMain(object):
    def __init__(self):
        self.__objConfigSimpleBuild = ConfigSimpleBuild()
        self.__objCompileWorker = None 
        self.__objCompileSharedWorker = None
        self.__objParser = RunnerSimpleBuildConfigParser()
        self.__objSectionParser = RunnerSectionBlockParser() 
        self.__objParserShared = None 
        self.__parsedConfigDictionary = dict()
        self.__prePath = None
        self.__absolutePathBuildFile = None
        self.__buildFileSimpleBuild = None
        ## The Pre Parsed Data ###
        self.__rawConfigListBinary = list()
        self.__rawConfigListSharedLibrary = list()
        # Bool the build file has a shared library config
        self.__boolHasSharedLibraryConfigSection = False
        # Bool the build file has a binary  file config
        self.__boolHasBinaryExecutableConfigSection = False

    def setValueBuildFile(self,buildFileSimpleBuild):
        self.__buildFileSimpleBuild = buildFileSimpleBuild

    def generateAbsolutePath(self):
        self.__absolutePathBuildFile = os.path.abspath(self.__buildFileSimpleBuild)
        print("Absolute Path: {0}".format(self.__absolutePathBuildFile))

    def generateAbsoluteDirPath(self):
        self.__prePath = os.path.dirname(self.__absolutePathBuildFile)
        print("Directory: {0}".format(self.__prePath))

    def runParserSimpleBuildConfig(self):
        self.__parsedConfigDictionary = self.__objParser.runParserSimpleBuildConfig(self.__buildFileSimpleBuild)

    def runParserConfigSectionReader(self):
        self.__objSectionParser.readTheWholeFile(self.__buildFileSimpleBuild)
        self.__objSectionParser.parseTheConfigCheckSection()
        self.__objSectionParser.parseTheConfigToSection()
        # now the list with the config entries is created !!!
        self.__boolHasSharedLibraryConfigSection = self.__objSectionParser.getResultBoolParserHasSharedSection()
        self.__boolHasBinaryExecutableConfigSection = self.__objSectionParser.getResultBoolParserHasBinarySection()
        if self.__boolHasSharedLibraryConfigSection is True:
            self.__rawConfigListSharedLibrary = self.__objSectionParser.\
                    getResultParsedConfigRawListSharedLibrary()
        if self.__boolHasBinaryExecutableConfigSection is True:
            self.__rawConfigListBinary = self.__objSectionParser.\
                    getResultParsedConfigRawListBinary()

    def __runSharedCreatorWorker(self):
        self.__objParserShared = ParseToDictionaryShared()
        self.__objParserShared.setValueConfigSharedList(self.__rawConfigListSharedLibrary)
        # Process the config Section, and return back the LIST variable with the options #
        dictionaryConfigSharedLibrary = self.__objParserShared.process()
        # CALL the compiler class 

        self.__objCompileSharedWorker = RunnerSimpleBuildCompile()
        # NEED To Set class variables
        self.__objCompileSharedWorker.setValuePrePath(self.__prePath)
        self.__objCompileSharedWorker.setValueProjectName(\
                dictionaryConfigSharedLibrary[self.__objConfigSimpleBuild.\
                configSharedProjectName])
        self.__objCompileSharedWorker.setValueSourceDirectoryToCompile(\
                dictionaryConfigSharedLibrary[self.__objConfigSimpleBuild.\
                configSharedSourceDirectory])
        self.__objCompileSharedWorker.setValueLinkToLibraryList(\
                dictionaryConfigSharedLibrary[self.__objConfigSimpleBuild.\
                configSharedLinkLibrary])
        self.__objCompileSharedWorker.setValueOutputSharedDynamicLibraryName(\
                dictionaryConfigSharedLibrary[self.__objConfigSimpleBuild.\
                configSharedBuildSharedLibraryFileName])
        # The Compiler class has the parameters. Call the compilation.
        self.__objCompileSharedWorker.runSimpleBuildSharedLibraryLinking()

    def __runCompileWorker(self):
        self.__objCompileWorker = RunnerSimpleBuildCompile()
        configProjectName = self.__parsedConfigDictionary[\
                self.__objConfigSimpleBuild.configProjectName]
        configBuildBinaryName = self.__parsedConfigDictionary[\
                self.__objConfigSimpleBuild.configBuildBinaryName]
        configLinkToLibraryList = self.__parsedConfigDictionary[\
                self.__objConfigSimpleBuild.configLinkLibrary]
        configSourceDirectory = self.__parsedConfigDictionary[\
                self.__objConfigSimpleBuild.configSourceDirectory]
        self.__objCompileWorker.setValuePrePath(self.__prePath)
        self.__objCompileWorker.setValueProjectName(configProjectName)
        self.__objCompileWorker.setValueSourceDirectoryToCompile(configSourceDirectory)
        self.__objCompileWorker.setValueLinkToLibraryList(configLinkToLibraryList)
        self.__objCompileWorker.setValueOutputBinaryName(configBuildBinaryName)
        self.__objCompileWorker.runSimpleBuildCompile()


    def runMainCompilerCaller(self):
        if self.__boolHasSharedLibraryConfigSection is True:
            self.__runSharedCreatorWorker()
        if self.__boolHasBinaryExecutableConfigSection is True:
            self.__runCompileWorker()


if __name__=='__main__':
    argumentumOne = sys.argv[1]
    simpleBuildMain = SimpleBuildMain()
    simpleBuildMain.setValueBuildFile(argumentumOne)
    simpleBuildMain.generateAbsolutePath()
    simpleBuildMain.generateAbsoluteDirPath()
    simpleBuildMain.runParserConfigSectionReader()
    simpleBuildMain.runMainCompilerCaller()
#!/usr/bin/evn python


import os
import sys
import re

class ExceptionParserSingleEntry(Exception):
    def __init__(self,message):
        self.__message = "Exception occured: In Single Entry NO Multiple value allowed." + os.linesep + message
        super().__init__(self.__message)

class ExceptionParserNoneValue(Exception):
    def __init__(self,message):
        self.__message = "Exception occured: In Config Build File has No Value Specified. " + os.linesep + message
        super().__init__(self.__message)

class ExceptionSimpleBuildFileOpener(Exception):
    def __init__(self,message):
        self.__message = "Exception occured: When Opening the SimpleBuild Build file. " + os.linesep + message
        super().__init__(self.__message)

class ConfigSimpleBuild(object):
    def __init__(self):
        self.configConfigSection = "ConfigSection"
        self.configProjectName = "ProjectName"
        self.configLinkLibrary = "LinkLibrary"
        self.configSourceDirectory = "SourceDirectory"
        self.configBuildBinaryName = "BuildBinaryName"
        self.configSectionStartChar = "["
        self.configSectionEndChar = "]"
        self.configRegexpConfigKeyValueSeparator = "="
        self.configStringMultiValueSeparatorCharacter = ","
        self.configStringConfigValueStartEndChar = "\""
        self.configRegexpCommentLine = "#"
        # Config for Shared Dynamic Library
        self.configMainSectionEnd = "End"
        self.configMainSectionSharedLibrary = "ConfigSectionSharedLibrary"
        self.configMainSectionBinaryBuild =  "ConfigSectionBuildBinary"
        self.configSharedProjectName = "ProjectName"
        self.configSharedLinkLibrary = "LinkLibrary"
        self.configSharedSourceDirectory = "SourceDirectory"
        self.configSharedBuildSharedLibraryFileName = "BuildSharedLibraryName"
       
class ConfigSimpleBuildSharedDictionary(object):
    def __init__(self):
        self.__objConfigSimpleBuild = ConfigSimpleBuild()
        self.__configDictionaryMainShared = dict()
        #call method 
        self.__buildConfigDictionary()
        self.__buildMultiValueAllowedConfigForParser()

    def __buildConfigDictionary(self):
        self.__configDictionaryMainShared[self.__objConfigSimpleBuild.configSharedProjectName] = None
        self.__configDictionaryMainShared[self.__objConfigSimpleBuild.configSharedLinkLibrary] = None
        self.__configDictionaryMainShared[self.__objConfigSimpleBuild.configSharedSourceDirectory] = None
        self.__configDictionaryMainShared[self.__objConfigSimpleBuild.configSharedBuildSharedLibraryFileName] = None

    def __buildMultiValueAllowedConfigForParser(self):
        # Multiple Value allowed in the "LinkLibrary"
        self.__configParserMultiValueDictionary = {self.__objConfigSimpleBuild.configLinkLibrary : 1}

    def getResultConfigSimpleBuildSharedDictionary(self):
        if self.__configDictionaryMainShared is not None:
            return self.__configDictionaryMainShared

    def getResultConfigSimpleBuildSharedMultiViewDictionary(self):
        if self.__configParserMultiValueDictionary is not None:
            return self.__configParserMultiValueDictionary

class ConfigSimpleBuildDictionary(object):
    def __init__(self):
        self.__configDictionaryMain = dict()
        self.__configParserMultiValueDictionary = None
        # object instantiation
        self.__objConfigSimpleBuild = ConfigSimpleBuild()
        self.__buildConfigDictionary()
        self.__buildMultiValueAllowedConfigForParser()

    def __buildMultiValueAllowedConfigForParser(self):
        # Multiple Value allowed in the "LinkLibrary"
        self.__configParserMultiValueDictionary = {self.__objConfigSimpleBuild.configLinkLibrary : 1}

    def __buildConfigDictionary(self):
        self.__configDictionaryMain[self.__objConfigSimpleBuild.configConfigSection] = None
        self.__configDictionaryMain[self.__objConfigSimpleBuild.configProjectName] = None
        self.__configDictionaryMain[self.__objConfigSimpleBuild.configLinkLibrary] = None
        self.__configDictionaryMain[self.__objConfigSimpleBuild.configSourceDirectory] = None
        self.__configDictionaryMain[self.__objConfigSimpleBuild.configBuildBinaryName] = None

    def getResultConfigSimpleBuildDictionary(self):
        if self.__configDictionaryMain is not None:
            return self.__configDictionaryMain

    def getResultConfigSimpleBuildMultiValueDictionary(self):
        if self.__configParserMultiValueDictionary is not None:
            return self.__configParserMultiValueDictionary

class ReadFileSimpleBuildConfig(object):
    def __init__(self):
        self.__fileNameBuildConfig = None
        self.__fileHandlerBuildConfig = None
        self.__wholeFileData = None

    def openSimpleBuildConfigFile(self,fileNameBuild):
        self.__fileNameBuildConfig = fileNameBuild
        try:
            self.__fileHandlerBuildConfig = open(self.__fileNameBuildConfig,"r")
        except OSError as exc:
            raise ExceptionSimpleBuildFileOpener("ERROR: When Opening file: {0}. Error was: {1} .".format(self.__fileNameBuildConfig,exc))

    def readSimpleBuildConfigFile(self):
        try:
            self.__wholeFileData = self.__fileHandlerBuildConfig.readlines()
            return self.__wholeFileData
        except OSError as exc:
            self.closeSimpleBuildConfigFile()
            raise ExceptionSimpleBuildFileOpener("ERROR: When Reading file:{0}. Error was: {1} .".format(self.__fileNameBuildConfig,exc))

    def closeSimpleBuildConfigFile(self):
        if self.__fileHandlerBuildConfig is not None:
            self.__fileHandlerBuildConfig.close()

    def __del__(self):
        if self.__fileHandlerBuildConfig is not None:
            self.__fileHandlerBuildConfig.close()

""" calls the SimpleBuild class with the Dictionary created """
""" This class parse The binary build config """
class ParseTheConfig(object):
    def __init__(self,wholeFileInputBuildConfig):
        self.__wholeFileInput = wholeFileInputBuildConfig
        # instantiate the config dictionary variables
        self.__objConfigSimpleBuild = ConfigSimpleBuild()
        # instantiate the ConfigClass
        self.__objConfigSimpleBuildDict = ConfigSimpleBuildDictionary()
        self.__configSimpleBuildDict = self.__objConfigSimpleBuildDict.\
                getResultConfigSimpleBuildDictionary()
        # for holding the Multiple Value allowed in the config value section
        self.__configSimpleBuildMultiValueDict = self.__objConfigSimpleBuildDict.getResultConfigSimpleBuildMultiValueDictionary()
        # for Holding the [ConfigSection] string
        self.__configSectionString = None
        self.__configLastParsedDictionary = self.__objConfigSimpleBuildDict.\
                getResultConfigSimpleBuildDictionary()

       
    def __preBuildTheConfigSectionString(self):
        self.__configSectionString =  self.__objConfigSimpleBuild.configSectionStartChar + \
                self.__objConfigSimpleBuild.configConfigSection + \
                self.__objConfigSimpleBuild.configSectionEndChar

    def __isCommentedOut(self,lineData):
        regExpStringComment = self.__objConfigSimpleBuild.configRegexpCommentLine + r'.+'
        regExpComment = re.compile(regExpStringComment) 
        isFoundComment = re.match(regExpComment,lineData)
        if isFoundComment is not None:
            print("Comment Found")
            return True
        else:
            #print("No commented line.")
            return False

    def __findConfigInLineOneValue(self,lineData,configKey):
        regExpStringStart = "^"
        regExpStringAfterKey = "\=([A-Z|a-z|0-9|\"].+)"
        regExpString = regExpStringStart + configKey + regExpStringAfterKey
        regexpConfigKey = re.compile(regExpString)
        isFound = re.match(regexpConfigKey,lineData)
        #print(isFound)
        if isFound is not None:
            #print("Regexp IS Found: {0}".format(isFound.groups()))
            countRegExpGroup = len(isFound.groups())
            #print("INFO::COUNT: Group: {0}".format(countRegExpGroup))
            if countRegExpGroup == 0:
                raise ExceptionParserNoneValue("ERROR: On Key: {0}, Has no Value.".format(configKey))
            elif countRegExpGroup > 1:
                raise ExceptionParserSingleEntry("ERROR:On Key: {0} has: {1}.".format(configKey,lineData))
            if countRegExpGroup == 1:
                returnRegExpElementAll = isFound.groups()
                returnRegExpElementOne = returnRegExpElementAll[0]
            return returnRegExpElementOne
        else:
            return False
 
    def __findConfigInLineMultipleValue(self,lineData,configKey):
        returnMultipleValue = list()
        regExpStringStart = "^"
        regExpStringAfterKey = "\=([A-Z|a-z|0-9|\"\[\]].+)"
        regExpString = regExpStringStart + configKey + regExpStringAfterKey
        regexpConfigKey = re.compile(regExpString)
        isFound = re.match(regexpConfigKey,lineData)
        if isFound is not None:
            #print("Regexp IS Found: {0}".format(isFound.groups()))
            countRegExpGroup = len(isFound.groups())
            print("INFO::COUNT: Group: {0}".format(countRegExpGroup))
            if countRegExpGroup == 0:
                raise ExceptionParserNoneValue("ERROR: On Key: {0}, Has no Value.".format(configKey))
            returnRegExpElementAll = isFound.groups()
            return returnRegExpElementAll 
        else:
            return False
 
    def __parseTheLine(self,lineData):
        multiValueDict = self.__configSimpleBuildMultiValueDict
        for configKey in self.__configSimpleBuildDict.keys():
            if configKey in multiValueDict.keys():
                configValue = self.__findConfigInLineMultipleValue(lineData,configKey) 
                if configValue is not False:
                    self.__configSimpleBuildDict[configKey] = configValue
            else:
                configValue = self.__findConfigInLineOneValue(lineData,configKey)
                if configValue is not False:
                    #print("Config found: {0}".format(configValue)
                    cleanedWithApostrophe = self.__removeLeftRightDoubleApostrophe(configValue)
                    self.__configSimpleBuildDict[configKey] = cleanedWithApostrophe 

    # Run parser first method
    def __firstRunSimpleBuildFileParser(self):
        for rawLine in self.__wholeFileInput:
            # filter out newline, empty line
            filteredOutLine = rawLine.rstrip(os.linesep)
            #print(filteredOutLine)
            if self.__isCommentedOut(filteredOutLine) is not True:
                self.__parseTheLine(filteredOutLine)

    def __removeLeftRightSquareBracket(self,inputString):
        cleanLeft = ""
        cleanRight = ""
        if inputString.startswith(self.__objConfigSimpleBuild.configSectionStartChar):
            cleanLeft = inputString.lstrip(self.__objConfigSimpleBuild.configSectionStartChar)
        if inputString.endswith(self.__objConfigSimpleBuild.configSectionEndChar):
            cleanRight =cleanLeft.rstrip(self.__objConfigSimpleBuild.configSectionEndChar)
        cleanedSquareBracket = cleanRight
        return cleanedSquareBracket

    def __removeLeftRightDoubleApostrophe(self,inputString):
        stringRemoveLeft = ""
        stringRemoveRight = ""
        if inputString.startswith(self.__objConfigSimpleBuild.configStringConfigValueStartEndChar):
            stringRemoveLeft = inputString.lstrip(self.__objConfigSimpleBuild.configStringConfigValueStartEndChar)
        if inputString.endswith(self.__objConfigSimpleBuild.configStringConfigValueStartEndChar):
            stringRemoveRight = stringRemoveLeft.rstrip(self.__objConfigSimpleBuild.configStringConfigValueStartEndChar)
        stringRemovedLeftRight = stringRemoveRight
        return stringRemovedLeftRight

    def __cleanMultiValue(self,multiValueInput):
        retMultiValueList = list()
        if type(multiValueInput) == tuple:
            #print("Tuple type found.")
            count = len(multiValueInput)
            elementString = multiValueInput[0]
            #print("INFO: __cleanMultiValue")
            print(elementString)
            bracketLessString = self.__removeLeftRightSquareBracket(elementString)
            #print(bracketLessString)
            splittedElement = bracketLessString.split(self.__objConfigSimpleBuild.configStringMultiValueSeparatorCharacter)
            for itemRaw in splittedElement:
                #print("Library item: {0}".format(itemRaw))
                itemCleaned = self.__removeLeftRightDoubleApostrophe(itemRaw)
                #print(itemCleaned)
                retMultiValueList.append(itemCleaned)
        return retMultiValueList
    
    # Run Parser Second
    def __secondRunSimpleConfigParserDictionary(self):
        for configKey, configValue in self.__configSimpleBuildDict.items():
            if configKey in self.__configSimpleBuildMultiValueDict.keys():
                #print("The MultiValue that need to filter: {0} , Type {1}".format(configValue,type(configValue)))
                cleanedValue = self.__cleanMultiValue(configValue)
                #print("The Key: {0}, Cleaned Value: {1}".format(configKey,cleanedValue))
                self.__configLastParsedDictionary[configKey] = cleanedValue
            else:
                # print("Single Key: {0}, Value pass to the filter: {1}".format(configKey,configValue))
                self.__configLastParsedDictionary[configKey] = configValue

    def __printOutLastDictionary(self):
        for configKey, configValue in self.__configLastParsedDictionary.items():
            if configKey in self.__configSimpleBuildMultiValueDict.keys():
                for itemValue in configValue:
                    print("SingleKey: {0}. MultipleValue: {1}".format(configKey,itemValue))
            else:
                print("SingleKey: {0}, Value: {1}".format(configKey,configValue))

    def process(self):
        self.__preBuildTheConfigSectionString()
        self.__firstRunSimpleBuildFileParser()
        self.__secondRunSimpleConfigParserDictionary()
        self.__printOutLastDictionary()
        return self.__configLastParsedDictionary

""" Exception class for parser ( shared library ) """
class ExceptionParserSharedWrongEqual(Exception):
    def __init__(self,message):
        self.__message = "Exception in Shared Library Config." + os.linesep + \
                "The split function could not split to two element." + os.linesep + message
        super().__init__(self.__message)

""" The new parser class to make config Dictionary for the SharedLibrary GCC """
""" Compiler """
""" The SHARED LIBRARY DICTIONARY PARSER """
class ParseToDictionaryShared(object):
    def __init__(self):
        self.__objConfigSimpleBuildShared = ConfigSimpleBuildSharedDictionary()
        self.__configConfigDictionary = self.__objConfigSimpleBuildShared.\
                getResultConfigSimpleBuildSharedDictionary()
        self.__configConfigMultiViewDictionary = self.__objConfigSimpleBuildShared.\
                getResultConfigSimpleBuildSharedMultiViewDictionary()
        self.__configFileEntryRawList = list()
        # the Datas #
        self.__readedDictionary = None
        # for comma 
        self.__objConfigBase = ConfigSimpleBuild()
        self.__configComma = self.__objConfigBase.configStringMultiValueSeparatorCharacter

    def setValueConfigSharedList(self,listOfConfigFileEntries):
        self.__configFileEntryRawList = listOfConfigFileEntries

    def __checkComa(self,dictValueMultiRaw):
        countComma = 0
        for character in dictValueMultiRaw:
            if character == self.__configComma:
                countComma += 1
        return countComma

    def __makeMultiValueToList(self,configMultiValue):
        returnDataList = list()
        dataRemoveLeft = configMultiValue.lstrip("[")
        dataRemoveRight = dataRemoveLeft.rstrip("]")
        countComa = self.__checkComa(dataRemoveRight)
        if countComa == 0:
            returnDataList.append(dataRemoveRight)
            return returnDataList 
        elif countComa >= 1:
            dataSplitted = dataRemoveRight.split(self.__configComma)
            return dataSplitted

    def __removeDoubleApostrophe(self,dictValueRaw):
        stripedLeft = dictValueRaw.lstrip("\"")
        stripedRight = stripedLeft.rstrip("\"")
        return stripedRight

    def __elementInDictionary(self,elementKey):
        if elementKey in self.__configConfigDictionary.keys():
            #print("Element found: {0}".format(elementKey))
            return True
        else:
            return False

    def __parseTheList(self,listSingleElement):
        parsedLineDict = dict()
        #print("PARSE THE LIST: {0}".format(listSingleElement))
        splittedElement = listSingleElement.split("=")
        lengthOfElement = len(splittedElement)
        #print("Split length: {0}".format(lengthOfElement))
        if lengthOfElement == 2:
            configRawKey = splittedElement[lengthOfElement - 2]
            configRawValue = splittedElement[lengthOfElement - 1]
            print("key: {0}, value: {1}".format(configRawKey,configRawValue))
            if self.__elementInDictionary(configRawKey) is True:
                if configRawKey  in self.__configConfigMultiViewDictionary.keys():
                    libraryList = self.__makeMultiValueToList(configRawValue)
                    self.__configConfigDictionary[configRawKey] = libraryList
                else:
                    configRemApostrophe = self.__removeDoubleApostrophe(configRawValue)
                    self.__configConfigDictionary[configRawKey] = configRemApostrophe
        else:
            raise ExceptionParserSharedWrongEqual("The lengthOfElement is not 2.")

    def process(self):
        for oneElement in self.__configFileEntryRawList:
            self.__parseTheList(oneElement)
        print("dump: ")
        print(self.__configConfigDictionary)
        return self.__configConfigDictionary


class RunnerSimpleBuildConfigParser(object):
    def __init__(self):
        self.__objReadFileSimpleBuildConfig = None
        self.__dataBuildFileWhole = None
        self.__objParseTheConfig = None
        self.__dataBuildDictionary = None

    def runParserSimpleBuildConfig(self,buildFileName):
        # File Read Block
        readFileSimpleBuildConfig = ReadFileSimpleBuildConfig()
        readFileSimpleBuildConfig.openSimpleBuildConfigFile(buildFileName)
        self.__dataBuildFileWhole = readFileSimpleBuildConfig.readSimpleBuildConfigFile()
        readFileSimpleBuildConfig.closeSimpleBuildConfigFile()
        # File Read Block End
        parseTheConfig = ParseTheConfig(self.__dataBuildFileWhole)
        self.__dataBuildDictionary  = parseTheConfig.process()
        return self.__dataBuildDictionary

class RunnerSectionBlockParser(object):
    def  __init__(self):
        self.__objReadFileWhole = ReadFileSimpleBuildConfig()
        self.__objConfigSimpleBuild = ConfigSimpleBuild()
        self.__configFileWhole = None
        self.__configSectionSharedLibrary = self.__objConfigSimpleBuild.configMainSectionSharedLibrary
        self.__configSectionBuildBinary = self.__objConfigSimpleBuild.configMainSectionBinaryBuild
        self.__configSectionMainEnd = self.__objConfigSimpleBuild.configMainSectionEnd
        self.__configCommentLine = self.__objConfigSimpleBuild.configRegexpCommentLine
        self.__confRegExpSharedStart = None
        self.__confRegExpSharedEnd = None
        self.__confRegExpBinaryStart = None
        self.__confRegExpBinaryEnd = None
        self.__dataHolderBuildBinaryList = list() 
        self.__dataHolderSharedLibraryList = list()
        self.__boolParserShared = False
        self.__boolParserBinary = False
        self.__regExpConfigSectionBuildBinary()
        self.__regExpConfigSectionSharedLibrary()

    def readTheWholeFile(self,configFile):
        self.__objReadFileWhole.openSimpleBuildConfigFile(configFile)
        self.__configFileWhole = self.__objReadFileWhole.readSimpleBuildConfigFile()
        self.__objReadFileWhole.closeSimpleBuildConfigFile()

    def __regExpConfigSectionSharedLibrary(self):
        self.__confRegExpSharedStart = r'^\[' + self.__configSectionSharedLibrary + r'\]$'
        fullStringSharedEnd = self.__configSectionMainEnd + self.__configSectionSharedLibrary 
        self.__confRegExpSharedEnd = r'^\[' + fullStringSharedEnd + r'\]$'

    def __regExpConfigSectionBuildBinary(self):
        self.__confRegExpBinaryStart = r'^\[' + self.__configSectionBuildBinary + r'\]$'
        fullStringBuildBinaryEnd = self.__configSectionMainEnd + self.__configSectionBuildBinary
        self.__confRegExpBinaryEnd = r'^\[' + fullStringBuildBinaryEnd + r'\]$'

    def __getSectionBuildBinaryStart(self,lineStriped):
        regExpCompiledBinaryStart = re.compile(self.__confRegExpBinaryStart)
        matched = re.match(regExpCompiledBinaryStart,lineStriped)
        if matched is not None:
            print("BuildBinary::Start Found.")
            return 1 
        else:
            return 0

    def __getSectionBuildBinaryEnd(self,lineStriped):
        regExpCompiledBinaryEnd = re.compile(self.__confRegExpBinaryEnd)
        matched = re.match(regExpCompiledBinaryEnd,lineStriped)
        if matched is not None:
            print("BuildBinary::End Found.")
            return 2 
        else:
            return 0 

    def __getSectionSharedLibraryStart(self,lineStriped):
        regExpCompiledSharedStart = re.compile(self.__confRegExpSharedStart)
        matched = re.match(regExpCompiledSharedStart,lineStriped)
        if matched is not None:
            print("SharedLibrary::Start Found.")
            return 3 
        else:
            return 0

    def __getSectionSharedLibraryEnd(self,lineStriped):
        regExpCompiledSharedEnd = re.compile(self.__confRegExpSharedEnd)
        matched = re.match(regExpCompiledSharedEnd,lineStriped)
        if matched is not None:
            print("SharedLibrary::End Found.")
            return 4 
        else:
            return 0

    def parseTheConfigCheckSection(self):
        checkSumParserShared = 0
        checksumParserBinary = 0
        for lineRaw in self.__configFileWhole:
            lineStriped = lineRaw.rstrip(os.linesep)
            if not lineStriped.startswith(self.__configCommentLine):
                #print(lineStriped)
                checkSumParserShared += self.__getSectionSharedLibraryStart(lineStriped)
                checkSumParserShared += self.__getSectionSharedLibraryEnd(lineStriped)
                checksumParserBinary += self.__getSectionBuildBinaryStart(lineStriped)
                checksumParserBinary += self.__getSectionBuildBinaryEnd(lineStriped)
        if checkSumParserShared == 7:
            print("CHECKSUM::SharedLibrary:: Section Found.")
            self.__boolParserShared = True
        else:
            self.__boolParserShared = False
        if checksumParserBinary == 3:
            print("CHECKSUM::Binary:: Section Found.")
            self.__boolParserBinary = True
        else:
            self.__boolParserBinary = False

    def parseTheConfigToSection(self):
        stringBufferSharedList = list()
        boolStartSharedCopy = False
        stringBufferBinaryList = list()
        boolStartBinaryCopy = False
        for lineRaw in self.__configFileWhole:
            lineStriped = lineRaw.rstrip(os.linesep)
            if not lineStriped.startswith(self.__configCommentLine):
                #print(lineStriped)
                if self.__boolParserShared is True:
                    boolStartShared = self.__getSectionSharedLibraryStart(lineStriped)
                    boolEndShared   = self.__getSectionSharedLibraryEnd(lineStriped)
                    if  boolStartShared == 3:
                        boolStartSharedCopy = True
                    if boolEndShared == 4:
                        boolStartSharedCopy = False
                    if boolStartSharedCopy is True:
                        stringBufferSharedList.append(lineStriped)
                if self.__boolParserBinary is True:
                    boolStartBinary = self.__getSectionBuildBinaryStart(lineStriped)
                    boolEndBinary   = self.__getSectionBuildBinaryEnd(lineStriped)
                    if boolStartBinary == 1:
                        boolStartBinaryCopy = True
                    if boolEndBinary == 2:
                        boolStartBinaryCopy = False
                    if boolStartBinaryCopy is True:
                        stringBufferBinaryList.append(lineStriped)
        """ Remove the [ConfigSection] from list """
        """ So remove the zero element from the list """
        if self.__boolParserBinary is True:
            stringBufferBinaryList.pop(0)
            print("Binary build list: {0}".format(stringBufferBinaryList))
            self.__dataHolderBuildBinaryList = stringBufferBinaryList
            print("The REsult Binary: {0}".format(self.__dataHolderBuildBinaryList))
        if self.__boolParserShared is True:
            stringBufferSharedList.pop(0)
            print("Shared library list: {0}".format(stringBufferSharedList))
            self.__dataHolderSharedLibraryList = stringBufferSharedList
            print("The REsult library: {0}".format(self.__dataHolderSharedLibraryList))

    def getResultBoolParserHasBinarySection(self):
        if self.__boolParserBinary is not None:
            return self.__boolParserBinary

    def getResultBoolParserHasSharedSection(self):
        if self.__boolParserShared is not None:
            return self.__boolParserShared

    def getResultParsedConfigRawListBinary(self):
        return self.__dataHolderBuildBinaryList

    def getResultParsedConfigRawListSharedLibrary(self):
        return self.__dataHolderSharedLibraryList

Reply via email to