예제 #1
0
    def testEnvModes(self):
        prepend = model.EnvironmentBinding('PYTHONPATH', 'lib', None,
                                           model.EnvironmentBinding.PREPEND)
        assert prepend.name == 'PYTHONPATH'
        assert prepend.insert == 'lib'
        assert prepend.mode is model.EnvironmentBinding.PREPEND

        self.assertEqual('/impl/lib:/usr/lib',
                         prepend.get_value('/impl', '/usr/lib'))
        self.assertEqual('/impl/lib', prepend.get_value('/impl', None))

        append = model.EnvironmentBinding('PYTHONPATH', 'lib', '/opt/lib',
                                          model.EnvironmentBinding.APPEND)
        assert append.name == 'PYTHONPATH'
        assert append.insert == 'lib'
        assert append.mode is model.EnvironmentBinding.APPEND

        self.assertEqual('/usr/lib:/impl/lib',
                         append.get_value('/impl', '/usr/lib'))
        self.assertEqual('/opt/lib:/impl/lib', append.get_value('/impl', None))

        append = model.EnvironmentBinding('PYTHONPATH', 'lib', None,
                                          model.EnvironmentBinding.REPLACE)
        assert append.name == 'PYTHONPATH'
        assert append.insert == 'lib'
        assert append.mode is model.EnvironmentBinding.REPLACE

        self.assertEqual('/impl/lib', append.get_value('/impl', '/usr/lib'))
        self.assertEqual('/impl/lib', append.get_value('/impl', None))

        assert model.EnvironmentBinding(
            'PYTHONPATH', 'lib').mode == model.EnvironmentBinding.PREPEND
예제 #2
0
def do_pkg_config_binding(binding, impl):
    if impl.id.startswith('package:'):
        return  # No bindings needed for native packages
    feed_name = impl.feed.split('/')[-1]
    path = lookup(impl)
    new_insert = correct_for_64bit(path, binding.insert)
    if new_insert != binding.insert:
        print "PKG_CONFIG_PATH dir <%s>/%s not found; using %s instead" % (
            feed_name, binding.insert, new_insert)
        binding = model.EnvironmentBinding(binding.name, new_insert,
                                           binding.default, binding.mode)

    orig_path = os.path.join(path, binding.insert)
    if os.path.isdir(orig_path):
        for pc in os.listdir(orig_path):
            stream = open(os.path.join(orig_path, pc))
            lines = stream.readlines()
            stream.close()
            for i, line in enumerate(lines):
                if '=' not in line: continue
                name, value = [x.strip() for x in line.split('=', 1)]
                if name == 'prefix' and os.path.isabs(value):
                    print "Absolute prefix=%s in %s; overriding..." % (
                        value, feed_name)
                    lines[i] = 'prefix=' + os.path.join(
                        path,
                        os.path.splitdrive(value)[1][1:]) + '\n'
                    write_pc(pc, lines)
                    break
    do_env_binding(binding, path)
예제 #3
0
    def implement(self, release, common_deps):
        impl_id = release['guid']

        impl = _Implementation(self, impl_id, None)
        impl.version = parse_version(release['version'])
        impl.released = 0
        impl.arch = release['arch']
        impl.upstream_stability = model.stability_levels[release['stability']]
        for i in common_deps:
            impl.requires.append(_Dependency(i, {}))
        impl.requires.extend(_read_requires(release.get('requires')))

        if isabs(impl_id):
            impl.local_path = impl_id
        else:
            impl.add_download_source(impl_id,
                                     release.get('size') or 0,
                                     release.get('extract'))

        for name, command in release['commands'].items():
            impl.commands[name] = _Command(name, command)

        for name, insert, mode in release.get('bindings') or []:
            binding = model.EnvironmentBinding(name, insert, mode=mode)
            impl.bindings.append(binding)

        self.implementations[impl_id] = impl
