예제 #1
0
def _build(tmpdir, ext, compiler_verbose=0, debug=None, universal_mode=False,
           cpython_include_dirs=None):
    # XXX compact but horrible :-(
    from distutils.core import Distribution
    import distutils.errors, distutils.log
    #
    dist = Distribution({'ext_modules': [ext]})
    dist.parse_config_files()
    options = dist.get_option_dict('build_ext')
    if debug is None:
        debug = sys.flags.debug
    options['debug'] = ('ffiplatform', debug)
    options['force'] = ('ffiplatform', True)
    options['build_lib'] = ('ffiplatform', tmpdir)
    options['build_temp'] = ('ffiplatform', tmpdir)
    #
    old_level = distutils.log.set_threshold(0) or 0
    try:
        distutils.log.set_verbosity(compiler_verbose)
        if universal_mode:
            cmd_obj = dist.get_command_obj('build_ext')
            cmd_obj.finalize_options()
            if cpython_include_dirs is None:
                cpython_include_dirs = cmd_obj.include_dirs
            soname = _build_universal(tmpdir, ext, cpython_include_dirs)
        else:
            dist.run_command('build_ext')
            cmd_obj = dist.get_command_obj('build_ext')
            [soname] = cmd_obj.get_outputs()
    finally:
        distutils.log.set_threshold(old_level)
    #
    return soname
예제 #2
0
    def run(self):
        cmd = self.reinitialize_command("build_ext")
        cmd.inplace = True
        cmd.enable_xpyb = self.enable_xpyb
        cmd.force = self.force
        cmd.ensure_finalized()
        cmd.run()

        import cairo

        tests_dir = os.path.join("tests", "cmodule")

        ext = Extension(
            name='tests.cmod',
            sources=[
                os.path.join(tests_dir, "cmodule.c"),
                os.path.join(tests_dir, "cmodulelib.c"),
            ],
            include_dirs=[
                tests_dir,
                cairo.get_include(),
            ],
            depends=[
                os.path.join(tests_dir, "cmodulelib.h"),
                os.path.join(cairo.get_include(), "pycairo.h"),
            ],
            define_macros=[("PY_SSIZE_T_CLEAN", None)],
        )

        compiler = new_compiler()
        customize_compiler(compiler)

        add_ext_cflags(ext, compiler)

        if compiler.compiler_type == "msvc":
            ext.libraries += ['cairo']
        else:
            pkg_config_version_check('cairo', CAIRO_VERSION_REQUIRED)
            ext.include_dirs += pkg_config_parse('--cflags-only-I', 'cairo')
            ext.library_dirs += pkg_config_parse('--libs-only-L', 'cairo')
            ext.libraries += pkg_config_parse('--libs-only-l', 'cairo')

        dist = Distribution({"ext_modules": [ext]})

        build_cmd = dist.get_command_obj("build")
        build_cmd.build_base = os.path.join(self.build_base, "pycairo_tests")
        build_cmd.ensure_finalized()

        cmd = dist.get_command_obj("build_ext")
        cmd.inplace = True
        cmd.force = self.force
        cmd.ensure_finalized()
        cmd.run()
예제 #3
0
def _build(tmpdir, ext, compiler_verbose=0, debug=None):
    # XXX compact but horrible :-(
    from distutils.core import Distribution
    import distutils.errors, distutils.log
    #
    dist = Distribution({'ext_modules': [ext]})
    dist.parse_config_files()
    options = dist.get_option_dict('build_ext')
    if debug is None:
        debug = sys.flags.debug
    options['debug'] = ('ffiplatform', debug)
    options['force'] = ('ffiplatform', True)
    options['build_lib'] = ('ffiplatform', tmpdir)
    options['build_temp'] = ('ffiplatform', tmpdir)
    #
    try:
        old_level = distutils.log.set_threshold(0) or 0
        try:
            distutils.log.set_verbosity(compiler_verbose)
            dist.run_command('build_ext')
            cmd_obj = dist.get_command_obj('build_ext')
            [soname] = cmd_obj.get_outputs()
        finally:
            distutils.log.set_threshold(old_level)
    except (distutils.errors.CompileError, distutils.errors.LinkError) as e:
        raise VerificationError('%s: %s' % (e.__class__.__name__, e))
    #
    return soname
예제 #4
0
    def get_paths(self) -> Dict[str, str]:
        # We can't use sysconfig.get_paths() because
        # on some distributions it does not return the proper paths
        # (those used by pip for instance). We go through distutils
        # to get the proper ones.
        import site

        from distutils.command.install import SCHEME_KEYS  # noqa
        from distutils.core import Distribution

        d = Distribution()
        d.parse_config_files()
        obj = d.get_command_obj("install", create=True)
        obj.finalize_options()

        paths = sysconfig.get_paths().copy()
        for key in SCHEME_KEYS:
            if key == "headers":
                # headers is not a path returned by sysconfig.get_paths()
                continue

            paths[key] = getattr(obj, "install_{}".format(key))

        if site.check_enableusersite() and hasattr(obj, "install_usersite"):
            paths["usersite"] = getattr(obj, "install_usersite")
            paths["userbase"] = getattr(obj, "install_userbase")

        return paths
