summaryrefslogtreecommitdiff
path: root/sw/ideScripts/updateWorkspaceSources.py
blob: 894a393256472c3d7e01332723835ab94414fbfb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
'''
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)