1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633 |
- # Copyright 2012-2017 The Meson development team
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- # http://www.apache.org/licenses/LICENSE-2.0
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- import contextlib, os.path, re, tempfile, shlex
- import subprocess
- from ..linkers import StaticLinker
- from .. import coredata
- from .. import mlog
- from .. import mesonlib
- from ..mesonlib import EnvironmentException, MesonException, version_compare, Popen_safe
- """This file contains the data files of all compilers Meson knows
- about. To support a new compiler, add its information below.
- Also add corresponding autodetection code in environment.py."""
- header_suffixes = ('h', 'hh', 'hpp', 'hxx', 'H', 'ipp', 'moc', 'vapi', 'di')
- obj_suffixes = ('o', 'obj', 'res')
- lib_suffixes = ('a', 'lib', 'dll', 'dylib', 'so')
- # Mapping of language to suffixes of files that should always be in that language
- # This means we can't include .h headers here since they could be C, C++, ObjC, etc.
- lang_suffixes = {
- 'c': ('c',),
- 'cpp': ('cpp', 'cc', 'cxx', 'c++', 'hh', 'hpp', 'ipp', 'hxx'),
- # f90, f95, f03, f08 are for free-form fortran ('f90' recommended)
- # f, for, ftn, fpp are for fixed-form fortran ('f' or 'for' recommended)
- 'fortran': ('f90', 'f95', 'f03', 'f08', 'f', 'for', 'ftn', 'fpp'),
- 'd': ('d', 'di'),
- 'objc': ('m',),
- 'objcpp': ('mm',),
- 'rust': ('rs',),
- 'vala': ('vala', 'vapi', 'gs'),
- 'cs': ('cs',),
- 'swift': ('swift',),
- 'java': ('java',),
- }
- all_languages = lang_suffixes.keys()
- cpp_suffixes = lang_suffixes['cpp'] + ('h',)
- c_suffixes = lang_suffixes['c'] + ('h',)
- # List of languages that by default consume and output libraries following the
- # C ABI; these can generally be used interchangebly
- clib_langs = ('objcpp', 'cpp', 'objc', 'c', 'fortran',)
- # List of languages that can be linked with C code directly by the linker
- # used in build.py:process_compilers() and build.py:get_dynamic_linker()
- # XXX: Add Rust to this?
- clink_langs = ('d',) + clib_langs
- clink_suffixes = ()
- for _l in clink_langs + ('vala',):
- clink_suffixes += lang_suffixes[_l]
- clink_suffixes += ('h', 'll', 's')
- soregex = re.compile(r'.*\.so(\.[0-9]+)?(\.[0-9]+)?(\.[0-9]+)?$')
- # Environment variables that each lang uses.
- cflags_mapping = {'c': 'CFLAGS',
- 'cpp': 'CXXFLAGS',
- 'objc': 'OBJCFLAGS',
- 'objcpp': 'OBJCXXFLAGS',
- 'fortran': 'FFLAGS',
- 'd': 'DFLAGS',
- 'vala': 'VALAFLAGS',
- 'rust': 'RUSTFLAGS'}
- # All these are only for C-linkable languages; see `clink_langs` above.
- def sort_clink(lang):
- '''
- Sorting function to sort the list of languages according to
- reversed(compilers.clink_langs) and append the unknown langs in the end.
- The purpose is to prefer C over C++ for files that can be compiled by
- both such as assembly, C, etc. Also applies to ObjC, ObjC++, etc.
- '''
- if lang not in clink_langs:
- return 1
- return -clink_langs.index(lang)
- def is_header(fname):
- if hasattr(fname, 'fname'):
- fname = fname.fname
- suffix = fname.split('.')[-1]
- return suffix in header_suffixes
- def is_source(fname):
- if hasattr(fname, 'fname'):
- fname = fname.fname
- suffix = fname.split('.')[-1].lower()
- return suffix in clink_suffixes
- def is_assembly(fname):
- if hasattr(fname, 'fname'):
- fname = fname.fname
- return fname.split('.')[-1].lower() == 's'
- def is_llvm_ir(fname):
- if hasattr(fname, 'fname'):
- fname = fname.fname
- return fname.split('.')[-1] == 'll'
- def is_object(fname):
- if hasattr(fname, 'fname'):
- fname = fname.fname
- suffix = fname.split('.')[-1]
- return suffix in obj_suffixes
- def is_library(fname):
- if hasattr(fname, 'fname'):
- fname = fname.fname
- if soregex.match(fname):
- return True
- suffix = fname.split('.')[-1]
- return suffix in lib_suffixes
- gnulike_buildtype_args = {'plain': [],
- # -O0 is passed for improved debugging information with gcc
- # See https://github.com/mesonbuild/meson/pull/509
- 'debug': ['-O0', '-g'],
- 'debugoptimized': ['-O2', '-g'],
- 'release': ['-O3'],
- 'minsize': ['-Os', '-g']}
- armclang_buildtype_args = {'plain': [],
- 'debug': ['-O0', '-g'],
- 'debugoptimized': ['-O1', '-g'],
- 'release': ['-Os'],
- 'minsize': ['-Oz']}
- arm_buildtype_args = {'plain': [],
- 'debug': ['-O0', '--debug'],
- 'debugoptimized': ['-O1', '--debug'],
- 'release': ['-O3', '-Otime'],
- 'minsize': ['-O3', '-Ospace'],
- }
- msvc_buildtype_args = {'plain': [],
- 'debug': ["/MDd", "/ZI", "/Ob0", "/Od", "/RTC1"],
- 'debugoptimized': ["/MD", "/Zi", "/O2", "/Ob1"],
- 'release': ["/MD", "/O2", "/Ob2"],
- 'minsize': ["/MD", "/Zi", "/Os", "/Ob1"],
- }
- apple_buildtype_linker_args = {'plain': [],
- 'debug': [],
- 'debugoptimized': [],
- 'release': [],
- 'minsize': [],
- }
- gnulike_buildtype_linker_args = {'plain': [],
- 'debug': [],
- 'debugoptimized': [],
- 'release': ['-Wl,-O1'],
- 'minsize': [],
- }
- arm_buildtype_linker_args = {'plain': [],
- 'debug': [],
- 'debugoptimized': [],
- 'release': [],
- 'minsize': [],
- }
- msvc_buildtype_linker_args = {'plain': [],
- 'debug': [],
- 'debugoptimized': [],
- # The otherwise implicit REF and ICF linker
- # optimisations are disabled by /DEBUG.
- # REF implies ICF.
- 'release': ['/OPT:REF'],
- 'minsize': ['/INCREMENTAL:NO', '/OPT:REF'],
- }
- java_buildtype_args = {'plain': [],
- 'debug': ['-g'],
- 'debugoptimized': ['-g'],
- 'release': [],
- 'minsize': [],
- }
- rust_buildtype_args = {'plain': [],
- 'debug': ['-C', 'debuginfo=2'],
- 'debugoptimized': ['-C', 'debuginfo=2', '-C', 'opt-level=2'],
- 'release': ['-C', 'opt-level=3'],
- 'minsize': [], # In a future release: ['-C', 'opt-level=s'],
- }
- d_gdc_buildtype_args = {'plain': [],
- 'debug': ['-g', '-O0'],
- 'debugoptimized': ['-g', '-O'],
- 'release': ['-O3', '-frelease'],
- 'minsize': [],
- }
- d_ldc_buildtype_args = {'plain': [],
- 'debug': ['-g', '-O0'],
- 'debugoptimized': ['-g', '-O'],
- 'release': ['-O3', '-release'],
- 'minsize': [],
- }
- d_dmd_buildtype_args = {'plain': [],
- 'debug': ['-g'],
- 'debugoptimized': ['-g', '-O'],
- 'release': ['-O', '-release'],
- 'minsize': [],
- }
- mono_buildtype_args = {'plain': [],
- 'debug': ['-debug'],
- 'debugoptimized': ['-debug', '-optimize+'],
- 'release': ['-optimize+'],
- 'minsize': [],
- }
- swift_buildtype_args = {'plain': [],
- 'debug': ['-g'],
- 'debugoptimized': ['-g', '-O'],
- 'release': ['-O'],
- 'minsize': [],
- }
- gnu_winlibs = ['-lkernel32', '-luser32', '-lgdi32', '-lwinspool', '-lshell32',
- '-lole32', '-loleaut32', '-luuid', '-lcomdlg32', '-ladvapi32']
- msvc_winlibs = ['kernel32.lib', 'user32.lib', 'gdi32.lib',
- 'winspool.lib', 'shell32.lib', 'ole32.lib', 'oleaut32.lib',
- 'uuid.lib', 'comdlg32.lib', 'advapi32.lib']
- gnu_color_args = {'auto': ['-fdiagnostics-color=auto'],
- 'always': ['-fdiagnostics-color=always'],
- 'never': ['-fdiagnostics-color=never'],
- }
- clang_color_args = {'auto': ['-Xclang', '-fcolor-diagnostics'],
- 'always': ['-Xclang', '-fcolor-diagnostics'],
- 'never': ['-Xclang', '-fno-color-diagnostics'],
- }
- base_options = {'b_pch': coredata.UserBooleanOption('b_pch', 'Use precompiled headers', True),
- 'b_lto': coredata.UserBooleanOption('b_lto', 'Use link time optimization', False),
- 'b_sanitize': coredata.UserComboOption('b_sanitize',
- 'Code sanitizer to use',
- ['none', 'address', 'thread', 'undefined', 'memory', 'address,undefined'],
- 'none'),
- 'b_lundef': coredata.UserBooleanOption('b_lundef', 'Use -Wl,--no-undefined when linking', True),
- 'b_asneeded': coredata.UserBooleanOption('b_asneeded', 'Use -Wl,--as-needed when linking', True),
- 'b_pgo': coredata.UserComboOption('b_pgo', 'Use profile guided optimization',
- ['off', 'generate', 'use'],
- 'off'),
- 'b_coverage': coredata.UserBooleanOption('b_coverage',
- 'Enable coverage tracking.',
- False),
- 'b_colorout': coredata.UserComboOption('b_colorout', 'Use colored output',
- ['auto', 'always', 'never'],
- 'always'),
- 'b_ndebug': coredata.UserComboOption('b_ndebug', 'Disable asserts',
- ['true', 'false', 'if-release'], 'false'),
- 'b_staticpic': coredata.UserBooleanOption('b_staticpic',
- 'Build static libraries as position independent',
- True),
- 'b_bitcode': coredata.UserBooleanOption('b_bitcode',
- 'Generate and embed bitcode (only macOS and iOS)',
- False),
- }
- gnulike_instruction_set_args = {'mmx': ['-mmmx'],
- 'sse': ['-msse'],
- 'sse2': ['-msse2'],
- 'sse3': ['-msse3'],
- 'ssse3': ['-mssse3'],
- 'sse41': ['-msse4.1'],
- 'sse42': ['-msse4.2'],
- 'avx': ['-mavx'],
- 'avx2': ['-mavx2'],
- 'neon': ['-mfpu=neon'],
- }
- vs32_instruction_set_args = {'mmx': ['/arch:SSE'], # There does not seem to be a flag just for MMX
- 'sse': ['/arch:SSE'],
- 'sse2': ['/arch:SSE2'],
- 'sse3': ['/arch:AVX'], # VS leaped from SSE2 directly to AVX.
- 'sse41': ['/arch:AVX'],
- 'sse42': ['/arch:AVX'],
- 'avx': ['/arch:AVX'],
- 'avx2': ['/arch:AVX2'],
- 'neon': None,
- }
- # The 64 bit compiler defaults to /arch:avx.
- vs64_instruction_set_args = {'mmx': ['/arch:AVX'],
- 'sse': ['/arch:AVX'],
- 'sse2': ['/arch:AVX'],
- 'sse3': ['/arch:AVX'],
- 'ssse3': ['/arch:AVX'],
- 'sse41': ['/arch:AVX'],
- 'sse42': ['/arch:AVX'],
- 'avx': ['/arch:AVX'],
- 'avx2': ['/arch:AVX2'],
- 'neon': None,
- }
- def sanitizer_compile_args(value):
- if value == 'none':
- return []
- args = ['-fsanitize=' + value]
- if 'address' in value: # For -fsanitize=address,undefined
- args.append('-fno-omit-frame-pointer')
- return args
- def sanitizer_link_args(value):
- if value == 'none':
- return []
- args = ['-fsanitize=' + value]
- return args
- def option_enabled(boptions, options, option):
- try:
- if option not in boptions:
- return False
- return options[option].value
- except KeyError:
- return False
- def get_base_compile_args(options, compiler):
- args = []
- # FIXME, gcc/clang specific.
- try:
- if options['b_lto'].value:
- args.append('-flto')
- except KeyError:
- pass
- try:
- args += compiler.get_colorout_args(options['b_colorout'].value)
- except KeyError:
- pass
- try:
- args += sanitizer_compile_args(options['b_sanitize'].value)
- except KeyError:
- pass
- try:
- pgo_val = options['b_pgo'].value
- if pgo_val == 'generate':
- args.append('-fprofile-generate')
- elif pgo_val == 'use':
- args.append('-fprofile-use')
- except KeyError:
- pass
- try:
- if options['b_coverage'].value:
- args += compiler.get_coverage_args()
- except KeyError:
- pass
- try:
- if (options['b_ndebug'].value == 'true' or
- (options['b_ndebug'].value == 'if-release' and
- options['buildtype'].value == 'release')):
- args += ['-DNDEBUG']
- except KeyError:
- pass
- # This does not need a try...except
- if option_enabled(compiler.base_options, options, 'b_bitcode'):
- args.append('-fembed-bitcode')
- return args
- def get_base_link_args(options, linker, is_shared_module):
- args = []
- # FIXME, gcc/clang specific.
- try:
- if options['b_lto'].value:
- args.append('-flto')
- except KeyError:
- pass
- try:
- args += sanitizer_link_args(options['b_sanitize'].value)
- except KeyError:
- pass
- try:
- pgo_val = options['b_pgo'].value
- if pgo_val == 'generate':
- args.append('-fprofile-generate')
- elif pgo_val == 'use':
- args.append('-fprofile-use')
- except KeyError:
- pass
- try:
- if options['b_coverage'].value:
- args += linker.get_coverage_link_args()
- except KeyError:
- pass
- # These do not need a try...except
- if not is_shared_module and option_enabled(linker.base_options, options, 'b_lundef'):
- args.append('-Wl,--no-undefined')
- as_needed = option_enabled(linker.base_options, options, 'b_asneeded')
- bitcode = option_enabled(linker.base_options, options, 'b_bitcode')
- # Shared modules cannot be built with bitcode_bundle because
- # -bitcode_bundle is incompatible with -undefined and -bundle
- if bitcode and not is_shared_module:
- args.append('-Wl,-bitcode_bundle')
- elif as_needed:
- # -Wl,-dead_strip_dylibs is incompatible with bitcode
- args.append(linker.get_asneeded_args())
- return args
- class CrossNoRunException(MesonException):
- pass
- class RunResult:
- def __init__(self, compiled, returncode=999, stdout='UNDEFINED', stderr='UNDEFINED'):
- self.compiled = compiled
- self.returncode = returncode
- self.stdout = stdout
- self.stderr = stderr
- class CompilerArgs(list):
- '''
- Class derived from list() that manages a list of compiler arguments. Should
- be used while constructing compiler arguments from various sources. Can be
- operated with ordinary lists, so this does not need to be used everywhere.
- All arguments must be inserted and stored in GCC-style (-lfoo, -Idir, etc)
- and can converted to the native type of each compiler by using the
- .to_native() method to which you must pass an instance of the compiler or
- the compiler class.
- New arguments added to this class (either with .append(), .extend(), or +=)
- are added in a way that ensures that they override previous arguments.
- For example:
- >>> a = ['-Lfoo', '-lbar']
- >>> a += ['-Lpho', '-lbaz']
- >>> print(a)
- ['-Lpho', '-Lfoo', '-lbar', '-lbaz']
- Arguments will also be de-duped if they can be de-duped safely.
- Note that because of all this, this class is not commutative and does not
- preserve the order of arguments if it is safe to not. For example:
- >>> ['-Ifoo', '-Ibar'] + ['-Ifez', '-Ibaz', '-Werror']
- ['-Ifez', '-Ibaz', '-Ifoo', '-Ibar', '-Werror']
- >>> ['-Ifez', '-Ibaz', '-Werror'] + ['-Ifoo', '-Ibar']
- ['-Ifoo', '-Ibar', '-Ifez', '-Ibaz', '-Werror']
- '''
- # NOTE: currently this class is only for C-like compilers, but it can be
- # extended to other languages easily. Just move the following to the
- # compiler class and initialize when self.compiler is set.
- # Arg prefixes that override by prepending instead of appending
- prepend_prefixes = ('-I', '-L')
- # Arg prefixes and args that must be de-duped by returning 2
- dedup2_prefixes = ('-I', '-L', '-D', '-U')
- dedup2_suffixes = ()
- dedup2_args = ()
- # Arg prefixes and args that must be de-duped by returning 1
- dedup1_prefixes = ('-l',)
- dedup1_suffixes = ('.lib', '.dll', '.so', '.dylib', '.a')
- # Match a .so of the form path/to/libfoo.so.0.1.0
- # Only UNIX shared libraries require this. Others have a fixed extension.
- dedup1_regex = re.compile(r'([\/\\]|\A)lib.*\.so(\.[0-9]+)?(\.[0-9]+)?(\.[0-9]+)?$')
- dedup1_args = ('-c', '-S', '-E', '-pipe', '-pthread')
- compiler = None
- def _check_args(self, args):
- cargs = []
- if len(args) > 2:
- raise TypeError("CompilerArgs() only accepts at most 2 arguments: "
- "The compiler, and optionally an initial list")
- elif not args:
- return cargs
- elif len(args) == 1:
- if isinstance(args[0], (Compiler, StaticLinker)):
- self.compiler = args[0]
- else:
- raise TypeError("you must pass a Compiler instance as one of "
- "the arguments")
- elif len(args) == 2:
- if isinstance(args[0], (Compiler, StaticLinker)):
- self.compiler = args[0]
- cargs = args[1]
- elif isinstance(args[1], (Compiler, StaticLinker)):
- cargs = args[0]
- self.compiler = args[1]
- else:
- raise TypeError("you must pass a Compiler instance as one of "
- "the two arguments")
- else:
- raise AssertionError('Not reached')
- return cargs
- def __init__(self, *args):
- super().__init__(self._check_args(args))
- @classmethod
- def _can_dedup(cls, arg):
- '''
- Returns whether the argument can be safely de-duped. This is dependent
- on three things:
- a) Whether an argument can be 'overridden' by a later argument. For
- example, -DFOO defines FOO and -UFOO undefines FOO. In this case, we
- can safely remove the previous occurrence and add a new one. The same
- is true for include paths and library paths with -I and -L. For
- these we return `2`. See `dedup2_prefixes` and `dedup2_args`.
- b) Arguments that once specified cannot be undone, such as `-c` or
- `-pipe`. New instances of these can be completely skipped. For these
- we return `1`. See `dedup1_prefixes` and `dedup1_args`.
- c) Whether it matters where or how many times on the command-line
- a particular argument is present. This can matter for symbol
- resolution in static or shared libraries, so we cannot de-dup or
- reorder them. For these we return `0`. This is the default.
- In addition to these, we handle library arguments specially.
- With GNU ld, we surround library arguments with -Wl,--start/end-group
- to recursively search for symbols in the libraries. This is not needed
- with other linkers.
- '''
- # A standalone argument must never be deduplicated because it is
- # defined by what comes _after_ it. Thus dedupping this:
- # -D FOO -D BAR
- # would yield either
- # -D FOO BAR
- # or
- # FOO -D BAR
- # both of which are invalid.
- if arg in cls.dedup2_prefixes:
- return 0
- if arg in cls.dedup2_args or \
- arg.startswith(cls.dedup2_prefixes) or \
- arg.endswith(cls.dedup2_suffixes):
- return 2
- if arg in cls.dedup1_args or \
- arg.startswith(cls.dedup1_prefixes) or \
- arg.endswith(cls.dedup1_suffixes) or \
- re.search(cls.dedup1_regex, arg):
- return 1
- return 0
- @classmethod
- def _should_prepend(cls, arg):
- if arg.startswith(cls.prepend_prefixes):
- return True
- return False
- def to_native(self):
- # Check if we need to add --start/end-group for circular dependencies
- # between static libraries, and for recursively searching for symbols
- # needed by static libraries that are provided by object files or
- # shared libraries.
- if get_compiler_uses_gnuld(self.compiler):
- global soregex
- group_start = -1
- for each in self:
- if not each.startswith('-l') and not each.endswith('.a') and \
- not soregex.match(each):
- continue
- i = self.index(each)
- if group_start < 0:
- # First occurrence of a library
- group_start = i
- if group_start >= 0:
- # Last occurrence of a library
- self.insert(i + 1, '-Wl,--end-group')
- self.insert(group_start, '-Wl,--start-group')
- return self.compiler.unix_args_to_native(self)
- def append_direct(self, arg):
- '''
- Append the specified argument without any reordering or de-dup
- except for absolute paths where the order of include search directories
- is not relevant
- '''
- if os.path.isabs(arg):
- self.append(arg)
- else:
- super().append(arg)
- def extend_direct(self, iterable):
- '''
- Extend using the elements in the specified iterable without any
- reordering or de-dup except for absolute paths where the order of
- include search directories is not relevant
- '''
- for elem in iterable:
- self.append_direct(elem)
- def __add__(self, args):
- new = CompilerArgs(self, self.compiler)
- new += args
- return new
- def __iadd__(self, args):
- '''
- Add two CompilerArgs while taking into account overriding of arguments
- and while preserving the order of arguments as much as possible
- '''
- pre = []
- post = []
- if not isinstance(args, list):
- raise TypeError('can only concatenate list (not "{}") to list'.format(args))
- for arg in args:
- # If the argument can be de-duped, do it either by removing the
- # previous occurrence of it and adding a new one, or not adding the
- # new occurrence.
- dedup = self._can_dedup(arg)
- if dedup == 1:
- # Argument already exists and adding a new instance is useless
- if arg in self or arg in pre or arg in post:
- continue
- if dedup == 2:
- # Remove all previous occurrences of the arg and add it anew
- if arg in self:
- self.remove(arg)
- if arg in pre:
- pre.remove(arg)
- if arg in post:
- post.remove(arg)
- if self._should_prepend(arg):
- pre.append(arg)
- else:
- post.append(arg)
- # Insert at the beginning
- self[:0] = pre
- # Append to the end
- super().__iadd__(post)
- return self
- def __radd__(self, args):
- new = CompilerArgs(args, self.compiler)
- new += self
- return new
- def __mul__(self, args):
- raise TypeError("can't multiply compiler arguments")
- def __imul__(self, args):
- raise TypeError("can't multiply compiler arguments")
- def __rmul__(self, args):
- raise TypeError("can't multiply compiler arguments")
- def append(self, arg):
- self.__iadd__([arg])
- def extend(self, args):
- self.__iadd__(args)
- class Compiler:
- # Libraries to ignore in find_library() since they are provided by the
- # compiler or the C library. Currently only used for MSVC.
- ignore_libs = ()
- # Cache for the result of compiler checks which can be cached
- compiler_check_cache = {}
- def __init__(self, exelist, version, **kwargs):
- if isinstance(exelist, str):
- self.exelist = [exelist]
- elif isinstance(exelist, list):
- self.exelist = exelist
- else:
- raise TypeError('Unknown argument to Compiler')
- # In case it's been overridden by a child class already
- if not hasattr(self, 'file_suffixes'):
- self.file_suffixes = lang_suffixes[self.language]
- if not hasattr(self, 'can_compile_suffixes'):
- self.can_compile_suffixes = set(self.file_suffixes)
- self.default_suffix = self.file_suffixes[0]
- self.version = version
- if 'full_version' in kwargs:
- self.full_version = kwargs['full_version']
- else:
- self.full_version = None
- self.base_options = []
- def __repr__(self):
- repr_str = "<{0}: v{1} `{2}`>"
- return repr_str.format(self.__class__.__name__, self.version,
- ' '.join(self.exelist))
- def can_compile(self, src):
- if hasattr(src, 'fname'):
- src = src.fname
- suffix = os.path.splitext(src)[1].lower()
- if suffix and suffix[1:] in self.can_compile_suffixes:
- return True
- return False
- def get_id(self):
- return self.id
- def get_language(self):
- return self.language
- def get_display_language(self):
- return self.language.capitalize()
- def get_default_suffix(self):
- return self.default_suffix
- def get_define(self, dname, prefix, env, extra_args, dependencies):
- raise EnvironmentException('%s does not support get_define ' % self.get_id())
- def compute_int(self, expression, low, high, guess, prefix, env, extra_args, dependencies):
- raise EnvironmentException('%s does not support compute_int ' % self.get_id())
- def has_members(self, typename, membernames, prefix, env, extra_args=None, dependencies=None):
- raise EnvironmentException('%s does not support has_member(s) ' % self.get_id())
- def has_type(self, typename, prefix, env, extra_args, dependencies=None):
- raise EnvironmentException('%s does not support has_type ' % self.get_id())
- def symbols_have_underscore_prefix(self, env):
- raise EnvironmentException('%s does not support symbols_have_underscore_prefix ' % self.get_id())
- def get_exelist(self):
- return self.exelist[:]
- def get_builtin_define(self, *args, **kwargs):
- raise EnvironmentException('%s does not support get_builtin_define.' % self.id)
- def has_builtin_define(self, *args, **kwargs):
- raise EnvironmentException('%s does not support has_builtin_define.' % self.id)
- def get_always_args(self):
- return []
- def can_linker_accept_rsp(self):
- """
- Determines whether the linker can accept arguments using the @rsp syntax.
- """
- return mesonlib.is_windows()
- def get_linker_always_args(self):
- return []
- def gen_import_library_args(self, implibname):
- """
- Used only on Windows for libraries that need an import library.
- This currently means C, C++, Fortran.
- """
- return []
- def get_preproc_flags(self):
- if self.get_language() in ('c', 'cpp', 'objc', 'objcpp'):
- return os.environ.get('CPPFLAGS', '')
- return ''
- def get_args_from_envvars(self):
- """
- Returns a tuple of (compile_flags, link_flags) for the specified language
- from the inherited environment
- """
- def log_var(var, val):
- if val:
- mlog.log('Appending {} from environment: {!r}'.format(var, val))
- lang = self.get_language()
- compiler_is_linker = False
- if hasattr(self, 'get_linker_exelist'):
- compiler_is_linker = (self.get_exelist() == self.get_linker_exelist())
- if lang not in cflags_mapping:
- return [], []
- compile_flags = os.environ.get(cflags_mapping[lang], '')
- log_var(cflags_mapping[lang], compile_flags)
- compile_flags = shlex.split(compile_flags)
- # Link flags (same for all languages)
- link_flags = os.environ.get('LDFLAGS', '')
- log_var('LDFLAGS', link_flags)
- link_flags = shlex.split(link_flags)
- if compiler_is_linker:
- # When the compiler is used as a wrapper around the linker (such as
- # with GCC and Clang), the compile flags can be needed while linking
- # too. This is also what Autotools does. However, we don't want to do
- # this when the linker is stand-alone such as with MSVC C/C++, etc.
- link_flags = compile_flags + link_flags
- # Pre-processor flags (not for fortran or D)
- preproc_flags = self.get_preproc_flags()
- log_var('CPPFLAGS', preproc_flags)
- preproc_flags = shlex.split(preproc_flags)
- compile_flags += preproc_flags
- return compile_flags, link_flags
- def get_options(self):
- opts = {} # build afresh every time
- # Take default values from env variables.
- compile_args, link_args = self.get_args_from_envvars()
- description = 'Extra arguments passed to the {}'.format(self.get_display_language())
- opts.update({
- self.language + '_args': coredata.UserArrayOption(
- self.language + '_args',
- description + ' compiler',
- compile_args, shlex_split=True, user_input=True),
- self.language + '_link_args': coredata.UserArrayOption(
- self.language + '_link_args',
- description + ' linker',
- link_args, shlex_split=True, user_input=True),
- })
- return opts
- def get_option_compile_args(self, options):
- return []
- def get_option_link_args(self, options):
- return []
- def check_header(self, *args, **kwargs):
- raise EnvironmentException('Language %s does not support header checks.' % self.get_display_language())
- def has_header(self, *args, **kwargs):
- raise EnvironmentException('Language %s does not support header checks.' % self.get_display_language())
- def has_header_symbol(self, *args, **kwargs):
- raise EnvironmentException('Language %s does not support header symbol checks.' % self.get_display_language())
- def compiles(self, *args, **kwargs):
- raise EnvironmentException('Language %s does not support compile checks.' % self.get_display_language())
- def links(self, *args, **kwargs):
- raise EnvironmentException('Language %s does not support link checks.' % self.get_display_language())
- def run(self, *args, **kwargs):
- raise EnvironmentException('Language %s does not support run checks.' % self.get_display_language())
- def sizeof(self, *args, **kwargs):
- raise EnvironmentException('Language %s does not support sizeof checks.' % self.get_display_language())
- def alignment(self, *args, **kwargs):
- raise EnvironmentException('Language %s does not support alignment checks.' % self.get_display_language())
- def has_function(self, *args, **kwargs):
- raise EnvironmentException('Language %s does not support function checks.' % self.get_display_language())
- @classmethod
- def unix_args_to_native(cls, args):
- "Always returns a copy that can be independently mutated"
- return args[:]
- def find_library(self, *args, **kwargs):
- raise EnvironmentException('Language {} does not support library finding.'.format(self.get_display_language()))
- def get_library_dirs(self):
- return []
- def has_multi_arguments(self, args, env):
- raise EnvironmentException(
- 'Language {} does not support has_multi_arguments.'.format(
- self.get_display_language()))
- def has_multi_link_arguments(self, args, env):
- raise EnvironmentException(
- 'Language {} does not support has_multi_link_arguments.'.format(
- self.get_display_language()))
- def get_cross_extra_flags(self, environment, link):
- extra_flags = []
- if self.is_cross and environment:
- if 'properties' in environment.cross_info.config:
- props = environment.cross_info.config['properties']
- lang_args_key = self.language + '_args'
- extra_flags += props.get(lang_args_key, [])
- lang_link_args_key = self.language + '_link_args'
- if link:
- extra_flags += props.get(lang_link_args_key, [])
- return extra_flags
- def _get_compile_output(self, dirname, mode):
- # In pre-processor mode, the output is sent to stdout and discarded
- if mode == 'preprocess':
- return None
- # Extension only matters if running results; '.exe' is
- # guaranteed to be executable on every platform.
- if mode == 'link':
- suffix = 'exe'
- else:
- suffix = 'obj'
- return os.path.join(dirname, 'output.' + suffix)
- @contextlib.contextmanager
- def compile(self, code, extra_args=None, mode='link', want_output=False):
- if extra_args is None:
- textra_args = None
- extra_args = []
- else:
- textra_args = tuple(extra_args)
- key = (code, textra_args, mode)
- if not want_output:
- if key in self.compiler_check_cache:
- p = self.compiler_check_cache[key]
- mlog.debug('Using cached compile:')
- mlog.debug('Cached command line: ', ' '.join(p.commands), '\n')
- mlog.debug('Code:\n', code)
- mlog.debug('Cached compiler stdout:\n', p.stdo)
- mlog.debug('Cached compiler stderr:\n', p.stde)
- yield p
- return
- try:
- with tempfile.TemporaryDirectory() as tmpdirname:
- if isinstance(code, str):
- srcname = os.path.join(tmpdirname,
- 'testfile.' + self.default_suffix)
- with open(srcname, 'w') as ofile:
- ofile.write(code)
- elif isinstance(code, mesonlib.File):
- srcname = code.fname
- # Construct the compiler command-line
- commands = CompilerArgs(self)
- commands.append(srcname)
- commands += self.get_always_args()
- if mode == 'compile':
- commands += self.get_compile_only_args()
- # Preprocess mode outputs to stdout, so no output args
- if mode == 'preprocess':
- commands += self.get_preprocess_only_args()
- else:
- output = self._get_compile_output(tmpdirname, mode)
- commands += self.get_output_args(output)
- # extra_args must be last because it could contain '/link' to
- # pass args to VisualStudio's linker. In that case everything
- # in the command line after '/link' is given to the linker.
- commands += extra_args
- # Generate full command-line with the exelist
- commands = self.get_exelist() + commands.to_native()
- mlog.debug('Running compile:')
- mlog.debug('Working directory: ', tmpdirname)
- mlog.debug('Command line: ', ' '.join(commands), '\n')
- mlog.debug('Code:\n', code)
- p, p.stdo, p.stde = Popen_safe(commands, cwd=tmpdirname)
- mlog.debug('Compiler stdout:\n', p.stdo)
- mlog.debug('Compiler stderr:\n', p.stde)
- p.commands = commands
- p.input_name = srcname
- if want_output:
- p.output_name = output
- else:
- self.compiler_check_cache[key] = p
- yield p
- except (PermissionError, OSError):
- # On Windows antivirus programs and the like hold on to files so
- # they can't be deleted. There's not much to do in this case. Also,
- # catch OSError because the directory is then no longer empty.
- pass
- def get_colorout_args(self, colortype):
- return []
- # Some compilers (msvc) write debug info to a separate file.
- # These args specify where it should be written.
- def get_compile_debugfile_args(self, rel_obj, **kwargs):
- return []
- def get_link_debugfile_args(self, rel_obj):
- return []
- def get_std_shared_lib_link_args(self):
- return []
- def get_std_shared_module_link_args(self, options):
- return self.get_std_shared_lib_link_args()
- def get_link_whole_for(self, args):
- if isinstance(args, list) and not args:
- return []
- raise EnvironmentException('Language %s does not support linking whole archives.' % self.get_display_language())
- # Compiler arguments needed to enable the given instruction set.
- # May be [] meaning nothing needed or None meaning the given set
- # is not supported.
- def get_instruction_set_args(self, instruction_set):
- return None
- def build_osx_rpath_args(self, build_dir, rpath_paths, build_rpath):
- if not rpath_paths and not build_rpath:
- return []
- # On OSX, rpaths must be absolute.
- abs_rpaths = [os.path.join(build_dir, p) for p in rpath_paths]
- if build_rpath != '':
- abs_rpaths.append(build_rpath)
- # Ensure that there is enough space for large RPATHs
- args = ['-Wl,-headerpad_max_install_names']
- args += ['-Wl,-rpath,' + rp for rp in abs_rpaths]
- return args
- def build_unix_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath):
- if not rpath_paths and not install_rpath and not build_rpath:
- return []
- # The rpaths we write must be relative, because otherwise
- # they have different length depending on the build
- # directory. This breaks reproducible builds.
- rel_rpaths = []
- for p in rpath_paths:
- if p == from_dir:
- relative = '' # relpath errors out in this case
- else:
- relative = os.path.relpath(os.path.join(build_dir, p), os.path.join(build_dir, from_dir))
- rel_rpaths.append(relative)
- paths = ':'.join([os.path.join('$ORIGIN', p) for p in rel_rpaths])
- # Build_rpath is used as-is (it is usually absolute).
- if build_rpath != '':
- if paths != '':
- paths += ':'
- paths += build_rpath
- if len(paths) < len(install_rpath):
- padding = 'X' * (len(install_rpath) - len(paths))
- if not paths:
- paths = padding
- else:
- paths = paths + ':' + padding
- args = []
- if mesonlib.is_dragonflybsd() or mesonlib.is_openbsd():
- # This argument instructs the compiler to record the value of
- # ORIGIN in the .dynamic section of the elf. On Linux this is done
- # by default, but is not on dragonfly/openbsd for some reason. Without this
- # $ORIGIN in the runtime path will be undefined and any binaries
- # linked against local libraries will fail to resolve them.
- args.append('-Wl,-z,origin')
- args.append('-Wl,-rpath,' + paths)
- if get_compiler_is_linuxlike(self):
- # Rpaths to use while linking must be absolute. These are not
- # written to the binary. Needed only with GNU ld:
- # https://sourceware.org/bugzilla/show_bug.cgi?id=16936
- # Not needed on Windows or other platforms that don't use RPATH
- # https://github.com/mesonbuild/meson/issues/1897
- lpaths = ':'.join([os.path.join(build_dir, p) for p in rpath_paths])
- # clang expands '-Wl,rpath-link,' to ['-rpath-link'] instead of ['-rpath-link','']
- # This eats the next argument, which happens to be 'ldstdc++', causing link failures.
- # We can dodge this problem by not adding any rpath_paths if the argument is empty.
- if lpaths.strip() != '':
- args += ['-Wl,-rpath-link,' + lpaths]
- return args
- def thread_flags(self, env):
- return []
- def openmp_flags(self):
- raise EnvironmentException('Language %s does not support OpenMP flags.' % self.get_display_language())
- def language_stdlib_only_link_flags(self):
- # The linker flags needed to link the standard library of the current
- # language in. This is needed in cases where you e.g. combine D and C++
- # and both of which need to link their runtime library in or otherwise
- # building fails with undefined symbols.
- return []
- GCC_STANDARD = 0
- GCC_OSX = 1
- GCC_MINGW = 2
- GCC_CYGWIN = 3
- CLANG_STANDARD = 0
- CLANG_OSX = 1
- CLANG_WIN = 2
- # Possibly clang-cl?
- ICC_STANDARD = 0
- ICC_OSX = 1
- ICC_WIN = 2
- # GNU ld cannot be installed on macOS
- # https://github.com/Homebrew/homebrew-core/issues/17794#issuecomment-328174395
- # Hence, we don't need to differentiate between OS and ld
- # for the sake of adding as-needed support
- GNU_LD_AS_NEEDED = '-Wl,--as-needed'
- APPLE_LD_AS_NEEDED = '-Wl,-dead_strip_dylibs'
- def get_macos_dylib_install_name(prefix, shlib_name, suffix, soversion):
- install_name = prefix + shlib_name
- if soversion is not None:
- install_name += '.' + soversion
- install_name += '.dylib'
- return '@rpath/' + install_name
- def get_gcc_soname_args(gcc_type, prefix, shlib_name, suffix, soversion, is_shared_module):
- if soversion is None:
- sostr = ''
- else:
- sostr = '.' + soversion
- if gcc_type == GCC_STANDARD:
- return ['-Wl,-soname,%s%s.%s%s' % (prefix, shlib_name, suffix, sostr)]
- elif gcc_type in (GCC_MINGW, GCC_CYGWIN):
- # For PE/COFF the soname argument has no effect with GNU LD
- return []
- elif gcc_type == GCC_OSX:
- if is_shared_module:
- return []
- name = get_macos_dylib_install_name(prefix, shlib_name, suffix, soversion)
- return ['-install_name', name]
- else:
- raise RuntimeError('Not implemented yet.')
- def get_compiler_is_linuxlike(compiler):
- if (getattr(compiler, 'gcc_type', None) == GCC_STANDARD) or \
- (getattr(compiler, 'clang_type', None) == CLANG_STANDARD) or \
- (getattr(compiler, 'icc_type', None) == ICC_STANDARD):
- return True
- return False
- def get_compiler_uses_gnuld(c):
- # FIXME: Perhaps we should detect the linker in the environment?
- # FIXME: Assumes that *BSD use GNU ld, but they might start using lld soon
- if (getattr(c, 'gcc_type', None) in (GCC_STANDARD, GCC_MINGW, GCC_CYGWIN)) or \
- (getattr(c, 'clang_type', None) in (CLANG_STANDARD, CLANG_WIN)) or \
- (getattr(c, 'icc_type', None) in (ICC_STANDARD, ICC_WIN)):
- return True
- return False
- def get_largefile_args(compiler):
- '''
- Enable transparent large-file-support for 32-bit UNIX systems
- '''
- if get_compiler_is_linuxlike(compiler):
- # Enable large-file support unconditionally on all platforms other
- # than macOS and Windows. macOS is now 64-bit-only so it doesn't
- # need anything special, and Windows doesn't have automatic LFS.
- # You must use the 64-bit counterparts explicitly.
- # glibc, musl, and uclibc, and all BSD libcs support this. On Android,
- # support for transparent LFS is available depending on the version of
- # Bionic: https://github.com/android/platform_bionic#32-bit-abi-bugs
- # https://code.google.com/p/android/issues/detail?id=64613
- #
- # If this breaks your code, fix it! It's been 20+ years!
- return ['-D_FILE_OFFSET_BITS=64']
- # We don't enable -D_LARGEFILE64_SOURCE since that enables
- # transitionary features and must be enabled by programs that use
- # those features explicitly.
- return []
- # TODO: The result from calling compiler should be cached. So that calling this
- # function multiple times don't add latency.
- def gnulike_default_include_dirs(compiler, lang):
- if lang == 'cpp':
- lang = 'c++'
- env = os.environ.copy()
- env["LC_ALL"] = 'C'
- cmd = compiler + ['-x{}'.format(lang), '-E', '-v', '-']
- p = subprocess.Popen(
- cmd,
- stdin=subprocess.DEVNULL,
- stderr=subprocess.PIPE,
- stdout=subprocess.PIPE,
- env=env
- )
- stderr = p.stderr.read().decode('utf-8', errors='replace')
- parse_state = 0
- paths = []
- for line in stderr.split('\n'):
- if parse_state == 0:
- if line == '#include "..." search starts here:':
- parse_state = 1
- elif parse_state == 1:
- if line == '#include <...> search starts here:':
- parse_state = 2
- else:
- paths.append(line[1:])
- elif parse_state == 2:
- if line == 'End of search list.':
- break
- else:
- paths.append(line[1:])
- if len(paths) == 0:
- mlog.warning('No include directory found parsing "{cmd}" output'.format(cmd=" ".join(cmd)))
- return paths
- class GnuCompiler:
- # Functionality that is common to all GNU family compilers.
- def __init__(self, gcc_type, defines):
- self.id = 'gcc'
- self.gcc_type = gcc_type
- self.defines = defines or {}
- self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage',
- 'b_colorout', 'b_ndebug', 'b_staticpic']
- if self.gcc_type == GCC_OSX:
- self.base_options.append('b_bitcode')
- else:
- self.base_options.append('b_lundef')
- self.base_options.append('b_asneeded')
- # All GCC backends can do assembly
- self.can_compile_suffixes.add('s')
- # TODO: centralise this policy more globally, instead
- # of fragmenting it into GnuCompiler and ClangCompiler
- def get_asneeded_args(self):
- if self.gcc_type == GCC_OSX:
- return APPLE_LD_AS_NEEDED
- else:
- return GNU_LD_AS_NEEDED
- def get_colorout_args(self, colortype):
- if mesonlib.version_compare(self.version, '>=4.9.0'):
- return gnu_color_args[colortype][:]
- return []
- def get_warn_args(self, level):
- args = super().get_warn_args(level)
- if mesonlib.version_compare(self.version, '<4.8.0') and '-Wpedantic' in args:
- # -Wpedantic was added in 4.8.0
- # https://gcc.gnu.org/gcc-4.8/changes.html
- args[args.index('-Wpedantic')] = '-pedantic'
- return args
- def has_builtin_define(self, define):
- return define in self.defines
- def get_builtin_define(self, define):
- if define in self.defines:
- return self.defines[define]
- def get_pic_args(self):
- if self.gcc_type in (GCC_CYGWIN, GCC_MINGW, GCC_OSX):
- return [] # On Window and OS X, pic is always on.
- return ['-fPIC']
- def get_buildtype_args(self, buildtype):
- return gnulike_buildtype_args[buildtype]
- def get_buildtype_linker_args(self, buildtype):
- if self.gcc_type == GCC_OSX:
- return apple_buildtype_linker_args[buildtype]
- return gnulike_buildtype_linker_args[buildtype]
- def get_pch_suffix(self):
- return 'gch'
- def split_shlib_to_parts(self, fname):
- return os.path.dirname(fname), fname
- def get_soname_args(self, prefix, shlib_name, suffix, soversion, is_shared_module):
- return get_gcc_soname_args(self.gcc_type, prefix, shlib_name, suffix, soversion, is_shared_module)
- def get_std_shared_lib_link_args(self):
- return ['-shared']
- def get_link_whole_for(self, args):
- return ['-Wl,--whole-archive'] + args + ['-Wl,--no-whole-archive']
- def gen_vs_module_defs_args(self, defsfile):
- if not isinstance(defsfile, str):
- raise RuntimeError('Module definitions file should be str')
- # On Windows targets, .def files may be specified on the linker command
- # line like an object file.
- if self.gcc_type in (GCC_CYGWIN, GCC_MINGW):
- return [defsfile]
- # For other targets, discard the .def file.
- return []
- def get_gui_app_args(self):
- if self.gcc_type in (GCC_CYGWIN, GCC_MINGW):
- return ['-mwindows']
- return []
- def get_instruction_set_args(self, instruction_set):
- return gnulike_instruction_set_args.get(instruction_set, None)
- def get_default_include_dirs(self):
- return gnulike_default_include_dirs(self.exelist, self.language)
- def openmp_flags(self):
- return ['-fopenmp']
- class ElbrusCompiler(GnuCompiler):
- # Elbrus compiler is nearly like GCC, but does not support
- # PCH, LTO, sanitizers and color output as of version 1.21.x.
- def __init__(self, gcc_type, defines):
- GnuCompiler.__init__(self, gcc_type, defines)
- self.id = 'lcc'
- self.base_options = ['b_pgo', 'b_coverage',
- 'b_ndebug', 'b_staticpic',
- 'b_lundef', 'b_asneeded']
- def get_library_dirs(self):
- env = os.environ.copy()
- env['LC_ALL'] = 'C'
- stdo = Popen_safe(self.exelist + ['--print-search-dirs'], env=env)[1]
- paths = []
- for line in stdo.split('\n'):
- if line.startswith('libraries:'):
- # lcc does not include '=' in --print-search-dirs output.
- libstr = line.split(' ', 1)[1]
- paths = [os.path.realpath(p) for p in libstr.split(':')]
- break
- return paths
- def get_program_dirs(self):
- env = os.environ.copy()
- env['LC_ALL'] = 'C'
- stdo = Popen_safe(self.exelist + ['--print-search-dirs'], env=env)[1]
- paths = []
- for line in stdo.split('\n'):
- if line.startswith('programs:'):
- # lcc does not include '=' in --print-search-dirs output.
- libstr = line.split(' ', 1)[1]
- paths = [os.path.realpath(p) for p in libstr.split(':')]
- break
- return paths
- class ClangCompiler:
- def __init__(self, clang_type):
- self.id = 'clang'
- self.clang_type = clang_type
- self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage',
- 'b_ndebug', 'b_staticpic', 'b_colorout']
- if self.clang_type == CLANG_OSX:
- self.base_options.append('b_bitcode')
- else:
- self.base_options.append('b_lundef')
- self.base_options.append('b_asneeded')
- # All Clang backends can do assembly and LLVM IR
- self.can_compile_suffixes.update(['ll', 's'])
- # TODO: centralise this policy more globally, instead
- # of fragmenting it into GnuCompiler and ClangCompiler
- def get_asneeded_args(self):
- if self.clang_type == CLANG_OSX:
- return APPLE_LD_AS_NEEDED
- else:
- return GNU_LD_AS_NEEDED
- def get_pic_args(self):
- if self.clang_type in (CLANG_WIN, CLANG_OSX):
- return [] # On Window and OS X, pic is always on.
- return ['-fPIC']
- def get_colorout_args(self, colortype):
- return clang_color_args[colortype][:]
- def get_buildtype_args(self, buildtype):
- return gnulike_buildtype_args[buildtype]
- def get_buildtype_linker_args(self, buildtype):
- if self.clang_type == CLANG_OSX:
- return apple_buildtype_linker_args[buildtype]
- return gnulike_buildtype_linker_args[buildtype]
- def get_pch_suffix(self):
- return 'pch'
- def get_pch_use_args(self, pch_dir, header):
- # Workaround for Clang bug http://llvm.org/bugs/show_bug.cgi?id=15136
- # This flag is internal to Clang (or at least not documented on the man page)
- # so it might change semantics at any time.
- return ['-include-pch', os.path.join(pch_dir, self.get_pch_name(header))]
- def get_soname_args(self, prefix, shlib_name, suffix, soversion, is_shared_module):
- if self.clang_type == CLANG_STANDARD:
- gcc_type = GCC_STANDARD
- elif self.clang_type == CLANG_OSX:
- gcc_type = GCC_OSX
- elif self.clang_type == CLANG_WIN:
- gcc_type = GCC_MINGW
- else:
- raise MesonException('Unreachable code when converting clang type to gcc type.')
- return get_gcc_soname_args(gcc_type, prefix, shlib_name, suffix, soversion, is_shared_module)
- def has_multi_arguments(self, args, env):
- myargs = ['-Werror=unknown-warning-option', '-Werror=unused-command-line-argument']
- if mesonlib.version_compare(self.version, '>=3.6.0'):
- myargs.append('-Werror=ignored-optimization-argument')
- return super().has_multi_arguments(
- myargs + args,
- env)
- def has_function(self, funcname, prefix, env, extra_args=None, dependencies=None):
- if extra_args is None:
- extra_args = []
- # Starting with XCode 8, we need to pass this to force linker
- # visibility to obey OS X and iOS minimum version targets with
- # -mmacosx-version-min, -miphoneos-version-min, etc.
- # https://github.com/Homebrew/homebrew-core/issues/3727
- if self.clang_type == CLANG_OSX and version_compare(self.version, '>=8.0'):
- extra_args.append('-Wl,-no_weak_imports')
- return super().has_function(funcname, prefix, env, extra_args, dependencies)
- def get_std_shared_module_link_args(self, options):
- if self.clang_type == CLANG_OSX:
- return ['-bundle', '-Wl,-undefined,dynamic_lookup']
- return ['-shared']
- def get_link_whole_for(self, args):
- if self.clang_type == CLANG_OSX:
- result = []
- for a in args:
- result += ['-Wl,-force_load', a]
- return result
- return ['-Wl,--whole-archive'] + args + ['-Wl,--no-whole-archive']
- def get_instruction_set_args(self, instruction_set):
- return gnulike_instruction_set_args.get(instruction_set, None)
- def get_default_include_dirs(self):
- return gnulike_default_include_dirs(self.exelist, self.language)
- def openmp_flags(self):
- if version_compare(self.version, '>=3.8.0'):
- return ['-fopenmp']
- elif version_compare(self.version, '>=3.7.0'):
- return ['-fopenmp=libomp']
- else:
- # Shouldn't work, but it'll be checked explicitly in the OpenMP dependency.
- return []
- class ArmclangCompiler:
- def __init__(self):
- if not self.is_cross:
- raise EnvironmentException('armclang supports only cross-compilation.')
- # Check whether 'armlink.exe' is available in path
- self.linker_exe = 'armlink.exe'
- args = '--vsn'
- try:
- p, stdo, stderr = Popen_safe(self.linker_exe, args)
- except OSError as e:
- err_msg = 'Unknown linker\nRunning "{0}" gave \n"{1}"'.format(' '.join([self.linker_exe] + [args]), e)
- raise EnvironmentException(err_msg)
- # Verify the armlink version
- ver_str = re.search('.*Component.*', stdo)
- if ver_str:
- ver_str = ver_str.group(0)
- else:
- EnvironmentException('armlink version string not found')
- # Using the regular expression from environment.search_version,
- # which is used for searching compiler version
- version_regex = '(?<!(\d|\.))(\d{1,2}(\.\d+)+(-[a-zA-Z0-9]+)?)'
- linker_ver = re.search(version_regex, ver_str)
- if linker_ver:
- linker_ver = linker_ver.group(0)
- if not version_compare(self.version, '==' + linker_ver):
- raise EnvironmentException('armlink version does not match with compiler version')
- self.id = 'armclang'
- self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage',
- 'b_ndebug', 'b_staticpic', 'b_colorout']
- # Assembly
- self.can_compile_suffixes.update('s')
- def can_linker_accept_rsp(self):
- return False
- def get_pic_args(self):
- # PIC support is not enabled by default for ARM,
- # if users want to use it, they need to add the required arguments explicitly
- return []
- def get_colorout_args(self, colortype):
- return clang_color_args[colortype][:]
- def get_buildtype_args(self, buildtype):
- return armclang_buildtype_args[buildtype]
- def get_buildtype_linker_args(self, buildtype):
- return arm_buildtype_linker_args[buildtype]
- # Override CCompiler.get_std_shared_lib_link_args
- def get_std_shared_lib_link_args(self):
- return []
- def get_pch_suffix(self):
- return 'gch'
- def get_pch_use_args(self, pch_dir, header):
- # Workaround for Clang bug http://llvm.org/bugs/show_bug.cgi?id=15136
- # This flag is internal to Clang (or at least not documented on the man page)
- # so it might change semantics at any time.
- return ['-include-pch', os.path.join(pch_dir, self.get_pch_name(header))]
- # Override CCompiler.get_dependency_gen_args
- def get_dependency_gen_args(self, outtarget, outfile):
- return []
- # Override CCompiler.build_rpath_args
- def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath):
- return []
- def get_linker_exelist(self):
- return [self.linker_exe]
- # Tested on linux for ICC 14.0.3, 15.0.6, 16.0.4, 17.0.1
- class IntelCompiler:
- def __init__(self, icc_type):
- self.id = 'intel'
- self.icc_type = icc_type
- self.lang_header = 'none'
- self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage',
- 'b_colorout', 'b_ndebug', 'b_staticpic', 'b_lundef', 'b_asneeded']
- # Assembly
- self.can_compile_suffixes.add('s')
- def get_pic_args(self):
- return ['-fPIC']
- def get_buildtype_args(self, buildtype):
- return gnulike_buildtype_args[buildtype]
- def get_buildtype_linker_args(self, buildtype):
- return gnulike_buildtype_linker_args[buildtype]
- def get_pch_suffix(self):
- return 'pchi'
- def get_pch_use_args(self, pch_dir, header):
- return ['-pch', '-pch_dir', os.path.join(pch_dir), '-x',
- self.lang_header, '-include', header, '-x', 'none']
- def get_pch_name(self, header_name):
- return os.path.basename(header_name) + '.' + self.get_pch_suffix()
- def split_shlib_to_parts(self, fname):
- return os.path.dirname(fname), fname
- def get_soname_args(self, prefix, shlib_name, suffix, soversion, is_shared_module):
- if self.icc_type == ICC_STANDARD:
- gcc_type = GCC_STANDARD
- elif self.icc_type == ICC_OSX:
- gcc_type = GCC_OSX
- elif self.icc_type == ICC_WIN:
- gcc_type = GCC_MINGW
- else:
- raise MesonException('Unreachable code when converting icc type to gcc type.')
- return get_gcc_soname_args(gcc_type, prefix, shlib_name, suffix, soversion, is_shared_module)
- # TODO: centralise this policy more globally, instead
- # of fragmenting it into GnuCompiler and ClangCompiler
- def get_asneeded_args(self):
- if self.icc_type == CLANG_OSX:
- return APPLE_LD_AS_NEEDED
- else:
- return GNU_LD_AS_NEEDED
- def get_std_shared_lib_link_args(self):
- # FIXME: Don't know how icc works on OSX
- # if self.icc_type == ICC_OSX:
- # return ['-bundle']
- return ['-shared']
- def get_default_include_dirs(self):
- return gnulike_default_include_dirs(self.exelist, self.language)
- def openmp_flags(self):
- if version_compare(self.version, '>=15.0.0'):
- return ['-qopenmp']
- else:
- return ['-openmp']
- class ArmCompiler:
- # Functionality that is common to all ARM family compilers.
- def __init__(self):
- if not self.is_cross:
- raise EnvironmentException('armcc supports only cross-compilation.')
- self.id = 'arm'
- default_warn_args = []
- self.warn_args = {'1': default_warn_args,
- '2': default_warn_args + [],
- '3': default_warn_args + []}
- # Assembly
- self.can_compile_suffixes.add('s')
- def can_linker_accept_rsp(self):
- return False
- def get_pic_args(self):
- # FIXME: Add /ropi, /rwpi, /fpic etc. qualifiers to --apcs
- return []
- def get_buildtype_args(self, buildtype):
- return arm_buildtype_args[buildtype]
- def get_buildtype_linker_args(self, buildtype):
- return arm_buildtype_linker_args[buildtype]
- # Override CCompiler.get_always_args
- def get_always_args(self):
- return []
- # Override CCompiler.get_dependency_gen_args
- def get_dependency_gen_args(self, outtarget, outfile):
- return []
- # Override CCompiler.get_std_shared_lib_link_args
- def get_std_shared_lib_link_args(self):
- return []
- def get_pch_use_args(self, pch_dir, header):
- # FIXME: Add required arguments
- # NOTE from armcc user guide:
- # "Support for Precompiled Header (PCH) files is deprecated from ARM Compiler 5.05
- # onwards on all platforms. Note that ARM Compiler on Windows 8 never supported
- # PCH files."
- return []
- def get_pch_suffix(self):
- # NOTE from armcc user guide:
- # "Support for Precompiled Header (PCH) files is deprecated from ARM Compiler 5.05
- # onwards on all platforms. Note that ARM Compiler on Windows 8 never supported
- # PCH files."
- return 'pch'
- def thread_flags(self, env):
- return []
- def thread_link_flags(self, env):
- return []
- def get_linker_exelist(self):
- args = ['armlink']
- return args
- def get_coverage_args(self):
- return []
- def get_coverage_link_args(self):
- return []
|