def testFile(self): with TemporaryDirectory() as tmp: fn = os.path.join(tmp, "file") with open(fn, "w") as f: f.write("data") removePath(fn) assert not os.path.exists(fn)
def testEmpty(self): removePath(self.repodir_local) s = SvnScm({ 'scm': "svn", 'url': 'file://' + self.repodir + '/trunk', 'recipe': "foo.yaml#0" }) self.assertEqual(s.status(self.repodir_local, '', 0), 'empty')
def testDir(self): with TemporaryDirectory() as tmp: d = os.path.join(tmp, "dir") os.mkdir(d) with open(os.path.join(d, "file"), "w") as f: f.write("data") removePath(d) assert not os.path.exists(d)
def qtProjectGenerator(package, argv, extra, bobRoot): parser = argparse.ArgumentParser( prog="bob project qt-project", description='Generate QTCreator Project Files') parser.add_argument( '-u', '--update', default=False, action='store_true', help="Update project files (.files, .includes, .config)") parser.add_argument( '--buildCfg', action='append', default=[], type=lambda a: a.split("::"), help="Adds a new buildconfiguration. Format: <Name>::<flags>") parser.add_argument('--overwrite', action='store_true', help="Remove destination folder before generating.") parser.add_argument('--destination', metavar="DEST", help="Destination of project files") parser.add_argument( '--name', metavar="NAME", help="Name of project. Default is complete_path_to_package") parser.add_argument( '-I', dest="additional_includes", default=[], action='append', help= "Additional include directories. (added recursive starting from this directory)." ) parser.add_argument( '-f', '--filter', metavar="Filter", help="File filter. A regex for matching additional files.") parser.add_argument( '--exclude', default=[], action='append', dest="excludes", help="Package filter. A regex for excluding packages in QTCreator.") parser.add_argument( '--include', default=[], action='append', dest="include", help= "Include package filter. A regex for including only the specified packages in QTCreator." ) parser.add_argument('--kit', help="Kit to use for this project") parser.add_argument( '-S', dest="start_includes", default=[], action='append', help= "Additional include directories, will be placed at the beginning of the include list." ) parser.add_argument( '-C', dest="config_defs", default=[], action='append', help= "Add line to .config file. Can be used to specify preprocessor defines used by the QTCreator." ) args = parser.parse_args(argv) extra = " ".join(quote(e) for e in extra) destination = args.destination projectName = args.name project = "/".join(package.getStack()) dirs = [] excludes = [] try: if args.excludes: for e in args.excludes: excludes.append(re.compile(e)) if args.include: for e in args.include: excludes.append(re.compile(r"^((?!" + e + ").)*$")) # regex for all source / header files source = re.compile(r"\.[ch](pp)?$") include = re.compile(r"\.[h](pp)?$") cmake = re.compile(r"\.cmake$") if args.filter: additionalFiles = re.compile(args.filter) # use default kit "Desktop" if no kit is given if args.kit is None: _kit = re.compile(r".*Desktop.*") else: _kit = re.compile(r"" + args.kit) except re.error as e: raise ParseError( "Invalid regular expression '{}': {}".format(e.pattern), e) getCheckOutDirs(package, excludes, dirs) if not projectName: # use package name for project name projectName = package.getName().replace('::', '__') if not destination: # use package name for project directory destination = os.path.join(cwd(), "projects", projectName) destination = destination.replace('::', '__') if args.overwrite: removePath(destination) if not os.path.exists(destination): os.makedirs(destination) # Path structure: # destination # -> files # -> project dir # -> symlinks # create a 'flat' source tree symlinkDir = os.path.join(destination, projectName) if not args.update: if os.path.exists(symlinkDir): shutil.rmtree(symlinkDir) os.makedirs(symlinkDir) # lists for storing all found sources files / include directories / defines sList = [] hList = [] sIncList = [] cList = [] # now go through all checkout dirs to find all header / include files for name, path in OrderedDict(sorted(dirs, key=lambda t: t[1])).items(): if isWindows(): name = name.replace('::', '__') newPath = os.path.join(cwd(), path) else: newPath = os.path.join(symlinkDir, name) if not args.update: os.symlink(os.path.join(cwd(), path), newPath) for root, directories, filenames in os.walk(newPath): hasInclude = False if (((os.path.sep + '.git' + os.path.sep) in root) or ((os.path.sep + '.svn' + os.path.sep) in root)): continue for filename in filenames: if source.search(filename) or cmake.search( filename) or filename == 'CMakeLists.txt': if isWindows(): sList.append(os.path.join(root, filename)) else: sList.append( os.path.join(cwd(), os.path.join(root, filename))) if args.filter and additionalFiles.search(filename): if isWindows(): sList.append(os.path.join(root, filename)) else: sList.append( os.path.join(cwd(), os.path.join(root, filename))) if not hasInclude and include.search(filename): hasInclude = True if hasInclude: oldPath = "" # need to recursively add all directories from the include up to cwd to get includes like # <a/b/c.h> resolved even if there is no include in 'a' relativePath = root[len(newPath):] for path in relativePath.split(os.path.sep): includePath = os.path.join(newPath, oldPath, path) if not includePath in hList: hList.append(includePath) oldPath = os.path.join(oldPath, path) for i in args.additional_includes: for e in parseArgumentLine(i): if os.path.exists(e): for root, directories, filenames in os.walk(e): hList.append(os.path.join(e, root)) # compose start includes for i in args.start_includes: for e in parseArgumentLine(i): if os.path.exists(i): sIncList.append(e) # compose content of .config file (preprocessor defines) for i in args.config_defs: for e in parseArgumentLine(i): cList.append(e) id = None name = None kits = [] try: if isWindows(): profiles = xml.etree.ElementTree.parse( os.path.join(os.getenv('APPDATA'), "QtProject/qtcreator/profiles.xml")).getroot() else: profiles = xml.etree.ElementTree.parse( os.path.join( expanduser('~'), ".config/QtProject/qtcreator/profiles.xml")).getroot() for profile in profiles: for valuemap in profile: id = None name = None for value in valuemap.findall('value'): if (value.attrib.get('key') == 'PE.Profile.Id'): id = str(value.text) if (value.attrib.get('key') == 'PE.Profile.Name'): name = str(value.text) if (id is not None) and (name is not None) and ( _kit.search(name)): kits.append([name, id]) break except FileNotFoundError: # if kits are generared using sdk tool they are stored somewhere else... (/usr/share...) pass if (len(kits) == 0): if (args.kit is None): raise BuildError( "No kit found!", help= "Run again with '--kit' and specify a kit or generate a Desktop kit, which is used by default." ) kitName = args.kit kitId = args.kit else: if (len(kits) > 1): print( colorize( "Warning: {} kits found. Using '{}'.".format( len(kits), str(kits[0][0])), "33")) kitName = kits[0][0] kitId = kits[0][1] buildMeFile = os.path.join(destination, "buildme") # Generate the includes file. Create a temporary file first and compare it with the old one. # only use the new one if different to prevent reindexing after each build. includesFile = os.path.join(destination, projectName + ".includes") generateFile( sIncList + sorted(hList, key=lambda file: (os.path.dirname(file))), includesFile + ".new") compareAndRenameFileIfNotEqual(includesFile, includesFile + ".new") # Generate files file filesFile = os.path.join(destination, projectName + ".files") sList.append(buildMeFile) generateFile( sorted(sList, key=lambda file: (os.path.dirname(file), os.path.basename(file))), filesFile + ".new") compareAndRenameFileIfNotEqual(filesFile, filesFile + ".new") # Generate a .config file configFile = os.path.join(destination, projectName + ".config") generateFile(cList, configFile + ".new") compareAndRenameFileIfNotEqual(configFile, configFile + ".new") if not args.update: # Generate Buildme.sh buildMe = [] buildMe.append("#!/bin/sh") buildMe.append('bob dev "$@" ' + extra + ' ' + quote(project)) projectCmd = "bob project -n " + extra + " qt-creator " + quote(project) + \ " -u --destination " + quote(destination) + ' --name ' + quote(projectName) # only add arguments which are relevant for .files or .includes. All other files are only modified if not build with # update only. for i in args.additional_includes: projectCmd += " -I " + quote(i) if args.filter: projectCmd += " --filter " + quote(args.filter) if args.excludes: for e in args.excludes: projectCmd += " --exclude " + quote(e) if args.include: for e in args.include: projectCmd += "--include " + quote(e) for e in args.start_includes: projectCmd += " -S " + quote(e) for e in args.config_defs: projectCmd += " -C " + quote(e) buildMe.append(projectCmd) generateFile(buildMe, buildMeFile) os.chmod( buildMeFile, stat.S_IRWXU | stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH | stat.S_IWOTH) # Generate creator file creatorFile = os.path.join(destination, projectName + ".creator") generateFile([], creatorFile) # Generate the creator.shared file using a template and modify some settings sharedFile = os.path.join(destination, projectName + ".creator.shared") template_head = """<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE QtCreatorProject> <qtcreator> <data> <variable>ProjectExplorer.Project.ActiveTarget</variable> <value type="int">0</value> </data> <data> <variable>ProjectExplorer.Project.EditorSettings</variable> <valuemap type="QVariantMap"> <value type="bool" key="EditorConfiguration.AutoIndent">true</value> <value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value> <value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value> <valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0"> <value type="QString" key="language">Cpp</value> <valuemap type="QVariantMap" key="value"> <value type="QByteArray" key="CurrentPreferences">CppGlobal</value> </valuemap> </valuemap> <valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1"> <value type="QString" key="language">QmlJS</value> <valuemap type="QVariantMap" key="value"> <value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value> </valuemap> </valuemap> <value type="int" key="EditorConfiguration.CodeStyle.Count">2</value> <value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value> <value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value> <value type="int" key="EditorConfiguration.IndentSize">4</value> <value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value> <value type="int" key="EditorConfiguration.MarginColumn">80</value> <value type="bool" key="EditorConfiguration.MouseHiding">true</value> <value type="bool" key="EditorConfiguration.MouseNavigation">true</value> <value type="int" key="EditorConfiguration.PaddingMode">1</value> <value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value> <value type="bool" key="EditorConfiguration.ShowMargin">false</value> <value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value> <value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value> <value type="bool" key="EditorConfiguration.SpacesForTabs">true</value> <value type="int" key="EditorConfiguration.TabKeyBehavior">0</value> <value type="int" key="EditorConfiguration.TabSize">4</value> <value type="bool" key="EditorConfiguration.UseGlobal">true</value> <value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value> <value type="bool" key="EditorConfiguration.addFinalNewLine">true</value> <value type="bool" key="EditorConfiguration.cleanIndentation">true</value> <value type="bool" key="EditorConfiguration.cleanWhitespace">true</value> <value type="bool" key="EditorConfiguration.inEntireDocument">false</value> </valuemap> </data> <data> <variable>ProjectExplorer.Project.PluginSettings</variable> <valuemap type="QVariantMap"/> </data>""" template_foot = """ <data> <variable>ProjectExplorer.Project.TargetCount</variable> <value type="int">1</value> </data> <data> <variable>ProjectExplorer.Project.Updater.FileVersion</variable> <value type="int">18</value> </data> <data> <variable>Version</variable> <value type="int">18</value> </data> </qtcreator>""" # find all executables in package dir runTargets = [] magic = summonMagic() if package.getPackageStep().isValid(): packageDir = package.getPackageStep().getWorkspacePath() for root, directory, filenames in os.walk(packageDir): for filename in filenames: try: ftype = magic.from_file(os.path.join(root, filename)) if 'executable' in ftype and 'x86' in ftype: runTargets.append( RunStep(os.path.join(cwd(), root), filename)) except OSError: pass with open(sharedFile, 'w') as sharedFile: sharedFile.write(template_head) sharedFile.write(' <data>\n') sharedFile.write( ' <variable>ProjectExplorer.Project.Target.0</variable>\n') sharedFile.write(' <valuemap type="QVariantMap">\n') sharedFile.write( ' <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">' + kitName + '</value>\n') sharedFile.write( ' <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">' + kitName + '</value>\n') sharedFile.write( ' <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">' + kitId + '</value>\n') sharedFile.write( ' <value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>\n' ) sharedFile.write( ' <value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>\n' ) sharedFile.write( ' <value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>\n' ) addBuildSteps(sharedFile, buildMeFile, args.buildCfg) sharedFile.write( ' <value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">0</value>\n' ) sharedFile.write( ' <valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>\n' ) addRunSteps(sharedFile, runTargets) sharedFile.write(' </valuemap>\n') sharedFile.write(' </data>\n') sharedFile.write(template_foot)
def eclipseCdtGenerator(package, argv, extra): parser = argparse.ArgumentParser( prog="bob project eclipse-cdt", description='Generate Eclipse CDT Project Files') parser.add_argument('-u', '--update', default=False, action='store_true', help="Update project files (.project)") parser.add_argument( '--buildCfg', action='append', default=[], type=lambda a: a.split("::"), help="Adds a new buildconfiguration. Format: <Name>::<flags>") parser.add_argument('--overwrite', action='store_true', help="Remove destination folder before generating.") parser.add_argument('--destination', metavar="DEST", help="Destination of project files") parser.add_argument( '--name', metavar="NAME", help="Name of project. Default is complete_path_to_package") parser.add_argument( '--exclude', default=[], action='append', dest="excludes", help= "Packages will be marked as 'exclude from build' in eclipse. Usefull if indexer runs OOM." ) parser.add_argument( '-I', dest="additional_includes", default=[], action='append', help= "Additional include directories. (added recursive starting from this directory)" ) args = parser.parse_args(argv) extra = " ".join(quote(e) for e in extra) destination = args.destination projectName = args.name project = "/".join(package.getStack()) dirs = [] getCheckOutDirs(package, dirs) if not projectName: # use package name for project name projectName = package.getName() projectName = projectName.replace(':', '_') if not destination: # use package stack for project directory destination = os.path.join(os.getcwd(), "projects", "_".join(package.getStack())) destination = destination.replace(':', '_') if args.overwrite: removePath(destination) if not os.path.exists(destination): os.makedirs(destination) buildMeFile = os.path.join(destination, "buildme") id = "0." + getId() cProjectHeader = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>' cProjectHeader += '<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">' cProjectHeader += '<storageModule moduleId="org.eclipse.cdt.core.settings">' cProjectFooter = '</storageModule>\n' cProjectFooter += '<storageModule moduleId="cdtBuildSystem" version="4.0.0">\n' cProjectFooter += ' <project id="bob4eclipse.null.' + getId( ) + '" name="bob4eclipse"/>\n' cProjectFooter += '</storageModule>\n' cProjectFooter += '<storageModule moduleId="scannerConfiguration">\n' cProjectFooter += ' <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>\n' cProjectFooter += ' <scannerConfigBuildInfo instanceId=" ' + id + '">\n' cProjectFooter += ' <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>\n' cProjectFooter += ' </scannerConfigBuildInfo>\n' cProjectFooter += '</storageModule>\n' cProjectFooter += '<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>\n' cProjectFooter += '<storageModule moduleId="refreshScope" versionNumber="2">\n' cProjectFooter += ' <configuration configurationName="bob (build only)">\n' cProjectFooter += ' <resource resourceType="PROJECT" workspacePath="/bob4eclipse"/>\n' cProjectFooter += ' </configuration>\n' cProjectFooter += ' <configuration configurationName="Default">\n' cProjectFooter += ' <resource resourceType="PROJECT" workspacePath="/bob4eclipse"/>\n' cProjectFooter += ' </configuration>\n' cProjectFooter += '</storageModule>\n' cProjectFooter += '</cproject>\n' # setup list of exclude packages excludePackages = [] for e in args.excludes: exp = re.compile(e) for name, path in OrderedDict(sorted(dirs, key=lambda t: t[1])).items(): if exp.match(name): excludePackages.append(name) includeDirs = [] # find additional include dirs for i in args.additional_includes: if os.path.exists(i): for root, directories, filenames in os.walk(i): includeDirs.append(os.path.join(i, root)) with open(os.path.join(destination, ".cproject"), 'w') as cProjectFile: cProjectFile.write(cProjectHeader) addCConfig(cProjectFile, excludePackages, includeDirs, "Bob dev", id, "", buildMeFile) addCConfig(cProjectFile, excludePackages, includeDirs, "Bob dev (force)", id + "." + getId(), "-f", buildMeFile) addCConfig(cProjectFile, excludePackages, includeDirs, "Bob dev (no checkout)", id + "." + getId(), "-b", buildMeFile) addCConfig(cProjectFile, excludePackages, includeDirs, "Bob dev (no deps)", id + "." + getId(), "-n", buildMeFile) addCConfig(cProjectFile, excludePackages, includeDirs, "Bob dev (no checkout, no deps)", id + "." + getId(), "-bn", buildMeFile) addCConfig(cProjectFile, excludePackages, includeDirs, "Bob dev (no checkout, clean)", id + "." + getId(), "-b --clean", buildMeFile) for name, flags in args.buildCfg: addCConfig(cProjectFile, excludePackages, includeDirs, name, id + "." + getId(), flags, buildMeFile) cProjectFile.write(cProjectFooter) projectFileHeader = """<?xml version="1.0" encoding="UTF-8"?> <projectDescription> <name>""" + projectName + """</name> <comment></comment> <projects> </projects> <buildSpec> <buildCommand> <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name> <arguments> </arguments> </buildCommand> <buildCommand> <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name> <triggers>full,incremental,</triggers> <arguments> </arguments> </buildCommand> </buildSpec> <natures> <nature>org.eclipse.cdt.core.cnature</nature> <nature>org.eclipse.cdt.core.ccnature</nature> <nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature> <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature> </natures> <linkedResources>""" projectFileFooter = """</linkedResources> </projectDescription>""" with open(os.path.join(destination, ".project"), 'w') as cProjectFile: cProjectFile.write(projectFileHeader) for name, path in OrderedDict(sorted(dirs, key=lambda t: t[1])).items(): cProjectFile.write('<link>\n') cProjectFile.write(' <name>' + name + '</name>\n') cProjectFile.write(' <type>2</type>\n') cProjectFile.write(' <location>' + os.path.join(os.getcwd(), path) + '</location>\n') cProjectFile.write('</link>\n') cProjectFile.write(projectFileFooter) if not args.update: # Generate buildme buildMe = [] buildMe.append("#!/bin/sh") buildMe.append('bob dev "$@" ' + extra + ' ' + quote(project)) projectCmd = "bob project -n " + extra + " eclipseCdt " + quote(project) + \ " -u --destination " + quote(destination) + ' --name ' + quote(projectName) for i in args.additional_includes: projectCmd += " -I " + quote(i) buildMe.append(projectCmd) generateFile(buildMe, buildMeFile) os.chmod( buildMeFile, stat.S_IRWXU | stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH | stat.S_IWOTH) # find all executables in package dir runTargets = [] magic = summonMagic() if package.getPackageStep().isValid(): packageDir = package.getPackageStep().getWorkspacePath() for root, directory, filenames in os.walk(packageDir): for filename in filenames: try: ftype = magic.from_file(os.path.join(root, filename)) if 'executable' in ftype and 'x86' in ftype: createLaunchFile( open( os.path.join(destination, filename + ".launch"), 'w'), os.path.join(os.getcwd(), root, filename), projectName) except OSError: pass
def tearDown(self): removePath(self.repodir) removePath(self.repodir_local)
def tearDown(self): self.jenkinsMock.stop_mock_server(8080) finalize() os.chdir(self.oldCwd) removePath(self.cwd)
def testNonExisting(self): removePath(self.repodir_local) s = self.statusGitScm() self.assertEqual(s.flags, {ScmTaint.error}) self.assertTrue(s.error)
def testEmpty(self): removePath(self.repodir_local) s = GitScm({ 'scm' : "git", 'url' : self.repodir, 'recipe' : "foo.yaml#0" }) self.assertEqual(s.status(self.repodir_local, '')[0], 'empty')
def testEmpty(self): removePath(self.repodir_local) s = self.createSvnScm() self.assertEqual(s.status(self.repodir_local)[0], 'empty')
def qtProjectGenerator(package, argv, extra): parser = argparse.ArgumentParser(prog="bob project qt-project", description='Generate QTCreator Project Files') parser.add_argument('-u', '--update', default=False, action='store_true', help="Update project files (.files, .includes, .config)") parser.add_argument('--buildCfg', action='append', default=[], type=lambda a: a.split("::"), help="Adds a new buildconfiguration. Format: <Name>::<flags>") parser.add_argument('--overwrite', action='store_true', help="Remove destination folder before generating.") parser.add_argument('--destination', metavar="DEST", help="Destination of project files") parser.add_argument('--name', metavar="NAME", help="Name of project. Default is complete_path_to_package") parser.add_argument('-I', dest="additional_includes", default=[], action='append', help="Additional include directories. (added recursive starting from this directory).") parser.add_argument('-f', '--filter', metavar="Filter", help="File filter. A regex for matching additional files.") parser.add_argument('--exclude', default=[], action='append', dest="excludes", help="Package filter. A regex for excluding packages in QTCreator.") parser.add_argument('--include', default=[], action='append', dest="include", help="Include package filter. A regex for including only the specified packages in QTCreator.") parser.add_argument('--kit', help="Kit to use for this project") parser.add_argument('-S', dest="start_includes", default=[], action='append', help="Additional include directories, will be placed at the beginning of the include list.") parser.add_argument('-C', dest="config_defs", default=[], action='append', help="Add line to .config file. Can be used to specify preprocessor defines used by the QTCreator.") args = parser.parse_args(argv) extra = " ".join(quote(e) for e in extra) destination = args.destination projectName = args.name project = "/".join(package.getStack()) dirs = [] excludes = [] if args.excludes: for e in args.excludes: excludes.append(re.compile(e)) if args.include: for e in args.include: excludes.append(re.compile(r"^((?!"+e+").)*$")) getCheckOutDirs(package, excludes, dirs) if not projectName: # use package name for project name projectName = package.getName() if not destination: # use package name for project directory destination = os.path.join(os.getcwd(), "projects", projectName) destination = destination.replace(':', '_') if args.overwrite: removePath(destination) if not os.path.exists(destination): os.makedirs(destination) # Path structure: # destination # -> files # -> project dir # -> symlinks # create a 'flat' source tree symlinkDir = os.path.join(destination, projectName) if not args.update: if os.path.exists(symlinkDir): shutil.rmtree(symlinkDir) os.makedirs(symlinkDir) # regex for all source / header files source = re.compile(r".*\.[ch](pp)?$") include = re.compile(r".*\.[h](pp)?$") cmake = re.compile(r".*\.cmake$") if args.filter: additionalFiles = re.compile(args.filter) # lists for storing all found sources files / include directories / defines sList = [] hList = [] sIncList = [] cList = [] # now go through all checkout dirs to find all header / include files for name,path in OrderedDict(sorted(dirs, key=lambda t: t[1])).items(): newPath = os.path.join(symlinkDir, name) if not args.update: os.symlink(os.path.join(os.getcwd(), path), newPath) for root, directories, filenames in os.walk(newPath): hasInclude = False if (((os.path.sep + '.git' + os.path.sep) in root) or ((os.path.sep + '.svn' + os.path.sep) in root)): continue for filename in filenames: if source.match(filename) or cmake.match(filename) or filename == 'CMakeLists.txt': sList.append(os.path.join(os.getcwd(), os.path.join(root,filename))) if args.filter and additionalFiles.match(filename): sList.append(os.path.join(os.getcwd(), os.path.join(root,filename))) if not hasInclude and include.match(filename): hasInclude = True if hasInclude: oldPath = "" # need to recursively add all directories from the include up to cwd to get includes like # <a/b/c.h> resolved even if there is no include in 'a' relativePath = root[len(newPath):] for path in relativePath.split(os.path.sep): includePath = os.path.join(newPath, oldPath, path) if not includePath in hList: hList.append(includePath) oldPath = os.path.join(oldPath, path) for i in args.additional_includes: for e in parseArgumentLine(i): if os.path.exists(e): for root, directories, filenames in os.walk(e): hList.append(os.path.join(e,root)) # use default kit "Desktop" if no kit is given if args.kit is None: _kit = re.compile(r".*Desktop.*") else: _kit = re.compile(r""+args.kit) # compose start includes for i in args.start_includes: for e in parseArgumentLine(i): if os.path.exists(i): sIncList.append(e) # compose content of .config file (preprocessor defines) for i in args.config_defs: for e in parseArgumentLine(i): cList.append(e) id = None name = None kits = [] try: profiles = xml.etree.ElementTree.parse(os.path.join(expanduser('~'), ".config/QtProject/qtcreator/profiles.xml")).getroot() for profile in profiles: for valuemap in profile: id = None name = None for value in valuemap.findall('value'): if (value.attrib.get('key') == 'PE.Profile.Id'): id = str(value.text) if (value.attrib.get('key') == 'PE.Profile.Name'): name = str(value.text) if (id is not None) and (name is not None) and (_kit.match(name)): kits.append([name, id]) break except FileNotFoundError: # if kits are generared using sdk tool they are stored somewhere else... (/usr/share...) pass if (len(kits) == 0): if (args.kit is None): raise BuildError("No kit found!", help = "Run again with '--kit' and specify a kit or generate a Desktop kit, which is used by default.") kitName = args.kit kitId = args.kit else: if (len(kits) > 1): print(colorize("Warning: {} kits found. Using '{}'.".format(len(kits), str(kits[0][0])), "33")) kitName = kits[0][0] kitId = kits[0][1] buildMeFile = os.path.join(destination, "buildme") # Generate the includes file. Create a temporary file first and compare it with the old one. # only use the new one if different to prevent reindexing after each build. includesFile = os.path.join(destination, projectName + ".includes") generateFile(sIncList + sorted(hList, key=lambda file: (os.path.dirname(file))), includesFile + ".new") compareAndRenameFileIfNotEqual(includesFile, includesFile + ".new") # Generate files file filesFile = os.path.join(destination, projectName + ".files") sList.append(buildMeFile) generateFile(sorted(sList, key=lambda file: (os.path.dirname(file), os.path.basename(file))), filesFile + ".new") compareAndRenameFileIfNotEqual(filesFile, filesFile + ".new") # Generate a .config file configFile = os.path.join(destination, projectName + ".config") generateFile(cList, configFile + ".new") compareAndRenameFileIfNotEqual(configFile, configFile + ".new") if not args.update: # Generate Buildme.sh buildMe = [] buildMe.append("#!/bin/sh") buildMe.append('bob dev "$@" ' + extra + ' ' + quote(project)) projectCmd = "bob project -n " + extra + " qt-creator " + quote(project) + \ " -u --destination " + quote(destination) + ' --name ' + quote(projectName) # only add arguments which are relevant for .files or .includes. All other files are only modified if not build with # update only. for i in args.additional_includes: projectCmd += " -I " + quote(i) if args.filter: projectCmd += " --filter " + quote(args.filter) if args.excludes: for e in args.excludes: projectCmd += " --exclude " + quote(e) if args.include: for e in args.include: projectCmd += "--include " + quote(e) for e in args.start_includes: projectCmd += " -S " + quote(e) for e in args.config_defs: projectCmd += " -C " + quote(e) buildMe.append(projectCmd) generateFile(buildMe, buildMeFile) os.chmod(buildMeFile, stat.S_IRWXU | stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH | stat.S_IWOTH) # Generate creator file creatorFile = os.path.join(destination, projectName + ".creator") generateFile([], creatorFile) # Generate the creator.shared file using a template and modify some settings sharedFile = os.path.join(destination, projectName + ".creator.shared") template_head = """<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE QtCreatorProject> <qtcreator> <data> <variable>ProjectExplorer.Project.ActiveTarget</variable> <value type="int">0</value> </data> <data> <variable>ProjectExplorer.Project.EditorSettings</variable> <valuemap type="QVariantMap"> <value type="bool" key="EditorConfiguration.AutoIndent">true</value> <value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value> <value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value> <valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0"> <value type="QString" key="language">Cpp</value> <valuemap type="QVariantMap" key="value"> <value type="QByteArray" key="CurrentPreferences">CppGlobal</value> </valuemap> </valuemap> <valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1"> <value type="QString" key="language">QmlJS</value> <valuemap type="QVariantMap" key="value"> <value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value> </valuemap> </valuemap> <value type="int" key="EditorConfiguration.CodeStyle.Count">2</value> <value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value> <value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value> <value type="int" key="EditorConfiguration.IndentSize">4</value> <value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value> <value type="int" key="EditorConfiguration.MarginColumn">80</value> <value type="bool" key="EditorConfiguration.MouseHiding">true</value> <value type="bool" key="EditorConfiguration.MouseNavigation">true</value> <value type="int" key="EditorConfiguration.PaddingMode">1</value> <value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value> <value type="bool" key="EditorConfiguration.ShowMargin">false</value> <value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value> <value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value> <value type="bool" key="EditorConfiguration.SpacesForTabs">true</value> <value type="int" key="EditorConfiguration.TabKeyBehavior">0</value> <value type="int" key="EditorConfiguration.TabSize">4</value> <value type="bool" key="EditorConfiguration.UseGlobal">true</value> <value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value> <value type="bool" key="EditorConfiguration.addFinalNewLine">true</value> <value type="bool" key="EditorConfiguration.cleanIndentation">true</value> <value type="bool" key="EditorConfiguration.cleanWhitespace">true</value> <value type="bool" key="EditorConfiguration.inEntireDocument">false</value> </valuemap> </data> <data> <variable>ProjectExplorer.Project.PluginSettings</variable> <valuemap type="QVariantMap"/> </data>""" template_foot = """ <data> <variable>ProjectExplorer.Project.TargetCount</variable> <value type="int">1</value> </data> <data> <variable>ProjectExplorer.Project.Updater.FileVersion</variable> <value type="int">18</value> </data> <data> <variable>Version</variable> <value type="int">18</value> </data> </qtcreator>""" # find all executables in package dir runTargets = [] magic = summonMagic() if package.getPackageStep().isValid(): packageDir = package.getPackageStep().getWorkspacePath() for root, directory, filenames in os.walk(packageDir): for filename in filenames: try: ftype = magic.from_file(os.path.join(root, filename)) if 'executable' in ftype and 'x86' in ftype: runTargets.append(RunStep(os.path.join(os.getcwd(), root), filename)) except OSError: pass with open(sharedFile, 'w') as sharedFile: sharedFile.write(template_head) sharedFile.write(' <data>\n') sharedFile.write(' <variable>ProjectExplorer.Project.Target.0</variable>\n') sharedFile.write(' <valuemap type="QVariantMap">\n') sharedFile.write(' <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">' + kitName + '</value>\n') sharedFile.write(' <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">' + kitName + '</value>\n') sharedFile.write(' <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">' + kitId + '</value>\n') sharedFile.write(' <value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>\n') sharedFile.write(' <value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>\n') sharedFile.write(' <value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>\n') addBuildSteps(sharedFile, buildMeFile, args.buildCfg) sharedFile.write(' <value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">0</value>\n') sharedFile.write(' <valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>\n') addRunSteps(sharedFile, runTargets) sharedFile.write(' </valuemap>\n') sharedFile.write(' </data>\n') sharedFile.write(template_foot)