rust.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  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. import subprocess, os.path
  12. import typing as T
  13. from ..mesonlib import EnvironmentException, MachineChoice, Popen_safe
  14. from .compilers import Compiler, rust_buildtype_args, clike_debug_args
  15. if T.TYPE_CHECKING:
  16. from ..envconfig import MachineInfo
  17. from ..environment import Environment # noqa: F401
  18. rust_optimization_args = {'0': [],
  19. 'g': ['-C', 'opt-level=0'],
  20. '1': ['-C', 'opt-level=1'],
  21. '2': ['-C', 'opt-level=2'],
  22. '3': ['-C', 'opt-level=3'],
  23. 's': ['-C', 'opt-level=s'],
  24. }
  25. class RustCompiler(Compiler):
  26. # rustc doesn't invoke the compiler itself, it doesn't need a LINKER_PREFIX
  27. language = 'rust'
  28. def __init__(self, exelist, version, for_machine: MachineChoice,
  29. is_cross, info: 'MachineInfo', exe_wrapper=None, **kwargs):
  30. super().__init__(exelist, version, for_machine, info, **kwargs)
  31. self.exe_wrapper = exe_wrapper
  32. self.id = 'rustc'
  33. self.is_cross = is_cross
  34. def needs_static_linker(self):
  35. return False
  36. def name_string(self):
  37. return ' '.join(self.exelist)
  38. def sanity_check(self, work_dir, environment):
  39. source_name = os.path.join(work_dir, 'sanity.rs')
  40. output_name = os.path.join(work_dir, 'rusttest')
  41. with open(source_name, 'w') as ofile:
  42. ofile.write('''fn main() {
  43. }
  44. ''')
  45. pc = subprocess.Popen(self.exelist + ['-o', output_name, source_name],
  46. stdout=subprocess.PIPE,
  47. stderr=subprocess.PIPE,
  48. cwd=work_dir)
  49. stdo, stde = pc.communicate()
  50. stdo = stdo.decode('utf-8', errors='replace')
  51. stde = stde.decode('utf-8', errors='replace')
  52. if pc.returncode != 0:
  53. raise EnvironmentException('Rust compiler %s can not compile programs.\n%s\n%s' % (
  54. self.name_string(),
  55. stdo,
  56. stde))
  57. if self.is_cross:
  58. if self.exe_wrapper is None:
  59. # Can't check if the binaries run so we have to assume they do
  60. return
  61. cmdlist = self.exe_wrapper + [output_name]
  62. else:
  63. cmdlist = [output_name]
  64. pe = subprocess.Popen(cmdlist, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
  65. pe.wait()
  66. if pe.returncode != 0:
  67. raise EnvironmentException('Executables created by Rust compiler %s are not runnable.' % self.name_string())
  68. def get_dependency_gen_args(self, outfile):
  69. return ['--dep-info', outfile]
  70. def get_buildtype_args(self, buildtype):
  71. return rust_buildtype_args[buildtype]
  72. def get_sysroot(self):
  73. cmd = self.exelist + ['--print', 'sysroot']
  74. p, stdo, stde = Popen_safe(cmd)
  75. return stdo.split('\n')[0]
  76. def get_debug_args(self, is_debug):
  77. return clike_debug_args[is_debug]
  78. def get_optimization_args(self, optimization_level):
  79. return rust_optimization_args[optimization_level]
  80. def compute_parameters_with_absolute_paths(self, parameter_list, build_dir):
  81. for idx, i in enumerate(parameter_list):
  82. if i[:2] == '-L':
  83. for j in ['dependency', 'crate', 'native', 'framework', 'all']:
  84. combined_len = len(j) + 3
  85. if i[:combined_len] == '-L{}='.format(j):
  86. parameter_list[idx] = i[:combined_len] + os.path.normpath(os.path.join(build_dir, i[combined_len:]))
  87. break
  88. return parameter_list
  89. def get_std_exe_link_args(self):
  90. return []
  91. # Rust does not have a use_linker_args because it dispatches to a gcc-like
  92. # C compiler for dynamic linking, as such we invoke the C compiler's
  93. # use_linker_args method instead.