''' Update/generate 'c_cpp_properties.json' file in .vscode subfolder. See details in "README_DETAILS.md'. 'c_cpp_properties.json' fields description: https://github.com/Microsoft/vscode-cpptools/blob/master/Documentation/LanguageServer/c_cpp_properties.json.md ''' import json import utilities as utils import templateStrings as tmpStr import updatePaths as pth import updateMakefile as mkf import updateBuildData as build __version__ = utils.__version__ class CPropertiesStrings(): user_cSources = 'user_cSources' user_asmSources = 'user_asmSources' user_ldSources = 'user_ldSources' user_cIncludes = 'user_cIncludes' user_asmIncludes = 'user_asmIncludes' user_ldIncludes = 'user_ldIncludes' user_cDefines = 'user_cDefines' user_asmDefines = 'user_asmDefines' user_cFlags = 'user_cFlags' user_asmFlags = 'user_asmFlags' user_ldFlags = 'user_ldFlags' cubemx_sourceFiles = 'cubemx_sourceFiles' cubemx_includes = 'cubemx_includes' cubemx_defines = 'cubemx_defines' gccExePath = 'gccExePath' gccIncludePath = 'gccIncludePath' class CProperties(): def __init__(self): self.cPStr = CPropertiesStrings() self.mkfStr = mkf.MakefileStrings() self.bStr = build.BuildDataStrings() def checkCPropertiesFile(self): ''' Check if 'c_cpp_properties.json' file exists. If it does, check if it is a valid JSON file. If it doesn't exist, create new according to template. ''' if utils.pathExists(utils.cPropertiesPath): # file exists, check if it loads OK try: with open(utils.cPropertiesPath, 'r') as cPropertiesFile: currentData = json.load(cPropertiesFile) # this is a valid json file print("Existing 'c_cpp_properties.json' file found.") # merge current 'c_cpp_properties.json' with its template templateData = json.loads(tmpStr.c_cpp_template) dataToWrite = utils.mergeCurrentDataWithTemplate(currentData, templateData) dataToWrite = json.dumps(dataToWrite, indent=4, sort_keys=False) with open(utils.cPropertiesPath, 'w') as cPropertiesFile: cPropertiesFile.write(dataToWrite) print("\tKeys updated according to the template.") return except Exception as err: errorMsg = "Invalid 'c_cpp_properties.json' file. Creating backup and new one.\n" errorMsg += "Possible cause: invalid json format or comments (not supported by this scripts). Error:\n" errorMsg += str(err) print(errorMsg) utils.copyAndRename(utils.cPropertiesPath, utils.cPropertiesBackupPath) self.createCPropertiesFile() else: # 'c_cpp_properties.json' file does not exist jet, create it according to template string self.createCPropertiesFile() def createCPropertiesFile(self): ''' Create fresh 'c_cpp_properties.json' file. ''' try: with open(utils.cPropertiesPath, 'w') as cPropertiesFile: data = json.loads(tmpStr.c_cpp_template) dataToWrite = json.dumps(data, indent=4, sort_keys=False) cPropertiesFile.seek(0) cPropertiesFile.truncate() cPropertiesFile.write(dataToWrite) print("New 'c_cpp_properties.json' file created.") except Exception as err: errorMsg = "Exception error creating new 'c_cpp_properties.json' file:\n" errorMsg += str(err) utils.printAndQuit(errorMsg) def getCPropertiesData(self): ''' Get data from current 'c_cpp_properties.json' file. File existance is previoulsy checked in 'checkCPropertiesFile()'. ''' with open(utils.cPropertiesPath, 'r') as cPropertiesFile: data = json.load(cPropertiesFile) return data def getCPropertiesKeyData(self, cPropertiesData, keyName): ''' Try to get data of keyName field from 'c_cpp_properties.json' file. Return list of data or empty list. ''' try: cPropEnvData = cPropertiesData['env'] return cPropEnvData[keyName] except Exception as err: errorMsg = "Unable to get '" + str(keyName) + "' data from 'c_cpp_properties.json' file." print("WARNING:", errorMsg) return [] def addMakefileDataToCPropertiesFile(self, cPropertiesData, makefileData): ''' Add data from Makefile to 'cubemx_...' fields in 'c_cpp_properties.json' file. Returns new data to be written to 'c_cpp_properties.json' file. ''' # source files sourceFiles = makefileData[self.mkfStr.cSources] sourceFiles += makefileData[self.mkfStr.asmSources] cPropertiesData["env"][self.cPStr.cubemx_sourceFiles] = sourceFiles # includes includes = makefileData[self.mkfStr.cIncludes] # includes += makefileData[self.mkfStr.asmIncludes] # TODO Should assembler includes be included here? cPropertiesData["env"][self.cPStr.cubemx_includes] = includes # defines defines = makefileData[self.mkfStr.cDefines] # defines += makefileData[self.mkfStr.asmDefines] # TODO Should assembler defines be included here? cPropertiesData["env"][self.cPStr.cubemx_defines] = defines return cPropertiesData def addBuildDataToCPropertiesFile(self, cPropertiesData, buildData): ''' Add data from buildData to tools fields in 'c_cpp_properties.json' file. Returns new data to be written to 'c_cpp_properties.json' file. ''' # gcc cPropertiesData["env"][self.cPStr.gccExePath] = buildData[self.bStr.gccExePath] cPropertiesData["env"][self.cPStr.gccIncludePath] = buildData[self.bStr.gccInludePath] return cPropertiesData def overwriteCPropertiesFile(self, data): ''' Overwrite existing 'c_cpp_properties.json' file with new data. ''' try: with open(utils.cPropertiesPath, 'r+') as cPropertiesFile: cPropertiesFile.seek(0) cPropertiesFile.truncate() dataToWrite = json.dumps(data, indent=4, sort_keys=False) cPropertiesFile.write(dataToWrite) print("'c_cpp_properties.json' file updated!") except Exception as err: errorMsg = "Exception error overwriting 'c_cpp_properties.json' file:\n" errorMsg += str(err) utils.printAndQuit(errorMsg) def addCustomDataToCPropertiesFile(self, cProperties, makefileData, buildData): ''' TODO USER Add custom data to 'c_cpp_properties.json' file. ''' cProperties["configurations"][0]["name"] = utils.getWorkspaceName() # TODO USER can add other specific here # Note: be careful not to override other parameters that are added from 'Makefile' and 'buildData.json' return cProperties ######################################################################################################################## if __name__ == "__main__": utils.verifyFolderStructure() paths = pth.UpdatePaths() cP = CProperties() makefile = mkf.Makefile() bData = build.BuildData() # Makefile must exist makefile.checkMakefileFile() # no point in continuing if Makefile does not exist makefile.restoreOriginalMakefile() # build data (update tools paths if neccessary) buildData = bData.prepareBuildData() # data from original makefile makeExePath = buildData[bData.bStr.buildToolsPath] gccExePath = buildData[bData.bStr.gccExePath] makefileData = makefile.getMakefileData(makeExePath, gccExePath) # create 'c_cpp_properties.json' file cP.checkCPropertiesFile() cPropertiesData = cP.getCPropertiesData() cPropertiesData = cP.addBuildDataToCPropertiesFile(cPropertiesData, buildData) cPropertiesData = cP.addMakefileDataToCPropertiesFile(cPropertiesData, makefileData) cPropertiesData = cP.addCustomDataToCPropertiesFile(cPropertiesData, makefileData, buildData) cP.overwriteCPropertiesFile(cPropertiesData) # create build folder if it does not exist jet buildFolderName = makefileData[mkf.MakefileStrings.buildDir] utils.createBuildFolder(buildFolderName)