123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392 |
- import os
- import subprocess
- import tempfile
- import sys
- import distutils
- from distutils.msvccompiler import MSVCCompiler
- from distutils.unixccompiler import UnixCCompiler
- from distutils.cygwinccompiler import Mingw32CCompiler
- from distutils.sysconfig import customize_compiler
- from . import utils
- class CCompiler(object):
- compiler_cmd = ''
- compiler = None
- _cflags_no_deprecation_warnings = ''
- def __init__(self,
- environ=os.environ,
- osname=os.name,
- compiler_name=None):
- if osname == 'nt':
-
-
-
-
- if compiler_name is None:
- if environ.get('MSYSTEM') == 'MINGW32' or environ.get('MSYSTEM') == 'MINGW64':
- compiler_name = 'mingw32'
- else:
- compiler_name = distutils.ccompiler.get_default_compiler()
- if compiler_name != 'msvc' and \
- compiler_name != 'mingw32':
- raise SystemExit('Specified Compiler \'%s\' is unsupported.' % compiler_name)
- else:
-
-
- compiler_name = distutils.ccompiler.get_default_compiler()
-
- if compiler_name == 'msvc':
-
-
-
- from . import msvccompiler
- self.compiler = msvccompiler.get_msvc_compiler()
- else:
- self.compiler = distutils.ccompiler.new_compiler(compiler=compiler_name)
- customize_compiler(self.compiler)
-
-
-
-
- if isinstance(self.compiler, Mingw32CCompiler):
- if self.compiler.dll_libraries != ['msvcrt']:
- self.compiler.dll_libraries = []
- if self.compiler.preprocessor is None:
- self.compiler.preprocessor = self.compiler.compiler + ['-E']
- if self.check_is_msvc():
-
-
-
-
-
- os.environ['DISTUTILS_USE_SDK'] = '1'
- if 'MSSdk' not in os.environ:
- if 'WindowsSDKDir' in os.environ:
- os.environ['MSSdk'] = os.environ.get('WindowsSDKDir')
- elif os.environ.get('VCInstallDir'):
- os.environ['MSSdk'] = os.environ.get('VCInstallDir')
- self.compiler_cmd = 'cl.exe'
- self._cflags_no_deprecation_warnings = "-wd4996"
- else:
- if (isinstance(self.compiler, Mingw32CCompiler)):
- self.compiler_cmd = self.compiler.compiler[0]
- else:
- self.compiler_cmd = ' '.join(self.compiler.compiler)
- self._cflags_no_deprecation_warnings = "-Wno-deprecated-declarations"
- def get_internal_link_flags(self, args, libtool, libraries, libpaths):
-
-
- if not libtool:
-
- if self.check_is_msvc():
- for library in libraries:
-
-
- self.compiler.add_library(library)
- for libpath in libpaths:
- self.compiler.add_library_dir(libpath)
- else:
-
-
- self.compiler.add_library_dir('.')
- if os.name != 'nt':
- self.compiler.add_runtime_library_dir('.')
-
- args.append('-Wl,-rpath,.')
-
-
- if sys.platform != 'darwin':
- args.append('-Wl,--no-as-needed')
- for library in libraries:
- self.compiler.add_library(library)
- if not self.check_is_msvc():
- for library_path in libpaths:
- args.append('-L' + library_path)
- if os.path.isabs(library_path):
- args.append('-Wl,-rpath,' + library_path)
- else:
-
- args.append('-L.')
- for library in libraries:
- if library.endswith(".la"):
- args.append(library)
- else:
- args.append('-l' + library)
- for library_path in libpaths:
- args.append('-L' + library_path)
- if os.path.isabs(library_path):
- args.append('-rpath')
- args.append(library_path)
- def get_external_link_flags(self, args, libtool, libraries):
-
-
-
- for library in libraries:
- if not libtool:
- self.compiler.add_library(library)
- else:
- if library.endswith(".la"):
- args.append(library)
- else:
- args.append('-l' + library)
- def preprocess(self, source, output, cpp_options):
- extra_postargs = ['-C']
- (include_paths, macros, postargs) = self._set_cpp_options(cpp_options)
-
- include_dirs = ['.']
- include_dirs.extend(include_paths)
- extra_postargs.extend(postargs)
-
-
-
- if self.check_is_msvc():
- macros.append(('_USE_DECLSPECS_FOR_SAL', None))
- macros.append(('_CRT_SECURE_NO_WARNINGS', None))
- macros.append(('_CRT_NONSTDC_NO_WARNINGS', None))
- macros.append(('SAL_NO_ATTRIBUTE_DECLARATIONS', None))
- self.compiler.preprocess(source=source,
- output_file=output,
- macros=macros,
- include_dirs=include_dirs,
- extra_postargs=extra_postargs)
- def compile(self, pkg_config_cflags, cpp_includes, source, init_sections):
- extra_postargs = []
- includes = []
- source_str = ''.join(source)
- tmpdir_idx = source_str.rfind(os.sep, 0, source_str.rfind(os.sep))
- (include_paths, macros, extra_args) = \
- self._set_cpp_options(pkg_config_cflags)
- for include in cpp_includes:
- includes.append(include)
- if isinstance(self.compiler, UnixCCompiler):
-
- cflags = os.environ.get('CFLAGS')
- if cflags:
- for i, cflag in enumerate(cflags.split()):
- if cflag.startswith('-D'):
- stridx = cflag.find('=')
- if stridx > -1:
- macroset = (cflag[2:stridx],
- cflag[stridx + 1:])
- else:
- macroset = (cflag[2:], None)
- if macroset not in macros:
- macros.append(macroset)
-
-
- if self.compiler_cmd == 'gcc' and not init_sections:
- extra_postargs.append('-Wall')
- extra_postargs.append(self._cflags_no_deprecation_warnings)
- includes.extend(include_paths)
- extra_postargs.extend(extra_args)
- return self.compiler.compile(sources=source,
- macros=macros,
- include_dirs=includes,
- extra_postargs=extra_postargs,
- output_dir=str(source_str[tmpdir_idx + 1:
- source_str.rfind(os.sep)]))
- def link(self, output, objects, lib_args):
-
- extra_preargs = []
- extra_postargs = []
- library_dirs = []
- libraries = []
- for arg in lib_args:
- extra_postargs.append(arg)
- self.compiler.link(target_desc=self.compiler.EXECUTABLE,
- objects=objects,
- output_filename=output,
- extra_preargs=extra_preargs,
- extra_postargs=extra_postargs)
- def resolve_windows_libs(self, libraries, options):
- args = []
- libsearch = []
-
- if self.check_is_msvc():
-
-
-
- libpath = os.environ.get('LIB')
- libsearch = libpath.split(';')
-
-
-
-
-
-
-
- args.append('dumpbin.exe')
- args.append('-symbols')
-
- else:
- libtool = utils.get_libtool_command(options)
- if libtool:
- if os.name == 'nt':
- args.append(utils.which(os.environ.get('SHELL', 'sh.exe')))
- args.extend(libtool)
- args.append('--mode=execute')
- args.extend([os.environ.get('DLLTOOL', 'dlltool.exe'), '--identify'])
- proc = subprocess.Popen([self.compiler_cmd, '-print-search-dirs'],
- stdout=subprocess.PIPE)
- o, e = proc.communicate()
- for line in o.decode('ascii').splitlines():
- if line.startswith('libraries: '):
- libsearch = line[len('libraries: '):].split(os.pathsep)
- shlibs = []
- not_resolved = []
- for lib in libraries:
- found = False
- candidates = [
- 'lib%s.dll.a' % lib,
- 'lib%s.a' % lib,
- '%s.dll.a' % lib,
- '%s.a' % lib,
- '%s.lib' % lib,
- ]
- for l in libsearch:
- if found:
- break
- if l.startswith('='):
- l = l[1:]
- for c in candidates:
- if found:
- break
- implib = os.path.join(l, c)
- if os.path.exists(implib):
- if self.check_is_msvc():
- tmp_fd, tmp_filename = \
- tempfile.mkstemp(prefix='g-ir-win32-resolve-lib-')
-
-
-
-
-
- os.close(tmp_fd)
- output_flag = ['-out:' + tmp_filename]
- proc = subprocess.call(args + [implib] + output_flag,
- stdout=subprocess.PIPE)
- with open(tmp_filename, 'r') as tmp_fileobj:
- for line in tmp_fileobj.read().splitlines():
- if '__IMPORT_DESCRIPTOR_' in line:
- line_tokens = line.split()
- for item in line_tokens:
- if item.startswith('__IMPORT_DESCRIPTOR_'):
- shlibs.append(item[20:] + '.dll')
- found = True
- break
- tmp_fileobj.close()
- os.unlink(tmp_filename)
- else:
- proc = subprocess.Popen(args + [implib],
- stdout=subprocess.PIPE)
- o, e = proc.communicate()
- for line in o.decode('ascii').splitlines():
- shlibs.append(line)
- found = True
- break
- if not found:
- not_resolved.append(lib)
- if len(not_resolved) > 0:
- raise SystemExit(
- "ERROR: can't resolve libraries to shared libraries: " +
- ", ".join(not_resolved))
- return shlibs
- def check_is_msvc(self):
- if isinstance(self.compiler, MSVCCompiler):
- return True
- else:
- return False
-
- def _set_cpp_options(self, options):
- includes = []
- macros = []
- other_options = []
- for o in options:
- option = utils.cflag_real_include_path(o)
- if option.startswith('-I'):
- includes.append(option[len('-I'):])
- elif option.startswith('-D'):
- macro = option[len('-D'):]
- macro_index = macro.find('=')
- if macro_index == -1:
- macro_name = macro
- macro_value = None
- else:
- macro_name = macro[:macro_index]
- macro_value = macro[macro_index + 1:]
- macros.append((macro_name, macro_value))
- elif option.startswith('-U'):
- macros.append((option[len('-U'):],))
- else:
-
-
- if option not in ['-g3', '-ggdb3', '-gstabs3', '-gcoff3', '-gxcoff3', '-gvms3']:
- other_options.append(option)
- return (includes, macros, other_options)
|