예제 #5
0
def _build(tmpdir, ext, compiler_verbose=0):
    # XXX compact but horrible :-(
    from distutils.core import Distribution
    import distutils.errors, distutils.log
    #
    dist = Distribution({'ext_modules': [ext]})
    dist.parse_config_files()
    options = dist.get_option_dict('build_ext')
    options['force'] = ('ffiplatform', True)
    options['build_lib'] = ('ffiplatform', tmpdir)
    options['build_temp'] = ('ffiplatform', tmpdir)
    #
    try:
        old_level = distutils.log.set_threshold(0) or 0
        try:
            distutils.log.set_verbosity(compiler_verbose)
            dist.run_command('build_ext')
        finally:
            distutils.log.set_threshold(old_level)
    except (distutils.errors.CompileError,
            distutils.errors.LinkError) as e:
        raise VerificationError('%s: %s' % (e.__class__.__name__, e))
    #
    cmd_obj = dist.get_command_obj('build_ext')
    [soname] = cmd_obj.get_outputs()
    return soname
예제 #6
0
def _build(tmpdir, ext, hpy_devel, hpy_abi, compiler_verbose=0, debug=None):
    # XXX compact but horrible :-(
    from distutils.core import Distribution
    import distutils.errors, distutils.log
    #
    dist = Distribution()
    dist.parse_config_files()
    options = dist.get_option_dict('build_ext')
    if debug is None:
        debug = sys.flags.debug
    options['debug'] = ('ffiplatform', debug)
    options['force'] = ('ffiplatform', True)
    options['build_lib'] = ('ffiplatform', tmpdir)
    options['build_temp'] = ('ffiplatform', tmpdir)
    #
    # this is the equivalent of passing --hpy-abi from setup.py's command line
    dist.hpy_abi = hpy_abi
    hpy_devel.fix_distribution(dist, hpy_ext_modules=[ext])
    #
    old_level = distutils.log.set_threshold(0) or 0
    try:
        distutils.log.set_verbosity(compiler_verbose)
        dist.run_command('build_ext')
        cmd_obj = dist.get_command_obj('build_ext')
        [soname] = cmd_obj.get_outputs()
    finally:
        distutils.log.set_threshold(old_level)
    #
    return soname
예제 #7
0
def _build(tmpdir, ext):
    # XXX compact but horrible :-(
    from distutils.core import Distribution
    import distutils.errors
    #
    dist = Distribution({'ext_modules': [ext]})
    options = dist.get_option_dict('build_ext')
    options['force'] = ('ffiplatform', True)
    options['build_lib'] = ('ffiplatform', tmpdir)
    options['build_temp'] = ('ffiplatform', tmpdir)
    #
    try:
        dist.run_command('build_ext')
    except (distutils.errors.CompileError, distutils.errors.LinkError) as e:
        raise VerificationError('%s: %s' % (e.__class__.__name__, e))
    #
    cmd_obj = dist.get_command_obj('build_ext')
    [soname] = cmd_obj.get_outputs()
    return soname
예제 #8
0
def _build(tmpdir, ext, hpy_devel, hpy_abi, compiler_verbose=0, debug=None):
    # XXX compact but horrible :-(
    from distutils.core import Distribution
    import distutils.errors
    import distutils.log
    #
    dist = Distribution()
    dist.parse_config_files()
    if debug is None:
        debug = sys.flags.debug
    options_build_ext = dist.get_option_dict('build_ext')
    options_build_ext['debug'] = ('ffiplatform', debug)
    options_build_ext['force'] = ('ffiplatform', True)
    options_build_ext['build_lib'] = ('ffiplatform', tmpdir)
    options_build_ext['build_temp'] = ('ffiplatform', tmpdir)
    options_build_py = dist.get_option_dict('build_py')
    options_build_py['build_lib'] = ('ffiplatform', tmpdir)

    # this is the equivalent of passing --hpy-abi from setup.py's command line
    dist.hpy_abi = hpy_abi
    dist.hpy_ext_modules = [ext]
    hpy_devel.fix_distribution(dist)

    old_level = distutils.log.set_threshold(0) or 0
    old_dir = os.getcwd()
    try:
        os.chdir(tmpdir)
        distutils.log.set_verbosity(compiler_verbose)
        dist.run_command('build_ext')
        cmd_obj = dist.get_command_obj('build_ext')
        outputs = cmd_obj.get_outputs()
        sonames = [
            x for x in outputs
            if not x.endswith(".py") and not x.endswith(".pyc")
        ]
        assert len(
            sonames) == 1, 'build_ext is not supposed to return multiple DLLs'
        soname = sonames[0]
    finally:
        os.chdir(old_dir)
        distutils.log.set_threshold(old_level)

    return soname
예제 #9
0
def _build(tmpdir, ext):
    # XXX compact but horrible :-(
    from distutils.core import Distribution
    import distutils.errors
    #
    dist = Distribution({'ext_modules': [ext]})
    options = dist.get_option_dict('build_ext')
    options['force'] = ('ffiplatform', True)
    options['build_lib'] = ('ffiplatform', tmpdir)
    options['build_temp'] = ('ffiplatform', tmpdir)
    #
    try:
        dist.run_command('build_ext')
    except (distutils.errors.CompileError,
            distutils.errors.LinkError) as e:
        raise VerificationError('%s: %s' % (e.__class__.__name__, e))
    #
    cmd_obj = dist.get_command_obj('build_ext')
    [soname] = cmd_obj.get_outputs()
    return soname
