''' Visual studio project file generator Grbl_ESP32 is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Grbl is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Grbl_ESP32. If not, see . @authors: atlaste [github.com/atlaste] ''' PATHS_TO_SEARCH = ['Grbl_Esp32'] HEADER_EXT = ['.h', '.inl'] SOURCE_EXT = ['.c', '.cpp'] OTHER_EXT = ['.ino', '.md'] import os, uuid def UUID(name): return str(uuid.uuid3(uuid.NAMESPACE_OID, name)).upper() def FilterFromPath(path): (head, tail) = os.path.split(path) head = head.replace('/', '\\').replace('..\\', '').replace('.\\', '') if head == '.': return '' h = head[0:10]; if h == 'Grbl_Esp32': h = head[11:] return h class Vcxproj: # configuration, platform ConfigurationFmt = '\n'.join([ ' ', ' {0}', ' {1}', ' ']) # item name, item file ItemFmt = '\n'.join([ ' <{0} Include="{1}" />']) # configuration, platform ConfigTypePropertyGroupFmt = '\n'.join([ ' ', ' Makefile', ' true', ' v142', ' ']) # configuration, platform ImportGroupFmt = '\n'.join([ ' ', ' ', ' ' ]) # configuration, platform PIOPropertyGroupFmt = '\n'.join([ ' ', ' platformio --force run', ' platformio --force run -t clean', ' WIN32;_DEBUG;$(NMakePreprocessorDefinitions)', ' $(HOMEDRIVE)$(HOMEPATH)\\.platformio\\packages\\toolchain-xtensa32\\xtensa-esp32-elf\\include;$(HOMEDRIVE)$(HOMEPATH)\\.platformio\\packages\\framework-arduinoespressif32\\cores\\esp32;$(NMakeIncludeSearchPath)', ' ' ]) @staticmethod def Configuration(configuration, platform): return Vcxproj.ConfigurationFmt.format(configuration, platform) @staticmethod def Item(name, file): return Vcxproj.ItemFmt.format(name, file) @staticmethod def ConfigTypePropertyGroup(configuration, platform): return Vcxproj.ConfigTypePropertyGroupFmt.format(configuration, platform) @staticmethod def ImportGroup(configuration, platform): return Vcxproj.ImportGroupFmt.format(configuration, platform) @staticmethod def PIOPropertyGroup(configuration, platform): return Vcxproj.PIOPropertyGroupFmt.format(configuration, platform) class Filters: # itemtype, path, folder ItemFmt = '\n'.join([ ' <{0} Include="{1}">', ' {2}', ' ']) # folder, uuid FilterFmt = '\n'.join([ ' ', ' {{{1}}}', ' ']) @staticmethod def Item(itemtype, path): folder = FilterFromPath(path) return Filters.ItemFmt.format(itemtype, path, folder) @staticmethod def Filter(folder): uid = UUID(folder) return Filters.FilterFmt.format(folder, uid) class Generator: Folders = set() # Files Headers = set() Sources = set() Others = set() # Stuffs Platforms = set(['Win32','x64']) Configurations = set(['Debug','Release']) Name = 'Grbl_Esp32' def AddFolder(self, path): filt = FilterFromPath(path) if filt == '': return if filt not in self.Folders: self.Folders.add(filt) filters = '' for f in os.path.split(filt): filters = os.path.join(filters, f) if filters != '': self.Folders.add(filters) def AddFile(self, path): (root, ext) = os.path.splitext(path) if ext in HEADER_EXT: self.Headers.add(path) elif ext in SOURCE_EXT: self.Sources.add(path) elif ext in OTHER_EXT: self.Others.add(path) else: return self.AddFolder(path) def Walk(self, path): if path == 'Grbl_Esp32\\Custom' or path == 'Grbl_Esp32/Custom': return if os.path.isfile(path): self.AddFile(path) else: for subPath in os.listdir(path): self.Walk(os.path.join(path, subPath)) def CreateProject(self): project = [] project.append('') project.append('') project.append('') for p in self.Platforms: for c in self.Configurations: project.append(Vcxproj.Configuration(c, p)) project.append('') # cpp header files project.append('') for f in self.Headers: project.append(Vcxproj.Item('ClInclude', f)) project.append('') # cpp source files project.append('') for f in self.Sources: project.append(Vcxproj.Item('ClCompile', f)) project.append('') # md files and ino file project.append('') for f in self.Others: project.append(Vcxproj.Item('None', f)) project.append('') # Bookkeeping, compilation, etc. project.append('') project.append(' 16.0') project.append(' {11C8A44F-A303-4885-B5AD-5B65F7FE41C0}') project.append(' Win32Proj') project.append('') project.append('') for p in self.Platforms: for c in self.Configurations: project.append(Vcxproj.ConfigTypePropertyGroup(c, p)) project.append('') project.append('') project.append('') project.append(' ') project.append('') for p in self.Platforms: for c in self.Configurations: project.append(Vcxproj.ImportGroup(c, p)) project.append('') for p in self.Platforms: for c in self.Configurations: project.append(Vcxproj.PIOPropertyGroup(c, p)) project.append('') project.append('') project.append('') project.append(' ') project.append('') project.append('') project.append(' ') project.append(' ') project.append(' ') project.append(' ') project.append('') return '\n'.join(project) def CreateFilters(self): project = [] project.append('') project.append('') project.append('') for f in self.Folders: project.append(Filters.Filter(f)) project.append('') project.append('') for f in self.Headers: project.append(Filters.Item('ClInclude', f)) project.append('') project.append('') for f in self.Sources: project.append(Filters.Item('ClCompile', f)) project.append('') project.append('') for f in self.Others: project.append(Filters.Item('None', f)) project.append('') project.append('') return '\n'.join(project) def Generate(self): f = open(self.Name + '.vcxproj', 'w') f.write(self.CreateProject()) f.close() f = open(self.Name + '.vcxproj.filters', 'w') f.write(self.CreateFilters()) f.close() def main(paths): generator = Generator() for path in paths: generator.Walk(path) generator.Generate() main(PATHS_TO_SEARCH)