def sage_create_extension(template, kwds): """ Create a distutils Extension given data from Cython This adjust the ``kwds`` in the following ways: - Make everything depend on *this* setup.py file - Add dependencies on header files for certain libraries - Ensure that C++ extensions link with -lstdc++ - Sort the libraries according to the library order - Add some default compile/link args and directories - Drop -std=c99 and similar from C++ extensions - Ensure that each flag, library, ... is listed at most once """ lang = kwds.get('language', 'c') # Libraries: add stdc++ if needed and sort them libs = kwds.get('libraries', []) if lang == 'c++': libs = libs + ['stdc++'] kwds['libraries'] = sorted(set(libs), key=lambda lib: library_order.get(lib, 0)) # Dependencies: add setup.py and lib_headers depends = kwds.get('depends', []) + [__file__] for lib, headers in lib_headers.items(): if lib in libs: depends += headers kwds['depends'] = depends # These are sorted and uniq'ed by Cython # Process extra_compile_args cflags = [] for flag in kwds.get('extra_compile_args', []): if lang == "c++": if flag.startswith("-std=") and "++" not in flag: continue # Skip -std=c99 and similar for C++ cflags.append(flag) cflags = extra_compile_args + cflags kwds['extra_compile_args'] = stable_uniq(cflags) # Process extra_link_args ldflags = kwds.get('extra_link_args', []) + extra_link_args kwds['extra_link_args'] = stable_uniq(ldflags) # Process library_dirs lib_dirs = kwds.get('library_dirs', []) + library_dirs kwds['library_dirs'] = stable_uniq(lib_dirs) # Process include_dirs inc_dirs = kwds.get('include_dirs', []) + include_dirs kwds['include_dirs'] = stable_uniq(inc_dirs) return default_create_extension(template, kwds)
def prepare_extension(self, ext): sources = ext.sources if sources is None or not isinstance(sources, (list, tuple)): raise DistutilsSetupError( ("in 'ext_modules' option (extension '%s'), " + "'sources' must be present and must be " + "a list of source filenames") % ext.name) sources = list(sources) fullname = self.get_ext_fullname(ext.name) if self.inplace: # ignore build-lib -- put the compiled extension into # the source tree along with pure Python modules modpath = string.split(fullname, '.') package = string.join(modpath[0:-1], '.') base = modpath[-1] build_py = self.get_finalized_command('build_py') package_dir = build_py.get_package_dir(package) ext_filename = os.path.join(package_dir, self.get_ext_filename(base)) relative_ext_filename = self.get_ext_filename(base) else: ext_filename = os.path.join(self.build_lib, self.get_ext_filename(fullname)) relative_ext_filename = self.get_ext_filename(fullname) # while dispatching the calls to gcc in parallel, we sometimes # hit a race condition where two separate build_ext objects # try to create a given directory at the same time; whoever # loses the race then seems to throw an error, saying that # the directory already exists. so, instead of fighting to # fix the race condition, we simply make sure the entire # directory tree exists now, while we're processing the # extensions in serial. relative_ext_dir = os.path.split(relative_ext_filename)[0] prefixes = ['', self.build_lib, self.build_temp] for prefix in prefixes: path = os.path.join(prefix, relative_ext_dir) try: os.makedirs(path) except OSError as e: assert e.errno == errno.EEXIST, 'Cannot create %s.' % path depends = sources + ext.depends if not (self.force or newer_group(depends, ext_filename, 'newer')): log.debug("skipping '%s' extension (up-to-date)", ext.name) need_to_compile = False elif getattr(ext, "skip_build", False): log.debug("skipping '%s' extension (optional)", ext.name) need_to_compile = False else: log.info("building '%s' extension", ext.name) need_to_compile = True # If we need to compile, adjust the given extension if need_to_compile: libs = ext.libraries if ext.language == 'c++' and 'stdc++' not in libs: libs = libs + ['stdc++'] # Sort libraries according to library_order ext.libraries = sorted(libs, key=lambda x: library_order.get(x, 0)) return need_to_compile, (sources, ext, ext_filename)
def create_extension(self, template, kwds): """ Create a distutils Extension given data from Cython. This adjust the ``kwds`` in the following ways: - Make everything depend on *this* setup.py file - Add dependencies on header files for certain libraries - Ensure that C++ extensions link with -lstdc++ - Sort the libraries according to the library order - Add some default compile/link args and directories - Choose C99 standard for C code and C++11 for C++ code - Drop -std=c99 and similar from C++ extensions - Ensure that each flag, library, ... is listed at most once """ lang = kwds.get('language', 'c') cplusplus = (lang == "c++") # Libraries: add stdc++ if needed and sort them libs = kwds.get('libraries', []) if cplusplus: libs = libs + ['stdc++'] kwds['libraries'] = sorted(set(libs), key=lambda lib: library_order.get(lib, 0)) # Dependencies: add setup.py and lib_headers depends = kwds.get('depends', []) + [__file__] for lib, headers in lib_headers.items(): if lib in libs: depends += headers kwds['depends'] = depends # These are sorted and uniq'ed by Cython # Process extra_compile_args cflags = [] have_std_flag = False for flag in kwds.get('extra_compile_args', []): if flag.startswith("-std="): if cplusplus and "++" not in flag: continue # Skip -std=c99 and similar for C++ have_std_flag = True cflags.append(flag) if not have_std_flag: # See Trac #23919 if sys.platform == 'cygwin': # Cygwin (particularly newlib, Cygwin's libc) has some bugs # with strict ANSI C/C++ in some headers; using the GNU # extensions typically fares better: # https://trac.sagemath.org/ticket/24192 if cplusplus: cflags.append("-std=gnu++11") else: cflags.append("-std=gnu99") else: if cplusplus: cflags.append("-std=c++11") else: cflags.append("-std=c99") cflags = extra_compile_args + cflags kwds['extra_compile_args'] = stable_uniq(cflags) # Process extra_link_args ldflags = kwds.get('extra_link_args', []) + extra_link_args kwds['extra_link_args'] = stable_uniq(ldflags) # Process library_dirs lib_dirs = kwds.get('library_dirs', []) + library_dirs kwds['library_dirs'] = stable_uniq(lib_dirs) # Process include_dirs inc_dirs = kwds.get('include_dirs', []) + include_dirs + [self.build_dir] kwds['include_dirs'] = stable_uniq(inc_dirs) return default_create_extension(template, kwds)
def prepare_extension(self, ext): sources = ext.sources if sources is None or not isinstance(sources, (list, tuple)): raise DistutilsSetupError(("in 'ext_modules' option (extension '%s'), " + "'sources' must be present and must be " + "a list of source filenames") % ext.name) sources = list(sources) fullname = self.get_ext_fullname(ext.name) if self.inplace: # ignore build-lib -- put the compiled extension into # the source tree along with pure Python modules modpath = string.split(fullname, '.') package = string.join(modpath[0:-1], '.') base = modpath[-1] build_py = self.get_finalized_command('build_py') package_dir = build_py.get_package_dir(package) ext_filename = os.path.join(package_dir, self.get_ext_filename(base)) relative_ext_filename = self.get_ext_filename(base) else: ext_filename = os.path.join(self.build_lib, self.get_ext_filename(fullname)) relative_ext_filename = self.get_ext_filename(fullname) # while dispatching the calls to gcc in parallel, we sometimes # hit a race condition where two separate build_ext objects # try to create a given directory at the same time; whoever # loses the race then seems to throw an error, saying that # the directory already exists. so, instead of fighting to # fix the race condition, we simply make sure the entire # directory tree exists now, while we're processing the # extensions in serial. relative_ext_dir = os.path.split(relative_ext_filename)[0] prefixes = ['', self.build_lib, self.build_temp] for prefix in prefixes: path = os.path.join(prefix, relative_ext_dir) try: os.makedirs(path) except OSError as e: assert e.errno==errno.EEXIST, 'Cannot create %s.' % path depends = sources + ext.depends if not (self.force or newer_group(depends, ext_filename, 'newer')): log.debug("skipping '%s' extension (up-to-date)", ext.name) need_to_compile = False elif getattr(ext, "skip_build", False): log.debug("skipping '%s' extension (optional)", ext.name) need_to_compile = False else: log.info("building '%s' extension", ext.name) need_to_compile = True # If we need to compile, adjust the given extension if need_to_compile: libs = ext.libraries if ext.language == 'c++' and 'stdc++' not in libs: libs = libs + ['stdc++'] # Sort libraries according to library_order ext.libraries = sorted(libs, key=lambda x: library_order.get(x, 0)) return need_to_compile, (sources, ext, ext_filename)