예제 #10
0
def _build(tmpdir, ext, hpy_devel, hpy_abi, compiler_verbose=0, debug=None):
    # XXX compact but horrible :-(
    from distutils.core import Distribution
    import distutils.errors
    import distutils.log
    #
    dist = Distribution()
    dist.parse_config_files()
    if debug is None:
        debug = sys.flags.debug
    options_build_ext = dist.get_option_dict('build_ext')
    options_build_ext['debug'] = ('ffiplatform', debug)
    options_build_ext['force'] = ('ffiplatform', True)
    options_build_ext['build_lib'] = ('ffiplatform', tmpdir)
    options_build_ext['build_temp'] = ('ffiplatform', tmpdir)
    options_build_py = dist.get_option_dict('build_py')
    options_build_py['build_lib'] = ('ffiplatform', tmpdir)

    # this is the equivalent of passing --hpy-abi from setup.py's command line
    dist.hpy_abi = hpy_abi
    dist.hpy_ext_modules = [ext]
    hpy_devel.fix_distribution(dist)

    old_level = distutils.log.set_threshold(0) or 0
    try:
        distutils.log.set_verbosity(compiler_verbose)
        dist.run_command('build_ext')
        cmd_obj = dist.get_command_obj('build_ext')
        outputs = cmd_obj.get_outputs()
        if hpy_abi == "cpython":
            [mod_filename] = [x for x in outputs if not x.endswith(".py")]
        else:
            [mod_filename] = [x for x in outputs if x.endswith(".py")]
    finally:
        distutils.log.set_threshold(old_level)

    return mod_filename
예제 #11
0
    def run(self):
        cmd = self.reinitialize_command("build_ext")
        cmd.inplace = True
        cmd.force = self.force
        cmd.ensure_finalized()
        cmd.run()

        gidatadir = pkg_config_parse("--variable=gidatadir",
                                     "gobject-introspection-1.0")[0]
        g_ir_scanner = pkg_config_parse("--variable=g_ir_scanner",
                                        "gobject-introspection-1.0")[0]
        g_ir_compiler = pkg_config_parse("--variable=g_ir_compiler",
                                         "gobject-introspection-1.0")[0]

        script_dir = get_script_dir()
        gi_dir = os.path.join(script_dir, "gi")
        tests_dir = os.path.join(script_dir, "tests")
        gi_tests_dir = os.path.join(gidatadir, "tests")

        schema_xml = os.path.join(tests_dir, "org.gnome.test.gschema.xml")
        schema_bin = os.path.join(tests_dir, "gschemas.compiled")
        if self._newer_group([schema_xml], schema_bin):
            subprocess.check_call([
                "glib-compile-schemas",
                "--targetdir=%s" % tests_dir,
                "--schema-file=%s" % schema_xml,
            ])

        compiler = new_compiler()
        customize_compiler(compiler)

        if os.name == "nt":
            compiler.shared_lib_extension = ".dll"
        elif sys.platform == "darwin":
            compiler.shared_lib_extension = ".dylib"
            if "-bundle" in compiler.linker_so:
                compiler.linker_so = list(compiler.linker_so)
                i = compiler.linker_so.index("-bundle")
                compiler.linker_so[i] = "-dynamiclib"
        else:
            compiler.shared_lib_extension = ".so"

        if compiler.compiler_type == "msvc":
            g_ir_scanner_cmd = [sys.executable, g_ir_scanner]
        else:
            g_ir_scanner_cmd = [g_ir_scanner]

        def build_ext(ext):

            libname = compiler.shared_object_filename(ext.name)
            ext_paths = [os.path.join(tests_dir, libname)]
            if os.name == "nt":
                if compiler.compiler_type == "msvc":
                    # MSVC: Get rid of the 'lib' prefix and the .dll
                    #       suffix from libname, and append .lib so
                    #       that we get the right .lib filename to
                    #       pass to g-ir-scanner with --library
                    implibname = libname[3:libname.rfind(".dll")] + '.lib'
                else:
                    implibname = libname + ".a"
                ext_paths.append(os.path.join(tests_dir, implibname))

            if self._newer_group(ext.sources + ext.depends, *ext_paths):
                # MSVC: We need to define _GI_EXTERN explcitly so that
                #       symbols get exported properly
                if compiler.compiler_type == "msvc":
                    extra_defines = [('_GI_EXTERN',
                                      '__declspec(dllexport)extern')]
                else:
                    extra_defines = []
                objects = compiler.compile(ext.sources,
                                           output_dir=self.build_temp,
                                           include_dirs=ext.include_dirs,
                                           macros=ext.define_macros +
                                           extra_defines)

                if os.name == "nt":
                    if compiler.compiler_type == "msvc":
                        postargs = [
                            "-implib:%s" % os.path.join(tests_dir, implibname)
                        ]
                    else:
                        postargs = [
                            "-Wl,--out-implib=%s" %
                            os.path.join(tests_dir, implibname)
                        ]
                else:
                    postargs = []

                compiler.link_shared_object(objects,
                                            compiler.shared_object_filename(
                                                ext.name),
                                            output_dir=tests_dir,
                                            libraries=ext.libraries,
                                            library_dirs=ext.library_dirs,
                                            extra_postargs=postargs)

            return ext_paths

        ext = Extension(
            name='libgimarshallingtests',
            sources=[
                os.path.join(gi_tests_dir, "gimarshallingtests.c"),
                os.path.join(tests_dir, "gimarshallingtestsextra.c"),
            ],
            include_dirs=[
                gi_tests_dir,
                tests_dir,
            ],
            depends=[
                os.path.join(gi_tests_dir, "gimarshallingtests.h"),
                os.path.join(tests_dir, "gimarshallingtestsextra.h"),
            ],
        )
        add_ext_pkg_config_dep(ext, compiler.compiler_type, "glib-2.0")
        add_ext_pkg_config_dep(ext, compiler.compiler_type, "gio-2.0")
        ext_paths = build_ext(ext)

        # We want to always use POSIX-style paths for g-ir-compiler
        # because it expects the input .gir file and .typelib file to use
        # POSIX-style paths, otherwise it fails
        gir_path = posixpath.join(tests_dir, "GIMarshallingTests-1.0.gir")
        typelib_path = posixpath.join(tests_dir,
                                      "GIMarshallingTests-1.0.typelib")

        gimarshal_g_ir_scanner_cmd = g_ir_scanner_cmd + [
            "--no-libtool",
            "--include=Gio-2.0",
            "--namespace=GIMarshallingTests",
            "--nsversion=1.0",
            "--symbol-prefix=gi_marshalling_tests",
            "--warn-all",
            "--warn-error",
            "--library-path=%s" % tests_dir,
            "--library=gimarshallingtests",
            "--pkg=glib-2.0",
            "--pkg=gio-2.0",
            "--cflags-begin",
            "-I%s" % gi_tests_dir,
            "--cflags-end",
            "--output=%s" % gir_path,
        ]

        if self._newer_group(ext_paths, gir_path):
            subprocess.check_call(gimarshal_g_ir_scanner_cmd + ext.sources +
                                  ext.depends)

        if self._newer_group([gir_path], typelib_path):
            subprocess.check_call([
                g_ir_compiler,
                gir_path,
                "--output=%s" % typelib_path,
            ])

        regress_macros = []
        if not WITH_CAIRO:
            regress_macros.append(("_GI_DISABLE_CAIRO", "1"))

        ext = Extension(
            name='libregress',
            sources=[
                os.path.join(gi_tests_dir, "regress.c"),
                os.path.join(tests_dir, "regressextra.c"),
            ],
            include_dirs=[
                gi_tests_dir,
            ],
            depends=[
                os.path.join(gi_tests_dir, "regress.h"),
                os.path.join(tests_dir, "regressextra.h"),
            ],
            define_macros=regress_macros,
        )
        add_ext_pkg_config_dep(ext, compiler.compiler_type, "glib-2.0")
        add_ext_pkg_config_dep(ext, compiler.compiler_type, "gio-2.0")
        if WITH_CAIRO:
            add_ext_pkg_config_dep(ext, compiler.compiler_type, "cairo")
            add_ext_pkg_config_dep(ext, compiler.compiler_type,
                                   "cairo-gobject")
        ext_paths = build_ext(ext)

        # We want to always use POSIX-style paths for g-ir-compiler
        # because it expects the input .gir file and .typelib file to use
        # POSIX-style paths, otherwise it fails
        gir_path = posixpath.join(tests_dir, "Regress-1.0.gir")
        typelib_path = posixpath.join(tests_dir, "Regress-1.0.typelib")
        regress_g_ir_scanner_cmd = g_ir_scanner_cmd + [
            "--no-libtool", "--include=Gio-2.0", "--namespace=Regress",
            "--nsversion=1.0", "--warn-all", "--warn-error",
            "--library-path=%s" % tests_dir, "--library=regress",
            "--pkg=glib-2.0", "--pkg=gio-2.0"
        ]

        if self._newer_group(ext_paths, gir_path):
            if WITH_CAIRO:
                regress_g_ir_scanner_cmd += ["--include=cairo-1.0"]
                # MSVC: We don't normally have the pkg-config files for
                # cairo and cairo-gobject, so use --extra-library
                # instead of --pkg to pass those to the linker, so that
                # g-ir-scanner won't fail due to linker errors
                if compiler.compiler_type == "msvc":
                    regress_g_ir_scanner_cmd += [
                        "--extra-library=cairo",
                        "--extra-library=cairo-gobject"
                    ]

                else:
                    regress_g_ir_scanner_cmd += [
                        "--pkg=cairo", "--pkg=cairo-gobject"
                    ]
            else:
                regress_g_ir_scanner_cmd += ["-D_GI_DISABLE_CAIRO"]

            regress_g_ir_scanner_cmd += ["--output=%s" % gir_path]

            subprocess.check_call(regress_g_ir_scanner_cmd + ext.sources +
                                  ext.depends)

        if self._newer_group([gir_path], typelib_path):
            subprocess.check_call([
                g_ir_compiler,
                gir_path,
                "--output=%s" % typelib_path,
            ])

        ext = Extension(
            name='tests.testhelper',
            sources=[
                os.path.join(tests_dir, "testhelpermodule.c"),
                os.path.join(tests_dir, "test-floating.c"),
                os.path.join(tests_dir, "test-thread.c"),
                os.path.join(tests_dir, "test-unknown.c"),
            ],
            include_dirs=[
                gi_dir,
                tests_dir,
            ],
            depends=list_headers(gi_dir) + list_headers(tests_dir),
            define_macros=[("PY_SSIZE_T_CLEAN", None)],
        )
        add_ext_pkg_config_dep(ext, compiler.compiler_type, "glib-2.0")
        add_ext_pkg_config_dep(ext, compiler.compiler_type, "gio-2.0")
        add_ext_compiler_flags(ext, compiler)

        dist = Distribution({"ext_modules": [ext]})

        build_cmd = dist.get_command_obj("build")
        build_cmd.build_base = os.path.join(self.build_base, "pygobject_tests")
        build_cmd.ensure_finalized()

        cmd = dist.get_command_obj("build_ext")
        cmd.inplace = True
        cmd.force = self.force
        cmd.ensure_finalized()
        cmd.run()
예제 #12
0
    def run(self):
        cmd = self.reinitialize_command("build_ext")
        cmd.inplace = True
        cmd.force = self.force
        cmd.ensure_finalized()
        cmd.run()

        gidatadir = pkg_config_parse("--variable=gidatadir",
                                     "gobject-introspection-1.0")[0]
        g_ir_scanner = pkg_config_parse("--variable=g_ir_scanner",
                                        "gobject-introspection-1.0")[0]
        g_ir_compiler = pkg_config_parse("--variable=g_ir_compiler",
                                         "gobject-introspection-1.0")[0]

        script_dir = get_script_dir()
        gi_dir = os.path.join(script_dir, "gi")
        tests_dir = os.path.join(script_dir, "tests")
        gi_tests_dir = os.path.join(gidatadir, "tests")

        schema_xml = os.path.join(tests_dir, "org.gnome.test.gschema.xml")
        schema_bin = os.path.join(tests_dir, "gschemas.compiled")
        if self._newer_group([schema_xml], schema_bin):
            subprocess.check_call([
                "glib-compile-schemas",
                "--targetdir=%s" % tests_dir,
                "--schema-file=%s" % schema_xml,
            ])

        compiler = new_compiler()
        customize_compiler(compiler)

        if os.name == "nt":
            compiler.shared_lib_extension = ".dll"
        elif sys.platform == "darwin":
            compiler.shared_lib_extension = ".dylib"
            if "-bundle" in compiler.linker_so:
                compiler.linker_so = list(compiler.linker_so)
                i = compiler.linker_so.index("-bundle")
                compiler.linker_so[i] = "-dynamiclib"
        else:
            compiler.shared_lib_extension = ".so"

        def build_ext(ext):
            if compiler.compiler_type == "msvc":
                raise Exception("MSVC support not implemented")

            libname = compiler.shared_object_filename(ext.name)
            ext_paths = [os.path.join(tests_dir, libname)]
            if os.name == "nt":
                implibname = libname + ".a"
                ext_paths.append(os.path.join(tests_dir, implibname))

            if self._newer_group(ext.sources + ext.depends, *ext_paths):
                objects = compiler.compile(ext.sources,
                                           output_dir=self.build_temp,
                                           include_dirs=ext.include_dirs)

                if os.name == "nt":
                    postargs = [
                        "-Wl,--out-implib=%s" %
                        os.path.join(tests_dir, implibname)
                    ]
                else:
                    postargs = []

                compiler.link_shared_object(objects,
                                            compiler.shared_object_filename(
                                                ext.name),
                                            output_dir=tests_dir,
                                            libraries=ext.libraries,
                                            library_dirs=ext.library_dirs,
                                            extra_postargs=postargs)

            return ext_paths

        ext = Extension(
            name='libgimarshallingtests',
            sources=[
                os.path.join(gi_tests_dir, "gimarshallingtests.c"),
                os.path.join(tests_dir, "gimarshallingtestsextra.c"),
            ],
            include_dirs=[
                gi_tests_dir,
                tests_dir,
            ],
            depends=[
                os.path.join(gi_tests_dir, "gimarshallingtests.h"),
                os.path.join(tests_dir, "gimarshallingtestsextra.h"),
            ],
        )
        add_ext_pkg_config_dep(ext, compiler.compiler_type, "glib-2.0")
        add_ext_pkg_config_dep(ext, compiler.compiler_type, "gio-2.0")
        ext_paths = build_ext(ext)

        gir_path = os.path.join(tests_dir, "GIMarshallingTests-1.0.gir")
        typelib_path = os.path.join(tests_dir,
                                    "GIMarshallingTests-1.0.typelib")

        if self._newer_group(ext_paths, gir_path):
            subprocess.check_call([
                g_ir_scanner,
                "--no-libtool",
                "--include=Gio-2.0",
                "--namespace=GIMarshallingTests",
                "--nsversion=1.0",
                "--symbol-prefix=gi_marshalling_tests",
                "--warn-all",
                "--warn-error",
                "--library-path=%s" % tests_dir,
                "--library=gimarshallingtests",
                "--pkg=glib-2.0",
                "--pkg=gio-2.0",
                "--cflags-begin",
                "-I%s" % gi_tests_dir,
                "--cflags-end",
                "--output=%s" % gir_path,
            ] + ext.sources + ext.depends)

        if self._newer_group([gir_path], typelib_path):
            subprocess.check_call([
                g_ir_compiler,
                gir_path,
                "--output=%s" % typelib_path,
            ])

        ext = Extension(
            name='libregress',
            sources=[
                os.path.join(gi_tests_dir, "regress.c"),
                os.path.join(tests_dir, "regressextra.c"),
            ],
            include_dirs=[
                gi_tests_dir,
            ],
            depends=[
                os.path.join(gi_tests_dir, "regress.h"),
                os.path.join(tests_dir, "regressextra.h"),
            ],
        )
        add_ext_pkg_config_dep(ext, compiler.compiler_type, "glib-2.0")
        add_ext_pkg_config_dep(ext, compiler.compiler_type, "gio-2.0")
        add_ext_pkg_config_dep(ext, compiler.compiler_type, "cairo")
        add_ext_pkg_config_dep(ext, compiler.compiler_type, "cairo-gobject")
        ext_paths = build_ext(ext)

        gir_path = os.path.join(tests_dir, "Regress-1.0.gir")
        typelib_path = os.path.join(tests_dir, "Regress-1.0.typelib")

        if self._newer_group(ext_paths, gir_path):
            subprocess.check_call([
                g_ir_scanner,
                "--no-libtool",
                "--include=cairo-1.0",
                "--include=Gio-2.0",
                "--namespace=Regress",
                "--nsversion=1.0",
                "--warn-all",
                "--warn-error",
                "--library-path=%s" % tests_dir,
                "--library=regress",
                "--pkg=glib-2.0",
                "--pkg=gio-2.0",
                "--pkg=cairo",
                "--pkg=cairo-gobject",
                "--output=%s" % gir_path,
            ] + ext.sources + ext.depends)

        if self._newer_group([gir_path], typelib_path):
            subprocess.check_call([
                g_ir_compiler,
                gir_path,
                "--output=%s" % typelib_path,
            ])

        ext = Extension(
            name='tests.testhelper',
            sources=[
                os.path.join(tests_dir, "testhelpermodule.c"),
                os.path.join(tests_dir, "test-floating.c"),
                os.path.join(tests_dir, "test-thread.c"),
                os.path.join(tests_dir, "test-unknown.c"),
            ],
            include_dirs=[
                gi_dir,
                tests_dir,
            ],
            depends=list_headers(gi_dir) + list_headers(tests_dir),
            define_macros=[("PY_SSIZE_T_CLEAN", None)],
        )
        add_ext_pkg_config_dep(ext, compiler.compiler_type, "glib-2.0")
        add_ext_pkg_config_dep(ext, compiler.compiler_type, "gio-2.0")
        add_ext_pkg_config_dep(ext, compiler.compiler_type, "cairo")
        add_ext_compiler_flags(ext, compiler)

        dist = Distribution({"ext_modules": [ext]})

        build_cmd = dist.get_command_obj("build")
        build_cmd.build_base = os.path.join(self.build_base, "pygobject_tests")
        build_cmd.ensure_finalized()

        cmd = dist.get_command_obj("build_ext")
        cmd.inplace = True
        cmd.force = self.force
        cmd.ensure_finalized()
        cmd.run()
예제 #13
0
def compile_c_extension(
    generated_source_path: str,
    build_dir: Optional[str] = None,
    verbose: bool = False,
    keep_asserts: bool = True,
    disable_optimization: bool = False,
    library_dir: Optional[str] = None,
) -> str:
    """Compile the generated source for a parser generator into an extension module.

    The extension module will be generated in the same directory as the provided path
    for the generated source, with the same basename (in addition to extension module
    metadata). For example, for the source mydir/parser.c the generated extension
    in a darwin system with python 3.8 will be mydir/parser.cpython-38-darwin.so.

    If *build_dir* is provided, that path will be used as the temporary build directory
    of distutils (this is useful in case you want to use a temporary directory).

    If *library_dir* is provided, that path will be used as the directory for a
    static library of the common parser sources (this is useful in case you are
    creating multiple extensions).
    """
    import distutils.log
    from distutils.core import Distribution, Extension
    from distutils.tests.support import fixup_build_ext  # type: ignore

    from distutils.ccompiler import new_compiler
    from distutils.dep_util import newer_group
    from distutils.sysconfig import customize_compiler

    if verbose:
        distutils.log.set_threshold(distutils.log.DEBUG)

    source_file_path = pathlib.Path(generated_source_path)
    extension_name = source_file_path.stem
    extra_compile_args = get_extra_flags("CFLAGS", "PY_CFLAGS_NODIST")
    extra_compile_args.append("-DPy_BUILD_CORE_MODULE")
    # Define _Py_TEST_PEGEN to not call PyAST_Validate() in Parser/pegen.c
    extra_compile_args.append("-D_Py_TEST_PEGEN")
    extra_link_args = get_extra_flags("LDFLAGS", "PY_LDFLAGS_NODIST")
    if keep_asserts:
        extra_compile_args.append("-UNDEBUG")
    if disable_optimization:
        if sys.platform == 'win32':
            extra_compile_args.append("/Od")
            extra_link_args.append("/LTCG:OFF")
        else:
            extra_compile_args.append("-O0")
            if sysconfig.get_config_var("GNULD") == "yes":
                extra_link_args.append("-fno-lto")

    common_sources = [
        str(MOD_DIR.parent.parent.parent / "Python" / "Python-ast.c"),
        str(MOD_DIR.parent.parent.parent / "Python" / "asdl.c"),
        str(MOD_DIR.parent.parent.parent / "Parser" / "tokenizer.c"),
        str(MOD_DIR.parent.parent.parent / "Parser" / "pegen.c"),
        str(MOD_DIR.parent.parent.parent / "Parser" / "pegen_errors.c"),
        str(MOD_DIR.parent.parent.parent / "Parser" / "action_helpers.c"),
        str(MOD_DIR.parent.parent.parent / "Parser" / "string_parser.c"),
        str(MOD_DIR.parent / "peg_extension" / "peg_extension.c"),
    ]
    include_dirs = [
        str(MOD_DIR.parent.parent.parent / "Include" / "internal"),
        str(MOD_DIR.parent.parent.parent / "Parser"),
    ]
    extension = Extension(
        extension_name,
        sources=[generated_source_path],
        extra_compile_args=extra_compile_args,
        extra_link_args=extra_link_args,
    )
    dist = Distribution({"name": extension_name, "ext_modules": [extension]})
    cmd = dist.get_command_obj("build_ext")
    fixup_build_ext(cmd)
    cmd.build_lib = str(source_file_path.parent)
    cmd.include_dirs = include_dirs
    if build_dir:
        cmd.build_temp = build_dir
    cmd.ensure_finalized()

    compiler = new_compiler()
    customize_compiler(compiler)
    compiler.set_include_dirs(cmd.include_dirs)
    compiler.set_library_dirs(cmd.library_dirs)
    # build static lib
    if library_dir:
        library_filename = compiler.library_filename(extension_name,
                                                     output_dir=library_dir)
        if newer_group(common_sources, library_filename, 'newer'):
            if sys.platform == 'win32':
                pdb = compiler.static_lib_format % (extension_name, '.pdb')
                compile_opts = [f"/Fd{library_dir}\\{pdb}"]
                compile_opts.extend(extra_compile_args)
            else:
                compile_opts = extra_compile_args
            objects = compiler.compile(common_sources,
                                       output_dir=library_dir,
                                       debug=cmd.debug,
                                       extra_postargs=compile_opts)
            compiler.create_static_lib(objects,
                                       extension_name,
                                       output_dir=library_dir,
                                       debug=cmd.debug)
        if sys.platform == 'win32':
            compiler.add_library_dir(library_dir)
            extension.libraries = [extension_name]
        elif sys.platform == 'darwin':
            compiler.set_link_objects([
                '-Wl,-force_load',
                library_filename,
            ])
        else:
            compiler.set_link_objects([
                '-Wl,--whole-archive',
                library_filename,
                '-Wl,--no-whole-archive',
            ])
    else:
        extension.sources[0:0] = common_sources

    # Compile the source code to object files.
    ext_path = cmd.get_ext_fullpath(extension_name)
    if newer_group(extension.sources, ext_path, 'newer'):
        objects = compiler.compile(extension.sources,
                                   output_dir=cmd.build_temp,
                                   debug=cmd.debug,
                                   extra_postargs=extra_compile_args)
    else:
        objects = compiler.object_filenames(extension.sources,
                                            output_dir=cmd.build_temp)
    # Now link the object files together into a "shared object"
    compiler.link_shared_object(
        objects,
        ext_path,
        libraries=cmd.get_libraries(extension),
        extra_postargs=extra_link_args,
        export_symbols=cmd.get_export_symbols(extension),
        debug=cmd.debug,
        build_temp=cmd.build_temp)

    return pathlib.Path(ext_path)
예제 #14
0
파일: setup.py 프로젝트: GNOME/pygobject
    def run(self):
        cmd = self.reinitialize_command("build_ext")
        cmd.inplace = True
        cmd.force = self.force
        cmd.ensure_finalized()
        cmd.run()

        gidatadir = pkg_config_parse(
            "--variable=gidatadir", "gobject-introspection-1.0")[0]
        g_ir_scanner = pkg_config_parse(
            "--variable=g_ir_scanner", "gobject-introspection-1.0")[0]
        g_ir_compiler = pkg_config_parse(
            "--variable=g_ir_compiler", "gobject-introspection-1.0")[0]

        script_dir = get_script_dir()
        gi_dir = os.path.join(script_dir, "gi")
        tests_dir = os.path.join(script_dir, "tests")
        gi_tests_dir = os.path.join(gidatadir, "tests")

        schema_xml = os.path.join(tests_dir, "org.gnome.test.gschema.xml")
        schema_bin = os.path.join(tests_dir, "gschemas.compiled")
        if self._newer_group([schema_xml], schema_bin):
            subprocess.check_call([
                "glib-compile-schemas",
                "--targetdir=%s" % tests_dir,
                "--schema-file=%s" % schema_xml,
            ])

        compiler = new_compiler()
        customize_compiler(compiler)

        if os.name == "nt":
            compiler.shared_lib_extension = ".dll"
        elif sys.platform == "darwin":
            compiler.shared_lib_extension = ".dylib"
            if "-bundle" in compiler.linker_so:
                compiler.linker_so = list(compiler.linker_so)
                i = compiler.linker_so.index("-bundle")
                compiler.linker_so[i] = "-dynamiclib"
        else:
            compiler.shared_lib_extension = ".so"

        if compiler.compiler_type == "msvc":
            g_ir_scanner_cmd = [sys.executable, g_ir_scanner]
        else:
            g_ir_scanner_cmd = [g_ir_scanner]

        def build_ext(ext):

            libname = compiler.shared_object_filename(ext.name)
            ext_paths = [os.path.join(tests_dir, libname)]
            if os.name == "nt":
                if compiler.compiler_type == "msvc":
                    # MSVC: Get rid of the 'lib' prefix and the .dll
                    #       suffix from libname, and append .lib so
                    #       that we get the right .lib filename to
                    #       pass to g-ir-scanner with --library
                    implibname = libname[3:libname.rfind(".dll")] + '.lib'
                else:
                    implibname = libname + ".a"
                ext_paths.append(os.path.join(tests_dir, implibname))

            if self._newer_group(ext.sources + ext.depends, *ext_paths):
                # MSVC: We need to define _GI_EXTERN explcitly so that
                #       symbols get exported properly
                if compiler.compiler_type == "msvc":
                    extra_defines = [('_GI_EXTERN',
                                      '__declspec(dllexport)extern')]
                else:
                    extra_defines = []
                objects = compiler.compile(
                    ext.sources,
                    output_dir=self.build_temp,
                    include_dirs=ext.include_dirs,
                    macros=ext.define_macros + extra_defines)

                if os.name == "nt":
                    if compiler.compiler_type == "msvc":
                        postargs = ["-implib:%s" %
                                    os.path.join(tests_dir, implibname)]
                    else:
                        postargs = ["-Wl,--out-implib=%s" %
                                    os.path.join(tests_dir, implibname)]
                else:
                    postargs = []

                compiler.link_shared_object(
                    objects,
                    compiler.shared_object_filename(ext.name),
                    output_dir=tests_dir,
                    libraries=ext.libraries,
                    library_dirs=ext.library_dirs,
                    extra_postargs=postargs)

            return ext_paths

        ext = Extension(
            name='libgimarshallingtests',
            sources=[
                os.path.join(gi_tests_dir, "gimarshallingtests.c"),
                os.path.join(tests_dir, "gimarshallingtestsextra.c"),
            ],
            include_dirs=[
                gi_tests_dir,
                tests_dir,
            ],
            depends=[
                os.path.join(gi_tests_dir, "gimarshallingtests.h"),
                os.path.join(tests_dir, "gimarshallingtestsextra.h"),
            ],
        )
        add_ext_pkg_config_dep(ext, compiler.compiler_type, "glib-2.0")
        add_ext_pkg_config_dep(ext, compiler.compiler_type, "gio-2.0")
        ext_paths = build_ext(ext)

        # We want to always use POSIX-style paths for g-ir-compiler
        # because it expects the input .gir file and .typelib file to use
        # POSIX-style paths, otherwise it fails
        gir_path = posixpath.join(
            tests_dir, "GIMarshallingTests-1.0.gir")
        typelib_path = posixpath.join(
            tests_dir, "GIMarshallingTests-1.0.typelib")

        gimarshal_g_ir_scanner_cmd = g_ir_scanner_cmd + [
            "--no-libtool",
            "--include=Gio-2.0",
            "--namespace=GIMarshallingTests",
            "--nsversion=1.0",
            "--symbol-prefix=gi_marshalling_tests",
            "--warn-all",
            "--warn-error",
            "--library-path=%s" % tests_dir,
            "--library=gimarshallingtests",
            "--pkg=glib-2.0",
            "--pkg=gio-2.0",
            "--cflags-begin",
            "-I%s" % gi_tests_dir,
            "--cflags-end",
            "--output=%s" % gir_path,
        ]

        if self._newer_group(ext_paths, gir_path):
            subprocess.check_call(gimarshal_g_ir_scanner_cmd +
                                  ext.sources + ext.depends)

        if self._newer_group([gir_path], typelib_path):
            subprocess.check_call([
                g_ir_compiler,
                gir_path,
                "--output=%s" % typelib_path,
            ])

        regress_macros = []
        if not WITH_CAIRO:
            regress_macros.append(("_GI_DISABLE_CAIRO", "1"))

        ext = Extension(
            name='libregress',
            sources=[
                os.path.join(gi_tests_dir, "regress.c"),
                os.path.join(tests_dir, "regressextra.c"),
            ],
            include_dirs=[
                gi_tests_dir,
            ],
            depends=[
                os.path.join(gi_tests_dir, "regress.h"),
                os.path.join(tests_dir, "regressextra.h"),
            ],
            define_macros=regress_macros,
        )
        add_ext_pkg_config_dep(ext, compiler.compiler_type, "glib-2.0")
        add_ext_pkg_config_dep(ext, compiler.compiler_type, "gio-2.0")
        if WITH_CAIRO:
            add_ext_pkg_config_dep(ext, compiler.compiler_type, "cairo")
            add_ext_pkg_config_dep(
                ext, compiler.compiler_type, "cairo-gobject")
        ext_paths = build_ext(ext)

        # We want to always use POSIX-style paths for g-ir-compiler
        # because it expects the input .gir file and .typelib file to use
        # POSIX-style paths, otherwise it fails
        gir_path = posixpath.join(tests_dir, "Regress-1.0.gir")
        typelib_path = posixpath.join(tests_dir, "Regress-1.0.typelib")
        regress_g_ir_scanner_cmd = g_ir_scanner_cmd + [
            "--no-libtool",
            "--include=Gio-2.0",
            "--namespace=Regress",
            "--nsversion=1.0",
            "--warn-all",
            "--warn-error",
            "--library-path=%s" % tests_dir,
            "--library=regress",
            "--pkg=glib-2.0",
            "--pkg=gio-2.0"]

        if self._newer_group(ext_paths, gir_path):
            if WITH_CAIRO:
                regress_g_ir_scanner_cmd += ["--include=cairo-1.0"]
                # MSVC: We don't normally have the pkg-config files for
                # cairo and cairo-gobject, so use --extra-library
                # instead of --pkg to pass those to the linker, so that
                # g-ir-scanner won't fail due to linker errors
                if compiler.compiler_type == "msvc":
                    regress_g_ir_scanner_cmd += [
                        "--extra-library=cairo",
                        "--extra-library=cairo-gobject"]

                else:
                    regress_g_ir_scanner_cmd += [
                        "--pkg=cairo",
                        "--pkg=cairo-gobject"]
            else:
                regress_g_ir_scanner_cmd += ["-D_GI_DISABLE_CAIRO"]

            regress_g_ir_scanner_cmd += ["--output=%s" % gir_path]

            subprocess.check_call(regress_g_ir_scanner_cmd +
                                  ext.sources + ext.depends)

        if self._newer_group([gir_path], typelib_path):
            subprocess.check_call([
                g_ir_compiler,
                gir_path,
                "--output=%s" % typelib_path,
            ])

        ext = Extension(
            name='tests.testhelper',
            sources=[
                os.path.join(tests_dir, "testhelpermodule.c"),
                os.path.join(tests_dir, "test-floating.c"),
                os.path.join(tests_dir, "test-thread.c"),
                os.path.join(tests_dir, "test-unknown.c"),
            ],
            include_dirs=[
                gi_dir,
                tests_dir,
            ],
            depends=list_headers(gi_dir) + list_headers(tests_dir),
            define_macros=[("PY_SSIZE_T_CLEAN", None)],
        )
        add_ext_pkg_config_dep(ext, compiler.compiler_type, "glib-2.0")
        add_ext_pkg_config_dep(ext, compiler.compiler_type, "gio-2.0")
        add_ext_compiler_flags(ext, compiler)

        dist = Distribution({"ext_modules": [ext]})

        build_cmd = dist.get_command_obj("build")
        build_cmd.build_base = os.path.join(self.build_base, "pygobject_tests")
        build_cmd.ensure_finalized()

        cmd = dist.get_command_obj("build_ext")
        cmd.inplace = True
        cmd.force = self.force
        cmd.ensure_finalized()
        cmd.run()