예제 #4
0
def do_build_internal(options, args):
    """build-internal"""
    # If a sandbox is being used, we're in it now.
    import getpass, socket

    buildenv = BuildEnv()
    sels = buildenv.get_selections()

    builddir = os.path.realpath('build')
    ensure_dir(buildenv.metadir)

    build_env_xml = join(buildenv.metadir, 'build-environment.xml')

    buildenv_doc = sels.toDOM()

    # Create build-environment.xml file
    root = buildenv_doc.documentElement
    info = buildenv_doc.createElementNS(XMLNS_0COMPILE, 'build-info')
    root.appendChild(info)
    info.setAttributeNS(None, 'time', time.strftime('%Y-%m-%d %H:%M').strip())
    info.setAttributeNS(None, 'host', socket.getfqdn())
    info.setAttributeNS(None, 'user', getpass.getuser())
    info.setAttributeNS(None, 'arch', '%s-%s' % (uname[0], uname[4]))
    stream = file(build_env_xml, 'w')
    buildenv_doc.writexml(stream, addindent="  ", newl="\n")
    stream.close()

    # Create local binary interface file.
    # We use the main feed for the interface as the template for the name,
    # summary, etc (note: this is not necessarily the feed that contained
    # the source code).
    master_feed = iface_cache.get_feed(buildenv.interface)
    src_impl = buildenv.chosen_impl(buildenv.interface)
    write_sample_feed(buildenv, master_feed, src_impl)

    # Check 0compile is new enough
    min_version = model.parse_version(
        src_impl.attrs.get(XMLNS_0COMPILE + ' min-version', None))
    if min_version and min_version > model.parse_version(__main__.version):
        raise SafeException(
            "%s-%s requires 0compile >= %s, but we are only version %s" %
            (master_feed.get_name(), src_impl.version,
             model.format_version(min_version), __main__.version))

    # Create the patch
    patch_file = join(buildenv.metadir, 'from-%s.patch' % src_impl.version)
    if buildenv.user_srcdir:
        with open(patch_file, 'w') as stream:
            # (ignore errors; will already be shown on stderr)
            try:
                subprocess.call(["diff", "-urN", buildenv.orig_srcdir, 'src'],
                                stdout=stream)
            except OSError as ex:
                print >> sys.stderr, "WARNING: Failed to run 'diff': ", ex
        if os.path.getsize(patch_file) == 0:
            os.unlink(patch_file)
    elif os.path.exists(patch_file):
        os.unlink(patch_file)

    env('BUILDDIR', builddir)
    env('DISTDIR', buildenv.distdir)
    env('SRCDIR', buildenv.user_srcdir or buildenv.orig_srcdir)
    env('BINARYFEED', buildenv.local_iface_file)
    os.chdir(builddir)
    print "cd", builddir

    setup = CompileSetup(iface_cache.stores, sels)
    setup.prepare_env()

    # These mappings are needed when mixing Zero Install -dev packages with
    # native package binaries.
    mappings = {}
    for impl in sels.selections.values():
        # Add mappings that have been set explicitly...
        new_mappings = impl.attrs.get(XMLNS_0COMPILE + ' lib-mappings', '')
        if new_mappings:
            new_mappings = new_mappings.split(' ')
            for mapping in new_mappings:
                assert ':' in mapping, "lib-mappings missing ':' in '%s' from '%s'" % (
                    mapping, impl.feed)
                name, major_version = mapping.split(':', 1)
                assert '/' not in mapping, "lib-mappings '%s' contains a / in the version number (from '%s')!" % (
                    mapping, impl.feed)
                if sys.platform == 'darwin':
                    mappings[name] = 'lib%s.%s.dylib' % (name, major_version)
                else:
                    mappings[name] = 'lib%s.so.%s' % (name, major_version)
        # Auto-detect required mappings where possible...
        # (if the -dev package is native, the symlinks will be OK)
        if not is_package_impl(impl):
            impl_path = lookup(impl)
            for libdirname in ['lib', 'usr/lib', 'lib64', 'usr/lib64']:
                libdir = os.path.join(impl_path, libdirname)
                if os.path.isdir(libdir):
                    find_broken_version_symlinks(libdir, mappings)

    if mappings:
        set_up_mappings(mappings)

    overrides_dir = os.path.join(os.environ['TMPDIR'], PKG_CONFIG_OVERRIDES)
    if os.path.isdir(overrides_dir):
        add_overrides = model.EnvironmentBinding('PKG_CONFIG_PATH',
                                                 PKG_CONFIG_OVERRIDES)
        do_env_binding(add_overrides, os.environ['TMPDIR'])

    # Some programs want to put temporary build files in the source directory.
    # Make a copy of the source if needed.
    dup_src_type = src_impl.attrs.get(XMLNS_0COMPILE + ' dup-src', None)
    if dup_src_type == 'true':
        dup_src(copy_file)
        env('SRCDIR', builddir)
    elif dup_src_type:
        raise Exception("Unknown dup-src value '%s'" % dup_src_type)

    if options.shell:
        spawn_and_check(find_in_path('cmd' if os.name == 'nt' else 'sh'), [])
    else:
        command = sels.commands[0].qdom.attrs.get('shell-command', None)
        if command is None:
            # New style <command>
            prog_args = setup.build_command(sels.interface,
                                            sels.command) + args
        else:
            # Old style shell-command='...'
            if os.name == 'nt':
                prog_args = [
                    os.environ['0COMPILE_BASH'], '-eux', '-c', command
                ] + args
            else:
                prog_args = ['/bin/sh', '-c', command + ' "$@"', '-'] + args
            assert len(sels.commands) == 1

        # Remove any existing log files
        for log in ['build.log', 'build-success.log', 'build-failure.log']:
            if os.path.exists(log):
                os.unlink(log)

        # Run the command, copying output to a new log
        with open('build.log', 'w') as log:
            print >> log, "Build log for %s-%s" % (master_feed.get_name(),
                                                   src_impl.version)
            print >> log, "\nBuilt using 0compile-%s" % __main__.version
            print >> log, "\nBuild system: " + ', '.join(uname)
            print >> log, "\n%s:\n" % ENV_FILE
            with open(os.path.join(os.pardir, ENV_FILE)) as properties_file:
                shutil.copyfileobj(properties_file, log)

            log.write('\n')

            if os.path.exists(patch_file):
                print >> log, "\nPatched with:\n"
                shutil.copyfileobj(file(patch_file), log)
                log.write('\n')

            if command:
                print "Executing: " + command, args
                print >> log, "Executing: " + command, args
            else:
                print "Executing: " + str(prog_args)
                print >> log, "Executing: " + str(prog_args)

            # Tee the output to the console and to the log
            child = subprocess.Popen(prog_args,
                                     stdout=subprocess.PIPE,
                                     stderr=subprocess.STDOUT)
            while True:
                data = os.read(child.stdout.fileno(), 100)
                if not data: break
                sys.stdout.write(data)
                log.write(data)
            status = child.wait()
            failure = None
            if status == 0:
                print >> log, "Build successful"
                shorten_dynamic_library_install_names()
                fixup_generated_pkgconfig_files()
                remove_la_files()
            elif status > 0:
                failure = "Build failed with exit code %d" % status
            else:
                failure = "Build failure: exited due to signal %d" % (-status)
            if failure:
                print >> log, failure

        if failure:
            os.rename('build.log', 'build-failure.log')
            raise SafeException("Command '%s': %s" % (prog_args, failure))
        else:
            os.rename('build.log', 'build-success.log')
예제 #5
0
 def testEnvBind(self):
     a = model.EnvironmentBinding('PYTHONPATH', 'path')
     assert a.name == 'PYTHONPATH'
     assert a.insert == 'path'
     str(a)