summaryrefslogtreecommitdiff
path: root/sw/ideScripts/updateBuildData.py
diff options
context:
space:
mode:
authorStijn Kuipers <stijnkuipers@gmail.com>2023-06-29 16:26:07 +0200
committerStijn Kuipers <stijnkuipers@gmail.com>2023-06-29 16:26:07 +0200
commitfb5a321dd7c2848128b04b306f3e1e59c87a3f70 (patch)
treea8ef6273f9f331ebb1971a9baf20a8c897955612 /sw/ideScripts/updateBuildData.py
parentbae7568fd4dd0676b370be8548c7ec95d6521ba1 (diff)
downloadplinky-fb5a321dd7c2848128b04b306f3e1e59c87a3f70.tar.gz
Initial Filedump
Tadaaa!!
Diffstat (limited to 'sw/ideScripts/updateBuildData.py')
-rwxr-xr-xsw/ideScripts/updateBuildData.py371
1 files changed, 371 insertions, 0 deletions
diff --git a/sw/ideScripts/updateBuildData.py b/sw/ideScripts/updateBuildData.py
new file mode 100755
index 0000000..3e84356
--- /dev/null
+++ b/sw/ideScripts/updateBuildData.py
@@ -0,0 +1,371 @@
+'''
+Update/generate 'buildData.json' file in '.vscode' subfolder from new Makefile.
+This file also handles 'toolsPaths.json' file.
+New Makefile is not updated by this script - it is updated with 'updateMakefile.py' or 'updateWorkspaceSources.py'
+'''
+import os
+import json
+import datetime
+
+import utilities as utils
+import templateStrings as tmpStr
+
+import updatePaths as pth
+import updateMakefile as mkf
+import updateWorkspaceSources as wks
+
+__version__ = utils.__version__
+
+
+class BuildDataStrings():
+ # project sources, includes, defines, ....
+ cSources = 'cSources'
+ asmSources = 'asmSources'
+ ldSources = 'ldSources'
+
+ cIncludes = 'cIncludes'
+ asmIncludes = 'asmIncludes'
+ ldIncludes = 'ldIncludes'
+
+ cDefines = 'cDefines'
+ asmDefines = 'asmDefines'
+
+ cFlags = 'cFlags'
+ asmFlags = 'asmFlags'
+ ldFlags = 'ldFlags'
+
+ buildDirPath = 'buildDir'
+
+ # build/interface tools paths, configuration files
+ gccInludePath = 'gccInludePath' # GCC standard libraries root folder path
+ gccExePath = 'gccExePath' # path to 'gcc.exe'
+
+ buildToolsPath = 'buildToolsPath' # path to 'make.exe'
+ targetExecutablePath = 'targetExecutablePath' # path to downloadable '*.elf' file
+
+ pythonExec = 'pythonExec'
+
+ openOcdPath = 'openOcdPath' # path to 'openocd.exe'
+ openOcdInterfacePath = "openOcdInterfacePath" # path to OpenOCD interface cofniguration file (currently 'stlink.cfg')
+
+ openOcdConfig = 'openOcdConfig' # path to target '*.cfg' file
+ stm32SvdPath = 'stm32SvdPath' # path to target '*.svd' file
+
+ cubeMxProjectPath = 'cubeMxProjectPath'
+
+ # list of paths that are automatically built (default, system or once their 'parent' paths are valid)
+ derivedPaths = [
+ pythonExec,
+ gccInludePath
+ ]
+
+ # list of target-specific configuration paths that must exist in 'buildData.json'
+ targetConfigurationPaths = [
+ openOcdConfig,
+ stm32SvdPath
+ ]
+
+ # list of paths that can be cached in 'toolsPaths.json'
+ toolsPaths = [
+ gccExePath,
+ buildToolsPath,
+ pythonExec,
+ openOcdPath,
+ openOcdInterfacePath
+ ]
+
+
+class BuildData():
+ def __init__(self):
+ self.mkfStr = mkf.MakefileStrings()
+ self.cPStr = wks.CPropertiesStrings()
+ self.bStr = BuildDataStrings()
+
+ def prepareBuildData(self, request=False):
+ '''
+ This function is used in all 'update*.py' scripts and makes sure, that 'toolsPaths.json' and 'buildData.json' with a
+ valid tools/target cofniguration paths exist. Invalid paths are updated (requested from the user).
+ Returns available, valid build data.
+
+ Note: tools paths listed in 'BuildDataStrings.toolsPaths' are stored in system local 'toolsPaths.json' file, and are
+ copied (overwritten) to 'buildData.json' on first 'Update' task run. This makes it possible for multiple code contributors.
+ '''
+ paths = pth.UpdatePaths()
+
+ self.checkBuildDataFile()
+ buildData = self.getBuildData()
+
+ if self.checkToolsPathFile(): # a valid toolsPaths.json exists
+ toolsPathsData = self.getToolsPathsData()
+
+ else:
+ # no valid data from 'toolsPaths.json' file
+ # try to get data from current 'buildData.json' - backward compatibility for paths that already exist in 'buildData.json'
+ toolsPathsData = json.loads(tmpStr.toolsPathsTemplate)
+ for path in self.bStr.toolsPaths:
+ if path in buildData:
+ if utils.pathExists(buildData[path]):
+ toolsPathsData[path] = buildData[path]
+
+ # update/overwrite tools paths file. Don't mind if paths are already valid.
+ toolsPathsData = paths.verifyToolsPaths(toolsPathsData, request)
+ self.createUserToolsFile(toolsPathsData)
+
+ buildData = self.addToolsPathsToBuildData(buildData, toolsPathsData)
+
+ templateBuildData = json.loads(tmpStr.buildDataTemplate)
+ buildData = utils.mergeCurrentDataWithTemplate(buildData, templateBuildData)
+
+ buildData = paths.verifyTargetConfigurationPaths(buildData, request)
+ buildData = paths.copyTargetConfigurationFiles(buildData)
+
+ return buildData
+
+ def checkToolsPathFile(self):
+ '''
+ Returns True if 'toolsPaths.json' file exists and is a valid JSON file.
+ If it is not a valid JSON, delete it and return False.
+ '''
+ if utils.pathExists(utils.toolsPaths):
+ # file exists, check if it loads OK
+ try:
+ with open(utils.toolsPaths, 'r') as toolsFileHandler:
+ json.load(toolsFileHandler)
+ print("Valid 'toolsPaths.json' file found.")
+ return True
+
+ except Exception as err:
+ errorMsg = "Invalid 'toolsPaths.json' file. Error:\n" + str(err)
+ print(errorMsg)
+
+ try:
+ os.remove(utils.toolsPaths)
+ msg = "\tDeleted. New 'toolsPaths.json' will be created on first workspace update."
+ print(msg)
+ except Exception as err:
+ errorMsg = "Error deleting 'toolsPaths.json'. Error:\n" + str(err)
+ utils.printAndQuit(errorMsg)
+
+ # else: toolsPaths.json does not exist
+ return False
+
+ def checkBuildDataFile(self):
+ '''
+ This function makes sure 'buildData.json' is available.
+ If existing 'buildData.json' file is a valid JSON, it returns immediately.
+ If it is not a valid JSON file OR it does not exist, new 'buildData.json' file is created from template.
+
+ Note: There is no backup file for buildData.json, since it is always regenerated on Update task.
+ '''
+ if utils.pathExists(utils.buildDataPath):
+ # file exists, check if it loads OK
+ try:
+ with open(utils.buildDataPath, 'r') as buildDataFileHandler:
+ json.load(buildDataFileHandler)
+ print("Valid 'buildData.json' file found.")
+
+ return
+
+ except Exception as err:
+ errorMsg = "Invalid 'buildData.json' file. Error:\n" + str(err)
+ print(errorMsg)
+
+ try:
+ os.remove(utils.buildDataPath)
+ msg = "\tDeleted. New 'buildData.json' will be created on first workspace update."
+ print(msg)
+ except Exception as err:
+ errorMsg = "Error deleting 'buildData.json'. Error:\n" + str(err)
+ utils.printAndQuit(errorMsg)
+
+ # else: buildData.json does not exist
+ self.createBuildDataFile()
+
+ def createUserToolsFile(self, toolsPaths):
+ '''
+ Create 'toolsPaths.json' file with current tools paths.
+ This pats are absolute and not project-specific.
+ '''
+ data = json.loads(tmpStr.toolsPathsTemplate)
+ try:
+ data["VERSION"] = __version__
+ data["LAST_RUN"] = str(datetime.datetime.now())
+
+ for path in self.bStr.toolsPaths:
+ data[path] = toolsPaths[path]
+
+ data = json.dumps(data, indent=4, sort_keys=False)
+ with open(utils.toolsPaths, 'w+') as toolsPathsFile:
+ toolsPathsFile.write(data)
+ print("'toolsPaths.json' file updated!")
+
+ except Exception as err:
+ errorMsg = "Exception error overwriting 'toolsPaths.json' file:\n"
+ errorMsg += str(err)
+ print("WARNING:", errorMsg)
+
+ def createBuildDataFile(self):
+ '''
+ Create fresh 'buildData.json' file.
+ '''
+ try:
+ data = json.loads(tmpStr.buildDataTemplate)
+ dataToWrite = json.dumps(data, indent=4, sort_keys=False)
+
+ with open(utils.buildDataPath, 'w+') as buildDataFile:
+ buildDataFile.truncate()
+ buildDataFile.write(dataToWrite)
+
+ print("New template 'buildData.json' file created.")
+ except Exception as err:
+ errorMsg = "Exception error creating new 'buildData.json' file:\n"
+ errorMsg += str(err)
+ utils.printAndQuit(errorMsg)
+
+ def getToolsPathsData(self):
+ '''
+ Get data from current 'toolsPaths.json' file.
+ File existance is previoulsy checked in 'checkToolsPathFile()'.
+ '''
+ with open(utils.toolsPaths, 'r') as toolsPathsFile:
+ data = json.load(toolsPathsFile)
+
+ return data
+
+ def getBuildData(self):
+ '''
+ Get data from current 'buildData.json' file.
+ File existance is previoulsy checked in 'checkBuildDataFile()'.
+ '''
+ with open(utils.buildDataPath, 'r') as buildDataFile:
+ data = json.load(buildDataFile)
+
+ return data
+
+ def addToolsPathsToBuildData(self, buildData, toolsPaths):
+ '''
+ Get tools paths from 'toolsPaths.json' and add it to buildData
+ Returns new data.
+ '''
+ allToolsPaths = []
+ allToolsPaths.extend(self.bStr.toolsPaths)
+ allToolsPaths.extend(self.bStr.derivedPaths)
+ for path in allToolsPaths:
+ try:
+ buildData[path] = toolsPaths[path]
+ except Exception as err:
+ errorMsg = "Missing '" + path + "' key in tools paths data:\n" + str(toolsPaths)
+ print("Warning:", errorMsg)
+
+ return buildData
+
+ def addMakefileDataToBuildDataFile(self, buildData, makefileData):
+ '''
+ This function fills buildData.json file with data from 'Makefile'.
+ Returns new data.
+ '''
+ # sources
+ cSources = makefileData[self.mkfStr.cSources]
+ buildData[self.bStr.cSources] = cSources
+
+ asmSources = makefileData[self.mkfStr.asmSources]
+ buildData[self.bStr.ldSources] = asmSources
+
+ ldSources = makefileData[self.mkfStr.ldSources]
+ buildData[self.bStr.ldSources] = ldSources
+
+ # includes
+ cIncludes = makefileData[self.mkfStr.cIncludes]
+ buildData[self.bStr.cIncludes] = cIncludes
+
+ asmIncludes = makefileData[self.mkfStr.asmIncludes]
+ buildData[self.bStr.asmIncludes] = asmIncludes
+
+ ldIncludes = makefileData[self.mkfStr.ldIncludes]
+ buildData[self.bStr.ldIncludes] = ldIncludes
+
+ # defines
+ cDefines = makefileData[self.mkfStr.cDefines]
+ buildData[self.bStr.cDefines] = cDefines
+
+ asmDefines = makefileData[self.mkfStr.asmDefines]
+ buildData[self.bStr.asmDefines] = asmDefines
+
+ # compiler flags and paths
+ cFlags = makefileData[self.mkfStr.cFlags]
+ buildData[self.bStr.cFlags] = cFlags
+
+ asmFlags = makefileData[self.mkfStr.asmFlags]
+ buildData[self.bStr.asmFlags] = asmFlags
+
+ ldFlags = makefileData[self.mkfStr.ldFlags]
+ buildData[self.bStr.ldFlags] = ldFlags
+
+ # build folder must be always inside workspace folder
+ buildDirPath = makefileData[self.mkfStr.buildDir]
+ buildData[self.bStr.buildDirPath] = buildDirPath
+
+ # Target executable '.elf' file
+ projectName = makefileData[self.mkfStr.projectName]
+ targetExecutablePath = utils.getBuildElfFilePath(buildDirPath, projectName)
+ buildData[self.bStr.targetExecutablePath] = targetExecutablePath
+
+ return buildData
+
+ def addCubeMxProjectPathToBuildData(self, buildData):
+ '''
+ If utils.cubeMxProjectFilePath is not None, add/update 'cubeMxProjectPath' field to 'buildData.json'.
+ '''
+ if utils.cubeMxProjectFilePath is not None:
+ buildData[self.bStr.cubeMxProjectPath] = utils.cubeMxProjectFilePath
+ else:
+ buildData.pop(self.bStr.cubeMxProjectPath)
+ return buildData
+
+ def overwriteBuildDataFile(self, data):
+ '''
+ Overwrite existing 'buildData.json' file with new data.
+ '''
+ try:
+ with open(utils.buildDataPath, 'r+') as buildDataFile:
+ data["VERSION"] = __version__
+ data["LAST_RUN"] = str(datetime.datetime.now())
+
+ buildDataFile.seek(0)
+ buildDataFile.truncate()
+ dataToWrite = json.dumps(data, indent=4, sort_keys=False)
+ buildDataFile.write(dataToWrite)
+
+ print("'buildData.json' file updated!")
+
+ except Exception as err:
+ errorMsg = "Exception error overwriting 'buildData.json' file:\n"
+ errorMsg += str(err)
+ utils.printAndQuit(errorMsg)
+
+
+########################################################################################################################
+if __name__ == "__main__":
+ utils.verifyFolderStructure()
+
+ paths = pth.UpdatePaths()
+ makefile = mkf.Makefile()
+ bData = BuildData()
+
+ # Makefile must exist - # point in continuing if Makefile does not exist
+ makefile.checkMakefileFile()
+
+ # build data (update tools paths if neccessary)
+ buildData = bData.prepareBuildData()
+
+ # data from current Makefile
+ makeExePath = buildData[bData.bStr.buildToolsPath]
+ gccExePath = buildData[bData.bStr.gccExePath]
+ makefileData = makefile.getMakefileData(makeExePath, gccExePath)
+
+ # try to add CubeMX project file path
+ buildData = bData.addCubeMxProjectPathToBuildData(buildData)
+
+ buildData = bData.addMakefileDataToBuildDataFile(buildData, makefileData)
+
+ bData.overwriteBuildDataFile(buildData)