clike.py 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134
  1. # Copyright 2012-2017 The Meson development team
  2. # Licensed under the Apache License, Version 2.0 (the "License");
  3. # you may not use this file except in compliance with the License.
  4. # You may obtain a copy of the License at
  5. # http://www.apache.org/licenses/LICENSE-2.0
  6. # Unless required by applicable law or agreed to in writing, software
  7. # distributed under the License is distributed on an "AS IS" BASIS,
  8. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  9. # See the License for the specific language governing permissions and
  10. # limitations under the License.
  11. """Mixin classes to be shared between C and C++ compilers.
  12. Without this we'll end up with awful diamond inherintance problems. The goal
  13. of this is to have mixin's, which are classes that are designed *not* to be
  14. standalone, they only work through inheritance.
  15. """
  16. import functools
  17. import glob
  18. import itertools
  19. import os
  20. import re
  21. import subprocess
  22. import typing as T
  23. from pathlib import Path
  24. from ... import mesonlib
  25. from ...mesonlib import LibType
  26. from ... import mlog
  27. from .. import compilers
  28. from .visualstudio import VisualStudioLikeCompiler
  29. if T.TYPE_CHECKING:
  30. from ...environment import Environment
  31. class CLikeCompiler:
  32. """Shared bits for the C and CPP Compilers."""
  33. # TODO: Replace this manual cache with functools.lru_cache
  34. library_dirs_cache = {}
  35. program_dirs_cache = {}
  36. find_library_cache = {}
  37. find_framework_cache = {}
  38. internal_libs = compilers.unixy_compiler_internal_libs
  39. def __init__(self, is_cross: bool, exe_wrapper: T.Optional[str] = None):
  40. # If a child ObjC or CPP class has already set it, don't set it ourselves
  41. self.is_cross = is_cross
  42. self.can_compile_suffixes.add('h')
  43. # If the exe wrapper was not found, pretend it wasn't set so that the
  44. # sanity check is skipped and compiler checks use fallbacks.
  45. if not exe_wrapper or not exe_wrapper.found() or not exe_wrapper.get_command():
  46. self.exe_wrapper = None
  47. else:
  48. self.exe_wrapper = exe_wrapper.get_command()
  49. def needs_static_linker(self):
  50. return True # When compiling static libraries, so yes.
  51. def get_always_args(self):
  52. '''
  53. Args that are always-on for all C compilers other than MSVC
  54. '''
  55. return ['-pipe'] + compilers.get_largefile_args(self)
  56. def get_no_stdinc_args(self):
  57. return ['-nostdinc']
  58. def get_no_stdlib_link_args(self):
  59. return ['-nostdlib']
  60. def get_warn_args(self, level):
  61. return self.warn_args[level]
  62. def get_no_warn_args(self):
  63. # Almost every compiler uses this for disabling warnings
  64. return ['-w']
  65. def split_shlib_to_parts(self, fname):
  66. return None, fname
  67. def depfile_for_object(self, objfile):
  68. return objfile + '.' + self.get_depfile_suffix()
  69. def get_depfile_suffix(self):
  70. return 'd'
  71. def get_exelist(self):
  72. return self.exelist[:]
  73. def get_preprocess_only_args(self):
  74. return ['-E', '-P']
  75. def get_compile_only_args(self):
  76. return ['-c']
  77. def get_no_optimization_args(self):
  78. return ['-O0']
  79. def get_compiler_check_args(self):
  80. '''
  81. Get arguments useful for compiler checks such as being permissive in
  82. the code quality and not doing any optimization.
  83. '''
  84. return self.get_no_optimization_args()
  85. def get_output_args(self, target):
  86. return ['-o', target]
  87. def get_werror_args(self):
  88. return ['-Werror']
  89. def get_std_exe_link_args(self):
  90. # TODO: is this a linker property?
  91. return []
  92. def get_include_args(self, path, is_system):
  93. if path == '':
  94. path = '.'
  95. if is_system:
  96. return ['-isystem', path]
  97. return ['-I' + path]
  98. def get_compiler_dirs(self, env: 'Environment', name: str) -> T.List[str]:
  99. '''
  100. Get dirs from the compiler, either `libraries:` or `programs:`
  101. '''
  102. return []
  103. @functools.lru_cache()
  104. def get_library_dirs(self, env, elf_class = None):
  105. dirs = self.get_compiler_dirs(env, 'libraries')
  106. if elf_class is None or elf_class == 0:
  107. return dirs
  108. # if we do have an elf class for 32-bit or 64-bit, we want to check that
  109. # the directory in question contains libraries of the appropriate class. Since
  110. # system directories aren't mixed, we only need to check one file for each
  111. # directory and go by that. If we can't check the file for some reason, assume
  112. # the compiler knows what it's doing, and accept the directory anyway.
  113. retval = []
  114. for d in dirs:
  115. files = [f for f in os.listdir(d) if f.endswith('.so') and os.path.isfile(os.path.join(d, f))]
  116. # if no files, accept directory and move on
  117. if not files:
  118. retval.append(d)
  119. continue
  120. file_to_check = os.path.join(d, files[0])
  121. with open(file_to_check, 'rb') as fd:
  122. header = fd.read(5)
  123. # if file is not an ELF file, it's weird, but accept dir
  124. # if it is elf, and the class matches, accept dir
  125. if header[1:4] != b'ELF' or int(header[4]) == elf_class:
  126. retval.append(d)
  127. # at this point, it's an ELF file which doesn't match the
  128. # appropriate elf_class, so skip this one
  129. return tuple(retval)
  130. @functools.lru_cache()
  131. def get_program_dirs(self, env):
  132. '''
  133. Programs used by the compiler. Also where toolchain DLLs such as
  134. libstdc++-6.dll are found with MinGW.
  135. '''
  136. return self.get_compiler_dirs(env, 'programs')
  137. def get_pic_args(self) -> T.List[str]:
  138. return ['-fPIC']
  139. def name_string(self) -> str:
  140. return ' '.join(self.exelist)
  141. def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]:
  142. return ['-include', os.path.basename(header)]
  143. def get_pch_name(self, header_name: str) -> str:
  144. return os.path.basename(header_name) + '.' + self.get_pch_suffix()
  145. def get_linker_search_args(self, dirname: str) -> T.List[str]:
  146. return self.linker.get_search_args(dirname)
  147. def get_default_include_dirs(self):
  148. return []
  149. def gen_export_dynamic_link_args(self, env: 'Environment') -> T.List[str]:
  150. return self.linker.export_dynamic_args(env)
  151. def gen_import_library_args(self, implibname: str) -> T.List[str]:
  152. return self.linker.import_library_args(implibname)
  153. def sanity_check_impl(self, work_dir, environment, sname, code):
  154. mlog.debug('Sanity testing ' + self.get_display_language() + ' compiler:', ' '.join(self.exelist))
  155. mlog.debug('Is cross compiler: %s.' % str(self.is_cross))
  156. source_name = os.path.join(work_dir, sname)
  157. binname = sname.rsplit('.', 1)[0]
  158. mode = 'link'
  159. if self.is_cross:
  160. binname += '_cross'
  161. if self.exe_wrapper is None:
  162. # Linking cross built apps is painful. You can't really
  163. # tell if you should use -nostdlib or not and for example
  164. # on OSX the compiler binary is the same but you need
  165. # a ton of compiler flags to differentiate between
  166. # arm and x86_64. So just compile.
  167. mode = 'compile'
  168. cargs, largs = self._get_basic_compiler_args(environment, mode)
  169. extra_flags = cargs + self.linker_to_compiler_args(largs)
  170. # Is a valid executable output for all toolchains and platforms
  171. binname += '.exe'
  172. # Write binary check source
  173. binary_name = os.path.join(work_dir, binname)
  174. with open(source_name, 'w') as ofile:
  175. ofile.write(code)
  176. # Compile sanity check
  177. # NOTE: extra_flags must be added at the end. On MSVC, it might contain a '/link' argument
  178. # after which all further arguments will be passed directly to the linker
  179. cmdlist = self.exelist + [source_name] + self.get_output_args(binary_name) + extra_flags
  180. pc, stdo, stde = mesonlib.Popen_safe(cmdlist, cwd=work_dir)
  181. mlog.debug('Sanity check compiler command line:', ' '.join(cmdlist))
  182. mlog.debug('Sanity check compile stdout:')
  183. mlog.debug(stdo)
  184. mlog.debug('-----\nSanity check compile stderr:')
  185. mlog.debug(stde)
  186. mlog.debug('-----')
  187. if pc.returncode != 0:
  188. raise mesonlib.EnvironmentException('Compiler {0} can not compile programs.'.format(self.name_string()))
  189. # Run sanity check
  190. if self.is_cross:
  191. if self.exe_wrapper is None:
  192. # Can't check if the binaries run so we have to assume they do
  193. return
  194. cmdlist = self.exe_wrapper + [binary_name]
  195. else:
  196. cmdlist = [binary_name]
  197. mlog.debug('Running test binary command: ' + ' '.join(cmdlist))
  198. try:
  199. pe = subprocess.Popen(cmdlist)
  200. except Exception as e:
  201. raise mesonlib.EnvironmentException('Could not invoke sanity test executable: %s.' % str(e))
  202. pe.wait()
  203. if pe.returncode != 0:
  204. raise mesonlib.EnvironmentException('Executables created by {0} compiler {1} are not runnable.'.format(self.language, self.name_string()))
  205. def sanity_check(self, work_dir, environment):
  206. code = 'int main(void) { int class=0; return class; }\n'
  207. return self.sanity_check_impl(work_dir, environment, 'sanitycheckc.c', code)
  208. def check_header(self, hname, prefix, env, *, extra_args=None, dependencies=None):
  209. fargs = {'prefix': prefix, 'header': hname}
  210. code = '''{prefix}
  211. #include <{header}>'''
  212. return self.compiles(code.format(**fargs), env, extra_args=extra_args,
  213. dependencies=dependencies)
  214. def has_header(self, hname, prefix, env, *, extra_args=None, dependencies=None, disable_cache=False):
  215. fargs = {'prefix': prefix, 'header': hname}
  216. code = '''{prefix}
  217. #ifdef __has_include
  218. #if !__has_include("{header}")
  219. #error "Header '{header}' could not be found"
  220. #endif
  221. #else
  222. #include <{header}>
  223. #endif'''
  224. return self.compiles(code.format(**fargs), env, extra_args=extra_args,
  225. dependencies=dependencies, mode='preprocess', disable_cache=disable_cache)
  226. def has_header_symbol(self, hname, symbol, prefix, env, *, extra_args=None, dependencies=None):
  227. fargs = {'prefix': prefix, 'header': hname, 'symbol': symbol}
  228. t = '''{prefix}
  229. #include <{header}>
  230. int main(void) {{
  231. /* If it's not defined as a macro, try to use as a symbol */
  232. #ifndef {symbol}
  233. {symbol};
  234. #endif
  235. return 0;
  236. }}'''
  237. return self.compiles(t.format(**fargs), env, extra_args=extra_args,
  238. dependencies=dependencies)
  239. def _get_basic_compiler_args(self, env, mode):
  240. cargs, largs = [], []
  241. # Select a CRT if needed since we're linking
  242. if mode == 'link':
  243. cargs += self.get_linker_debug_crt_args()
  244. # Add CFLAGS/CXXFLAGS/OBJCFLAGS/OBJCXXFLAGS and CPPFLAGS from the env
  245. sys_args = env.coredata.get_external_args(self.for_machine, self.language)
  246. # Apparently it is a thing to inject linker flags both
  247. # via CFLAGS _and_ LDFLAGS, even though the former are
  248. # also used during linking. These flags can break
  249. # argument checks. Thanks, Autotools.
  250. cleaned_sys_args = self.remove_linkerlike_args(sys_args)
  251. cargs += cleaned_sys_args
  252. if mode == 'link':
  253. ld_value = env.lookup_binary_entry(self.for_machine, self.language + '_ld')
  254. if ld_value is not None:
  255. largs += self.use_linker_args(ld_value[0])
  256. # Add LDFLAGS from the env
  257. sys_ld_args = env.coredata.get_external_link_args(self.for_machine, self.language)
  258. # CFLAGS and CXXFLAGS go to both linking and compiling, but we want them
  259. # to only appear on the command line once. Remove dupes.
  260. largs += [x for x in sys_ld_args if x not in sys_args]
  261. cargs += self.get_compiler_args_for_mode(mode)
  262. return cargs, largs
  263. def _get_compiler_check_args(self, env, extra_args: list, dependencies, mode: str = 'compile') -> T.List[str]:
  264. if extra_args is None:
  265. extra_args = []
  266. else:
  267. extra_args = mesonlib.listify(extra_args)
  268. extra_args = mesonlib.listify([e(mode) if callable(e) else e for e in extra_args])
  269. if dependencies is None:
  270. dependencies = []
  271. elif not isinstance(dependencies, list):
  272. dependencies = [dependencies]
  273. # Collect compiler arguments
  274. cargs = compilers.CompilerArgs(self)
  275. largs = []
  276. for d in dependencies:
  277. # Add compile flags needed by dependencies
  278. cargs += d.get_compile_args()
  279. if mode == 'link':
  280. # Add link flags needed to find dependencies
  281. largs += d.get_link_args()
  282. ca, la = self._get_basic_compiler_args(env, mode)
  283. cargs += ca
  284. largs += la
  285. cargs += self.get_compiler_check_args()
  286. # on MSVC compiler and linker flags must be separated by the "/link" argument
  287. # at this point, the '/link' argument may already be part of extra_args, otherwise, it is added here
  288. if self.linker_to_compiler_args([]) == ['/link'] and largs != [] and not ('/link' in extra_args):
  289. extra_args += ['/link']
  290. args = cargs + extra_args + largs
  291. return args
  292. def compiles(self, code: str, env, *,
  293. extra_args: T.Sequence[T.Union[T.Sequence[str], str]] = None,
  294. dependencies=None, mode: str = 'compile', disable_cache=False) -> T.Tuple[bool, bool]:
  295. with self._build_wrapper(code, env, extra_args, dependencies, mode, disable_cache=disable_cache) as p:
  296. return p.returncode == 0, p.cached
  297. def _build_wrapper(self, code: str, env, extra_args, dependencies=None, mode: str = 'compile', want_output: bool = False, disable_cache: bool = False, temp_dir=None) -> T.Tuple[bool, bool]:
  298. args = self._get_compiler_check_args(env, extra_args, dependencies, mode)
  299. if disable_cache or want_output:
  300. return self.compile(code, extra_args=args, mode=mode, want_output=want_output, temp_dir=env.scratch_dir)
  301. return self.cached_compile(code, env.coredata, extra_args=args, mode=mode, temp_dir=env.scratch_dir)
  302. def links(self, code, env, *, extra_args=None, dependencies=None, disable_cache=False):
  303. return self.compiles(code, env, extra_args=extra_args,
  304. dependencies=dependencies, mode='link', disable_cache=disable_cache)
  305. def run(self, code: str, env, *, extra_args=None, dependencies=None):
  306. if self.is_cross and self.exe_wrapper is None:
  307. raise compilers.CrossNoRunException('Can not run test applications in this cross environment.')
  308. with self._build_wrapper(code, env, extra_args, dependencies, mode='link', want_output=True) as p:
  309. if p.returncode != 0:
  310. mlog.debug('Could not compile test file %s: %d\n' % (
  311. p.input_name,
  312. p.returncode))
  313. return compilers.RunResult(False)
  314. if self.is_cross:
  315. cmdlist = self.exe_wrapper + [p.output_name]
  316. else:
  317. cmdlist = p.output_name
  318. try:
  319. pe, so, se = mesonlib.Popen_safe(cmdlist)
  320. except Exception as e:
  321. mlog.debug('Could not run: %s (error: %s)\n' % (cmdlist, e))
  322. return compilers.RunResult(False)
  323. mlog.debug('Program stdout:\n')
  324. mlog.debug(so)
  325. mlog.debug('Program stderr:\n')
  326. mlog.debug(se)
  327. return compilers.RunResult(True, pe.returncode, so, se)
  328. def _compile_int(self, expression, prefix, env, extra_args, dependencies):
  329. fargs = {'prefix': prefix, 'expression': expression}
  330. t = '''#include <stdio.h>
  331. {prefix}
  332. int main(void) {{ static int a[1-2*!({expression})]; a[0]=0; return 0; }}'''
  333. return self.compiles(t.format(**fargs), env, extra_args=extra_args,
  334. dependencies=dependencies)[0]
  335. def cross_compute_int(self, expression, low, high, guess, prefix, env, extra_args, dependencies):
  336. # Try user's guess first
  337. if isinstance(guess, int):
  338. if self._compile_int('%s == %d' % (expression, guess), prefix, env, extra_args, dependencies):
  339. return guess
  340. # If no bounds are given, compute them in the limit of int32
  341. maxint = 0x7fffffff
  342. minint = -0x80000000
  343. if not isinstance(low, int) or not isinstance(high, int):
  344. if self._compile_int('%s >= 0' % (expression), prefix, env, extra_args, dependencies):
  345. low = cur = 0
  346. while self._compile_int('%s > %d' % (expression, cur), prefix, env, extra_args, dependencies):
  347. low = cur + 1
  348. if low > maxint:
  349. raise mesonlib.EnvironmentException('Cross-compile check overflowed')
  350. cur = cur * 2 + 1
  351. if cur > maxint:
  352. cur = maxint
  353. high = cur
  354. else:
  355. high = cur = -1
  356. while self._compile_int('%s < %d' % (expression, cur), prefix, env, extra_args, dependencies):
  357. high = cur - 1
  358. if high < minint:
  359. raise mesonlib.EnvironmentException('Cross-compile check overflowed')
  360. cur = cur * 2
  361. if cur < minint:
  362. cur = minint
  363. low = cur
  364. else:
  365. # Sanity check limits given by user
  366. if high < low:
  367. raise mesonlib.EnvironmentException('high limit smaller than low limit')
  368. condition = '%s <= %d && %s >= %d' % (expression, high, expression, low)
  369. if not self._compile_int(condition, prefix, env, extra_args, dependencies):
  370. raise mesonlib.EnvironmentException('Value out of given range')
  371. # Binary search
  372. while low != high:
  373. cur = low + int((high - low) / 2)
  374. if self._compile_int('%s <= %d' % (expression, cur), prefix, env, extra_args, dependencies):
  375. high = cur
  376. else:
  377. low = cur + 1
  378. return low
  379. def compute_int(self, expression, low, high, guess, prefix, env, *, extra_args=None, dependencies=None):
  380. if extra_args is None:
  381. extra_args = []
  382. if self.is_cross:
  383. return self.cross_compute_int(expression, low, high, guess, prefix, env, extra_args, dependencies)
  384. fargs = {'prefix': prefix, 'expression': expression}
  385. t = '''#include<stdio.h>
  386. {prefix}
  387. int main(void) {{
  388. printf("%ld\\n", (long)({expression}));
  389. return 0;
  390. }};'''
  391. res = self.run(t.format(**fargs), env, extra_args=extra_args,
  392. dependencies=dependencies)
  393. if not res.compiled:
  394. return -1
  395. if res.returncode != 0:
  396. raise mesonlib.EnvironmentException('Could not run compute_int test binary.')
  397. return int(res.stdout)
  398. def cross_sizeof(self, typename, prefix, env, *, extra_args=None, dependencies=None):
  399. if extra_args is None:
  400. extra_args = []
  401. fargs = {'prefix': prefix, 'type': typename}
  402. t = '''#include <stdio.h>
  403. {prefix}
  404. int main(void) {{
  405. {type} something;
  406. return 0;
  407. }}'''
  408. if not self.compiles(t.format(**fargs), env, extra_args=extra_args,
  409. dependencies=dependencies)[0]:
  410. return -1
  411. return self.cross_compute_int('sizeof(%s)' % typename, None, None, None, prefix, env, extra_args, dependencies)
  412. def sizeof(self, typename, prefix, env, *, extra_args=None, dependencies=None):
  413. if extra_args is None:
  414. extra_args = []
  415. fargs = {'prefix': prefix, 'type': typename}
  416. if self.is_cross:
  417. return self.cross_sizeof(typename, prefix, env, extra_args=extra_args,
  418. dependencies=dependencies)
  419. t = '''#include<stdio.h>
  420. {prefix}
  421. int main(void) {{
  422. printf("%ld\\n", (long)(sizeof({type})));
  423. return 0;
  424. }};'''
  425. res = self.run(t.format(**fargs), env, extra_args=extra_args,
  426. dependencies=dependencies)
  427. if not res.compiled:
  428. return -1
  429. if res.returncode != 0:
  430. raise mesonlib.EnvironmentException('Could not run sizeof test binary.')
  431. return int(res.stdout)
  432. def cross_alignment(self, typename, prefix, env, *, extra_args=None, dependencies=None):
  433. if extra_args is None:
  434. extra_args = []
  435. fargs = {'prefix': prefix, 'type': typename}
  436. t = '''#include <stdio.h>
  437. {prefix}
  438. int main(void) {{
  439. {type} something;
  440. return 0;
  441. }}'''
  442. if not self.compiles(t.format(**fargs), env, extra_args=extra_args,
  443. dependencies=dependencies)[0]:
  444. return -1
  445. t = '''#include <stddef.h>
  446. {prefix}
  447. struct tmp {{
  448. char c;
  449. {type} target;
  450. }};'''
  451. return self.cross_compute_int('offsetof(struct tmp, target)', None, None, None, t.format(**fargs), env, extra_args, dependencies)
  452. def alignment(self, typename, prefix, env, *, extra_args=None, dependencies=None):
  453. if extra_args is None:
  454. extra_args = []
  455. if self.is_cross:
  456. return self.cross_alignment(typename, prefix, env, extra_args=extra_args,
  457. dependencies=dependencies)
  458. fargs = {'prefix': prefix, 'type': typename}
  459. t = '''#include <stdio.h>
  460. #include <stddef.h>
  461. {prefix}
  462. struct tmp {{
  463. char c;
  464. {type} target;
  465. }};
  466. int main(void) {{
  467. printf("%d", (int)offsetof(struct tmp, target));
  468. return 0;
  469. }}'''
  470. res = self.run(t.format(**fargs), env, extra_args=extra_args,
  471. dependencies=dependencies)
  472. if not res.compiled:
  473. raise mesonlib.EnvironmentException('Could not compile alignment test.')
  474. if res.returncode != 0:
  475. raise mesonlib.EnvironmentException('Could not run alignment test binary.')
  476. align = int(res.stdout)
  477. if align == 0:
  478. raise mesonlib.EnvironmentException('Could not determine alignment of %s. Sorry. You might want to file a bug.' % typename)
  479. return align
  480. def get_define(self, dname, prefix, env, extra_args, dependencies, disable_cache=False):
  481. delim = '"MESON_GET_DEFINE_DELIMITER"'
  482. fargs = {'prefix': prefix, 'define': dname, 'delim': delim}
  483. code = '''
  484. {prefix}
  485. #ifndef {define}
  486. # define {define}
  487. #endif
  488. {delim}\n{define}'''
  489. args = self._get_compiler_check_args(env, extra_args, dependencies,
  490. mode='preprocess').to_native()
  491. func = lambda: self.cached_compile(code.format(**fargs), env.coredata, extra_args=args, mode='preprocess')
  492. if disable_cache:
  493. func = lambda: self.compile(code.format(**fargs), extra_args=args, mode='preprocess', temp_dir=env.scratch_dir)
  494. with func() as p:
  495. cached = p.cached
  496. if p.returncode != 0:
  497. raise mesonlib.EnvironmentException('Could not get define {!r}'.format(dname))
  498. # Get the preprocessed value after the delimiter,
  499. # minus the extra newline at the end and
  500. # merge string literals.
  501. return self.concatenate_string_literals(p.stdo.split(delim + '\n')[-1][:-1]), cached
  502. def get_return_value(self, fname, rtype, prefix, env, extra_args, dependencies):
  503. if rtype == 'string':
  504. fmt = '%s'
  505. cast = '(char*)'
  506. elif rtype == 'int':
  507. fmt = '%lli'
  508. cast = '(long long int)'
  509. else:
  510. raise AssertionError('BUG: Unknown return type {!r}'.format(rtype))
  511. fargs = {'prefix': prefix, 'f': fname, 'cast': cast, 'fmt': fmt}
  512. code = '''{prefix}
  513. #include <stdio.h>
  514. int main(void) {{
  515. printf ("{fmt}", {cast} {f}());
  516. return 0;
  517. }}'''.format(**fargs)
  518. res = self.run(code, env, extra_args=extra_args, dependencies=dependencies)
  519. if not res.compiled:
  520. m = 'Could not get return value of {}()'
  521. raise mesonlib.EnvironmentException(m.format(fname))
  522. if rtype == 'string':
  523. return res.stdout
  524. elif rtype == 'int':
  525. try:
  526. return int(res.stdout.strip())
  527. except ValueError:
  528. m = 'Return value of {}() is not an int'
  529. raise mesonlib.EnvironmentException(m.format(fname))
  530. @staticmethod
  531. def _no_prototype_templ():
  532. """
  533. Try to find the function without a prototype from a header by defining
  534. our own dummy prototype and trying to link with the C library (and
  535. whatever else the compiler links in by default). This is very similar
  536. to the check performed by Autoconf for AC_CHECK_FUNCS.
  537. """
  538. # Define the symbol to something else since it is defined by the
  539. # includes or defines listed by the user or by the compiler. This may
  540. # include, for instance _GNU_SOURCE which must be defined before
  541. # limits.h, which includes features.h
  542. # Then, undef the symbol to get rid of it completely.
  543. head = '''
  544. #define {func} meson_disable_define_of_{func}
  545. {prefix}
  546. #include <limits.h>
  547. #undef {func}
  548. '''
  549. # Override any GCC internal prototype and declare our own definition for
  550. # the symbol. Use char because that's unlikely to be an actual return
  551. # value for a function which ensures that we override the definition.
  552. head += '''
  553. #ifdef __cplusplus
  554. extern "C"
  555. #endif
  556. char {func} (void);
  557. '''
  558. # The actual function call
  559. main = '''
  560. int main(void) {{
  561. return {func} ();
  562. }}'''
  563. return head, main
  564. @staticmethod
  565. def _have_prototype_templ():
  566. """
  567. Returns a head-er and main() call that uses the headers listed by the
  568. user for the function prototype while checking if a function exists.
  569. """
  570. # Add the 'prefix', aka defines, includes, etc that the user provides
  571. # This may include, for instance _GNU_SOURCE which must be defined
  572. # before limits.h, which includes features.h
  573. head = '{prefix}\n#include <limits.h>\n'
  574. # We don't know what the function takes or returns, so return it as an int.
  575. # Just taking the address or comparing it to void is not enough because
  576. # compilers are smart enough to optimize it away. The resulting binary
  577. # is not run so we don't care what the return value is.
  578. main = '''\nint main(void) {{
  579. void *a = (void*) &{func};
  580. long b = (long) a;
  581. return (int) b;
  582. }}'''
  583. return head, main
  584. def has_function(self, funcname, prefix, env, *, extra_args=None, dependencies=None):
  585. """
  586. First, this function looks for the symbol in the default libraries
  587. provided by the compiler (stdlib + a few others usually). If that
  588. fails, it checks if any of the headers specified in the prefix provide
  589. an implementation of the function, and if that fails, it checks if it's
  590. implemented as a compiler-builtin.
  591. """
  592. if extra_args is None:
  593. extra_args = []
  594. # Short-circuit if the check is already provided by the cross-info file
  595. varname = 'has function ' + funcname
  596. varname = varname.replace(' ', '_')
  597. if self.is_cross:
  598. val = env.properties.host.get(varname, None)
  599. if val is not None:
  600. if isinstance(val, bool):
  601. return val, False
  602. raise mesonlib.EnvironmentException('Cross variable {0} is not a boolean.'.format(varname))
  603. fargs = {'prefix': prefix, 'func': funcname}
  604. # glibc defines functions that are not available on Linux as stubs that
  605. # fail with ENOSYS (such as e.g. lchmod). In this case we want to fail
  606. # instead of detecting the stub as a valid symbol.
  607. # We already included limits.h earlier to ensure that these are defined
  608. # for stub functions.
  609. stubs_fail = '''
  610. #if defined __stub_{func} || defined __stub___{func}
  611. fail fail fail this function is not going to work
  612. #endif
  613. '''
  614. # If we have any includes in the prefix supplied by the user, assume
  615. # that the user wants us to use the symbol prototype defined in those
  616. # includes. If not, then try to do the Autoconf-style check with
  617. # a dummy prototype definition of our own.
  618. # This is needed when the linker determines symbol availability from an
  619. # SDK based on the prototype in the header provided by the SDK.
  620. # Ignoring this prototype would result in the symbol always being
  621. # marked as available.
  622. if '#include' in prefix:
  623. head, main = self._have_prototype_templ()
  624. else:
  625. head, main = self._no_prototype_templ()
  626. templ = head + stubs_fail + main
  627. res, cached = self.links(templ.format(**fargs), env, extra_args=extra_args,
  628. dependencies=dependencies)
  629. if res:
  630. return True, cached
  631. # MSVC does not have compiler __builtin_-s.
  632. if self.get_id() in {'msvc', 'intel-cl'}:
  633. return False, False
  634. # Detect function as a built-in
  635. #
  636. # Some functions like alloca() are defined as compiler built-ins which
  637. # are inlined by the compiler and you can't take their address, so we
  638. # need to look for them differently. On nice compilers like clang, we
  639. # can just directly use the __has_builtin() macro.
  640. fargs['no_includes'] = '#include' not in prefix
  641. fargs['__builtin_'] = '' if funcname.startswith('__builtin_') else '__builtin_'
  642. t = '''{prefix}
  643. int main(void) {{
  644. #ifdef __has_builtin
  645. #if !__has_builtin({__builtin_}{func})
  646. #error "{__builtin_}{func} not found"
  647. #endif
  648. #elif ! defined({func})
  649. /* Check for {__builtin_}{func} only if no includes were added to the
  650. * prefix above, which means no definition of {func} can be found.
  651. * We would always check for this, but we get false positives on
  652. * MSYS2 if we do. Their toolchain is broken, but we can at least
  653. * give them a workaround. */
  654. #if {no_includes:d}
  655. {__builtin_}{func};
  656. #else
  657. #error "No definition for {__builtin_}{func} found in the prefix"
  658. #endif
  659. #endif
  660. return 0;
  661. }}'''
  662. return self.links(t.format(**fargs), env, extra_args=extra_args,
  663. dependencies=dependencies)
  664. def has_members(self, typename, membernames, prefix, env, *, extra_args=None, dependencies=None):
  665. if extra_args is None:
  666. extra_args = []
  667. fargs = {'prefix': prefix, 'type': typename, 'name': 'foo'}
  668. # Create code that accesses all members
  669. members = ''
  670. for member in membernames:
  671. members += '{}.{};\n'.format(fargs['name'], member)
  672. fargs['members'] = members
  673. t = '''{prefix}
  674. void bar(void) {{
  675. {type} {name};
  676. {members}
  677. }};'''
  678. return self.compiles(t.format(**fargs), env, extra_args=extra_args,
  679. dependencies=dependencies)
  680. def has_type(self, typename, prefix, env, extra_args, dependencies=None):
  681. fargs = {'prefix': prefix, 'type': typename}
  682. t = '''{prefix}
  683. void bar(void) {{
  684. sizeof({type});
  685. }};'''
  686. return self.compiles(t.format(**fargs), env, extra_args=extra_args,
  687. dependencies=dependencies)
  688. def symbols_have_underscore_prefix(self, env):
  689. '''
  690. Check if the compiler prefixes an underscore to global C symbols
  691. '''
  692. symbol_name = b'meson_uscore_prefix'
  693. code = '''#ifdef __cplusplus
  694. extern "C" {
  695. #endif
  696. void ''' + symbol_name.decode() + ''' (void) {}
  697. #ifdef __cplusplus
  698. }
  699. #endif
  700. '''
  701. args = self.get_compiler_check_args()
  702. n = 'symbols_have_underscore_prefix'
  703. with self._build_wrapper(code, env, extra_args=args, mode='compile', want_output=True, temp_dir=env.scratch_dir) as p:
  704. if p.returncode != 0:
  705. m = 'BUG: Unable to compile {!r} check: {}'
  706. raise RuntimeError(m.format(n, p.stdo))
  707. if not os.path.isfile(p.output_name):
  708. m = 'BUG: Can\'t find compiled test code for {!r} check'
  709. raise RuntimeError(m.format(n))
  710. with open(p.output_name, 'rb') as o:
  711. for line in o:
  712. # Check if the underscore form of the symbol is somewhere
  713. # in the output file.
  714. if b'_' + symbol_name in line:
  715. mlog.debug("Symbols have underscore prefix: YES")
  716. return True
  717. # Else, check if the non-underscored form is present
  718. elif symbol_name in line:
  719. mlog.debug("Symbols have underscore prefix: NO")
  720. return False
  721. raise RuntimeError('BUG: {!r} check failed unexpectedly'.format(n))
  722. def _get_patterns(self, env, prefixes, suffixes, shared=False):
  723. patterns = []
  724. for p in prefixes:
  725. for s in suffixes:
  726. patterns.append(p + '{}.' + s)
  727. if shared and env.machines[self.for_machine].is_openbsd():
  728. # Shared libraries on OpenBSD can be named libfoo.so.X.Y:
  729. # https://www.openbsd.org/faq/ports/specialtopics.html#SharedLibs
  730. #
  731. # This globbing is probably the best matching we can do since regex
  732. # is expensive. It's wrong in many edge cases, but it will match
  733. # correctly-named libraries and hopefully no one on OpenBSD names
  734. # their files libfoo.so.9a.7b.1.0
  735. for p in prefixes:
  736. patterns.append(p + '{}.so.[0-9]*.[0-9]*')
  737. return patterns
  738. def get_library_naming(self, env, libtype: LibType, strict=False):
  739. '''
  740. Get library prefixes and suffixes for the target platform ordered by
  741. priority
  742. '''
  743. stlibext = ['a']
  744. # We've always allowed libname to be both `foo` and `libfoo`, and now
  745. # people depend on it. Also, some people use prebuilt `foo.so` instead
  746. # of `libfoo.so` for unknown reasons, and may also want to create
  747. # `foo.so` by setting name_prefix to ''
  748. if strict and not isinstance(self, VisualStudioLikeCompiler): # lib prefix is not usually used with msvc
  749. prefixes = ['lib']
  750. else:
  751. prefixes = ['lib', '']
  752. # Library suffixes and prefixes
  753. if env.machines[self.for_machine].is_darwin():
  754. shlibext = ['dylib', 'so']
  755. elif env.machines[self.for_machine].is_windows():
  756. # FIXME: .lib files can be import or static so we should read the
  757. # file, figure out which one it is, and reject the wrong kind.
  758. if isinstance(self, VisualStudioLikeCompiler):
  759. shlibext = ['lib']
  760. else:
  761. shlibext = ['dll.a', 'lib', 'dll']
  762. # Yep, static libraries can also be foo.lib
  763. stlibext += ['lib']
  764. elif env.machines[self.for_machine].is_cygwin():
  765. shlibext = ['dll', 'dll.a']
  766. prefixes = ['cyg'] + prefixes
  767. else:
  768. # Linux/BSDs
  769. shlibext = ['so']
  770. # Search priority
  771. if libtype is LibType.PREFER_SHARED:
  772. patterns = self._get_patterns(env, prefixes, shlibext, True)
  773. patterns.extend([x for x in self._get_patterns(env, prefixes, stlibext, False) if x not in patterns])
  774. elif libtype is LibType.PREFER_STATIC:
  775. patterns = self._get_patterns(env, prefixes, stlibext, False)
  776. patterns.extend([x for x in self._get_patterns(env, prefixes, shlibext, True) if x not in patterns])
  777. elif libtype is LibType.SHARED:
  778. patterns = self._get_patterns(env, prefixes, shlibext, True)
  779. else:
  780. assert libtype is LibType.STATIC
  781. patterns = self._get_patterns(env, prefixes, stlibext, False)
  782. return tuple(patterns)
  783. @staticmethod
  784. def _sort_shlibs_openbsd(libs):
  785. filtered = []
  786. for lib in libs:
  787. # Validate file as a shared library of type libfoo.so.X.Y
  788. ret = lib.rsplit('.so.', maxsplit=1)
  789. if len(ret) != 2:
  790. continue
  791. try:
  792. float(ret[1])
  793. except ValueError:
  794. continue
  795. filtered.append(lib)
  796. float_cmp = lambda x: float(x.rsplit('.so.', maxsplit=1)[1])
  797. return sorted(filtered, key=float_cmp, reverse=True)
  798. @classmethod
  799. def _get_trials_from_pattern(cls, pattern, directory, libname):
  800. f = Path(directory) / pattern.format(libname)
  801. # Globbing for OpenBSD
  802. if '*' in pattern:
  803. # NOTE: globbing matches directories and broken symlinks
  804. # so we have to do an isfile test on it later
  805. return [Path(x) for x in cls._sort_shlibs_openbsd(glob.glob(str(f)))]
  806. return [f]
  807. @staticmethod
  808. def _get_file_from_list(env, files: T.List[str]) -> Path:
  809. '''
  810. We just check whether the library exists. We can't do a link check
  811. because the library might have unresolved symbols that require other
  812. libraries. On macOS we check if the library matches our target
  813. architecture.
  814. '''
  815. # If not building on macOS for Darwin, do a simple file check
  816. files = [Path(f) for f in files]
  817. if not env.machines.host.is_darwin() or not env.machines.build.is_darwin():
  818. for f in files:
  819. if f.is_file():
  820. return f
  821. # Run `lipo` and check if the library supports the arch we want
  822. for f in files:
  823. if not f.is_file():
  824. continue
  825. archs = mesonlib.darwin_get_object_archs(str(f))
  826. if archs and env.machines.host.cpu_family in archs:
  827. return f
  828. else:
  829. mlog.debug('Rejected {}, supports {} but need {}'
  830. .format(f, archs, env.machines.host.cpu_family))
  831. return None
  832. @functools.lru_cache()
  833. def output_is_64bit(self, env):
  834. '''
  835. returns true if the output produced is 64-bit, false if 32-bit
  836. '''
  837. return self.sizeof('void *', '', env) == 8
  838. def find_library_real(self, libname, env, extra_dirs, code, libtype: LibType):
  839. # First try if we can just add the library as -l.
  840. # Gcc + co seem to prefer builtin lib dirs to -L dirs.
  841. # Only try to find std libs if no extra dirs specified.
  842. # The built-in search procedure will always favour .so and then always
  843. # search for .a. This is only allowed if libtype is LibType.PREFER_SHARED
  844. if ((not extra_dirs and libtype is LibType.PREFER_SHARED) or
  845. libname in self.internal_libs):
  846. cargs = ['-l' + libname]
  847. largs = self.get_allow_undefined_link_args()
  848. extra_args = cargs + self.linker_to_compiler_args(largs)
  849. if self.links(code, env, extra_args=extra_args, disable_cache=True)[0]:
  850. return cargs
  851. # Don't do a manual search for internal libs
  852. if libname in self.internal_libs:
  853. return None
  854. # Not found or we want to use a specific libtype? Try to find the
  855. # library file itself.
  856. patterns = self.get_library_naming(env, libtype)
  857. # try to detect if we are 64-bit or 32-bit. If we can't
  858. # detect, we will just skip path validity checks done in
  859. # get_library_dirs() call
  860. try:
  861. if self.output_is_64bit(env):
  862. elf_class = 2
  863. else:
  864. elf_class = 1
  865. except (mesonlib.MesonException, KeyError): # TODO evaluate if catching KeyError is wanted here
  866. elf_class = 0
  867. # Search in the specified dirs, and then in the system libraries
  868. for d in itertools.chain(extra_dirs, self.get_library_dirs(env, elf_class)):
  869. for p in patterns:
  870. trial = self._get_trials_from_pattern(p, d, libname)
  871. if not trial:
  872. continue
  873. trial = self._get_file_from_list(env, trial)
  874. if not trial:
  875. continue
  876. return [trial.as_posix()]
  877. return None
  878. def find_library_impl(self, libname, env, extra_dirs, code, libtype: LibType):
  879. # These libraries are either built-in or invalid
  880. if libname in self.ignore_libs:
  881. return []
  882. if isinstance(extra_dirs, str):
  883. extra_dirs = [extra_dirs]
  884. key = (tuple(self.exelist), libname, tuple(extra_dirs), code, libtype)
  885. if key not in self.find_library_cache:
  886. value = self.find_library_real(libname, env, extra_dirs, code, libtype)
  887. self.find_library_cache[key] = value
  888. else:
  889. value = self.find_library_cache[key]
  890. if value is None:
  891. return None
  892. return value[:]
  893. def find_library(self, libname, env, extra_dirs, libtype: LibType = LibType.PREFER_SHARED):
  894. code = 'int main(void) { return 0; }'
  895. return self.find_library_impl(libname, env, extra_dirs, code, libtype)
  896. def find_framework_paths(self, env):
  897. '''
  898. These are usually /Library/Frameworks and /System/Library/Frameworks,
  899. unless you select a particular macOS SDK with the -isysroot flag.
  900. You can also add to this by setting -F in CFLAGS.
  901. '''
  902. if self.id != 'clang':
  903. raise mesonlib.MesonException('Cannot find framework path with non-clang compiler')
  904. # Construct the compiler command-line
  905. commands = self.get_exelist() + ['-v', '-E', '-']
  906. commands += self.get_always_args()
  907. # Add CFLAGS/CXXFLAGS/OBJCFLAGS/OBJCXXFLAGS from the env
  908. commands += env.coredata.get_external_args(self.for_machine, self.language)
  909. mlog.debug('Finding framework path by running: ', ' '.join(commands), '\n')
  910. os_env = os.environ.copy()
  911. os_env['LC_ALL'] = 'C'
  912. _, _, stde = mesonlib.Popen_safe(commands, env=os_env, stdin=subprocess.PIPE)
  913. paths = []
  914. for line in stde.split('\n'):
  915. if '(framework directory)' not in line:
  916. continue
  917. # line is of the form:
  918. # ` /path/to/framework (framework directory)`
  919. paths.append(line[:-21].strip())
  920. return paths
  921. def find_framework_real(self, name, env, extra_dirs, allow_system):
  922. code = 'int main(void) { return 0; }'
  923. link_args = []
  924. for d in extra_dirs:
  925. link_args += ['-F' + d]
  926. # We can pass -Z to disable searching in the system frameworks, but
  927. # then we must also pass -L/usr/lib to pick up libSystem.dylib
  928. extra_args = [] if allow_system else ['-Z', '-L/usr/lib']
  929. link_args += ['-framework', name]
  930. if self.links(code, env, extra_args=(extra_args + link_args), disable_cache=True)[0]:
  931. return link_args
  932. def find_framework_impl(self, name, env, extra_dirs, allow_system):
  933. if isinstance(extra_dirs, str):
  934. extra_dirs = [extra_dirs]
  935. key = (tuple(self.exelist), name, tuple(extra_dirs), allow_system)
  936. if key in self.find_framework_cache:
  937. value = self.find_framework_cache[key]
  938. else:
  939. value = self.find_framework_real(name, env, extra_dirs, allow_system)
  940. self.find_framework_cache[key] = value
  941. if value is None:
  942. return None
  943. return value[:]
  944. def find_framework(self, name, env, extra_dirs, allow_system=True):
  945. '''
  946. Finds the framework with the specified name, and returns link args for
  947. the same or returns None when the framework is not found.
  948. '''
  949. if self.id != 'clang':
  950. raise mesonlib.MesonException('Cannot find frameworks with non-clang compiler')
  951. return self.find_framework_impl(name, env, extra_dirs, allow_system)
  952. def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]:
  953. return []
  954. def get_crt_link_args(self, crt_val: str, buildtype: str) -> T.List[str]:
  955. return []
  956. def thread_flags(self, env):
  957. host_m = env.machines[self.for_machine]
  958. if host_m.is_haiku() or host_m.is_darwin():
  959. return []
  960. return ['-pthread']
  961. def thread_link_flags(self, env: 'Environment') -> T.List[str]:
  962. return self.linker.thread_flags(env)
  963. def linker_to_compiler_args(self, args):
  964. return args
  965. def has_arguments(self, args: T.Sequence[str], env, code: str, mode: str) -> T.Tuple[bool, bool]:
  966. return self.compiles(code, env, extra_args=args, mode=mode)
  967. def has_multi_arguments(self, args, env):
  968. for arg in args[:]:
  969. # some compilers, e.g. GCC, don't warn for unsupported warning-disable
  970. # flags, so when we are testing a flag like "-Wno-forgotten-towel", also
  971. # check the equivalent enable flag too "-Wforgotten-towel"
  972. if arg.startswith('-Wno-'):
  973. args.append('-W' + arg[5:])
  974. if arg.startswith('-Wl,'):
  975. mlog.warning('{} looks like a linker argument, '
  976. 'but has_argument and other similar methods only '
  977. 'support checking compiler arguments. Using them '
  978. 'to check linker arguments are never supported, '
  979. 'and results are likely to be wrong regardless of '
  980. 'the compiler you are using. has_link_argument or '
  981. 'other similar method can be used instead.'
  982. .format(arg))
  983. code = 'int i;\n'
  984. return self.has_arguments(args, env, code, mode='compile')
  985. def has_multi_link_arguments(self, args, env):
  986. # First time we check for link flags we need to first check if we have
  987. # --fatal-warnings, otherwise some linker checks could give some
  988. # false positive.
  989. args = self.linker.fatal_warnings() + args
  990. args = self.linker_to_compiler_args(args)
  991. code = 'int main(void) { return 0; }'
  992. return self.has_arguments(args, env, code, mode='link')
  993. @staticmethod
  994. def concatenate_string_literals(s):
  995. pattern = re.compile(r'(?P<pre>.*([^\\]")|^")(?P<str1>([^\\"]|\\.)*)"\s+"(?P<str2>([^\\"]|\\.)*)(?P<post>".*)')
  996. ret = s
  997. m = pattern.match(ret)
  998. while m:
  999. ret = ''.join(m.group('pre', 'str1', 'str2', 'post'))
  1000. m = pattern.match(ret)
  1001. return ret
  1002. def get_has_func_attribute_extra_args(self, name):
  1003. # Most compilers (such as GCC and Clang) only warn about unknown or
  1004. # ignored attributes, so force an error. Overriden in GCC and Clang
  1005. # mixins.
  1006. return ['-Werror']
  1007. def has_func_attribute(self, name, env):
  1008. # Just assume that if we're not on windows that dllimport and dllexport
  1009. # don't work
  1010. m = env.machines[self.for_machine]
  1011. if not (m.is_windows() or m.is_cygwin()):
  1012. if name in ['dllimport', 'dllexport']:
  1013. return False, False
  1014. return self.compiles(self.attribute_check_func(name), env,
  1015. extra_args=self.get_has_func_attribute_extra_args(name))