Exemple #1
0
    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
Exemple #3
0
    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)
Exemple #5
0
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)')
Exemple #9
0
    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()
Exemple #10
0
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
Exemple #11
0
    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)
Exemple #15
0
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)
Exemple #18
0
    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)
Exemple #19
0
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
Exemple #20
0
    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)
Exemple #21
0
    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_()
Exemple #22
0
    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)
Exemple #23
0
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: