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
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()
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
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
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
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
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
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
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
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()
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()
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)
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()