def _setHostEnv( self ): """ Set some environment variables which are used by some CMakeLists.txt / packageVar.cmake files. Note: Target-related env.variables (TARGETARCH etc.) will be temp. modified by self._switchToTargetEnv() and set back with self._switchToHostEnv(). """ hostArch = Platforms.getHostArch() hostOS = Platforms.getHostOS() clangEnv = FastScript.getEnv( 'BST_USE_CLANG' ) if clangEnv is None: try: useClang = PkgInfo.getPkgInfoContent()['BST_useClang'] except ( AssertionError, KeyError ): useClang = getConfigOption( 'BST_useClang' ) clangEnv = 'TRUE' if useClang else 'FALSE' else: useClang = True if clangEnv == 'TRUE' else False logging.debug( 'use Clang/LLVM: %s', useClang ) envSettings = { 'BST_USE_CLANG': clangEnv, 'HOSTARCH': hostArch, 'HOSTOS': hostOS, 'TARGETARCH': hostArch, 'TARGETOS': hostOS } FastScript.getEnv().update( envSettings )
def loadLibrary(name, version=''): """ Returns a handle to the given library. """ Any.requireIsTextNonEmpty(name) # if neither '.so' nor '.dll' in the name, assume it is the inner part # of the library only ext = '.dll' if Platforms.getSystemType() == 'win' else '.so' if ext in name: libName = name else: libName = computeLibName(name, version) libPath = locate(libName) logging.debug('loading %s', libPath) logging.debug('LD_LIBRARY_PATH: %s', FastScript.getEnv('LD_LIBRARY_PATH')) try: if Platforms.getSystemType() == 'win': libHandle = ctypes.WinDLL(libPath) else: libHandle = ctypes.CDLL(libPath, ctypes.RTLD_GLOBAL) except OSError as details: raise OSError(details) _setDebugLevel(libHandle) _setAssertHandler(libHandle) return libHandle
def __init__( self ): self._hostPlatform = Platforms.getHostPlatform() self._targetPlatform = self._hostPlatform self._oldCWD = os.getcwd() self._origEnv = copy.deepcopy( FastScript.getEnv() ) self._stdout = None self._stderr = None self._sourceTree = os.getcwd() self._binaryTree = self._sourceTree self._outOfTree = False self._buildDir = os.path.join( self._sourceTree, 'build', self._targetPlatform ) self._buildType = 'Release' self._crossCompiling = False self._isSetUp = False self._isConfigured = False self._isCompiled = False self._runScripts = FastScript.getEnv( 'BST_SKIP_SCRIPTS' ) != 'TRUE' self._cmakeModPath = None self._cmakeOptions = FastScript.getEnv( 'BST_CMAKE_OPTIONS' ) try: self._parallelJobs = int( FastScript.getEnv( 'BST_BUILD_JOBS' ) ) except ( KeyError, TypeError, ValueError ): self._parallelJobs = 1
def locate(libName): """ Searches within LD_LIBRARY_PATH for the given library, and in case returns the absolute path to it. If not found raises an EnvironmentError. """ Any.requireIsTextNonEmpty(libName) if Platforms.getSystemType() == 'win': envName = 'PATH' else: envName = 'LD_LIBRARY_PATH' searchPath = FastScript.getEnv(envName) Any.requireIsTextNonEmpty(searchPath) for path in searchPath.split(':'): # logging.debug( path ) libPath = os.path.join(path, libName) if os.path.exists(libPath): logging.debug('found %s', libPath) return libPath # else: # logging.debug( '%s: No such file', libPath ) raise EnvironmentError('%s not found within LD_LIBRARY_PATH' % libName)
def switchEnvironment(toPlatform): """ Modifies the environment variables to appear as if this was another operating system. This is primary used for cross-compilations. If you would like to later restore the original settings, make sure to call "origEnv = FastScript.getEnv()" before invoking this function. When you are done, you can then reset the whole environment by calling "FastScript.setEnv( origMap )". """ Any.requireIsTextNonEmpty(toPlatform) fromPlatform = Platforms.getHostPlatform() src = fromPlatform.replace('-', '') dst = toPlatform.replace('-', '') funcName = "_switchEnv_%s_to_%s" % (src, dst) if fromPlatform == toPlatform: return try: func = globals()[funcName] except KeyError: msg = "requested platform switch (%s to %s) is not supported" % \ ( fromPlatform, toPlatform ) raise NotImplementedError(msg) func() FastScript.setEnv('MAKEFILE_PLATFORM', toPlatform)
def test_proxyInstallation(self): oldcwd = os.getcwd() packageName = 'ExamplePackage' packageVersion = '1.0' category = 'Applications' projectRoot = os.path.join('.', packageName, packageVersion) output = StringIO() if Any.getDebugLevel() <= 3 else None platform = Platforms.getHostPlatform() sitPath = SIT.getPath() # build + install package FastScript.changeDirectory(projectRoot) bst = BuildSystemTools() bst.setStdOut(output) bst.setStdErr(output) bst.compile() Any.requireIsDirNonEmpty('build') Any.requireIsDirNonEmpty(os.path.join('build', platform)) Any.requireIsDirNonEmpty('examples') Any.requireIsDirNonEmpty(os.path.join('examples', platform)) for fileName in ('ThreadingExampleAtomicOperation', 'ThreadingExampleJoin', 'ThreadingExampleTraps'): Any.requireIsFileNonEmpty(os.path.join('bin', platform, fileName)) if not ProxyDir.isProxyDir(sitPath): self.skip("%s: Is not a proxy directory" % sitPath) bst.makeDocumentation() bst.proxyInstall() installRoot = os.path.join(sitPath, category, packageName, packageVersion) # check result Any.requireIsDir(installRoot) Any.requireIsDirNonEmpty(os.path.join(installRoot, 'bin', platform)) Any.requireIsDirNonEmpty(os.path.join(installRoot, 'doc/html')) Any.requireIsFileNonEmpty( os.path.join(installRoot, 'doc/html/index.html')) Any.requireIsFileNonEmpty(os.path.join(installRoot, 'pkgInfo.py')) Any.requireIsFileNonEmpty(os.path.join(installRoot, 'packageVar.cmake')) for fileName in ('ThreadingExampleAtomicOperation', 'ThreadingExampleJoin', 'ThreadingExampleTraps'): Any.requireIsFileNonEmpty( os.path.join(installRoot, 'bin', platform, fileName)) # clean-up bst.uninstall(cleanGlobalInstallation=False) bst.distclean() self.assertFalse(os.path.exists(installRoot)) FastScript.changeDirectory(oldcwd)
def normalizeOutput(string): result = string # replace possible platform names by placeholder for candidate in Platforms.getPlatformNames(): result = result.replace(candidate, '${MAKEFILE_PLATFORM}') return result
def uninstall(canonicalPath, cleanGlobalInstallation, dryRun=False): """ Delete a package from SIT, this includes: * Proxy SIT directory * Global SIT installation * BBCM *.def file * RTMaps index entry If 'cleanGlobalInstallation=True' the package will also be uninstalled from global SIT (if applicable). If False it will only be uninstalled from the proxy SIT. """ from ToolBOSCore.Platforms import Platforms from ToolBOSCore.Tools import RTMaps requireIsCanonicalPath(canonicalPath) Any.requireIsBool(dryRun) sitProxyPath = SIT.getPath() sitRootPath = SIT.getRootPath() Any.requireIsTextNonEmpty(sitProxyPath) Any.requireIsTextNonEmpty(sitRootPath) installRoot_proxy = os.path.join(sitProxyPath, canonicalPath) installRoot_root = os.path.join(sitRootPath, canonicalPath) rtmapsVersion = FastScript.getEnv('RTMAPS_VERSION') logging.info('uninstalling %s', canonicalPath) logging.info('cleaning proxy-installation') FastScript.remove(installRoot_proxy, dryRun) if cleanGlobalInstallation: logging.info('cleaning global-installation') FastScript.remove(installRoot_root, dryRun) if rtmapsVersion: Any.requireIsTextNonEmpty(rtmapsVersion) hostPlatform = Platforms.getHostPlatform() symlink_relHGR = RTMaps.getIndexFilePath_relHGR( canonicalPath, rtmapsVersion, hostPlatform) Any.requireIsTextNonEmpty(symlink_relHGR) symlinkPath = os.path.join(sitProxyPath, symlink_relHGR) Any.requireIsTextNonEmpty(symlinkPath) FastScript.remove(symlinkPath, dryRun) else: logging.debug( 'skipped searching for RTMaps index symlink (RTMaps not sourced)')
def setTargetPlatform( self, platform ): Any.requireIsTextNonEmpty( platform ) Any.requireMsg( platform in Platforms.getPlatformNames(), "Unknown platform: %s" % platform ) if platform != self._hostPlatform: self._crossCompiling = True self._targetPlatform = platform logging.info( 'targetPlatform=%s' % self._targetPlatform ) self._detectBuildDir()
def getNativeCompilationList(): """ Returns the value of the ToolBOS config option 'BST_defaultPlatforms_native', defaulting to the current host platform if not overwritten by the user. """ platformList = list( ToolBOSSettings.getConfigOption('BST_defaultPlatforms_native')) if not platformList: platformList = [Platforms.getHostPlatform()] platformList.sort() return platformList
def test_helpText(self): tcRoot = FastScript.getEnv('TOOLBOSCORE_ROOT') hostPlatform = Platforms.getHostPlatform() binDirNoArch = os.path.join(tcRoot, 'bin') Any.requireIsDirNonEmpty(binDirNoArch) pyScripts = glob.glob(os.path.join(binDirNoArch, '*.py')) shScripts = glob.glob(os.path.join(binDirNoArch, '*.sh')) executables = glob.glob(os.path.join(binDirNoArch, hostPlatform, '*')) # unset VERBOSE and BST_BUILD_JOBS to make output comparable origEnv = FastScript.getEnv() FastScript.unsetEnv('VERBOSE') FastScript.unsetEnv('BST_BUILD_JOBS') for program in pyScripts + shScripts + executables: basename = os.path.basename(program) Any.requireIsTextNonEmpty(basename) logging.info('processing %s', basename) output = StringIO() cmd = '%s --help' % program fileName = os.path.join('ReferenceData', '%s.txt' % basename) Any.requireIsTextNonEmpty(cmd) Any.requireIsTextNonEmpty(fileName) FastScript.execProgram(cmd, stdout=output, stderr=output) expected = FastScript.getFileContent(fileName) result = normalizeOutput(output.getvalue()) Any.isTextNonEmpty(expected) Any.isTextNonEmpty(result) if result != expected: logging.info('differences in output of %s:', basename) logging.info('<result>\n%s', result) logging.info('</result>') logging.info('<expected>\n%s', expected) logging.info('</expected>') self.fail('help text of %s differs' % basename) FastScript.setEnv(origEnv)
def test_wineMSVC( self ): oldcwd = os.getcwd() tmpDir = tempfile.mkdtemp( prefix='test-' ) packageName = 'HelloWorld' packageVersion = '42.0' projectRoot = os.path.join( tmpDir, packageName, packageVersion ) output = StringIO() if Any.getDebugLevel() <= 3 else None hostPlatform = Platforms.getHostPlatform() targetPlatform = 'windows-amd64-vs2012' if targetPlatform not in CrossCompilation.getSwitchEnvironmentList( hostPlatform ): self.skipTest( '%s to %s cross-compilation not supported' % \ ( hostPlatform, targetPlatform ) ) # create package on-the-fly PackageCreator_C_Library( packageName, packageVersion, outputDir=tmpDir ).run() # build package FastScript.changeDirectory( projectRoot ) bst = BuildSystemTools() bst.setStdOut( output ) bst.setStdErr( output ) bst.setTargetPlatform( targetPlatform ) bst.compile() # check result Any.requireIsDirNonEmpty( os.path.join( projectRoot, 'build' ) ) Any.requireIsDirNonEmpty( os.path.join( projectRoot, 'build', targetPlatform ) ) Any.requireIsDirNonEmpty( os.path.join( projectRoot, 'lib' ) ) Any.requireIsDirNonEmpty( os.path.join( projectRoot, 'lib', targetPlatform ) ) Any.requireIsDirNonEmpty( os.path.join( projectRoot, 'src' ) ) Any.requireIsDirNonEmpty( os.path.join( projectRoot, 'test' ) ) Any.requireIsDirNonEmpty( os.path.join( projectRoot, 'test', targetPlatform ) ) # clean-up bst.distclean() self.assertFalse( os.path.exists( os.path.join( projectRoot, 'build' ) ) ) self.assertFalse( os.path.exists( os.path.join( projectRoot, 'lib' ) ) ) FastScript.remove( tmpDir ) FastScript.changeDirectory( oldcwd )
def computeLibName(name, version=''): """ Returns the proper name of a shared library, depending on the platform, f.i. with '.so' or '.dll' extension and the like. """ Any.requireIsTextNonEmpty(name) Any.requireIsText(version) if version: postfix = '.' + version else: postfix = '' if Platforms.getSystemType() == 'win': return '%s.dll%s' % (name, postfix) else: return 'lib%s.so%s' % (name, postfix)
def test_serializeUtility_convert(self): tcRoot = FastScript.getEnv('TOOLBOSCORE_ROOT') platform = Platforms.getHostPlatform() exe = os.path.join(tcRoot, 'bin', platform, 'ConvertSerializedData') inFile = 'BBDMArrayBlockF32-binary.ser' outFile = tempfile.mkstemp(prefix='test-')[1] cmd = '%s -i %s -f Ascii -o %s' % (exe, inFile, outFile) tmp = StringIO() try: FastScript.execProgram(cmd, stdout=tmp, stderr=tmp) except OSError: raise RuntimeError("Please compile this package first!") output = tmp.getvalue() # typical error could be: # # [... SerializeUtility.c:809 Error] Could not load data library # 'BBDMArrayBlockF32' (libBBDMArrayBlockF32.so): Reason # 'libBBDMArrayBlockF32.so: cannot open shared object file: # No such file or directory' # # [... SerializeUtility.c:653 Error] The input file # 'test/miscInputFiles/BBDMArrayBlockF32-binary.ser' # does not contain valid data # check result self.assertTrue(output.find('libBBDMArrayBlockF32.so') == -1) self.assertTrue(output.find('Could not load data library') == -1) self.assertTrue(output.find('No such file or directory') == -1) self.assertTrue( output.find('Aborting serialization function') > 0) # at EOF self.assertTrue(output.find('does not contain valid data') == -1) Any.requireIsFileNonEmpty(outFile) content = FastScript.getFileContent(outFile) # there must be 3x "HRIS" in the ASCII representation of this file matches = re.findall('HRIS', content) self.assertTrue(len(matches) == 3) # clean-up FastScript.remove(outFile)
def getDefaultDistcleanPatterns(): """ Returns the list of filename patterns to be used by the distclean routine. """ patternList = [] for platform in Platforms.getPlatformNames(): patternList.append( os.path.join( 'bin', platform ) ) patternList.append( os.path.join( 'examples', platform ) ) patternList.append( os.path.join( 'lib', platform ) ) patternList.append( os.path.join( 'obj', platform ) ) patternList.append( os.path.join( 'src', platform ) ) patternList.append( os.path.join( 'test', platform ) ) patternList.append( os.path.join( 'wrapper', platform ) ) patternList.extend( [ # big directories first 'sources', 'build', '.tmp-install*', 'precompiled/package', # compilation files 'makeDepend', 'ui_*h', 'qrc_*.cpp', 'moc_*.cpp', 'qt/*.h', 'qt/*.cpp', 'qt/moc_*cpp', '.*ui.md5', 'wrapper/*.mex*', # editor backup files '*~', '*.bak', # temp. files left from previous program executions '*.pyc', '*.backup.zip', 'LibIndex', # install procedure files 'install/??shSrc', 'bin/??shSrc', 'examples/??shSrc', 'test/??shSrc', 'install/CmdSrc.bat', 'doc/autoDoxyfile', 'doc/doxygen*', 'doc/*.tag', 'doc/html', 'matdoc.log', 'install/LinkAllLibraries', 'install/MD5SUMS', 'install/*.tar.gz', 'install/*.deb', 'install/*.tar.bz2', 'install/packageVar.cmake', 'install/pkgInfo.py', 'install/*.def', 'install/debControl.txt', 'install/HRI_GLOBAL_ROOT', '[A-Za-z]*[A-Za-z]PHP', '[A-Za-z]*[A-Za-z]PY', 'run*([^.])', 'src/.*.h.md5', 'build4all.cfg', 'run' ] ) return patternList
def test_serializeUtility_createSerializedData(self): random.seed(self) tcRoot = FastScript.getEnv('TOOLBOSCORE_ROOT') platform = Platforms.getHostPlatform() exe = os.path.join(tcRoot, 'bin', platform, 'CreateSerializedData') count = random.randint(3, 20) outFile = tempfile.mkstemp(prefix='test-')[1] cmd = '%s -t BBDMArrayBlockF32 -c %d -r -f Ascii -o %s' % (exe, count, outFile) tmp = StringIO() try: FastScript.execProgram(cmd, stdout=tmp, stderr=tmp) except OSError: raise RuntimeError("Please compile this package first!") output = tmp.getvalue() # typical error could be: # # [... SerializeUtility.c:809 Error] Could not load data library # 'BBDMBaseF32' (libBBDMBaseF32.so): Reason 'libBBDMBaseF32.so: # cannot open shared object file: No such file or directory' # # SerializeUtility.c:1083 BBDMBaseF32: unsupported datatype # (BBDMBaseF32_new() not found) # check result self.assertTrue(output.find('libBBDMArrayBlockF32.so') == -1) self.assertTrue(output.find('cannot open shared object file') == -1) self.assertTrue(output.find('No such file or directory') == -1) self.assertTrue(output.find('unsupported datatype') == -1) Any.requireIsFileNonEmpty(outFile) content = FastScript.getFileContent(outFile) # we must find "count"-times the keyword "HRIS" inside the file matches = re.findall('HRIS', content) self.assertTrue(len(matches) == count) # clean-up FastScript.remove(outFile)
def test_serializeUtility_printSerializedData(self): tcRoot = FastScript.getEnv('TOOLBOSCORE_ROOT') platform = Platforms.getHostPlatform() exe = os.path.join(tcRoot, 'bin', platform, 'PrintSerializedData') inFile = os.path.join('BBDMArrayBlockF32-binary.ser') outFile = os.path.join('BBDMArrayBlockF32-ascii.ser') cmd = '%s -f %s' % (exe, inFile) tmp = StringIO() Any.requireIsFileNonEmpty(inFile) Any.requireIsFileNonEmpty(outFile) try: # do not redirect stderr to file, otherwise we can't compare with # the expected output (ANY_LOG timestamps would differ), there is # at least stderr-message "Aborting serialization function" at EOF FastScript.execProgram(cmd, stdout=tmp) except OSError: raise RuntimeError("Please compile this package first!") expected = FastScript.getFileContent(outFile) output = tmp.getvalue() # typical error could be: # # [... SerializeUtility.c:809 Error] Could not load data library # 'BBDMArrayBlockF32' (libBBDMArrayBlockF32.so): Reason # 'libBBDMArrayBlockF32.so: cannot open shared object file: # No such file or directory' # # [... SerializeUtility.c:591 Error] The input file # 'test/miscInputFiles/BBDMArrayBlockF32-binary.ser' does not # contain valid data # check result self.assertTrue(output.find('libBBDMArrayBlockF32.so') == -1) self.assertTrue(output.find('cannot open shared object file') == -1) self.assertTrue(output.find('No such file or directory') == -1) self.assertTrue(output.find('does not contain valid data') == -1) self.assertEqual(expected, output)
def test_nativeCompilation(self): oldcwd = os.getcwd() tmpDir = tempfile.mkdtemp(prefix='test-') packageName = 'HelloWorld' packageVersion = '42.0' projectRoot = os.path.join(tmpDir, packageName, packageVersion) output = StringIO() if Any.getDebugLevel() <= 3 else None platform = Platforms.getHostPlatform() # create package on-the-fly PackageCreator_C_Library(packageName, packageVersion, outputDir=tmpDir).run() # build package FastScript.changeDirectory(projectRoot) bst = BuildSystemTools() bst.setStdOut(output) bst.setStdErr(output) bst.compile() # check result Any.requireIsDirNonEmpty(os.path.join(projectRoot, 'build')) Any.requireIsDirNonEmpty(os.path.join(projectRoot, 'build', platform)) Any.requireIsDirNonEmpty(os.path.join(projectRoot, 'lib')) Any.requireIsDirNonEmpty(os.path.join(projectRoot, 'lib', platform)) Any.requireIsDirNonEmpty(os.path.join(projectRoot, 'src')) Any.requireIsDirNonEmpty(os.path.join(projectRoot, 'test')) Any.requireIsDirNonEmpty(os.path.join(projectRoot, 'test', platform)) # clean-up bst.distclean() self.assertFalse(os.path.exists(os.path.join(projectRoot, 'build'))) self.assertFalse(os.path.exists(os.path.join(projectRoot, 'lib'))) FastScript.remove(tmpDir) FastScript.changeDirectory(oldcwd)
def getSwitchEnvironmentList(fromPlatform=None): """ This function can be used to fetch a list of platforms to which the <fromPlatform> can be switched to. Example: getSwitchEnvironmentList( 'lucid64' ) According to the returned list it is possible to switchEnvironment() from 'precise64' to 'windows-amd64-vs2012', but not to 'vxworks'. If <fromPlatform> is None, all possible cross-compilation platforms are returned. """ if fromPlatform is None: xcmpHosts = ToolBOSSettings.getConfigOption('BST_crossCompileHosts') # only return those which are not None result = filter(bool, xcmpHosts.keys()) result.sort() return result Any.requireIsTextNonEmpty(fromPlatform) if fromPlatform not in Platforms.getPlatformNames(): raise ValueError('%s: unsupported platform name' % fromPlatform) # get list of all functions in this module, then filter it by name # (function-name convention allows us to filter-out the supported target # platforms) allSymbols = globals().keys() criteria = lambda s: s.startswith('_switchEnv_') candidates = filter(criteria, allSymbols) regexp = re.compile('^_switchEnv_%s_to_(.*)$' % fromPlatform) resultList = [] for candidate in candidates: tmp = regexp.search(candidate) if tmp is not None: targetPlatform = tmp.group(1) Any.requireIsTextNonEmpty(targetPlatform) # At the time of writing the Windows-platforms are named # windows-i386-msvc and windows-amd64-msvc. However names with # dashes can't be used as function names thus the above # candidates don't contain such dashes. # # As a hack I'm replacing such well-known names here by hand. # Better solutions are highly appreciated. Alternatively the # Windows platforms could be renamed, e.g. "win32". # if targetPlatform == 'windowsi386vs2010': targetPlatform = 'windows-i386-vs2010' elif targetPlatform == 'windowsamd64vs2010': targetPlatform = 'windows-amd64-vs2010' elif targetPlatform == 'windowsi386vs2012': targetPlatform = 'windows-i386-vs2012' elif targetPlatform == 'windowsamd64vs2012': targetPlatform = 'windows-amd64-vs2012' elif targetPlatform == 'windowsi386vs2017': targetPlatform = 'windows-i386-vs2017' elif targetPlatform == 'windowsamd64vs2017': targetPlatform = 'windows-amd64-vs2017' resultList.append(targetPlatform) resultList.sort() return resultList
def __init__(self, projectRoot=None, pkgInfoContent=None): from ToolBOSCore.SoftwareQuality.CheckRoutine import sqLevelDefault if not projectRoot: projectRoot = ProjectProperties.detectTopLevelDir() if not projectRoot: raise AssertionError('unknown project root location') Any.requireIsDir(projectRoot) # general meta-info self.canonicalPath = None self.cmakelistsContent = None self.hasCMakeLists = None self.installRoot = None self.isDeprecated = None self.packageCategory = None self.packageName = None self.packageVersion = None # e.g. "2.0" self.packageVersionRaw = None # e.g. "2.0-rc3" (corresponds to dir.name) self.patchlevel = None # e.g. 42, may correspond to SVN rev. self.topLevelDir = None self.versionTokens = None # e.g. ( "2", "0", "123" ) # dependencies self.buildDependencies = [] # direct build-deps self.buildDependsArch = {} self.dependencies = [] # direct deps self.dependsArch = {} self.inheritedProjects = [] # deps. + recommend. (used in BashSrc) self.recommendations = [] self.suggestions = [] # values extracted from install/user{Install,Src}.php / pkgInfo.py self.pkgInfoContent = pkgInfoContent self.docTool = None self.install = [] self.installHooks = {} self.installMatching = [] self.installSymlinks = [] self.installGroup = None self.installUmask = None self.installMode = 'incremental' self.linkAllLibraries = False self.usePatchlevels = False self.userSrcContent = None self.userSrcEnv = () self.userSrcAlias = () self.userSrcBashCode = () self.userSrcCmdCode = () self.sqLevel = sqLevelDefault self.sqOptInRules = [] self.sqOptOutRules = [] self.sqOptInDirs = [] self.sqOptOutDirs = [] self.sqOptInFiles = [] self.sqOptOutFiles = [] self.sqCheckExe = None self.sqComments = {} self.useClang = None # revision control system self.gitBranch = None self.gitBranchForCIA = None self.gitFound = None self.gitCommitIdLong = None self.gitCommitIdShort = None self.gitOrigin = None self.gitOriginForCIA = None self.gitRelPath = None self.gitRepositoryRoot = None self.svnFound = None self.svnRelPath = None self.svnRevision = None self.svnRepositoryURL = None self.svnRepositoryRoot = None self.svnRevisionForCIA = None self.vcsBranch = None self.vcsFound = None self.vcsURL = None self.vcsRelPath = None self.vcsRevision = None self.vcsRoot = None # current user (likely the maintainer when working on source tree) self.userAccount = None self.userName = None # maintainer (filesystem owner when accessing SIT packages) self.maintainerAccount = None self.maintainerName = None cmakePath = os.path.join(projectRoot, 'CMakeLists.txt') self.hasCMakeLists = os.path.exists(cmakePath) self.topLevelDir = projectRoot self.packageName = ProjectProperties.getPackageName(self.topLevelDir) self.packageVersion = ProjectProperties.getPackageVersion( self.topLevelDir, False) self.packageVersionRaw = ProjectProperties.getPackageVersion( self.topLevelDir, True) self.versionTokens = ProjectProperties.splitVersion( self.packageVersionRaw) Any.requireIsTextNonEmpty(self.packageName) Any.requireIsTextNonEmpty(self.packageVersion) # compute typical directory names (may not be present!) hostPlatform = Platforms.getHostPlatform() Any.requireIsTextNonEmpty(hostPlatform) self.binDir = os.path.join(self.topLevelDir, 'bin') self.binDirArch = os.path.join(self.topLevelDir, 'bin', hostPlatform) self.examplesDir = os.path.join(self.topLevelDir, 'examples') self.examplesDirArch = os.path.join(self.topLevelDir, 'examples', hostPlatform) self.includeDir = os.path.join(self.topLevelDir, 'include') self.installDir = os.path.join(self.topLevelDir, 'install') self.libDir = os.path.join(self.topLevelDir, 'lib') self.libDirArch = os.path.join(self.topLevelDir, 'lib', hostPlatform) self.srcDir = os.path.join(self.topLevelDir, 'src') self.testDir = os.path.join(self.topLevelDir, 'test') self.testDirArch = os.path.join(self.topLevelDir, 'test', hostPlatform) if self.hasCMakeLists: # source tree, C/C++ package self.cmakelistsContent = FastScript.getFileContent(cmakePath) if self.cmakelistsContent: self.packageCategory = CMakeLists.getCategory( self.cmakelistsContent) else: logging.debug('skipping empty %s', cmakePath) else: # source tree w/o CMakeLists.txt, or package installed in SIT self.cmakelistsContent = None try: self.packageCategory = ProjectProperties.getPackageCategoryFromPath( projectRoot) except AssertionError: raise AssertionError('unable to detect package category') if self.packageCategory: self.canonicalPath = os.path.join(self.packageCategory, self.packageName, self.packageVersion) self._retrieveCurrentUser() # Any.requireIsTextNonEmpty( self.maintainerAccount ) # might be empty # Any.requireIsTextNonEmpty( self.maintainerName ) # might be empty Any.requireIsTextNonEmpty(self.packageName) Any.requireIsTextNonEmpty(self.packageVersion) Any.requireIsTextNonEmpty(self.packageVersionRaw) Any.requireIsTextNonEmpty(self.topLevelDir) Any.requireIsTextNonEmpty(self.userAccount) Any.requireIsTextNonEmpty(self.userName)
def main( self ): self.app = QApplication( [] ) self.app.setStyle( 'fusion' ) self.window = QMainWindow() self.menuBar = MenuBar.MenuBar( self.window ) self.mainLayout = QGridLayout() self.mainWidget = QWidget() self.multiTermWidget = TerminalWidget.MultiTermWidget() self.optionsWidget = BuildOptionsWidget.BuildOptionsWidget() self.controlsLayout = QHBoxLayout() self.controlsWidget = QWidget() self.metaInfo = MetaInfoWidget.MetaInfoWidget( self.model, self.controlsWidget ) self.console = ConsoleWidget.ConsoleWidget( self.controlsWidget ) self.taskButtons = TaskButtonsWidget.TaskButtonsWidget() self.platformCBs_natLayout = QVBoxLayout() self.platformCBs_natWidget = QGroupBox( 'build natively on' ) self.platformCBs_xcmpLayout = QVBoxLayout() self.platformCBs_xcmpWidget = QGroupBox( 'cross-compile for' ) self.rightPaneLayout = QVBoxLayout() self.rightPaneWidget = QWidget() self.runningProcesses = 0 self._seqTasksRun.connect( self._onSeqTasksRun ) self._seqTasksFinished.connect( self._onSeqTasksFinished ) # create an always existing terminal for localhost commands terminal = TerminalWidget.TerminalWidget( True, parent=self.multiTermWidget ) terminal.setToolTip( 'localhost' ) terminal.setWindowTitle('localhost') self.terminals[ 'localhost' ] = terminal self.multiTermWidget.addTerminal( terminal ) BST_localPaths = tuple( ToolBOSConf.getConfigOption( 'BST_localPaths' ) ) localHostname = socket.gethostname() sshPossible = SSH.guessRemoteAccessIsPossible() sshToolTip = 'Remote compilation not possible as SSH authorized keys are not configured' onLocaldiskToolTip = 'Remote compilation not possible as project is on local disc' projectOnLocaldisk = self.projectRoot.startswith( BST_localPaths ) remoteCompilation = sshPossible and not projectOnLocaldisk xcmpPlatforms = [] crossCompileHosts = self._toolBOSConf.getConfigOption( 'BST_crossCompileHosts' ) Any.requireIsDictNonEmpty( crossCompileHosts ) for platformName, compileHost in crossCompileHosts.items(): if compileHost: xcmpPlatforms.append( platformName ) xcmpPlatforms.sort() # platform selection in right pane, # create terminals for all other platforms (hide disabled ones) nativePlatforms = Platforms.getPlatformNames() defaultNative = CrossCompilation.getNativeCompilationList() defaultXcmp = CrossCompilation.getCrossCompilationList() for platform in nativePlatforms: checkbox = QCheckBox( platform ) checkbox.setChecked( platform in defaultNative ) checkbox.stateChanged.connect( self._onPlatformSelectionChange ) compileHost = CrossCompilation.getNativeCompileHost( platform ) natHost = 'Natively compile for "%s" on "%s"' % (platform, compileHost) checkbox.setToolTip( natHost ) self.platformCBs_nat[ platform ] = checkbox self.platformCBs_natLayout.addWidget( checkbox ) if remoteCompilation or compileHost == localHostname: checkbox.setEnabled( True ) else: checkbox.setEnabled( False ) checkbox.setChecked( False ) if projectOnLocaldisk: checkbox.setToolTip( onLocaldiskToolTip ) elif not sshPossible: checkbox.setToolTip( sshToolTip ) try: compileHost = CrossCompilation.getNativeCompileHost( platform ) if compileHost: logging.debug( 'native compile-host for platform=%s: %s', platform, compileHost ) fullPlatformString = Platforms.getFullPlatformString( platform ) infoText = 'Console output for %s (%s)' % ( platform, fullPlatformString ) terminal = TerminalWidget.TerminalWidget( False, parent=self.multiTermWidget ) terminal.setHostname( compileHost ) terminal.setToolTip( infoText ) terminal.setWindowTitle( infoText ) terminal.isNative = True terminal.hostChanged.connect( functools.partial( self._onHostChange, terminal ) ) terminal.closeRequest.connect( functools.partial( self._closeTerminal, terminal, checkbox ) ) self.terminals[ 'nativ_' + platform ] = terminal else: logging.debug( 'no native compile-host for platform=%s', platform ) checkbox.setEnabled( False ) checkbox.hide() # skip non-working platforms except KeyError: logging.error( "No native compile-host for platform=%s", platform ) return False for platform in xcmpPlatforms: checkbox = QCheckBox( platform ) compileHost = CrossCompilation.getCrossCompileHost(platform) xcmp = 'Cross-compile for "%s" on "%s"' % ( platform, compileHost ) checkbox.setToolTip( xcmp ) checkbox.setChecked( platform in defaultXcmp ) checkbox.stateChanged.connect( self._onPlatformSelectionChange ) self.platformCBs_xcmp[ platform ] = checkbox self.platformCBs_xcmpLayout.addWidget( checkbox ) if remoteCompilation or compileHost == localHostname: checkbox.setEnabled( True ) else: checkbox.setEnabled( False ) checkbox.setChecked( False ) if projectOnLocaldisk: checkbox.setToolTip( onLocaldiskToolTip ) elif not sshPossible: checkbox.setToolTip( sshToolTip ) try: compileHost = CrossCompilation.getCrossCompileHost( platform ) if compileHost: logging.debug( 'cross-compile host for platform=%s: %s', platform, compileHost ) fullPlatformString = Platforms.getFullPlatformString(platform) infoText = 'Console output for %s (%s)' % ( platform, fullPlatformString ) terminal = TerminalWidget.TerminalWidget( False, parent=self.multiTermWidget ) terminal.setHostname( compileHost ) terminal.setToolTip( infoText ) terminal.setWindowTitle(infoText) terminal.isNative = False terminal.hostChanged.connect( functools.partial( self._onHostChange, terminal ) ) terminal.closeRequest.connect( functools.partial( self._closeTerminal, terminal, checkbox ) ) self.terminals[ 'xcomp_' + platform ] = terminal else: logging.debug( 'no cross-compile host for platform=%s', platform ) checkbox.setEnabled( False ) checkbox.hide() # skip non-working platforms except KeyError: logging.error( "No cross-compile host for platform=%s", platform ) return False self.terminals[ 'xcomp_' + platform ] = terminal # do this once to get initial grid configuration right # (localhost + platform terminals) self._onPlatformSelectionChange() self.externalTools = ExternalToolsWidget.ExternalToolsWidget( self.model, self.window ) self.model.updatesAvailable.connect( self.externalTools.showUpdateIndicator ) # build options in right pane self.rightPaneLayout.setContentsMargins( 0, 0, 0, 0 ) self.platformCBs_natWidget.setLayout( self.platformCBs_natLayout ) self.platformCBs_xcmpWidget.setLayout( self.platformCBs_xcmpLayout ) self.rightPaneWidget.setLayout( self.rightPaneLayout ) self.rightPaneLayout.addWidget( self.externalTools ) self.rightPaneLayout.addWidget( self.platformCBs_natWidget ) self.rightPaneLayout.addWidget( self.platformCBs_xcmpWidget ) self.rightPaneLayout.addWidget( self.optionsWidget ) self.console.localCommand.connect( self._onLocalShellInput ) self.console.remoteCommand.connect( self._onRemoteShellInput ) self.controlsLayout.addWidget( self.metaInfo ) self.controlsLayout.addWidget( self.console ) # self.terminalWidget.setLayout( self.terminalLayout ) self.controlsWidget.setLayout( self.controlsLayout ) self.controlsLayout.setContentsMargins( 0, 0, 0, 0 ) self.taskButtons.clean.connect( self.clean ) self.taskButtons.build.connect( self.build ) self.taskButtons.proxyInstall.connect( self.proxyInstall ) self.taskButtons.globalInstall.connect(self.globalInstall) self.taskButtons.test.connect( self.test ) self.taskButtons.quit.connect( self.quit ) self.menuBar.clean.connect( self.clean ) self.menuBar.build.connect( self.build ) self.menuBar.proxyInstall.connect( self.proxyInstall ) self.menuBar.globalInstall.connect(self.globalInstall) self.menuBar.test.connect( self.test ) try: Any.requireIsDir( self.projectRoot ) FastScript.changeDirectory( self.projectRoot ) BuildSystemTools.requireTopLevelDir() self.openPackage( self.projectRoot ) except ( AssertionError, OSError, RuntimeError ): self.projectRoot = None self.taskButtons.setEnabled( False ) # main window configuration self.mainLayout.setColumnStretch( 0, 5 ) self.mainLayout.addWidget( self.multiTermWidget, 0, 0 ) self.mainLayout.addWidget( self.rightPaneWidget, 0, 1 ) self.mainLayout.addWidget( self.controlsWidget, 1, 0 ) self.mainLayout.addWidget( self.taskButtons, 1, 1 ) self.mainWidget.setLayout( self.mainLayout ) screen = QDesktopWidget().availableGeometry() self.window.setWindowIcon( IconProvider.getIcon( 'ToolBOS' ) ) self.window.setWindowTitle( 'BST.py (zen build mode)' ) self.window.setMenuBar( self.menuBar ) self.window.setCentralWidget( self.mainWidget ) self.window.resize( screen.width() / 5 * 4, screen.height() / 5 * 4 ) self.window.move( screen.center() - self.window.rect().center() ) self.window.show() self.menuBar.openPackage.connect( self.openPackage ) self.menuBar.quit.connect( self.quit ) if not self.projectRoot: self.menuBar.fileOpen() self.app.aboutToQuit.connect( self.quit ) return self.app.exec_()
def __init__(self, filepath, isCPlusPlus, langStd, verbose=False, includepaths=None, defines=None, args=None): """ Creates a new CParser instance. The file is indexed at constructor time. :param filepath: the file to parse :param verbose: whether or not to print diagnostic information during parsing. :param includepaths: a list of include paths. All the basic include paths must be specified, including at least: - the most basic include path, on unix usually /usr/include - the clang standard library include path. Distribution and clang version dependent. On Ubuntu Precise 64 with clang 3.4 this is /usr/lib/clang/3.4/include For C++, the C++ include paths are also required. On Precise 64 these are: - /usr/include/c++/4.6/ - /usr/include/c++/4.6/x86_64-linux-gnu/ :param args: extra compiler flags """ Any.requireIsFileNonEmpty(filepath) includepaths = includepaths or [] systemIncludePaths = self._getSystemIncludePaths() defines = defines or [] self.langStd = langStd self.isCPlusPlus = isCPlusPlus self.verbose = verbose try: self._index = cidx.Index.create() except cidx.LibclangError: hostPlatform = Platforms.getHostPlatform() Any.requireIsTextNonEmpty(hostPlatform) libs = ToolBOSConf.getConfigOption('clang_lib') Any.requireIsDictNonEmpty(libs) try: libPath = libs[hostPlatform] except KeyError: logging.error('unsupported platform: %s', hostPlatform) return Any.requireIsFileNonEmpty(libPath) cidx.Config.set_library_file(libPath) self._index = cidx.Index.create() self.filepath = filepath # build a list of include directory compile flags to pass to the parse method of the index. argsIncludeDirs = ["-I{}".format(d) for d in systemIncludePaths] completeArgs = argsIncludeDirs + (args or []) self.args = completeArgs translationUnit = self._index.parse( filepath, options=cidx.TranslationUnit.PARSE_DETAILED_PROCESSING_RECORD, args=completeArgs) self.translationUnit = translationUnit # call super with the translation unit cursor super(CParser, self).__init__(translationUnit.cursor) # macros are extracted separately as the clang C bindings - and thus # the python ones - do not provide helpers to extract the info we need. self._populateMacros(filepath, list(systemIncludePaths) + list(includepaths), defines, langStd)
def createLocalProject(klocworkDir='klocwork', stdout=None, stderr=None): """ Creates a local .kwlp directory so that the analysis can be performed. @Retuns: nothing. Throws an RuntimeError in case of problems. """ Any.requireIsTextNonEmpty(klocworkDir) requireOutsideTmpDir() kwPackage = ToolBOSSettings.getConfigOption('package_klocwork') buildSpec = os.path.join(klocworkDir, 'kwinject.out') kwlpDir = os.path.join(klocworkDir, '.kwlp') # KW local project kwpsDir = os.path.join(klocworkDir, '.kwps') # KW project settings hostPlatform = Platforms.getHostPlatform() licenseServerHost = ToolBOSSettings.getConfigOption('kwLicenseServerHost') licenseServerPort = ToolBOSSettings.getConfigOption('kwLicenseServerPort') Any.requireIsTextNonEmpty(kwPackage) Any.requireIsTextNonEmpty(hostPlatform) ProcessEnv.source(kwPackage) FastScript.mkdir(klocworkDir) # ensure this exists FastScript.remove(kwlpDir) # but those should not exist FastScript.remove(kwpsDir) # but those should not exist if ProcessEnv.which('kwinject') is None: msg = '%s not installed for platform=%s' % (kwPackage, hostPlatform) raise EnvironmentError(msg) # inspect the build process to capture source files, defines, flags,... cmd = 'kwinject -o %s %s' % (buildSpec, 'BST.py -sb') FastScript.execProgram(cmd, stdout=stdout, stderr=stderr) Any.requireIsFileNonEmpty(buildSpec) # create Klocwork project directory cmd = 'kwcheck create --license-host %s --license-port %d -pd %s -sd %s %s' % \ ( licenseServerHost, licenseServerPort, kwlpDir, kwpsDir, buildSpec ) FastScript.execProgram(cmd, stdout=stdout, stderr=stderr) Any.requireIsDir(kwlpDir) Any.requireIsDir(kwpsDir) # import the build specification into project directory cmd = 'kwcheck import -pd %s %s' % (kwlpDir, buildSpec) FastScript.execProgram(cmd, stdout=stdout, stderr=stderr) # install the HIS-Subset taxonomy so that the user may select it tcRoot = FastScript.getEnv('TOOLBOSCORE_ROOT') fileName = 'HIS_Subset_MISRA_C_1.0.2.tconf' srcFile = os.path.join(tcRoot, 'external/emenda.com', fileName) dstDir = os.path.join(kwpsDir, 'servercache') dstFile = os.path.join(dstDir, fileName) Any.requireIsFileNonEmpty(srcFile) FastScript.mkdir(dstDir) FastScript.copy(srcFile, dstFile) # auto-detect source code directories (exclude some blacklisted ones) dirList = [] cwd = os.getcwd() for dirName in FastScript.getDirsInDir(): if dirName not in ('build', 'doc', 'external', 'lib'): dirList.append(os.path.join(cwd, dirName)) # create workingset values = {'dirList': dirList} creator = PackageCreator.PackageCreator('dummy', '1.0', values) srcDir = os.path.join(creator.templateDir, 'KlocworkProject') dstDir = kwlpDir creator.templatize(os.path.join(srcDir, 'workingsets.xml'), os.path.join(dstDir, 'workingsets.xml'))
def __init__(self, parent): super(QWidget, self).__init__() hostPlatform = Platforms.getHostPlatform() nativePlatforms = Platforms.getPlatformNames() xcmpPlatforms = CrossCompilation.getSwitchEnvironmentList(hostPlatform) defaultNative = CrossCompilation.getNativeCompilationList() defaultXcmp = CrossCompilation.getCrossCompilationList() self._platformCBs_nat = {} self._platformCBs_xcmp = {} self._hostnameFields_nat = {} self._hostnameFields_xcmp = {} self._settingsDialog = None self._toolBOSConf = ToolBOSConf.getGlobalToolBOSConf() # rows corresponds to number of total platforms (native + # cross-compilation), plus 2 lines for the bold headlines rows = len(nativePlatforms) + len(xcmpPlatforms) + 2 table = QTableWidget() table.setRowCount(rows) table.setColumnCount(3) table.setHorizontalHeaderLabels( ('platform name', 'enabled at start-up', 'hostname')) hHeader = table.horizontalHeader() hHeader.setSectionResizeMode(QHeaderView.Stretch) hHeader.setSectionsClickable(False) vHeader = table.verticalHeader() vHeader.setSectionResizeMode(QHeaderView.Stretch) vHeader.setSectionsClickable(False) vHeader.hide() boldFont = QFont("Helvetica", 14, QFont.Bold) nativeLabel = QTableWidgetItem('native compilation:') nativeLabel.setFont(boldFont) nativeLabel.setFlags(Qt.ItemIsEnabled) table.setSpan(0, 0, 1, 3) table.setItem(0, 0, nativeLabel) validator = QRegExpValidator(QRegExp("[a-z]{1,16}[a-z0-9\-]*")) i = 1 for platform in nativePlatforms: # column 1: platform name platformLabel = QTableWidgetItem(platform) platformLabel.setFlags(Qt.ItemIsEnabled) table.setItem(i, 0, platformLabel) # column 2: enabled at start-up? cellLayout = QHBoxLayout() cellWidget = QWidget() checkbox = QCheckBox() checkbox.setChecked(platform in defaultNative) self._platformCBs_nat[platform] = checkbox cellLayout.setAlignment(Qt.AlignCenter) cellLayout.addWidget(checkbox) cellLayout.setContentsMargins(0, 0, 0, 0) cellWidget.setLayout(cellLayout) table.setCellWidget(i, 1, cellWidget) # column 3: hostname hostname = CrossCompilation.getNativeCompileHost(platform) hostnameField = QLineEdit(hostname) hostnameField.setMaxLength(64) hostnameField.setValidator(validator) table.setCellWidget(i, 2, hostnameField) self._hostnameFields_nat[platform] = hostnameField i += 1 xcmpLabel = QTableWidgetItem('cross-compilation:') xcmpLabel.setFont(boldFont) xcmpLabel.setFlags(Qt.ItemIsEnabled) table.setSpan(i, 0, 1, 3) table.setItem(i, 0, xcmpLabel) # i = 1 # append, thus do not reset to 1 i += 1 # instead mind add. row for xcmpLabel for platform in xcmpPlatforms: # column 1: platform name platformLabel = QTableWidgetItem(platform) platformLabel.setFlags(Qt.ItemIsEnabled) table.setItem(i, 0, platformLabel) # column 2: enabled at start-up? cellLayout = QHBoxLayout() cellWidget = QWidget() checkbox = QCheckBox() checkbox.setChecked(platform in defaultXcmp) self._platformCBs_xcmp[platform] = checkbox cellLayout.setAlignment(Qt.AlignCenter) cellLayout.addWidget(checkbox) cellLayout.setContentsMargins(0, 0, 0, 0) cellWidget.setLayout(cellLayout) table.setCellWidget(i, 1, cellWidget) # column 3: hostname hostname = CrossCompilation.getCrossCompileHost(platform) hostnameField = QLineEdit(hostname) hostnameField.setMaxLength(64) hostnameField.setValidator(validator) table.setCellWidget(i, 2, hostnameField) self._hostnameFields_xcmp[platform] = hostnameField i += 1 table.resizeRowsToContents() table.resizeColumnsToContents() self._tableLayout = QVBoxLayout() self._tableLayout.addWidget(table) self._tableWidget = QGroupBox('Compile hosts') self._tableWidget.setLayout(self._tableLayout) self._restoreButton = QPushButton('&Restore defaults') self._okButton = QPushButton('&Save') self._cancelButton = QPushButton('&Cancel') self._submitLayout = QHBoxLayout() self._submitLayout.setContentsMargins(0, 0, 0, 0) self._submitLayout.addStretch(1) self._submitLayout.addWidget(self._restoreButton) self._submitLayout.addWidget(self._okButton) self._submitLayout.addWidget(self._cancelButton) self._submitWidget = QWidget() self._submitWidget.setLayout(self._submitLayout) self._dialogLayout = QVBoxLayout() self._dialogLayout.addWidget(self._tableWidget) self._dialogLayout.addWidget(self._submitWidget) dialogWidth = table.width() * 1.75 # screen.width() / 5 * 3 dialogHeight = table.height() * 1.5 #screen.height() / 5 * 3 self._settingsDialog = QDialog(parent) self._settingsDialog.setLayout(self._dialogLayout) self._settingsDialog.setWindowTitle('Preferences') self._settingsDialog.resize(dialogWidth, dialogHeight) self._settingsDialog.setModal(True) self._settingsDialog.show() self._restoreButton.pressed.connect(self._restoreDefaults) self._restoreButton.pressed.connect(self._settingsDialog.close) self._cancelButton.pressed.connect(self._settingsDialog.close) self._okButton.pressed.connect(self._saveSettings) self._okButton.pressed.connect(self._settingsDialog.close)
result = string # replace possible platform names by placeholder for candidate in Platforms.getPlatformNames(): result = result.replace(candidate, '${MAKEFILE_PLATFORM}') return result #---------------------------------------------------------------------------- # Main program #---------------------------------------------------------------------------- tcRoot = FastScript.getEnv('TOOLBOSCORE_ROOT') hostPlatform = Platforms.getHostPlatform() binDirNoArch = os.path.join(tcRoot, 'bin') Any.requireIsDirNonEmpty(binDirNoArch) # unset VERBOSE and BST_BUILD_JOBS make output comparable origEnv = FastScript.getEnv() FastScript.unsetEnv('VERBOSE') FastScript.unsetEnv('BST_BUILD_JOBS') pyScripts = glob.glob(os.path.join(binDirNoArch, '*.py')) shScripts = glob.glob(os.path.join(binDirNoArch, '*.sh')) executables = glob.glob(os.path.join(binDirNoArch, hostPlatform, '*')) for program in pyScripts + shScripts + executables: