diff options
Diffstat (limited to 'sw/ideScripts/importKeilProject.py')
| -rwxr-xr-x | sw/ideScripts/importKeilProject.py | 670 |
1 files changed, 670 insertions, 0 deletions
diff --git a/sw/ideScripts/importKeilProject.py b/sw/ideScripts/importKeilProject.py new file mode 100755 index 0000000..38dcdaa --- /dev/null +++ b/sw/ideScripts/importKeilProject.py @@ -0,0 +1,670 @@ +''' +This file gets data from Keil project and creates: + - base Makefile which can be used with VS Code STM32 IDE ideScripts + - VS Code workspace +''' +import copy +import json +import os +import shutil +import subprocess +import sys +from xml.dom import minidom + +import templateStrings as tmpStr +import updateMakefile as mkf +import utilities as utils +from updateMakefile import MakefileStrings as mkfStr + +__version__ = '1.0' + + +class Paths(): + def __init__(self): + self.rootFolder = None # path where ideScripts folder is placed + + self.cubeMxExe = None # path to STM32CubeMX executable + self.tmpCubeMxFolder = None # path to temporary folder, there CubeMx performs its magic + self.tmpCubeMxScript = None # path to temporary script file for CubeMx + self.tmpMakefile = None # tempory Makefile that is later modified and copied to ideScripts root folder + self.outputMakefile = None # final clean Makefile that is later used by ideScripts + + self.keilProjectFolder = None # path to Keil project file directory + self.keilProject = None # path to Keil project file + + +class KeilProjectData: + def __init__(self): + self.projName = None + self.cpuName = None + self.stmExactCpuName = None + self.svdFile = None + + self.cDefines = [] + self.asmDefines = [] + + self.cIncludes = [] # relative paths + self.asmIncludes = [] + + self.allSources = [] + self.cSources = [] + self.asmSources = [] + + self.cCompilerSettings = [] + self.asmCompilerSettings = [] + self.linkerSettings = [] + + +def getCubeMxExePath(): + ''' + Get absolute path to STM32CubeMX.exe either by windows default associated program or user input. + ''' + cubeMxPath = utils.findExecutablePath('ioc', raiseException=False) + if cubeMxPath is not None: + if os.path.exists(cubeMxPath): + cubeMxPath = utils.pathWithForwardSlashes(cubeMxPath) + print("STM32CubeMX.exe path automatically updated.") + return cubeMxPath + else: + while cubeMxPath is None: + cubeMxPath = utils.getUserPath('STM32CubeMX.exe') + if os.path.exists(cubeMxPath): + cubeMxPath = utils.pathWithForwardSlashes(cubeMxPath) + return cubeMxPath + else: + cubeMxPath = None + + +def getKeilProjectPath(paths: Paths): + ''' + Try to find Keil *.uvprojx file. If found, this file is used as project file. + If not found, throw error. + If multiple files found, user is asked to enter specific file path. + + Return files absolute paths: *.uvprojx + ''' + KEIL_PROJECT_FILE_EXTENSION = '.uvprojx' + + # Get the list of all files in directory tree at given path + allFiles = utils.getAllFilesInFolderTree(paths.rootFolder) + keilProjectFiles = [] + for theFile in allFiles: + if theFile.find(KEIL_PROJECT_FILE_EXTENSION) != -1: + keilProjectFiles.append(theFile) + + if len(keilProjectFiles) == 0: + errorMsg = "Unable to find any Keil project files ending with " + KEIL_PROJECT_FILE_EXTENSION + ". " + errorMsg += "Is folder structure correct?\n\t" + errorMsg += "Searched files in folder tree: " + paths.rootFolder + raise Exception(errorMsg) + + elif len(keilProjectFiles) == 1: + # only one keil project file available, take this one + print("Keil project file found:", keilProjectFiles[0]) + return keilProjectFiles[0] + + else: + print("More than one Keil project files available. Select the right one.") + keilProjectPath = None + while keilProjectPath is None: + keilProjectPath = utils.getUserPath('Keil project (.uvprojx)') + if os.path.exists(keilProjectPath): + break + else: + keilProjectPath = None + + print("Keil project path updated.") + return keilProjectPath + + +def getKeilProjectData(paths: Paths) -> KeilProjectData: + ''' + Read Keil project file and return filled KeilProjectData class. + + Some blocks are placed in try...except statements - error is thrown if xml field does not contain any items. + ''' + projData = KeilProjectData() + + _, fileName = os.path.split(paths.keilProject) + projData.projName, _ = os.path.splitext(fileName) + + projFileData = minidom.parse(paths.keilProject) + projData.cpuName = projFileData.getElementsByTagName('Device')[0].firstChild.data + + svdFile = projFileData.getElementsByTagName('SFDFile')[0].firstChild.data + _, projData.svdFile = os.path.split(svdFile) + + # c stuff + _cads = projFileData.getElementsByTagName('Cads')[0] + try: # c defines + cDefines = _cads.getElementsByTagName('Define')[0].firstChild.data + projData.cDefines = utils.stringToList(cDefines, ',') + except Exception as err: + print("WARNING: unable to get C Defines: error or no items") + try: # c include folders + cIncludes = _cads.getElementsByTagName('IncludePath')[0].firstChild.data + cIncludesList = utils.stringToList(cIncludes, ';') + projData.cIncludes = _fixRelativePaths(paths, cIncludesList) + except Exception as err: + print("WARNING: unable to get C Includes (folders): error or no items") + try: # c miscelaneous controls + cMiscControls = _cads.getElementsByTagName('MiscControls')[0].firstChild.data + projData.cCompilerSettings = utils.stringToList(cMiscControls, ',') + except Exception as err: + print("WARNING: unable to get C Miscelaneous settings: error or no items") + + # asm stuff + _aads = projFileData.getElementsByTagName('Aads')[0] + try: # asm defines + asmDefines = _aads.getElementsByTagName('Define')[0].firstChild.data + projData.asmDefines = utils.stringToList(asmDefines, ',') + except Exception as err: + print("WARNING: unable to get Asm Defines: error or no items") + try: # asm include folders + asmIncludes = _aads.getElementsByTagName('IncludePath')[0].firstChild.data + asmIncludes = utils.stringToList(asmIncludes, ';') + projData.asmIncludes = _fixRelativePaths(paths, asmIncludes) + except Exception as err: + print("WARNING: unable to get Asm Includes (folders): error or no items") + try: # asm miscelaneous controls + asmMiscControls = _aads.getElementsByTagName('MiscControls')[0].firstChild.data + projData.asmCompilerSettings = utils.stringToList(asmMiscControls, ',') + except Exception as err: + print("WARNING: unable to get Asm Miscelaneous settings: error or no items") + + # get linker misc controls + _lads = projFileData.getElementsByTagName('Cads')[0] + try: # asm miscelaneous controls + linkerMiscControls = _lads.getElementsByTagName('MiscControls')[0].firstChild.data + projData.linkerSettings = utils.stringToList(linkerMiscControls, ',') + except Exception as err: + print("WARNING: unable to get Linker Miscelaneous settings: error or no items") + + # get all source files. Add only '.c' and '.s' files. Throw error on exception, this data is mandatory. + files = projFileData.getElementsByTagName('FilePath') + cSourceFiles = [] + asmSourceFiles = [] + for fileData in files: + filePathList = _fixRelativePaths(paths, [fileData.firstChild.data]) + if len(filePathList) == 1: + filePath = filePathList[0] + projData.allSources.append(filePath) + + _, extension = os.path.splitext(filePath) + if extension == '.c': + cSourceFiles.append(filePath) + elif extension == '.s': + asmSourceFiles.append(filePath) + else: + msg = "WARNING: this file is not '.c' or '.s'. Not added to project (user must handle this manually).\n" + msg += "\t" + filePath + print(msg) + else: + # missing file reported in _fixRelativePaths + msg = "WARNING: seems like none or more than one file is specified. This is not a valid Keil project syntax: " + msg += str(filePathList) + print(msg) + + projData.cSources = cSourceFiles + print("\nC source files added:\n\t" + '\n\t'.join(cSourceFiles)) + projData.asmSources = asmSourceFiles + print("\nAsm source files added:\n\t" + '\n\t'.join(asmSourceFiles) + '\n') + + return projData + + +def _fixRelativePaths(paths: Paths, relativePaths: list): + ''' + Correct relative paths according to the folder structure as it is expected. + Relative paths in Keil project file are relative to the keil file path, + while we need paths relative to root folder where 'ideScripts' is. + + Return list of a VALID relative paths paths. + ''' + keilProjectAbsPath = os.path.normpath(os.path.join(paths.rootFolder, paths.keilProject)) + + allPaths = [] + for relativePath in relativePaths: + if os.path.isabs(relativePath): + relativePath = os.path.normpath(relativePath) + relativePath = utils.pathWithForwardSlashes(relativePath) + allPaths.append(relativePath) + continue + + absolutePath = os.path.normpath(os.path.join(paths.keilProjectFolder, relativePath)) + if os.path.exists(absolutePath): + # path is valid, build correct relative path + try: + newRelativePath = os.path.relpath(absolutePath, paths.rootFolder) + newRelativePath = utils.pathWithForwardSlashes(newRelativePath) + allPaths.append(newRelativePath) + except: + absolutePath = utils.pathWithForwardSlashes(absolutePath) + allPaths.append(absolutePath) + else: + print("WARNING: unable to find file/folder:", absolutePath) + print("\tBuilt from relative path:", relativePath) + + return allPaths + + +def _getAbsolutePaths(relativePaths): + ''' + Get list of relative paths and try to build absolute paths. + If any path does not exist, print warning message. + Return list of valid absolute paths. + ''' + absolutePaths = [] + for relativePath in relativePaths: + relativePath = relativePath.strip() + relativePath = os.path.normpath(os.path.join(paths.keilProjectFolder, relativePath)) + if os.path.exists(relativePath): + relativePath = utils.pathWithForwardSlashes(relativePath) + absolutePaths.append(relativePath) + else: + print("WARNING: unable to find file/folder:", relativePath) + + return absolutePaths + + +def createMakefileTemplate(paths: Paths, keilProjData: KeilProjectData): + ''' + Create Makefile template with CubeMX. + ''' + # create script that CubeMX executes + paths.tmpCubeMxFolder = os.path.join(paths.rootFolder, tmpStr.cubeMxTmpFolderName) + paths.tmpCubeMxFolder = utils.pathWithForwardSlashes(paths.tmpCubeMxFolder) + if not os.path.exists(paths.tmpCubeMxFolder): + try: + os.mkdir(paths.tmpCubeMxFolder) + except Exception as err: + errorMsg = "Unable to create existing temporary folder:\n" + str(err) + print(errorMsg) + + # even if any error occured, try to create files anyway + _createCubeMxTmpScript(paths, keilProjData) + + # run CubeMX as subprocess with this script as a parameter + cmd = ['java', '-jar', paths.cubeMxExe, '-s', paths.tmpCubeMxScript] + if _checkCubeMxFirmwarePackage(paths, keilProjData): + cmd.append('-q') # no-gui mode + print("\tSTM32CubeMX GUI set to non-visible mode.") + else: + print("\tSTM32CubeMX GUI set to visible because of repository warning.") + + try: + print("Generating template Makefile with STM32CubeMX...") + proc = subprocess.run(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE) + if proc.returncode == 0: + print("\tSTM32CubeMX project generated.") + else: + errorMsg = "CubeMx returned non-zero exit code. Something went wrong:\n" + errorMsg += str(proc.stderr) + '\n' + errorMsg += str(proc.stdout) + + utils.printAndQuit(errorMsg) + except Exception as err: + errorMsg = "Exception error while creating template Makefile with STM32CubeMX:\n" + str(err) + utils.printAndQuit(errorMsg) + + # get makefile path + allGeneratedFiles = utils.getAllFilesInFolderTree(paths.tmpCubeMxFolder) + for theFile in allGeneratedFiles: + _, fileName = os.path.split(theFile) + if fileName == 'Makefile': + paths.tmpMakefile = theFile + print("\tMakefile found: " + paths.tmpMakefile) + + _copyStartupFile(paths, keilProjData) + return + else: + errorMsg = "Unable to find template Makefile generated by STM32CubeMX. Was project really generated?" + utils.printAndQuit(errorMsg) + + +def _copyStartupFile(paths: Paths, keilProjData: KeilProjectData): + ''' + Get '*.s' startup file in the same folder as CubeMX template Makefile file and + copy it into the same location as current startup file is. + ''' + # find CubeMX temporary generated startup file + filesInMakefileDir = os.listdir(os.path.dirname(paths.tmpMakefile)) + for theFile in filesInMakefileDir: + name, ext = os.path.splitext(theFile) + if ext == '.s': + startupFile = os.path.join(os.path.dirname(paths.tmpMakefile), theFile) + newStartupFilePath = os.path.join(paths.rootFolder, theFile) + try: + shutil.copy(startupFile, newStartupFilePath) + print("Default STM32CubeMX startup file copied to:", newStartupFilePath) + + relativeStartupFilePath = os.path.relpath(newStartupFilePath, paths.rootFolder) + relativeStartupFilePath = utils.pathWithForwardSlashes(relativeStartupFilePath) + break + except Exception as err: + pass + #print("Seems like default STM32CubeMX startup file already exist:", newStartupFilePath) + + # find startup file in current keil project data and replace it with this one + if len(keilProjData.asmSources) == 1: + # no problem only one '*.s' file, assume this is the startup file + originalStartupFile = keilProjData.asmSources[0] + keilProjData.asmSources = [relativeStartupFilePath] + + msg = "Default " + originalStartupFile + " source was replaced with CubeMX one: " + relativeStartupFilePath + print(msg) + return + + else: + # more than one assembler file found, try to find file with 'startup' string or throw error + possibleStartupFiles = [] + for startupFileListIndex, asmFile in enumerate(keilProjData.asmSources): + _, fileName = os.path.split(asmFile) + if fileName.lower().find('startup') != -1: + possibleStartupFiles.append((asmFile, startupFileListIndex)) # asm file, file index in list + + if len(possibleStartupFiles) == 1: + # OK, only one file with startup string + originalStartupFile = keilProjData.asmSources[possibleStartupFiles[0][1]] + keilProjData.asmSources[possibleStartupFiles[0][1]] = relativeStartupFilePath + + msg = "WARNING: Multiple '*.s' files found. " + msg += originalStartupFile + " source file was replaced with CubeMX one: " + relativeStartupFilePath + print(msg) + + else: + errorMsg = "Multiple '*.s' source files listed. Can't determine startup file (searched with 'startup' string)." + errorMsg += "\n\tAsm files: " + str(keilProjData.asmSources) + utils.printAndQuit(errorMsg) + + +def cleanTempMakefile(paths: Paths): + ''' + Clean default generated Makefile data (sources, includes, names, ...). + ''' + makefile = mkf.Makefile() + + try: + with open(paths.tmpMakefile, 'r') as makefileHandler: + data = makefileHandler.readlines() + + # do not change project name intentionally + # data = makefile.searchAndCleanData(data, makefile.mkfStr.projectName) + + data = makefile.searchAndCleanData(data, makefile.mkfStr.cSources) + data = makefile.searchAndCleanData(data, makefile.mkfStr.asmSources) + + data = makefile.searchAndCleanData(data, makefile.mkfStr.cDefines) + data = makefile.searchAndCleanData(data, makefile.mkfStr.asmDefines) + + data = makefile.searchAndCleanData(data, makefile.mkfStr.cIncludes) + data = makefile.searchAndCleanData(data, makefile.mkfStr.asmIncludes) + + data = makefile.searchAndCleanData(data, makefile.mkfStr.cIncludes) + + print("Makefile template prepared.") + return data + + except Exception as err: + errorMsg = "Exception during Makefile template preparation:\n" + str(err) + utils.printAndQuit(errorMsg) + + +def createNewMakefile(paths: Paths, keilProjData: KeilProjectData, newMakefileData): + ''' + Fill and write new makefile with data from Keil project. + ''' + makefile = mkf.Makefile() + try: + # sources + data = makefile.searchAndAppend(newMakefileData, makefile.mkfStr.cSources, keilProjData.cSources) + data = makefile.searchAndAppend(newMakefileData, makefile.mkfStr.asmSources, keilProjData.asmSources) + + # includes + data = makefile.searchAndAppend(newMakefileData, makefile.mkfStr.cIncludes, keilProjData.cIncludes, preappend='-I') + data = makefile.searchAndAppend(newMakefileData, makefile.mkfStr.asmIncludes, keilProjData.asmIncludes, preappend='-I') + + # defines + data = makefile.searchAndAppend(newMakefileData, makefile.mkfStr.cDefines, keilProjData.cDefines, preappend='-D') + data = makefile.searchAndAppend(newMakefileData, makefile.mkfStr.asmDefines, keilProjData.asmDefines, preappend='-D') + + # compiler flags + # TODO should import? + # data = makefile.searchAndAppend(newMakefileData, makefile.mkfStr.cFlags, keilProjData.cCompilerSettings) + # data = makefile.searchAndAppend(newMakefileData, makefile.mkfStr.asmFlags, keilProjData.asmCompilerSettings) + if keilProjData.cCompilerSettings: + print("WARNING: C compiler settings not imported (user must handle manualy):", str(keilProjData.cCompilerSettings)) + if keilProjData.asmCompilerSettings: + print("WARNING: Asm compiler settings not imported (user must handle manualy):", str(keilProjData.asmCompilerSettings)) + if keilProjData.linkerSettings: + print("WARNING: Linker settings not imported (user must handle manualy):", str(keilProjData.linkerSettings)) + + with open(paths.outputMakefile, 'w+') as newMakefileHandler: + newMakefileHandler.writelines(data) + + print("Makefile created in: " + paths.outputMakefile) + + except Exception as err: + errorMsg = "Exception during creating new Makefile:\n" + str(err) + utils.printAndQuit(errorMsg) + + +def _getCPUName(paths: Paths, keilProjData: KeilProjectData): + ''' + Try to get correct CPU family name from Keil project device tag. + + STM32 CPU name, passed to CubeMX is not the same as Keil device name. + CubeMX device firmware pack must be installed so CubeMX is able to generate template Makefile. + ''' + cubeMxMcuFolderPath = os.path.join(os.path.dirname(paths.cubeMxExe), 'db', 'mcu') + allFamiliesFilePath = os.path.join(cubeMxMcuFolderPath, 'families.xml') + + allFiles = os.listdir(cubeMxMcuFolderPath) + for theFile in allFiles: + theFilePath = os.path.join(cubeMxMcuFolderPath, theFile) + if os.path.isfile(theFilePath): + if theFile.find(keilProjData.cpuName) != -1: + fileName, ext = os.path.splitext(theFile) + return fileName + + errorMsg = "Unable to find matching STM32 CPU name for Keil project device: " + keilProjData.cpuName + utils.printAndQuit(errorMsg) + + stm32McuData = minidom.parse(allFamiliesFilePath) + + # build possible device family name search strings. Search order is important + allMcuData = stm32McuData.getElementsByTagName('Mcu') + minimumSearchStringLenght = len('STM32xx') + numOfStrippedCharacters = len(keilProjData.cpuName) - minimumSearchStringLenght + possibleDeviceSearchString = [] + possibleDeviceSearchString.append(keilProjData.cpuName) + for charIndexFromBack in range(-1, -numOfStrippedCharacters-1, -1): + possibleDeviceSearchString.append(keilProjData.cpuName[:charIndexFromBack]) + + # find possible mcu ref names + allPossibleMcu = [None] * len(allMcuData) + subFamilyMcuData = None + for thisDeviceSearchString in possibleDeviceSearchString: + thisSearchStringPossibleMcu = [] + for mcuData in allMcuData: + thisMcuName = mcuData.attributes._attrs['RPN'].value + if thisMcuName.find(thisDeviceSearchString) != -1: + thisSearchStringPossibleMcu.append(thisMcuName) + + if thisSearchStringPossibleMcu: + if len(thisSearchStringPossibleMcu) <= len(allPossibleMcu): + allPossibleMcu = copy.copy(thisSearchStringPossibleMcu) + break + + if not allPossibleMcu: + errorMsg = "Unable to find any (even partly) matching device name:" + keilProjData.cpuName + utils.printAndQuit(errorMsg) + allPossibleMcu = list(set(allPossibleMcu)) # remove cuplicates + + # all possible MCUs are listed, ask user to select correct one + if len(allPossibleMcu) == 1: + keilProjData.stmExactCpuName = allPossibleMcu[0] + return allPossibleMcu[0] + else: + msg = "\n\n??? Please select exact CPU..." + for mcuIndex, mcu in enumerate(allPossibleMcu): + msg += '\n\t' + str(mcuIndex) + ': ' + mcu + limits = list(range(0, len(allPossibleMcu))) + askMsg = "Type number (0 - " + str(len(allPossibleMcu)) + ") and press Enter:" + print(msg + '\n' + askMsg) + + while(True): + userAnswer = input() + try: + userNumber = int(userAnswer) + except: + print(askMsg) + continue + if userNumber not in limits: + print(askMsg) + else: + print("--> " + allPossibleMcu[userNumber] + " selected.") + keilProjData.stmExactCpuName = allPossibleMcu[userNumber] + return allPossibleMcu[userNumber] + + +def _checkCubeMxFirmwarePackage(paths: Paths, keilProjData: KeilProjectData): + ''' + Check if this cpu family firmware package can be found inside CubeMX local repository. + Returns True if found, False otherwise. + ''' + errorMsg = '' + try: + # get all files inside local repository + appDataFolder = os.path.expandvars(os.environ['APPDATA']) + stm32CubeRepositoryFolder = os.path.join(appDataFolder, '..', '..', 'STM32Cube', 'Repository') + stm32CubeRepositoryFolder = os.path.normpath(stm32CubeRepositoryFolder) + + # get start of package name + cpuFamilyName = keilProjData.cpuName[len('STM32'):len('STM32xx')] + fwPackageName = 'STM32Cube_FW_' + cpuFamilyName + + # search if any folder name contains fwPackageName + for item in os.listdir(stm32CubeRepositoryFolder): + if os.path.isdir(os.path.join(stm32CubeRepositoryFolder, item)): + if item.find(fwPackageName) != -1: + print("Seems like STM32CubeMX " + fwPackageName + "* package is installed.") + return True + + except Exception as err: + errorMsg = "\nException:\n" + str(err) + + msg = "WARNING: unable to check if STM32Cube " + keilProjData.cpuName + " firmware package is installed." + msg += errorMsg + print(msg) + return False + + +def _createCubeMxTmpScript(paths: Paths, keilProjData: KeilProjectData): + ''' + Create tempory script for CubeMX Makefile generation. + Raises exception on error. + ''' + paths.tmpCubeMxScript = os.path.join(paths.tmpCubeMxFolder, tmpStr.cubeMxTmpFileName) + paths.tmpCubeMxScript = utils.pathWithForwardSlashes(paths.tmpCubeMxScript) + + dataToWrite = "// Temporary script for generating Base Makefile with STM32CubeMX.\n" + dataToWrite += "load " + _getCPUName(paths, keilProjData) + "\n" + dataToWrite += "project name " + keilProjData.projName + "\n" + dataToWrite += "project toolchain Makefile\n" + dataToWrite += "project path \"" + paths.tmpCubeMxFolder + "\"\n" + dataToWrite += "project generate\n" + dataToWrite += "exit" + + with open(paths.tmpCubeMxScript, 'w+') as scriptHandler: + scriptHandler.write(dataToWrite) + + print("Temporary STM32CubeMX script created.") + + +def deleteTemporaryFiles(paths: Paths): + ''' + Delete (clean) CubeMX temporary files. + ''' + try: + shutil.rmtree(paths.tmpCubeMxFolder) + print("STM32CubeMX temporary files deleted.") + except Exception as err: + errorMsg = "Exception while deleting STM32CubeMX temporary files:\n" + str(err) + raise Exception(err) + + +def _separateAbsoluteAndRelativePaths(pathsListToSeparate: list): + ''' + This function splits pathsListToSeparate to relative and absolute paths. + Returns two lists: absolutePaths, relativePaths + ''' + absPaths = [] + relPaths = [] + for path in pathsListToSeparate: + if os.path.isabs(path): + absPaths.append(path) + else: + relPaths.append(path) + + return absPaths, relPaths + + +def createVSCodeWorkspace(paths: Paths, keilProjData: KeilProjectData): + ''' + Create VS Code workspace so user can easily run 'update.py' from ideScripts. + ''' + # add non-relative source folders to VS Code workspace folders. + allPaths = [] + # TODO are c and asm includes folders needed in Code workspace? + # allPaths.extend(keilProjData.cIncludes) + # allPaths.extend(keilProjData.asmIncludes) + cSourcesFolders = [os.path.dirname(source) for source in keilProjData.cSources] + allPaths.extend(list(set(cSourcesFolders))) + asmSourcesFolders = [os.path.dirname(source) for source in keilProjData.asmSources] + allPaths.extend(list(set(asmSourcesFolders))) + absPaths, relPaths = _separateAbsoluteAndRelativePaths(allPaths) + + dataToWrite = """ + { + "folders": [ + { + "path": "." + } + """ + for absPath in absPaths: + addToFoldersStr = ",{ \"path\": \"" + absPath + "\"}" + dataToWrite += addToFoldersStr + dataToWrite += "]" + dataToWrite += ",\"settings\": { }" + dataToWrite += "}" + data = json.loads(dataToWrite) + data = json.dumps(data, indent=4, sort_keys=False) + + codeWorkspaceFileName = keilProjData.projName + '.code-workspace' + codeWorkspaceFilePath = os.path.join(paths.rootFolder, codeWorkspaceFileName) + with open(codeWorkspaceFilePath, 'w+') as fileHandler: + fileHandler.write(data) + + print("VS Code workspace file created:", codeWorkspaceFilePath) + + +if __name__ == "__main__": + paths = Paths() + thisFileAbsPath = os.path.abspath(sys.argv[0]) + paths.rootFolder = os.path.dirname(os.path.dirname(thisFileAbsPath)) + paths.rootFolder = utils.pathWithForwardSlashes(paths.rootFolder) + + paths.cubeMxExe = getCubeMxExePath() + paths.keilProject = getKeilProjectPath(paths) + paths.keilProjectFolder = utils.pathWithForwardSlashes(os.path.dirname(paths.keilProject)) + paths.outputMakefile = utils.pathWithForwardSlashes(os.path.join(paths.rootFolder, 'Makefile')) + + keilProjData = getKeilProjectData(paths) + + createMakefileTemplate(paths, keilProjData) + cleanMakefileData = cleanTempMakefile(paths) + createNewMakefile(paths, keilProjData, cleanMakefileData) + deleteTemporaryFiles(paths) + + createVSCodeWorkspace(paths, keilProjData) |
