environment.py 79 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812
  1. # Copyright 2012-2016 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. import os, platform, re, sys, shutil, subprocess
  12. import tempfile
  13. import shlex
  14. import typing as T
  15. from . import coredata
  16. from .linkers import ArLinker, ArmarLinker, VisualStudioLinker, DLinker, CcrxLinker, Xc16Linker, C2000Linker, IntelVisualStudioLinker
  17. from . import mesonlib
  18. from .mesonlib import (
  19. MesonException, EnvironmentException, MachineChoice, Popen_safe,
  20. PerMachineDefaultable, PerThreeMachineDefaultable, split_args, quote_arg
  21. )
  22. from . import mlog
  23. from .envconfig import (
  24. BinaryTable, Directories, MachineInfo, MesonConfigFile,
  25. Properties, known_cpu_families,
  26. )
  27. from . import compilers
  28. from .compilers import (
  29. Compiler,
  30. is_assembly,
  31. is_header,
  32. is_library,
  33. is_llvm_ir,
  34. is_object,
  35. is_source,
  36. )
  37. from .linkers import (
  38. AppleDynamicLinker,
  39. ArmClangDynamicLinker,
  40. ArmDynamicLinker,
  41. CcrxDynamicLinker,
  42. Xc16DynamicLinker,
  43. C2000DynamicLinker,
  44. ClangClDynamicLinker,
  45. DynamicLinker,
  46. GnuBFDDynamicLinker,
  47. GnuGoldDynamicLinker,
  48. LLVMDynamicLinker,
  49. MSVCDynamicLinker,
  50. OptlinkDynamicLinker,
  51. PGIDynamicLinker,
  52. PGIStaticLinker,
  53. SolarisDynamicLinker,
  54. XilinkDynamicLinker,
  55. CudaLinker,
  56. VisualStudioLikeLinkerMixin,
  57. WASMDynamicLinker,
  58. )
  59. from functools import lru_cache
  60. from .compilers import (
  61. ArmCCompiler,
  62. ArmCPPCompiler,
  63. ArmclangCCompiler,
  64. ArmclangCPPCompiler,
  65. AppleClangCCompiler,
  66. AppleClangCPPCompiler,
  67. ClangCCompiler,
  68. ClangCPPCompiler,
  69. ClangObjCCompiler,
  70. ClangObjCPPCompiler,
  71. ClangClCCompiler,
  72. ClangClCPPCompiler,
  73. FlangFortranCompiler,
  74. G95FortranCompiler,
  75. GnuCCompiler,
  76. GnuCPPCompiler,
  77. GnuFortranCompiler,
  78. GnuObjCCompiler,
  79. GnuObjCPPCompiler,
  80. ElbrusCCompiler,
  81. ElbrusCPPCompiler,
  82. ElbrusFortranCompiler,
  83. EmscriptenCCompiler,
  84. EmscriptenCPPCompiler,
  85. IntelCCompiler,
  86. IntelClCCompiler,
  87. IntelCPPCompiler,
  88. IntelClCPPCompiler,
  89. IntelFortranCompiler,
  90. IntelClFortranCompiler,
  91. JavaCompiler,
  92. MonoCompiler,
  93. CudaCompiler,
  94. VisualStudioCsCompiler,
  95. NAGFortranCompiler,
  96. Open64FortranCompiler,
  97. PathScaleFortranCompiler,
  98. PGICCompiler,
  99. PGICPPCompiler,
  100. PGIFortranCompiler,
  101. RustCompiler,
  102. CcrxCCompiler,
  103. CcrxCPPCompiler,
  104. Xc16CCompiler,
  105. C2000CCompiler,
  106. C2000CPPCompiler,
  107. SunFortranCompiler,
  108. ValaCompiler,
  109. VisualStudioCCompiler,
  110. VisualStudioCPPCompiler,
  111. )
  112. build_filename = 'meson.build'
  113. CompilersDict = T.Dict[str, Compiler]
  114. def detect_gcovr(min_version='3.3', new_rootdir_version='4.2', log=False):
  115. gcovr_exe = 'gcovr'
  116. try:
  117. p, found = Popen_safe([gcovr_exe, '--version'])[0:2]
  118. except (FileNotFoundError, PermissionError):
  119. # Doesn't exist in PATH or isn't executable
  120. return None, None
  121. found = search_version(found)
  122. if p.returncode == 0 and mesonlib.version_compare(found, '>=' + min_version):
  123. if log:
  124. mlog.log('Found gcovr-{} at {}'.format(found, quote_arg(shutil.which(gcovr_exe))))
  125. return gcovr_exe, mesonlib.version_compare(found, '>=' + new_rootdir_version)
  126. return None, None
  127. def find_coverage_tools():
  128. gcovr_exe, gcovr_new_rootdir = detect_gcovr()
  129. lcov_exe = 'lcov'
  130. genhtml_exe = 'genhtml'
  131. if not mesonlib.exe_exists([lcov_exe, '--version']):
  132. lcov_exe = None
  133. if not mesonlib.exe_exists([genhtml_exe, '--version']):
  134. genhtml_exe = None
  135. return gcovr_exe, gcovr_new_rootdir, lcov_exe, genhtml_exe
  136. def detect_ninja(version: str = '1.7', log: bool = False) -> str:
  137. r = detect_ninja_command_and_version(version, log)
  138. return r[0] if r else None
  139. def detect_ninja_command_and_version(version: str = '1.7', log: bool = False) -> (str, str):
  140. env_ninja = os.environ.get('NINJA', None)
  141. for n in [env_ninja] if env_ninja else ['ninja', 'ninja-build', 'samu']:
  142. try:
  143. p, found = Popen_safe([n, '--version'])[0:2]
  144. except (FileNotFoundError, PermissionError):
  145. # Doesn't exist in PATH or isn't executable
  146. continue
  147. found = found.strip()
  148. # Perhaps we should add a way for the caller to know the failure mode
  149. # (not found or too old)
  150. if p.returncode == 0 and mesonlib.version_compare(found, '>=' + version):
  151. n = shutil.which(n)
  152. if log:
  153. name = os.path.basename(n)
  154. if name.endswith('-' + found):
  155. name = name[0:-1 - len(found)]
  156. if name == 'ninja-build':
  157. name = 'ninja'
  158. if name == 'samu':
  159. name = 'samurai'
  160. mlog.log('Found {}-{} at {}'.format(name, found, quote_arg(n)))
  161. return (n, found)
  162. def get_llvm_tool_names(tool: str) -> T.List[str]:
  163. # Ordered list of possible suffixes of LLVM executables to try. Start with
  164. # base, then try newest back to oldest (3.5 is arbitrary), and finally the
  165. # devel version. Please note that the development snapshot in Debian does
  166. # not have a distinct name. Do not move it to the beginning of the list
  167. # unless it becomes a stable release.
  168. suffixes = [
  169. '', # base (no suffix)
  170. '-9', '90',
  171. '-8', '80',
  172. '-7', '70',
  173. '-6.0', '60',
  174. '-5.0', '50',
  175. '-4.0', '40',
  176. '-3.9', '39',
  177. '-3.8', '38',
  178. '-3.7', '37',
  179. '-3.6', '36',
  180. '-3.5', '35',
  181. '-10', # Debian development snapshot
  182. '-devel', # FreeBSD development snapshot
  183. ]
  184. names = []
  185. for suffix in suffixes:
  186. names.append(tool + suffix)
  187. return names
  188. def detect_scanbuild() -> T.List[str]:
  189. """ Look for scan-build binary on build platform
  190. First, if a SCANBUILD env variable has been provided, give it precedence
  191. on all platforms.
  192. For most platforms, scan-build is found is the PATH contains a binary
  193. named "scan-build". However, some distribution's package manager (FreeBSD)
  194. don't. For those, loop through a list of candidates to see if one is
  195. available.
  196. Return: a single-element list of the found scan-build binary ready to be
  197. passed to Popen()
  198. """
  199. exelist = []
  200. if 'SCANBUILD' in os.environ:
  201. exelist = split_args(os.environ['SCANBUILD'])
  202. else:
  203. tools = get_llvm_tool_names('scan-build')
  204. for tool in tools:
  205. if shutil.which(tool) is not None:
  206. exelist = [shutil.which(tool)]
  207. break
  208. if exelist:
  209. tool = exelist[0]
  210. if os.path.isfile(tool) and os.access(tool, os.X_OK):
  211. return [tool]
  212. return []
  213. def detect_clangformat() -> T.List[str]:
  214. """ Look for clang-format binary on build platform
  215. Do the same thing as detect_scanbuild to find clang-format except it
  216. currently does not check the environment variable.
  217. Return: a single-element list of the found clang-format binary ready to be
  218. passed to Popen()
  219. """
  220. tools = get_llvm_tool_names('clang-format')
  221. for tool in tools:
  222. path = shutil.which(tool)
  223. if path is not None:
  224. return [path]
  225. return []
  226. def detect_native_windows_arch():
  227. """
  228. The architecture of Windows itself: x86, amd64 or arm64
  229. """
  230. # These env variables are always available. See:
  231. # https://msdn.microsoft.com/en-us/library/aa384274(VS.85).aspx
  232. # https://blogs.msdn.microsoft.com/david.wang/2006/03/27/howto-detect-process-bitness/
  233. arch = os.environ.get('PROCESSOR_ARCHITEW6432', '').lower()
  234. if not arch:
  235. try:
  236. # If this doesn't exist, something is messing with the environment
  237. arch = os.environ['PROCESSOR_ARCHITECTURE'].lower()
  238. except KeyError:
  239. raise EnvironmentException('Unable to detect native OS architecture')
  240. return arch
  241. def detect_windows_arch(compilers: CompilersDict) -> str:
  242. """
  243. Detecting the 'native' architecture of Windows is not a trivial task. We
  244. cannot trust that the architecture that Python is built for is the 'native'
  245. one because you can run 32-bit apps on 64-bit Windows using WOW64 and
  246. people sometimes install 32-bit Python on 64-bit Windows.
  247. We also can't rely on the architecture of the OS itself, since it's
  248. perfectly normal to compile and run 32-bit applications on Windows as if
  249. they were native applications. It's a terrible experience to require the
  250. user to supply a cross-info file to compile 32-bit applications on 64-bit
  251. Windows. Thankfully, the only way to compile things with Visual Studio on
  252. Windows is by entering the 'msvc toolchain' environment, which can be
  253. easily detected.
  254. In the end, the sanest method is as follows:
  255. 1. Check environment variables that are set by Windows and WOW64 to find out
  256. if this is x86 (possibly in WOW64), if so use that as our 'native'
  257. architecture.
  258. 2. If the compiler toolchain target architecture is x86, use that as our
  259. 'native' architecture.
  260. 3. Otherwise, use the actual Windows architecture
  261. """
  262. os_arch = detect_native_windows_arch()
  263. if os_arch == 'x86':
  264. return os_arch
  265. # If we're on 64-bit Windows, 32-bit apps can be compiled without
  266. # cross-compilation. So if we're doing that, just set the native arch as
  267. # 32-bit and pretend like we're running under WOW64. Else, return the
  268. # actual Windows architecture that we deduced above.
  269. for compiler in compilers.values():
  270. if compiler.id == 'msvc' and (compiler.target == 'x86' or compiler.target == '80x86'):
  271. return 'x86'
  272. if compiler.id == 'clang-cl' and compiler.target == 'x86':
  273. return 'x86'
  274. if compiler.id == 'gcc' and compiler.has_builtin_define('__i386__'):
  275. return 'x86'
  276. return os_arch
  277. def any_compiler_has_define(compilers: CompilersDict, define):
  278. for c in compilers.values():
  279. try:
  280. if c.has_builtin_define(define):
  281. return True
  282. except mesonlib.MesonException:
  283. # Ignore compilers that do not support has_builtin_define.
  284. pass
  285. return False
  286. def detect_cpu_family(compilers: CompilersDict) -> str:
  287. """
  288. Python is inconsistent in its platform module.
  289. It returns different values for the same cpu.
  290. For x86 it might return 'x86', 'i686' or somesuch.
  291. Do some canonicalization.
  292. """
  293. if mesonlib.is_windows():
  294. trial = detect_windows_arch(compilers)
  295. elif mesonlib.is_freebsd() or mesonlib.is_netbsd() or mesonlib.is_openbsd():
  296. trial = platform.processor().lower()
  297. else:
  298. trial = platform.machine().lower()
  299. if trial.startswith('i') and trial.endswith('86'):
  300. trial = 'x86'
  301. elif trial == 'bepc':
  302. trial = 'x86'
  303. elif trial.startswith('arm') or trial.startswith('earm'):
  304. trial = 'arm'
  305. elif trial.startswith(('powerpc64', 'ppc64')):
  306. trial = 'ppc64'
  307. elif trial.startswith(('powerpc', 'ppc')) or trial in {'macppc', 'power machintosh'}:
  308. trial = 'ppc'
  309. elif trial in ('amd64', 'x64', 'i86pc'):
  310. trial = 'x86_64'
  311. elif trial in {'sun4u', 'sun4v'}:
  312. trial = 'sparc64'
  313. elif trial in {'mipsel', 'mips64el'}:
  314. trial = trial.rstrip('el')
  315. # On Linux (and maybe others) there can be any mixture of 32/64 bit code in
  316. # the kernel, Python, system, 32-bit chroot on 64-bit host, etc. The only
  317. # reliable way to know is to check the compiler defines.
  318. if trial == 'x86_64':
  319. if any_compiler_has_define(compilers, '__i386__'):
  320. trial = 'x86'
  321. elif trial == 'aarch64':
  322. if any_compiler_has_define(compilers, '__arm__'):
  323. trial = 'arm'
  324. # Add more quirks here as bugs are reported. Keep in sync with detect_cpu()
  325. # below.
  326. elif trial == 'parisc64':
  327. # ATM there is no 64 bit userland for PA-RISC. Thus always
  328. # report it as 32 bit for simplicity.
  329. trial = 'parisc'
  330. if trial not in known_cpu_families:
  331. mlog.warning('Unknown CPU family {!r}, please report this at '
  332. 'https://github.com/mesonbuild/meson/issues/new with the '
  333. 'output of `uname -a` and `cat /proc/cpuinfo`'.format(trial))
  334. return trial
  335. def detect_cpu(compilers: CompilersDict):
  336. if mesonlib.is_windows():
  337. trial = detect_windows_arch(compilers)
  338. elif mesonlib.is_freebsd() or mesonlib.is_netbsd() or mesonlib.is_openbsd():
  339. trial = platform.processor().lower()
  340. else:
  341. trial = platform.machine().lower()
  342. if trial in ('amd64', 'x64', 'i86pc'):
  343. trial = 'x86_64'
  344. if trial == 'x86_64':
  345. # Same check as above for cpu_family
  346. if any_compiler_has_define(compilers, '__i386__'):
  347. trial = 'i686' # All 64 bit cpus have at least this level of x86 support.
  348. elif trial == 'aarch64':
  349. # Same check as above for cpu_family
  350. if any_compiler_has_define(compilers, '__arm__'):
  351. trial = 'arm'
  352. elif trial.startswith('earm'):
  353. trial = 'arm'
  354. elif trial == 'e2k':
  355. # Make more precise CPU detection for Elbrus platform.
  356. trial = platform.processor().lower()
  357. elif trial.startswith('mips'):
  358. trial = trial.rstrip('el')
  359. # Add more quirks here as bugs are reported. Keep in sync with
  360. # detect_cpu_family() above.
  361. return trial
  362. def detect_system():
  363. system = platform.system().lower()
  364. if system.startswith('cygwin'):
  365. return 'cygwin'
  366. return system
  367. def detect_msys2_arch():
  368. if 'MSYSTEM_CARCH' in os.environ:
  369. return os.environ['MSYSTEM_CARCH']
  370. return None
  371. def detect_machine_info(compilers: T.Optional[CompilersDict] = None) -> MachineInfo:
  372. """Detect the machine we're running on
  373. If compilers are not provided, we cannot know as much. None out those
  374. fields to avoid accidentally depending on partial knowledge. The
  375. underlying ''detect_*'' method can be called to explicitly use the
  376. partial information.
  377. """
  378. return MachineInfo(
  379. detect_system(),
  380. detect_cpu_family(compilers) if compilers is not None else None,
  381. detect_cpu(compilers) if compilers is not None else None,
  382. sys.byteorder)
  383. # TODO make this compare two `MachineInfo`s purely. How important is the
  384. # `detect_cpu_family({})` distinction? It is the one impediment to that.
  385. def machine_info_can_run(machine_info: MachineInfo):
  386. """Whether we can run binaries for this machine on the current machine.
  387. Can almost always run 32-bit binaries on 64-bit natively if the host
  388. and build systems are the same. We don't pass any compilers to
  389. detect_cpu_family() here because we always want to know the OS
  390. architecture, not what the compiler environment tells us.
  391. """
  392. if machine_info.system != detect_system():
  393. return False
  394. true_build_cpu_family = detect_cpu_family({})
  395. return \
  396. (machine_info.cpu_family == true_build_cpu_family) or \
  397. ((true_build_cpu_family == 'x86_64') and (machine_info.cpu_family == 'x86'))
  398. def search_version(text):
  399. # Usually of the type 4.1.4 but compiler output may contain
  400. # stuff like this:
  401. # (Sourcery CodeBench Lite 2014.05-29) 4.8.3 20140320 (prerelease)
  402. # Limiting major version number to two digits seems to work
  403. # thus far. When we get to GCC 100, this will break, but
  404. # if we are still relevant when that happens, it can be
  405. # considered an achievement in itself.
  406. #
  407. # This regex is reaching magic levels. If it ever needs
  408. # to be updated, do not complexify but convert to something
  409. # saner instead.
  410. # We'll demystify it a bit with a verbose definition.
  411. version_regex = re.compile(r"""
  412. (?<! # Zero-width negative lookbehind assertion
  413. (
  414. \d # One digit
  415. | \. # Or one period
  416. ) # One occurrence
  417. )
  418. # Following pattern must not follow a digit or period
  419. (
  420. \d{1,2} # One or two digits
  421. (
  422. \.\d+ # Period and one or more digits
  423. )+ # One or more occurrences
  424. (
  425. -[a-zA-Z0-9]+ # Hyphen and one or more alphanumeric
  426. )? # Zero or one occurrence
  427. ) # One occurrence
  428. """, re.VERBOSE)
  429. match = version_regex.search(text)
  430. if match:
  431. return match.group(0)
  432. return 'unknown version'
  433. class Environment:
  434. private_dir = 'meson-private'
  435. log_dir = 'meson-logs'
  436. info_dir = 'meson-info'
  437. def __init__(self, source_dir, build_dir, options):
  438. self.source_dir = source_dir
  439. self.build_dir = build_dir
  440. # Do not try to create build directories when build_dir is none.
  441. # This reduced mode is used by the --buildoptions introspector
  442. if build_dir is not None:
  443. self.scratch_dir = os.path.join(build_dir, Environment.private_dir)
  444. self.log_dir = os.path.join(build_dir, Environment.log_dir)
  445. self.info_dir = os.path.join(build_dir, Environment.info_dir)
  446. os.makedirs(self.scratch_dir, exist_ok=True)
  447. os.makedirs(self.log_dir, exist_ok=True)
  448. os.makedirs(self.info_dir, exist_ok=True)
  449. try:
  450. self.coredata = coredata.load(self.get_build_dir())
  451. self.first_invocation = False
  452. except FileNotFoundError:
  453. self.create_new_coredata(options)
  454. except MesonException as e:
  455. # If we stored previous command line options, we can recover from
  456. # a broken/outdated coredata.
  457. if os.path.isfile(coredata.get_cmd_line_file(self.build_dir)):
  458. mlog.warning('Regenerating configuration from scratch.')
  459. mlog.log('Reason:', mlog.red(str(e)))
  460. coredata.read_cmd_line_file(self.build_dir, options)
  461. self.create_new_coredata(options)
  462. else:
  463. raise e
  464. else:
  465. # Just create a fresh coredata in this case
  466. self.scratch_dir = ''
  467. self.create_new_coredata(options)
  468. ## locally bind some unfrozen configuration
  469. # Stores machine infos, the only *three* machine one because we have a
  470. # target machine info on for the user (Meson never cares about the
  471. # target machine.)
  472. machines = PerThreeMachineDefaultable()
  473. # Similar to coredata.compilers, but lower level in that there is no
  474. # meta data, only names/paths.
  475. binaries = PerMachineDefaultable()
  476. # Misc other properties about each machine.
  477. properties = PerMachineDefaultable()
  478. # Store paths for native and cross build files. There is no target
  479. # machine information here because nothing is installed for the target
  480. # architecture, just the build and host architectures
  481. paths = PerMachineDefaultable()
  482. ## Setup build machine defaults
  483. # Will be fully initialized later using compilers later.
  484. machines.build = detect_machine_info()
  485. # Just uses hard-coded defaults and environment variables. Might be
  486. # overwritten by a native file.
  487. binaries.build = BinaryTable()
  488. properties.build = Properties()
  489. ## Read in native file(s) to override build machine configuration
  490. if self.coredata.config_files is not None:
  491. config = MesonConfigFile.from_config_parser(
  492. coredata.load_configs(self.coredata.config_files))
  493. binaries.build = BinaryTable(config.get('binaries', {}))
  494. paths.build = Directories(**config.get('paths', {}))
  495. properties.build = Properties(config.get('properties', {}))
  496. ## Read in cross file(s) to override host machine configuration
  497. if self.coredata.cross_files:
  498. config = MesonConfigFile.from_config_parser(
  499. coredata.load_configs(self.coredata.cross_files))
  500. properties.host = Properties(config.get('properties', {}))
  501. binaries.host = BinaryTable(config.get('binaries', {}))
  502. if 'host_machine' in config:
  503. machines.host = MachineInfo.from_literal(config['host_machine'])
  504. if 'target_machine' in config:
  505. machines.target = MachineInfo.from_literal(config['target_machine'])
  506. paths.host = Directories(**config.get('paths', {}))
  507. ## "freeze" now initialized configuration, and "save" to the class.
  508. self.machines = machines.default_missing()
  509. self.binaries = binaries.default_missing()
  510. self.properties = properties.default_missing()
  511. self.paths = paths.default_missing()
  512. exe_wrapper = self.lookup_binary_entry(MachineChoice.HOST, 'exe_wrapper')
  513. if exe_wrapper is not None:
  514. from .dependencies import ExternalProgram
  515. self.exe_wrapper = ExternalProgram.from_bin_list(self, MachineChoice.HOST, 'exe_wrapper')
  516. else:
  517. self.exe_wrapper = None
  518. self.cmd_line_options = options.cmd_line_options.copy()
  519. # List of potential compilers.
  520. if mesonlib.is_windows():
  521. # Intel C and C++ compiler is icl on Windows, but icc and icpc elsewhere.
  522. # Search for icl before cl, since Intel "helpfully" provides a
  523. # cl.exe that returns *exactly the same thing* that microsofts
  524. # cl.exe does, and if icl is present, it's almost certainly what
  525. # you want.
  526. self.default_c = ['icl', 'cl', 'cc', 'gcc', 'clang', 'clang-cl', 'pgcc']
  527. # There is currently no pgc++ for Windows, only for Mac and Linux.
  528. self.default_cpp = ['icl', 'cl', 'c++', 'g++', 'clang++', 'clang-cl']
  529. self.default_fortran = ['ifort', 'gfortran', 'flang', 'pgfortran', 'g95']
  530. # Clang and clang++ are valid, but currently unsupported.
  531. self.default_objc = ['cc', 'gcc']
  532. self.default_objcpp = ['c++', 'g++']
  533. self.default_cs = ['csc', 'mcs']
  534. else:
  535. if platform.machine().lower() == 'e2k':
  536. # There are no objc or objc++ compilers for Elbrus,
  537. # and there's no clang which can build binaries for host.
  538. self.default_c = ['cc', 'gcc', 'lcc']
  539. self.default_cpp = ['c++', 'g++', 'l++']
  540. self.default_objc = []
  541. self.default_objcpp = []
  542. else:
  543. self.default_c = ['cc', 'gcc', 'clang', 'pgcc', 'icc']
  544. self.default_cpp = ['c++', 'g++', 'clang++', 'pgc++', 'icpc']
  545. self.default_objc = ['cc', 'gcc', 'clang']
  546. self.default_objcpp = ['c++', 'g++', 'clang++']
  547. self.default_fortran = ['gfortran', 'flang', 'pgfortran', 'ifort', 'g95']
  548. self.default_cs = ['mcs', 'csc']
  549. self.default_d = ['ldc2', 'ldc', 'gdc', 'dmd']
  550. self.default_java = ['javac']
  551. self.default_cuda = ['nvcc']
  552. self.default_rust = ['rustc']
  553. self.default_swift = ['swiftc']
  554. self.default_vala = ['valac']
  555. self.default_static_linker = ['ar', 'gar']
  556. self.default_strip = ['strip']
  557. self.vs_static_linker = ['lib']
  558. self.clang_cl_static_linker = ['llvm-lib']
  559. self.cuda_static_linker = ['nvlink']
  560. self.gcc_static_linker = ['gcc-ar']
  561. self.clang_static_linker = ['llvm-ar']
  562. self.default_cmake = ['cmake']
  563. self.default_pkgconfig = ['pkg-config']
  564. def create_new_coredata(self, options):
  565. # WARNING: Don't use any values from coredata in __init__. It gets
  566. # re-initialized with project options by the interpreter during
  567. # build file parsing.
  568. self.coredata = coredata.CoreData(options, self.scratch_dir)
  569. # Used by the regenchecker script, which runs meson
  570. self.coredata.meson_command = mesonlib.meson_command
  571. self.first_invocation = True
  572. def is_cross_build(self) -> bool:
  573. return self.coredata.is_cross_build()
  574. def dump_coredata(self):
  575. return coredata.save(self.coredata, self.get_build_dir())
  576. def get_script_dir(self):
  577. import mesonbuild.scripts
  578. return os.path.dirname(mesonbuild.scripts.__file__)
  579. def get_log_dir(self):
  580. return self.log_dir
  581. def get_coredata(self):
  582. return self.coredata
  583. def get_build_command(self, unbuffered=False):
  584. cmd = mesonlib.meson_command[:]
  585. if unbuffered and 'python' in os.path.basename(cmd[0]):
  586. cmd.insert(1, '-u')
  587. return cmd
  588. def is_header(self, fname):
  589. return is_header(fname)
  590. def is_source(self, fname):
  591. return is_source(fname)
  592. def is_assembly(self, fname):
  593. return is_assembly(fname)
  594. def is_llvm_ir(self, fname):
  595. return is_llvm_ir(fname)
  596. def is_object(self, fname):
  597. return is_object(fname)
  598. @lru_cache(maxsize=None)
  599. def is_library(self, fname):
  600. return is_library(fname)
  601. def lookup_binary_entry(self, for_machine: MachineChoice, name: str):
  602. return self.binaries[for_machine].lookup_entry(
  603. for_machine,
  604. self.is_cross_build(),
  605. name)
  606. @staticmethod
  607. def get_gnu_compiler_defines(compiler):
  608. """
  609. Detect GNU compiler platform type (Apple, MinGW, Unix)
  610. """
  611. # Arguments to output compiler pre-processor defines to stdout
  612. # gcc, g++, and gfortran all support these arguments
  613. args = compiler + ['-E', '-dM', '-']
  614. p, output, error = Popen_safe(args, write='', stdin=subprocess.PIPE)
  615. if p.returncode != 0:
  616. raise EnvironmentException('Unable to detect GNU compiler type:\n' + output + error)
  617. # Parse several lines of the type:
  618. # `#define ___SOME_DEF some_value`
  619. # and extract `___SOME_DEF`
  620. defines = {}
  621. for line in output.split('\n'):
  622. if not line:
  623. continue
  624. d, *rest = line.split(' ', 2)
  625. if d != '#define':
  626. continue
  627. if len(rest) == 1:
  628. defines[rest] = True
  629. if len(rest) == 2:
  630. defines[rest[0]] = rest[1]
  631. return defines
  632. @staticmethod
  633. def get_gnu_version_from_defines(defines):
  634. dot = '.'
  635. major = defines.get('__GNUC__', '0')
  636. minor = defines.get('__GNUC_MINOR__', '0')
  637. patch = defines.get('__GNUC_PATCHLEVEL__', '0')
  638. return dot.join((major, minor, patch))
  639. @staticmethod
  640. def get_lcc_version_from_defines(defines):
  641. dot = '.'
  642. generation_and_major = defines.get('__LCC__', '100')
  643. generation = generation_and_major[:1]
  644. major = generation_and_major[1:]
  645. minor = defines.get('__LCC_MINOR__', '0')
  646. return dot.join((generation, major, minor))
  647. def _get_compilers(self, lang, for_machine):
  648. '''
  649. The list of compilers is detected in the exact same way for
  650. C, C++, ObjC, ObjC++, Fortran, CS so consolidate it here.
  651. '''
  652. value = self.lookup_binary_entry(for_machine, lang)
  653. if value is not None:
  654. compilers, ccache = BinaryTable.parse_entry(value)
  655. # Return value has to be a list of compiler 'choices'
  656. compilers = [compilers]
  657. else:
  658. if not self.machines.matches_build_machine(for_machine):
  659. raise EnvironmentException('{!r} compiler binary not defined in cross or native file'.format(lang))
  660. compilers = getattr(self, 'default_' + lang)
  661. ccache = BinaryTable.detect_ccache()
  662. if self.machines.matches_build_machine(for_machine):
  663. exe_wrap = None
  664. else:
  665. exe_wrap = self.get_exe_wrapper()
  666. return compilers, ccache, exe_wrap
  667. def _handle_exceptions(self, exceptions, binaries, bintype='compiler'):
  668. errmsg = 'Unknown {}(s): {}'.format(bintype, binaries)
  669. if exceptions:
  670. errmsg += '\nThe follow exceptions were encountered:'
  671. for (c, e) in exceptions.items():
  672. errmsg += '\nRunning "{0}" gave "{1}"'.format(c, e)
  673. raise EnvironmentException(errmsg)
  674. def _guess_win_linker(self, compiler: T.List[str], comp_class: Compiler,
  675. for_machine: MachineChoice, *,
  676. use_linker_prefix: bool = True, invoked_directly: bool = True,
  677. extra_args: T.Optional[T.List[str]] = None) -> 'DynamicLinker':
  678. self.coredata.add_lang_args(comp_class.language, comp_class, for_machine, self)
  679. # Explicitly pass logo here so that we can get the version of link.exe
  680. if not use_linker_prefix or comp_class.LINKER_PREFIX is None:
  681. check_args = ['/logo', '--version']
  682. elif isinstance(comp_class.LINKER_PREFIX, str):
  683. check_args = [comp_class.LINKER_PREFIX + '/logo', comp_class.LINKER_PREFIX + '--version']
  684. elif isinstance(comp_class.LINKER_PREFIX, list):
  685. check_args = comp_class.LINKER_PREFIX + ['/logo'] + comp_class.LINKER_PREFIX + ['--version']
  686. check_args += self.coredata.compiler_options[for_machine][comp_class.language]['args'].value
  687. override = [] # type: T.List[str]
  688. value = self.lookup_binary_entry(for_machine, comp_class.language + '_ld')
  689. if value is not None:
  690. override = comp_class.use_linker_args(value[0])
  691. check_args += override
  692. if extra_args is not None:
  693. check_args.extend(extra_args)
  694. p, o, _ = Popen_safe(compiler + check_args)
  695. if o.startswith('LLD'):
  696. if '(compatible with GNU linkers)' in o:
  697. return LLVMDynamicLinker(
  698. compiler, for_machine, comp_class.LINKER_PREFIX,
  699. override, version=search_version(o))
  700. if value is not None and invoked_directly:
  701. compiler = value
  702. # We've already hanedled the non-direct case above
  703. p, o, e = Popen_safe(compiler + check_args)
  704. if o.startswith('LLD'):
  705. return ClangClDynamicLinker(
  706. for_machine, [],
  707. prefix=comp_class.LINKER_PREFIX if use_linker_prefix else [],
  708. exelist=compiler, version=search_version(o), direct=invoked_directly)
  709. elif 'OPTLINK' in o:
  710. # Opltink's stdout *may* beging with a \r character.
  711. return OptlinkDynamicLinker(compiler, for_machine, version=search_version(o))
  712. elif o.startswith('Microsoft') or e.startswith('Microsoft'):
  713. out = o or e
  714. match = re.search(r'.*(X86|X64|ARM|ARM64).*', out)
  715. if match:
  716. target = str(match.group(1))
  717. else:
  718. target = 'x86'
  719. return MSVCDynamicLinker(
  720. for_machine, [], machine=target, exelist=compiler,
  721. prefix=comp_class.LINKER_PREFIX if use_linker_prefix else [],
  722. version=search_version(out), direct=invoked_directly)
  723. elif 'GNU coreutils' in o:
  724. raise EnvironmentException(
  725. "Found GNU link.exe instead of MSVC link.exe. This link.exe "
  726. "is not a linker. You may need to reorder entries to your "
  727. "%PATH% variable to resolve this.")
  728. raise EnvironmentException('Unable to determine dynamic linker')
  729. def _guess_nix_linker(self, compiler: T.List[str], comp_class: T.Type[Compiler],
  730. for_machine: MachineChoice, *,
  731. extra_args: T.Optional[T.List[str]] = None) -> 'DynamicLinker':
  732. """Helper for guessing what linker to use on Unix-Like OSes.
  733. :compiler: Invocation to use to get linker
  734. :comp_class: The Compiler Type (uninstantiated)
  735. :for_machine: which machine this linker targets
  736. :extra_args: Any additional arguments required (such as a source file)
  737. """
  738. self.coredata.add_lang_args(comp_class.language, comp_class, for_machine, self)
  739. extra_args = T.cast(T.List[str], extra_args or [])
  740. extra_args += self.coredata.compiler_options[for_machine][comp_class.language]['args'].value
  741. if isinstance(comp_class.LINKER_PREFIX, str):
  742. check_args = [comp_class.LINKER_PREFIX + '--version'] + extra_args
  743. else:
  744. check_args = comp_class.LINKER_PREFIX + ['--version'] + extra_args
  745. override = [] # type: T.List[str]
  746. value = self.lookup_binary_entry(for_machine, comp_class.language + '_ld')
  747. if value is not None:
  748. override = comp_class.use_linker_args(value[0])
  749. check_args += override
  750. _, o, e = Popen_safe(compiler + check_args)
  751. v = search_version(o)
  752. if o.startswith('LLD'):
  753. linker = LLVMDynamicLinker(
  754. compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v) # type: DynamicLinker
  755. elif e.startswith('lld-link: '):
  756. # The LLD MinGW frontend didn't respond to --version before version 9.0.0,
  757. # and produced an error message about failing to link (when no object
  758. # files were specified), instead of printing the version number.
  759. # Let's try to extract the linker invocation command to grab the version.
  760. _, o, e = Popen_safe(compiler + check_args + ['-v'])
  761. try:
  762. linker_cmd = re.match(r'.*\n(.*?)\nlld-link: ', e, re.DOTALL).group(1)
  763. linker_cmd = shlex.split(linker_cmd)[0]
  764. except (AttributeError, IndexError, ValueError):
  765. pass
  766. else:
  767. _, o, e = Popen_safe([linker_cmd, '--version'])
  768. v = search_version(o)
  769. linker = LLVMDynamicLinker(compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v)
  770. # first is for apple clang, second is for real gcc, the third is icc
  771. elif e.endswith('(use -v to see invocation)\n') or 'macosx_version' in e or 'ld: unknown option:' in e:
  772. if isinstance(comp_class.LINKER_PREFIX, str):
  773. _, _, e = Popen_safe(compiler + [comp_class.LINKER_PREFIX + '-v'] + extra_args)
  774. else:
  775. _, _, e = Popen_safe(compiler + comp_class.LINKER_PREFIX + ['-v'] + extra_args)
  776. for line in e.split('\n'):
  777. if 'PROJECT:ld' in line:
  778. v = line.split('-')[1]
  779. break
  780. else:
  781. v = 'unknown version'
  782. linker = AppleDynamicLinker(compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v)
  783. elif 'GNU' in o:
  784. if 'gold' in o:
  785. cls = GnuGoldDynamicLinker
  786. else:
  787. cls = GnuBFDDynamicLinker
  788. linker = cls(compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v)
  789. elif 'Solaris' in e or 'Solaris' in o:
  790. linker = SolarisDynamicLinker(
  791. compiler, for_machine, comp_class.LINKER_PREFIX, override,
  792. version=search_version(e))
  793. else:
  794. raise EnvironmentException('Unable to determine dynamic linker')
  795. return linker
  796. def _detect_c_or_cpp_compiler(self, lang: str, for_machine: MachineChoice) -> Compiler:
  797. popen_exceptions = {}
  798. compilers, ccache, exe_wrap = self._get_compilers(lang, for_machine)
  799. is_cross = not self.machines.matches_build_machine(for_machine)
  800. info = self.machines[for_machine]
  801. for compiler in compilers:
  802. if isinstance(compiler, str):
  803. compiler = [compiler]
  804. compiler_name = os.path.basename(compiler[0])
  805. if not set(['cl', 'cl.exe', 'clang-cl', 'clang-cl.exe']).isdisjoint(compiler):
  806. # Watcom C provides it's own cl.exe clone that mimics an older
  807. # version of Microsoft's compiler. Since Watcom's cl.exe is
  808. # just a wrapper, we skip using it if we detect its presence
  809. # so as not to confuse Meson when configuring for MSVC.
  810. #
  811. # Additionally the help text of Watcom's cl.exe is paged, and
  812. # the binary will not exit without human intervention. In
  813. # practice, Meson will block waiting for Watcom's cl.exe to
  814. # exit, which requires user input and thus will never exit.
  815. if 'WATCOM' in os.environ:
  816. def sanitize(p):
  817. return os.path.normcase(os.path.abspath(p))
  818. watcom_cls = [sanitize(os.path.join(os.environ['WATCOM'], 'BINNT', 'cl')),
  819. sanitize(os.path.join(os.environ['WATCOM'], 'BINNT', 'cl.exe'))]
  820. found_cl = sanitize(shutil.which('cl'))
  821. if found_cl in watcom_cls:
  822. continue
  823. arg = '/?'
  824. elif 'armcc' in compiler_name:
  825. arg = '--vsn'
  826. elif 'ccrx' in compiler_name:
  827. arg = '-v'
  828. elif 'xc16' in compiler_name:
  829. arg = '--version'
  830. elif 'cl2000' in compiler_name:
  831. arg = '-version'
  832. elif compiler_name in {'icl', 'icl.exe'}:
  833. # if you pass anything to icl you get stuck in a pager
  834. arg = ''
  835. else:
  836. arg = '--version'
  837. try:
  838. p, out, err = Popen_safe(compiler + [arg])
  839. except OSError as e:
  840. popen_exceptions[' '.join(compiler + [arg])] = e
  841. continue
  842. if 'ccrx' in compiler_name:
  843. out = err
  844. full_version = out.split('\n', 1)[0]
  845. version = search_version(out)
  846. guess_gcc_or_lcc = False
  847. if 'Free Software Foundation' in out or 'xt-' in out:
  848. guess_gcc_or_lcc = 'gcc'
  849. if 'e2k' in out and 'lcc' in out:
  850. guess_gcc_or_lcc = 'lcc'
  851. if 'Microchip Technology' in out:
  852. # this output has "Free Software Foundation" in its version
  853. guess_gcc_or_lcc = False
  854. if guess_gcc_or_lcc:
  855. defines = self.get_gnu_compiler_defines(compiler)
  856. if not defines:
  857. popen_exceptions[' '.join(compiler)] = 'no pre-processor defines'
  858. continue
  859. if guess_gcc_or_lcc == 'lcc':
  860. version = self.get_lcc_version_from_defines(defines)
  861. cls = ElbrusCCompiler if lang == 'c' else ElbrusCPPCompiler
  862. else:
  863. version = self.get_gnu_version_from_defines(defines)
  864. cls = GnuCCompiler if lang == 'c' else GnuCPPCompiler
  865. linker = self._guess_nix_linker(compiler, cls, for_machine)
  866. return cls(
  867. ccache + compiler, version, for_machine, is_cross,
  868. info, exe_wrap, defines, full_version=full_version,
  869. linker=linker)
  870. if 'Emscripten' in out:
  871. cls = EmscriptenCCompiler if lang == 'c' else EmscriptenCPPCompiler
  872. self.coredata.add_lang_args(cls.language, cls, for_machine, self)
  873. # emcc cannot be queried to get the version out of it (it
  874. # ignores -Wl,--version and doesn't have an alternative).
  875. # Further, wasm-id *is* lld and will return `LLD X.Y.Z` if you
  876. # call `wasm-ld --version`, but a special version of lld that
  877. # takes different options.
  878. p, o, _ = Popen_safe(['wasm-ld', '--version'])
  879. linker = WASMDynamicLinker(
  880. compiler, for_machine, cls.LINKER_PREFIX,
  881. [], version=search_version(o))
  882. return cls(
  883. ccache + compiler, version, for_machine, is_cross, info,
  884. exe_wrap, linker=linker, full_version=full_version)
  885. if 'armclang' in out:
  886. # The compiler version is not present in the first line of output,
  887. # instead it is present in second line, startswith 'Component:'.
  888. # So, searching for the 'Component' in out although we know it is
  889. # present in second line, as we are not sure about the
  890. # output format in future versions
  891. arm_ver_str = re.search('.*Component.*', out)
  892. if arm_ver_str is None:
  893. popen_exceptions[' '.join(compiler)] = 'version string not found'
  894. continue
  895. arm_ver_str = arm_ver_str.group(0)
  896. # Override previous values
  897. version = search_version(arm_ver_str)
  898. full_version = arm_ver_str
  899. cls = ArmclangCCompiler if lang == 'c' else ArmclangCPPCompiler
  900. linker = ArmClangDynamicLinker(for_machine, version=version)
  901. self.coredata.add_lang_args(cls.language, cls, for_machine, self)
  902. return cls(
  903. ccache + compiler, version, for_machine, is_cross, info,
  904. exe_wrap, full_version=full_version, linker=linker)
  905. if 'CL.EXE COMPATIBILITY' in out:
  906. # if this is clang-cl masquerading as cl, detect it as cl, not
  907. # clang
  908. arg = '--version'
  909. try:
  910. p, out, err = Popen_safe(compiler + [arg])
  911. except OSError as e:
  912. popen_exceptions[' '.join(compiler + [arg])] = e
  913. version = search_version(out)
  914. match = re.search('^Target: (.*?)-', out, re.MULTILINE)
  915. if match:
  916. target = match.group(1)
  917. else:
  918. target = 'unknown target'
  919. cls = ClangClCCompiler if lang == 'c' else ClangClCPPCompiler
  920. linker = self._guess_win_linker(['lld-link'], cls, for_machine)
  921. return cls(
  922. compiler, version, for_machine, is_cross, info, exe_wrap,
  923. target, linker=linker)
  924. if 'clang' in out:
  925. linker = None
  926. # Even if the for_machine is darwin, we could be using vanilla
  927. # clang.
  928. if 'Apple' in out:
  929. cls = AppleClangCCompiler if lang == 'c' else AppleClangCPPCompiler
  930. else:
  931. cls = ClangCCompiler if lang == 'c' else ClangCPPCompiler
  932. if 'windows' in out or self.machines[for_machine].is_windows():
  933. # If we're in a MINGW context this actually will use a gnu
  934. # style ld, but for clang on "real" windows we'll use
  935. # either link.exe or lld-link.exe
  936. try:
  937. linker = self._guess_win_linker(compiler, cls, for_machine)
  938. except MesonException:
  939. pass
  940. if linker is None:
  941. linker = self._guess_nix_linker(compiler, cls, for_machine)
  942. return cls(
  943. ccache + compiler, version, for_machine, is_cross, info,
  944. exe_wrap, full_version=full_version, linker=linker)
  945. if 'Intel(R) C++ Intel(R)' in err:
  946. version = search_version(err)
  947. target = 'x86' if 'IA-32' in err else 'x86_64'
  948. cls = IntelClCCompiler if lang == 'c' else IntelClCPPCompiler
  949. self.coredata.add_lang_args(cls.language, cls, for_machine, self)
  950. linker = XilinkDynamicLinker(for_machine, [], version=version)
  951. return cls(
  952. compiler, version, for_machine, is_cross, info=info,
  953. exe_wrap=exe_wrap, target=target, linker=linker)
  954. if 'Microsoft' in out or 'Microsoft' in err:
  955. # Latest versions of Visual Studio print version
  956. # number to stderr but earlier ones print version
  957. # on stdout. Why? Lord only knows.
  958. # Check both outputs to figure out version.
  959. for lookat in [err, out]:
  960. version = search_version(lookat)
  961. if version != 'unknown version':
  962. break
  963. else:
  964. m = 'Failed to detect MSVC compiler version: stderr was\n{!r}'
  965. raise EnvironmentException(m.format(err))
  966. cl_signature = lookat.split('\n')[0]
  967. match = re.search('.*(x86|x64|ARM|ARM64)( |$)', cl_signature)
  968. if match:
  969. target = match.group(1)
  970. else:
  971. m = 'Failed to detect MSVC compiler target architecture: \'cl /?\' output is\n{}'
  972. raise EnvironmentException(m.format(cl_signature))
  973. cls = VisualStudioCCompiler if lang == 'c' else VisualStudioCPPCompiler
  974. linker = self._guess_win_linker(['link'], cls, for_machine)
  975. return cls(
  976. compiler, version, for_machine, is_cross, info, exe_wrap,
  977. target, linker=linker)
  978. if 'PGI Compilers' in out:
  979. cls = PGICCompiler if lang == 'c' else PGICPPCompiler
  980. self.coredata.add_lang_args(cls.language, cls, for_machine, self)
  981. linker = PGIDynamicLinker(compiler, for_machine, cls.LINKER_PREFIX, [], version=version)
  982. return cls(
  983. ccache + compiler, version, for_machine, is_cross,
  984. info, exe_wrap, linker=linker)
  985. if '(ICC)' in out:
  986. cls = IntelCCompiler if lang == 'c' else IntelCPPCompiler
  987. l = self._guess_nix_linker(compiler, cls, for_machine)
  988. return cls(
  989. ccache + compiler, version, for_machine, is_cross, info,
  990. exe_wrap, full_version=full_version, linker=l)
  991. if 'ARM' in out:
  992. cls = ArmCCompiler if lang == 'c' else ArmCPPCompiler
  993. self.coredata.add_lang_args(cls.language, cls, for_machine, self)
  994. linker = ArmDynamicLinker(for_machine, version=version)
  995. return cls(
  996. ccache + compiler, version, for_machine, is_cross,
  997. info, exe_wrap, full_version=full_version, linker=linker)
  998. if 'RX Family' in out:
  999. cls = CcrxCCompiler if lang == 'c' else CcrxCPPCompiler
  1000. self.coredata.add_lang_args(cls.language, cls, for_machine, self)
  1001. linker = CcrxDynamicLinker(for_machine, version=version)
  1002. return cls(
  1003. ccache + compiler, version, for_machine, is_cross, info,
  1004. exe_wrap, full_version=full_version, linker=linker)
  1005. if 'Microchip Technology' in out:
  1006. cls = Xc16CCompiler if lang == 'c' else Xc16CCompiler
  1007. self.coredata.add_lang_args(cls.language, cls, for_machine, self)
  1008. linker = Xc16DynamicLinker(for_machine, version=version)
  1009. return cls(
  1010. ccache + compiler, version, for_machine, is_cross, info,
  1011. exe_wrap, full_version=full_version, linker=linker)
  1012. if 'TMS320C2000 C/C++' in out:
  1013. cls = C2000CCompiler if lang == 'c' else C2000CPPCompiler
  1014. self.coredata.add_lang_args(cls.language, cls, for_machine, self)
  1015. linker = C2000DynamicLinker(for_machine, version=version)
  1016. return cls(
  1017. ccache + compiler, version, for_machine, is_cross, info,
  1018. exe_wrap, full_version=full_version, linker=linker)
  1019. self._handle_exceptions(popen_exceptions, compilers)
  1020. def detect_c_compiler(self, for_machine):
  1021. return self._detect_c_or_cpp_compiler('c', for_machine)
  1022. def detect_cpp_compiler(self, for_machine):
  1023. return self._detect_c_or_cpp_compiler('cpp', for_machine)
  1024. def detect_cuda_compiler(self, for_machine):
  1025. popen_exceptions = {}
  1026. is_cross = not self.machines.matches_build_machine(for_machine)
  1027. compilers, ccache, exe_wrap = self._get_compilers('cuda', for_machine)
  1028. info = self.machines[for_machine]
  1029. for compiler in compilers:
  1030. if isinstance(compiler, str):
  1031. compiler = [compiler]
  1032. else:
  1033. raise EnvironmentException()
  1034. arg = '--version'
  1035. try:
  1036. p, out, err = Popen_safe(compiler + [arg])
  1037. except OSError as e:
  1038. popen_exceptions[' '.join(compiler + [arg])] = e
  1039. continue
  1040. # Example nvcc printout:
  1041. #
  1042. # nvcc: NVIDIA (R) Cuda compiler driver
  1043. # Copyright (c) 2005-2018 NVIDIA Corporation
  1044. # Built on Sat_Aug_25_21:08:01_CDT_2018
  1045. # Cuda compilation tools, release 10.0, V10.0.130
  1046. #
  1047. # search_version() first finds the "10.0" after "release",
  1048. # rather than the more precise "10.0.130" after "V".
  1049. # The patch version number is occasionally important; For
  1050. # instance, on Linux,
  1051. # - CUDA Toolkit 8.0.44 requires NVIDIA Driver 367.48
  1052. # - CUDA Toolkit 8.0.61 requires NVIDIA Driver 375.26
  1053. # Luckily, the "V" also makes it very simple to extract
  1054. # the full version:
  1055. version = out.strip().split('V')[-1]
  1056. cpp_compiler = self.detect_cpp_compiler(for_machine)
  1057. cls = CudaCompiler
  1058. self.coredata.add_lang_args(cls.language, cls, for_machine, self)
  1059. linker = CudaLinker(compiler, for_machine, CudaCompiler.LINKER_PREFIX, [], version=CudaLinker.parse_version())
  1060. return cls(ccache + compiler, version, for_machine, is_cross, exe_wrap, host_compiler=cpp_compiler, info=info, linker=linker)
  1061. raise EnvironmentException('Could not find suitable CUDA compiler: "' + ' '.join(compilers) + '"')
  1062. def detect_fortran_compiler(self, for_machine: MachineChoice):
  1063. popen_exceptions = {}
  1064. compilers, ccache, exe_wrap = self._get_compilers('fortran', for_machine)
  1065. is_cross = not self.machines.matches_build_machine(for_machine)
  1066. info = self.machines[for_machine]
  1067. for compiler in compilers:
  1068. if isinstance(compiler, str):
  1069. compiler = [compiler]
  1070. for arg in ['--version', '-V']:
  1071. try:
  1072. p, out, err = Popen_safe(compiler + [arg])
  1073. except OSError as e:
  1074. popen_exceptions[' '.join(compiler + [arg])] = e
  1075. continue
  1076. version = search_version(out)
  1077. full_version = out.split('\n', 1)[0]
  1078. guess_gcc_or_lcc = False
  1079. if 'GNU Fortran' in out:
  1080. guess_gcc_or_lcc = 'gcc'
  1081. if 'e2k' in out and 'lcc' in out:
  1082. guess_gcc_or_lcc = 'lcc'
  1083. if guess_gcc_or_lcc:
  1084. defines = self.get_gnu_compiler_defines(compiler)
  1085. if not defines:
  1086. popen_exceptions[' '.join(compiler)] = 'no pre-processor defines'
  1087. continue
  1088. if guess_gcc_or_lcc == 'lcc':
  1089. version = self.get_lcc_version_from_defines(defines)
  1090. cls = ElbrusFortranCompiler
  1091. else:
  1092. version = self.get_gnu_version_from_defines(defines)
  1093. cls = GnuFortranCompiler
  1094. linker = self._guess_nix_linker(
  1095. compiler, cls, for_machine)
  1096. return cls(
  1097. compiler, version, for_machine, is_cross, info,
  1098. exe_wrap, defines, full_version=full_version,
  1099. linker=linker)
  1100. if 'G95' in out:
  1101. linker = self._guess_nix_linker(
  1102. compiler, cls, for_machine)
  1103. return G95FortranCompiler(
  1104. compiler, version, for_machine, is_cross, info,
  1105. exe_wrap, full_version=full_version, linker=linker)
  1106. if 'Sun Fortran' in err:
  1107. version = search_version(err)
  1108. linker = self._guess_nix_linker(
  1109. compiler, cls, for_machine)
  1110. return SunFortranCompiler(
  1111. compiler, version, for_machine, is_cross, info,
  1112. exe_wrap, full_version=full_version, linker=linker)
  1113. if 'Intel(R) Visual Fortran' in err:
  1114. version = search_version(err)
  1115. target = 'x86' if 'IA-32' in err else 'x86_64'
  1116. cls = IntelClFortranCompiler
  1117. self.coredata.add_lang_args(cls.language, cls, for_machine, self)
  1118. linker = XilinkDynamicLinker(for_machine, [], version=version)
  1119. return cls(
  1120. compiler, version, for_machine, is_cross, target,
  1121. info, exe_wrap, linker=linker)
  1122. if 'ifort (IFORT)' in out:
  1123. linker = self._guess_nix_linker(compiler, IntelFortranCompiler, for_machine)
  1124. return IntelFortranCompiler(
  1125. compiler, version, for_machine, is_cross, info,
  1126. exe_wrap, full_version=full_version, linker=linker)
  1127. if 'PathScale EKOPath(tm)' in err:
  1128. return PathScaleFortranCompiler(
  1129. compiler, version, for_machine, is_cross, info,
  1130. exe_wrap, full_version=full_version)
  1131. if 'PGI Compilers' in out:
  1132. cls = PGIFortranCompiler
  1133. self.coredata.add_lang_args(cls.language, cls, for_machine, self)
  1134. linker = PGIDynamicLinker(compiler, for_machine,
  1135. cls.LINKER_PREFIX, [], version=version)
  1136. return cls(
  1137. compiler, version, for_machine, is_cross, info, exe_wrap,
  1138. full_version=full_version, linker=linker)
  1139. if 'flang' in out or 'clang' in out:
  1140. linker = self._guess_nix_linker(
  1141. compiler, FlangFortranCompiler, for_machine)
  1142. return FlangFortranCompiler(
  1143. compiler, version, for_machine, is_cross, info,
  1144. exe_wrap, full_version=full_version, linker=linker)
  1145. if 'Open64 Compiler Suite' in err:
  1146. linker = self._guess_nix_linker(
  1147. compiler, Open64FortranCompiler, for_machine)
  1148. return Open64FortranCompiler(
  1149. compiler, version, for_machine, is_cross, info,
  1150. exe_wrap, full_version=full_version, linker=linker)
  1151. if 'NAG Fortran' in err:
  1152. linker = self._guess_nix_linker(
  1153. compiler, NAGFortranCompiler, for_machine)
  1154. return NAGFortranCompiler(
  1155. compiler, version, for_machine, is_cross, info,
  1156. exe_wrap, full_version=full_version, linker=linker)
  1157. self._handle_exceptions(popen_exceptions, compilers)
  1158. def get_scratch_dir(self):
  1159. return self.scratch_dir
  1160. def detect_objc_compiler(self, for_machine: MachineInfo) -> 'Compiler':
  1161. return self._detect_objc_or_objcpp_compiler(for_machine, True)
  1162. def detect_objcpp_compiler(self, for_machine: MachineInfo) -> 'Compiler':
  1163. return self._detect_objc_or_objcpp_compiler(for_machine, False)
  1164. def _detect_objc_or_objcpp_compiler(self, for_machine: MachineInfo, objc: bool) -> 'Compiler':
  1165. popen_exceptions = {}
  1166. compilers, ccache, exe_wrap = self._get_compilers('objc' if objc else 'objcpp', for_machine)
  1167. is_cross = not self.machines.matches_build_machine(for_machine)
  1168. info = self.machines[for_machine]
  1169. for compiler in compilers:
  1170. if isinstance(compiler, str):
  1171. compiler = [compiler]
  1172. arg = ['--version']
  1173. try:
  1174. p, out, err = Popen_safe(compiler + arg)
  1175. except OSError as e:
  1176. popen_exceptions[' '.join(compiler + arg)] = e
  1177. continue
  1178. version = search_version(out)
  1179. if 'Free Software Foundation' in out:
  1180. defines = self.get_gnu_compiler_defines(compiler)
  1181. if not defines:
  1182. popen_exceptions[' '.join(compiler)] = 'no pre-processor defines'
  1183. continue
  1184. version = self.get_gnu_version_from_defines(defines)
  1185. comp = GnuObjCCompiler if objc else GnuObjCPPCompiler
  1186. linker = self._guess_nix_linker(compiler, comp, for_machine)
  1187. return comp(
  1188. ccache + compiler, version, for_machine, is_cross, info,
  1189. exe_wrap, defines, linker=linker)
  1190. if 'clang' in out:
  1191. linker = None
  1192. comp = ClangObjCCompiler if objc else ClangObjCPPCompiler
  1193. if 'windows' in out or self.machines[for_machine].is_windows():
  1194. # If we're in a MINGW context this actually will use a gnu style ld
  1195. try:
  1196. linker = self._guess_win_linker(compiler, comp, for_machine)
  1197. except MesonException:
  1198. pass
  1199. if not linker:
  1200. linker = self._guess_nix_linker(
  1201. compiler, comp, for_machine)
  1202. return comp(
  1203. ccache + compiler, version, for_machine,
  1204. is_cross, info, exe_wrap, linker=linker)
  1205. self._handle_exceptions(popen_exceptions, compilers)
  1206. def detect_java_compiler(self, for_machine):
  1207. exelist = self.lookup_binary_entry(for_machine, 'java')
  1208. info = self.machines[for_machine]
  1209. if exelist is None:
  1210. # TODO support fallback
  1211. exelist = [self.default_java[0]]
  1212. try:
  1213. p, out, err = Popen_safe(exelist + ['-version'])
  1214. except OSError:
  1215. raise EnvironmentException('Could not execute Java compiler "{}"'.format(' '.join(exelist)))
  1216. if 'javac' in out or 'javac' in err:
  1217. version = search_version(err if 'javac' in err else out)
  1218. if not version or version == 'unknown version':
  1219. parts = (err if 'javac' in err else out).split()
  1220. if len(parts) > 1:
  1221. version = parts[1]
  1222. comp_class = JavaCompiler
  1223. self.coredata.add_lang_args(comp_class.language, comp_class, for_machine, self)
  1224. return comp_class(exelist, version, for_machine, info)
  1225. raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"')
  1226. def detect_cs_compiler(self, for_machine):
  1227. compilers, ccache, exe_wrap = self._get_compilers('cs', for_machine)
  1228. popen_exceptions = {}
  1229. info = self.machines[for_machine]
  1230. for comp in compilers:
  1231. if not isinstance(comp, list):
  1232. comp = [comp]
  1233. try:
  1234. p, out, err = Popen_safe(comp + ['--version'])
  1235. except OSError as e:
  1236. popen_exceptions[' '.join(comp + ['--version'])] = e
  1237. continue
  1238. version = search_version(out)
  1239. if 'Mono' in out:
  1240. cls = MonoCompiler
  1241. elif "Visual C#" in out:
  1242. cls = VisualStudioCsCompiler
  1243. else:
  1244. continue
  1245. self.coredata.add_lang_args(cls.language, cls, for_machine, self)
  1246. return cls(comp, version, for_machine, info)
  1247. self._handle_exceptions(popen_exceptions, compilers)
  1248. def detect_vala_compiler(self, for_machine):
  1249. exelist = self.lookup_binary_entry(for_machine, 'vala')
  1250. is_cross = not self.machines.matches_build_machine(for_machine)
  1251. info = self.machines[for_machine]
  1252. if exelist is None:
  1253. # TODO support fallback
  1254. exelist = [self.default_vala[0]]
  1255. try:
  1256. p, out = Popen_safe(exelist + ['--version'])[0:2]
  1257. except OSError:
  1258. raise EnvironmentException('Could not execute Vala compiler "{}"'.format(' '.join(exelist)))
  1259. version = search_version(out)
  1260. if 'Vala' in out:
  1261. comp_class = ValaCompiler
  1262. self.coredata.add_lang_args(comp_class.language, comp_class, for_machine, self)
  1263. return comp_class(exelist, version, for_machine, info, is_cross)
  1264. raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"')
  1265. def detect_rust_compiler(self, for_machine):
  1266. popen_exceptions = {}
  1267. compilers, ccache, exe_wrap = self._get_compilers('rust', for_machine)
  1268. is_cross = not self.machines.matches_build_machine(for_machine)
  1269. info = self.machines[for_machine]
  1270. cc = self.detect_c_compiler(for_machine)
  1271. is_link_exe = isinstance(cc.linker, VisualStudioLikeLinkerMixin)
  1272. override = self.lookup_binary_entry(for_machine, 'rust_ld')
  1273. for compiler in compilers:
  1274. if isinstance(compiler, str):
  1275. compiler = [compiler]
  1276. arg = ['--version']
  1277. try:
  1278. p, out = Popen_safe(compiler + arg)[0:2]
  1279. except OSError as e:
  1280. popen_exceptions[' '.join(compiler + arg)] = e
  1281. continue
  1282. version = search_version(out)
  1283. if 'rustc' in out:
  1284. # On Linux and mac rustc will invoke gcc (clang for mac
  1285. # presumably) and it can do this windows, for dynamic linking.
  1286. # this means the easiest way to C compiler for dynamic linking.
  1287. # figure out what linker to use is to just get the value of the
  1288. # C compiler and use that as the basis of the rust linker.
  1289. # However, there are two things we need to change, if CC is not
  1290. # the default use that, and second add the necessary arguments
  1291. # to rust to use -fuse-ld
  1292. if override is None:
  1293. extra_args = {}
  1294. always_args = []
  1295. if is_link_exe:
  1296. compiler.extend(['-C', 'linker={}'.format(cc.linker.exelist[0])])
  1297. extra_args['direct'] = True
  1298. extra_args['machine'] = cc.linker.machine
  1299. elif not ((info.is_darwin() and isinstance(cc, AppleClangCCompiler)) or
  1300. isinstance(cc, GnuCCompiler)):
  1301. c = cc.exelist[1] if cc.exelist[0].endswith('ccache') else cc.exelist[0]
  1302. compiler.extend(['-C', 'linker={}'.format(c)])
  1303. # This trickery with type() gets us the class of the linker
  1304. # so we can initialize a new copy for the Rust Compiler
  1305. if is_link_exe:
  1306. linker = type(cc.linker)(for_machine, always_args, exelist=cc.linker.exelist,
  1307. version=cc.linker.version, **extra_args)
  1308. else:
  1309. linker = type(cc.linker)(compiler, for_machine, cc.LINKER_PREFIX,
  1310. always_args=always_args, version=cc.linker.version,
  1311. **extra_args)
  1312. elif 'link' in override[0]:
  1313. linker = self._guess_win_linker(
  1314. override, RustCompiler, for_machine, use_linker_prefix=False)
  1315. linker.direct = True
  1316. else:
  1317. # We're creating a new type of "C" compiler, that has rust
  1318. # as it's language. This is gross, but I can't figure out
  1319. # another way to handle this, because rustc is actually
  1320. # invoking the c compiler as it's linker.
  1321. b = type('b', (type(cc), ), {})
  1322. b.language = RustCompiler.language
  1323. linker = self._guess_nix_linker(cc.exelist, b, for_machine)
  1324. # Of course, we're not going to use any of that, we just
  1325. # need it to get the proper arguments to pass to rustc
  1326. c = cc.exelist[1] if cc.exelist[0].endswith('ccache') else cc.exelist[0]
  1327. compiler.extend(['-C', 'linker={}'.format(c)])
  1328. compiler.extend(['-C', 'link-args={}'.format(' '.join(cc.use_linker_args(override[0])))])
  1329. self.coredata.add_lang_args(RustCompiler.language, RustCompiler, for_machine, self)
  1330. return RustCompiler(
  1331. compiler, version, for_machine, is_cross, info, exe_wrap,
  1332. linker=linker)
  1333. self._handle_exceptions(popen_exceptions, compilers)
  1334. def detect_d_compiler(self, for_machine: MachineChoice):
  1335. info = self.machines[for_machine]
  1336. # Detect the target architecture, required for proper architecture handling on Windows.
  1337. # MSVC compiler is required for correct platform detection.
  1338. c_compiler = {'c': self.detect_c_compiler(for_machine)}
  1339. is_msvc = isinstance(c_compiler['c'], VisualStudioCCompiler)
  1340. if not is_msvc:
  1341. c_compiler = {}
  1342. arch = detect_cpu_family(c_compiler)
  1343. if is_msvc and arch == 'x86':
  1344. arch = 'x86_mscoff'
  1345. popen_exceptions = {}
  1346. is_cross = not self.machines.matches_build_machine(for_machine)
  1347. results, ccache, exe_wrap = self._get_compilers('d', for_machine)
  1348. for exelist in results:
  1349. # Search for a D compiler.
  1350. # We prefer LDC over GDC unless overridden with the DC
  1351. # environment variable because LDC has a much more
  1352. # up to date language version at time (2016).
  1353. if not isinstance(exelist, list):
  1354. exelist = [exelist]
  1355. if os.path.basename(exelist[-1]).startswith(('ldmd', 'gdmd')):
  1356. raise EnvironmentException(
  1357. 'Meson does not support {} as it is only a DMD frontend for another compiler.'
  1358. 'Please provide a valid value for DC or unset it so that Meson can resolve the compiler by itself.'.format(exelist[-1]))
  1359. try:
  1360. p, out = Popen_safe(exelist + ['--version'])[0:2]
  1361. except OSError as e:
  1362. popen_exceptions[' '.join(exelist + ['--version'])] = e
  1363. continue
  1364. version = search_version(out)
  1365. full_version = out.split('\n', 1)[0]
  1366. if 'LLVM D compiler' in out:
  1367. # LDC seems to require a file
  1368. # We cannot use NamedTemproraryFile on windows, its documented
  1369. # to not work for our uses. So, just use mkstemp and only have
  1370. # one path for simplicity.
  1371. o, f = tempfile.mkstemp('.d')
  1372. os.close(o)
  1373. try:
  1374. if info.is_windows() or info.is_cygwin():
  1375. objfile = os.path.basename(f)[:-1] + 'obj'
  1376. linker = self._guess_win_linker(
  1377. exelist,
  1378. compilers.LLVMDCompiler, for_machine,
  1379. use_linker_prefix=True, invoked_directly=False,
  1380. extra_args=[f])
  1381. else:
  1382. # LDC writes an object file to the current working directory.
  1383. # Clean it up.
  1384. objfile = os.path.basename(f)[:-1] + 'o'
  1385. linker = self._guess_nix_linker(
  1386. exelist, compilers.LLVMDCompiler, for_machine,
  1387. extra_args=[f])
  1388. finally:
  1389. mesonlib.windows_proof_rm(f)
  1390. mesonlib.windows_proof_rm(objfile)
  1391. return compilers.LLVMDCompiler(
  1392. exelist, version, for_machine, info, arch,
  1393. full_version=full_version, linker=linker)
  1394. elif 'gdc' in out:
  1395. linker = self._guess_nix_linker(exelist, compilers.GnuDCompiler, for_machine)
  1396. return compilers.GnuDCompiler(
  1397. exelist, version, for_machine, info, arch, is_cross, exe_wrap,
  1398. full_version=full_version, linker=linker)
  1399. elif 'The D Language Foundation' in out or 'Digital Mars' in out:
  1400. # DMD seems to require a file
  1401. # We cannot use NamedTemproraryFile on windows, its documented
  1402. # to not work for our uses. So, just use mkstemp and only have
  1403. # one path for simplicity.
  1404. o, f = tempfile.mkstemp('.d')
  1405. os.close(o)
  1406. # DMD as different detection logic for x86 and x86_64
  1407. arch_arg = '-m64' if arch == 'x86_64' else '-m32'
  1408. try:
  1409. if info.is_windows() or info.is_cygwin():
  1410. objfile = os.path.basename(f)[:-1] + 'obj'
  1411. linker = self._guess_win_linker(
  1412. exelist, compilers.DmdDCompiler, for_machine,
  1413. invoked_directly=False, extra_args=[f, arch_arg])
  1414. else:
  1415. objfile = os.path.basename(f)[:-1] + 'o'
  1416. linker = self._guess_nix_linker(
  1417. exelist, compilers.DmdDCompiler, for_machine,
  1418. extra_args=[f, arch_arg])
  1419. finally:
  1420. mesonlib.windows_proof_rm(f)
  1421. mesonlib.windows_proof_rm(objfile)
  1422. return compilers.DmdDCompiler(
  1423. exelist, version, for_machine, info, arch,
  1424. full_version=full_version, linker=linker)
  1425. raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"')
  1426. self._handle_exceptions(popen_exceptions, compilers)
  1427. def detect_swift_compiler(self, for_machine):
  1428. exelist = self.lookup_binary_entry(for_machine, 'swift')
  1429. is_cross = not self.machines.matches_build_machine(for_machine)
  1430. info = self.machines[for_machine]
  1431. if exelist is None:
  1432. # TODO support fallback
  1433. exelist = [self.default_swift[0]]
  1434. try:
  1435. p, _, err = Popen_safe(exelist + ['-v'])
  1436. except OSError:
  1437. raise EnvironmentException('Could not execute Swift compiler "{}"'.format(' '.join(exelist)))
  1438. version = search_version(err)
  1439. if 'Swift' in err:
  1440. # As for 5.0.1 swiftc *requires* a file to check the linker:
  1441. with tempfile.NamedTemporaryFile(suffix='.swift') as f:
  1442. linker = self._guess_nix_linker(
  1443. exelist, compilers.SwiftCompiler, for_machine,
  1444. extra_args=[f.name])
  1445. return compilers.SwiftCompiler(
  1446. exelist, version, for_machine, info, is_cross, linker=linker)
  1447. raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"')
  1448. def compiler_from_language(self, lang: str, for_machine: MachineChoice):
  1449. if lang == 'c':
  1450. comp = self.detect_c_compiler(for_machine)
  1451. elif lang == 'cpp':
  1452. comp = self.detect_cpp_compiler(for_machine)
  1453. elif lang == 'objc':
  1454. comp = self.detect_objc_compiler(for_machine)
  1455. elif lang == 'cuda':
  1456. comp = self.detect_cuda_compiler(for_machine)
  1457. elif lang == 'objcpp':
  1458. comp = self.detect_objcpp_compiler(for_machine)
  1459. elif lang == 'java':
  1460. comp = self.detect_java_compiler(for_machine)
  1461. elif lang == 'cs':
  1462. comp = self.detect_cs_compiler(for_machine)
  1463. elif lang == 'vala':
  1464. comp = self.detect_vala_compiler(for_machine)
  1465. elif lang == 'd':
  1466. comp = self.detect_d_compiler(for_machine)
  1467. elif lang == 'rust':
  1468. comp = self.detect_rust_compiler(for_machine)
  1469. elif lang == 'fortran':
  1470. comp = self.detect_fortran_compiler(for_machine)
  1471. elif lang == 'swift':
  1472. comp = self.detect_swift_compiler(for_machine)
  1473. else:
  1474. comp = None
  1475. return comp
  1476. def detect_compiler_for(self, lang: str, for_machine: MachineChoice):
  1477. comp = self.compiler_from_language(lang, for_machine)
  1478. if comp is not None:
  1479. assert comp.for_machine == for_machine
  1480. self.coredata.process_new_compiler(lang, comp, self)
  1481. return comp
  1482. def detect_static_linker(self, compiler):
  1483. linker = self.lookup_binary_entry(compiler.for_machine, 'ar')
  1484. if linker is not None:
  1485. linkers = [linker]
  1486. else:
  1487. defaults = [[l] for l in self.default_static_linker]
  1488. if isinstance(compiler, compilers.CudaCompiler):
  1489. linkers = [self.cuda_static_linker] + defaults
  1490. elif isinstance(compiler, compilers.VisualStudioLikeCompiler):
  1491. linkers = [self.vs_static_linker, self.clang_cl_static_linker]
  1492. elif isinstance(compiler, compilers.GnuCompiler):
  1493. # Use gcc-ar if available; needed for LTO
  1494. linkers = [self.gcc_static_linker] + defaults
  1495. elif isinstance(compiler, compilers.ClangCompiler):
  1496. # Use llvm-ar if available; needed for LTO
  1497. linkers = [self.clang_static_linker] + defaults
  1498. elif isinstance(compiler, compilers.DCompiler):
  1499. # Prefer static linkers over linkers used by D compilers
  1500. if mesonlib.is_windows():
  1501. linkers = [self.vs_static_linker, self.clang_cl_static_linker, compiler.get_linker_exelist()]
  1502. else:
  1503. linkers = defaults
  1504. elif isinstance(compiler, IntelClCCompiler):
  1505. # Intel has it's own linker that acts like microsoft's lib
  1506. linkers = ['xilib']
  1507. elif isinstance(compiler, (PGICCompiler, PGIFortranCompiler)) and mesonlib.is_windows():
  1508. linkers = [['ar']] # For PGI on Windows, "ar" is just a wrapper calling link/lib.
  1509. else:
  1510. linkers = defaults
  1511. popen_exceptions = {}
  1512. for linker in linkers:
  1513. if not {'lib', 'lib.exe', 'llvm-lib', 'llvm-lib.exe', 'xilib', 'xilib.exe'}.isdisjoint(linker):
  1514. arg = '/?'
  1515. elif not {'ar2000', 'ar2000.exe'}.isdisjoint(linker):
  1516. arg = '?'
  1517. else:
  1518. arg = '--version'
  1519. try:
  1520. p, out, err = Popen_safe(linker + [arg])
  1521. except OSError as e:
  1522. popen_exceptions[' '.join(linker + [arg])] = e
  1523. continue
  1524. if "xilib: executing 'lib'" in err:
  1525. return IntelVisualStudioLinker(linker, getattr(compiler, 'machine', None))
  1526. if '/OUT:' in out.upper() or '/OUT:' in err.upper():
  1527. return VisualStudioLinker(linker, getattr(compiler, 'machine', None))
  1528. if 'ar-Error-Unknown switch: --version' in err:
  1529. return PGIStaticLinker(linker)
  1530. if p.returncode == 0 and ('armar' in linker or 'armar.exe' in linker):
  1531. return ArmarLinker(linker)
  1532. if 'DMD32 D Compiler' in out or 'DMD64 D Compiler' in out:
  1533. return DLinker(linker, compiler.arch)
  1534. if 'LDC - the LLVM D compiler' in out:
  1535. return DLinker(linker, compiler.arch)
  1536. if 'GDC' in out and ' based on D ' in out:
  1537. return DLinker(linker, compiler.arch)
  1538. if err.startswith('Renesas') and ('rlink' in linker or 'rlink.exe' in linker):
  1539. return CcrxLinker(linker)
  1540. if out.startswith('GNU ar') and ('xc16-ar' in linker or 'xc16-ar.exe' in linker):
  1541. return Xc16Linker(linker)
  1542. if out.startswith('TMS320C2000') and ('ar2000' in linker or 'ar2000.exe' in linker):
  1543. return C2000Linker(linker)
  1544. if p.returncode == 0:
  1545. return ArLinker(linker)
  1546. if p.returncode == 1 and err.startswith('usage'): # OSX
  1547. return ArLinker(linker)
  1548. if p.returncode == 1 and err.startswith('Usage'): # AIX
  1549. return ArLinker(linker)
  1550. if p.returncode == 1 and err.startswith('ar: bad option: --'): # Solaris
  1551. return ArLinker(linker)
  1552. self._handle_exceptions(popen_exceptions, linkers, 'linker')
  1553. raise EnvironmentException('Unknown static linker "{}"'.format(' '.join(linkers)))
  1554. def get_source_dir(self):
  1555. return self.source_dir
  1556. def get_build_dir(self):
  1557. return self.build_dir
  1558. def get_import_lib_dir(self) -> str:
  1559. "Install dir for the import library (library used for linking)"
  1560. return self.get_libdir()
  1561. def get_shared_module_dir(self) -> str:
  1562. "Install dir for shared modules that are loaded at runtime"
  1563. return self.get_libdir()
  1564. def get_shared_lib_dir(self) -> str:
  1565. "Install dir for the shared library"
  1566. m = self.machines.host
  1567. # Windows has no RPATH or similar, so DLLs must be next to EXEs.
  1568. if m.is_windows() or m.is_cygwin():
  1569. return self.get_bindir()
  1570. return self.get_libdir()
  1571. def get_static_lib_dir(self) -> str:
  1572. "Install dir for the static library"
  1573. return self.get_libdir()
  1574. def get_prefix(self) -> str:
  1575. return self.coredata.get_builtin_option('prefix')
  1576. def get_libdir(self) -> str:
  1577. return self.coredata.get_builtin_option('libdir')
  1578. def get_libexecdir(self) -> str:
  1579. return self.coredata.get_builtin_option('libexecdir')
  1580. def get_bindir(self) -> str:
  1581. return self.coredata.get_builtin_option('bindir')
  1582. def get_includedir(self) -> str:
  1583. return self.coredata.get_builtin_option('includedir')
  1584. def get_mandir(self) -> str:
  1585. return self.coredata.get_builtin_option('mandir')
  1586. def get_datadir(self) -> str:
  1587. return self.coredata.get_builtin_option('datadir')
  1588. def get_compiler_system_dirs(self, for_machine: MachineChoice):
  1589. for comp in self.coredata.compilers[for_machine].values():
  1590. if isinstance(comp, compilers.ClangCompiler):
  1591. index = 1
  1592. break
  1593. elif isinstance(comp, compilers.GnuCompiler):
  1594. index = 2
  1595. break
  1596. else:
  1597. # This option is only supported by gcc and clang. If we don't get a
  1598. # GCC or Clang compiler return and empty list.
  1599. return []
  1600. p, out, _ = Popen_safe(comp.get_exelist() + ['-print-search-dirs'])
  1601. if p.returncode != 0:
  1602. raise mesonlib.MesonException('Could not calculate system search dirs')
  1603. out = out.split('\n')[index].lstrip('libraries: =').split(':')
  1604. return [os.path.normpath(p) for p in out]
  1605. def need_exe_wrapper(self, for_machine: MachineChoice = MachineChoice.HOST):
  1606. value = self.properties[for_machine].get('needs_exe_wrapper', None)
  1607. if value is not None:
  1608. return value
  1609. return not machine_info_can_run(self.machines[for_machine])
  1610. def get_exe_wrapper(self):
  1611. if not self.need_exe_wrapper():
  1612. from .dependencies import EmptyExternalProgram
  1613. return EmptyExternalProgram()
  1614. return self.exe_wrapper