|
|
|
@ -133,17 +133,18 @@ class NinjaBackend(backends.Backend): |
|
|
|
|
self.all_outputs = {} |
|
|
|
|
self.valgrind = environment.find_valgrind() |
|
|
|
|
|
|
|
|
|
def detect_vs_dep_prefix(self, outfile, tempfilename): |
|
|
|
|
def detect_vs_dep_prefix(self, tempfilename): |
|
|
|
|
'''VS writes its dependency in a locale dependent format. |
|
|
|
|
Detect the search prefix to use.''' |
|
|
|
|
# Of course there is another program called 'cl' on |
|
|
|
|
# some platforms. Let's just require that on Windows |
|
|
|
|
# cl points to msvc. |
|
|
|
|
if not mesonlib.is_windows() or shutil.which('cl') is None: |
|
|
|
|
return outfile |
|
|
|
|
outfile.close() |
|
|
|
|
open(os.path.join(self.environment.get_scratch_dir(), 'incdetect.c'), |
|
|
|
|
'w').write('''#include<stdio.h> |
|
|
|
|
return open(tempfilename, 'a') |
|
|
|
|
filename = os.path.join(self.environment.get_scratch_dir(), |
|
|
|
|
'incdetect.c') |
|
|
|
|
with open(filename, 'w') as f: |
|
|
|
|
f.write('''#include<stdio.h> |
|
|
|
|
int dummy; |
|
|
|
|
''') |
|
|
|
|
|
|
|
|
@ -157,9 +158,8 @@ int dummy; |
|
|
|
|
for line in stdo.split(b'\r\n'): |
|
|
|
|
if line.endswith(b'stdio.h'): |
|
|
|
|
matchstr = b':'.join(line.split(b':')[0:2]) + b':' |
|
|
|
|
binfile = open(tempfilename, 'ab') |
|
|
|
|
binfile.write(b'msvc_deps_prefix = ' + matchstr + b'\r\n') |
|
|
|
|
binfile.close() |
|
|
|
|
with open(tempfilename, 'ab') as binfile: |
|
|
|
|
binfile.write(b'msvc_deps_prefix = ' + matchstr + b'\r\n') |
|
|
|
|
return open(tempfilename, 'a') |
|
|
|
|
raise MesonException('Could not determine vs dep dependency prefix string.') |
|
|
|
|
|
|
|
|
@ -167,30 +167,31 @@ int dummy; |
|
|
|
|
self.interpreter = interp |
|
|
|
|
outfilename = os.path.join(self.environment.get_build_dir(), self.ninja_filename) |
|
|
|
|
tempfilename = outfilename + '~' |
|
|
|
|
outfile = open(tempfilename, 'w') |
|
|
|
|
outfile.write('# This is the build file for project "%s"\n' % self.build.get_project()) |
|
|
|
|
outfile.write('# It is autogenerated by the Meson build system.\n') |
|
|
|
|
outfile.write('# Do not edit by hand.\n\n') |
|
|
|
|
outfile.write('ninja_required_version = 1.5.1\n\n') |
|
|
|
|
outfile = self.detect_vs_dep_prefix(outfile, tempfilename) |
|
|
|
|
self.generate_rules(outfile) |
|
|
|
|
self.generate_phony(outfile) |
|
|
|
|
outfile.write('# Build rules for targets\n\n') |
|
|
|
|
[self.generate_target(t, outfile) for t in self.build.get_targets().values()] |
|
|
|
|
outfile.write('# Test rules\n\n') |
|
|
|
|
self.generate_tests(outfile) |
|
|
|
|
outfile.write('# Install rules\n\n') |
|
|
|
|
self.generate_install(outfile) |
|
|
|
|
if 'b_coverage' in self.environment.coredata.base_options and \ |
|
|
|
|
self.environment.coredata.base_options['b_coverage'].value: |
|
|
|
|
outfile.write('# Coverage rules\n\n') |
|
|
|
|
self.generate_coverage_rules(outfile) |
|
|
|
|
outfile.write('# Suffix\n\n') |
|
|
|
|
self.generate_utils(outfile) |
|
|
|
|
self.generate_ending(outfile) |
|
|
|
|
with open(tempfilename, 'w') as outfile: |
|
|
|
|
outfile.write('# This is the build file for project "%s"\n' % |
|
|
|
|
self.build.get_project()) |
|
|
|
|
outfile.write('# It is autogenerated by the Meson build system.\n') |
|
|
|
|
outfile.write('# Do not edit by hand.\n\n') |
|
|
|
|
outfile.write('ninja_required_version = 1.5.1\n\n') |
|
|
|
|
with self.detect_vs_dep_prefix(tempfilename) as outfile: |
|
|
|
|
self.generate_rules(outfile) |
|
|
|
|
self.generate_phony(outfile) |
|
|
|
|
outfile.write('# Build rules for targets\n\n') |
|
|
|
|
for t in self.build.get_targets().values(): |
|
|
|
|
self.generate_target(t, outfile) |
|
|
|
|
outfile.write('# Test rules\n\n') |
|
|
|
|
self.generate_tests(outfile) |
|
|
|
|
outfile.write('# Install rules\n\n') |
|
|
|
|
self.generate_install(outfile) |
|
|
|
|
if 'b_coverage' in self.environment.coredata.base_options and \ |
|
|
|
|
self.environment.coredata.base_options['b_coverage'].value: |
|
|
|
|
outfile.write('# Coverage rules\n\n') |
|
|
|
|
self.generate_coverage_rules(outfile) |
|
|
|
|
outfile.write('# Suffix\n\n') |
|
|
|
|
self.generate_utils(outfile) |
|
|
|
|
self.generate_ending(outfile) |
|
|
|
|
# Only ovewrite the old build file after the new one has been |
|
|
|
|
# fully created. |
|
|
|
|
outfile.close() |
|
|
|
|
os.replace(tempfilename, outfilename) |
|
|
|
|
self.generate_compdb() |
|
|
|
|
|
|
|
|
@ -202,7 +203,8 @@ int dummy; |
|
|
|
|
jsondb = subprocess.check_output([ninja_exe, '-t', 'compdb', 'c_COMPILER', 'cpp_COMPILER'], cwd=builddir) |
|
|
|
|
except Exception: |
|
|
|
|
raise MesonException('Could not create compilation database.') |
|
|
|
|
open(os.path.join(builddir, 'compile_commands.json'), 'wb').write(jsondb) |
|
|
|
|
with open(os.path.join(builddir, 'compile_commands.json'), 'wb') as f: |
|
|
|
|
f.write(jsondb) |
|
|
|
|
|
|
|
|
|
# Get all generated headers. Any source file might need them so |
|
|
|
|
# we need to add an order dependency to them. |
|
|
|
@ -505,8 +507,8 @@ int dummy; |
|
|
|
|
self.generate_subdir_install(d) |
|
|
|
|
elem.write(outfile) |
|
|
|
|
|
|
|
|
|
ofile = open(install_data_file, 'wb') |
|
|
|
|
pickle.dump(d, ofile) |
|
|
|
|
with open(install_data_file, 'wb') as ofile: |
|
|
|
|
pickle.dump(d, ofile) |
|
|
|
|
|
|
|
|
|
def generate_target_install(self, d): |
|
|
|
|
should_strip = self.environment.coredata.get_builtin_option('strip') |
|
|
|
@ -1416,16 +1418,22 @@ rule FORTRAN_DEP_HACK |
|
|
|
|
# but those are really rare. I hope. |
|
|
|
|
if not compiler.can_compile(s): |
|
|
|
|
continue |
|
|
|
|
for line in open(os.path.join(self.environment.get_source_dir(), s.subdir, s.fname)): |
|
|
|
|
modmatch = modre.match(line) |
|
|
|
|
if modmatch is not None: |
|
|
|
|
modname = modmatch.group(1) |
|
|
|
|
if modname.lower() == 'procedure': # MODULE PROCEDURE construct |
|
|
|
|
continue |
|
|
|
|
if modname in module_files: |
|
|
|
|
raise InvalidArguments('Namespace collision: module %s defined in two files %s and %s.' % |
|
|
|
|
(modname, module_files[modname], s)) |
|
|
|
|
module_files[modname] = s |
|
|
|
|
filename = os.path.join(self.environment.get_source_dir(), |
|
|
|
|
s.subdir, s.fname) |
|
|
|
|
with open(filename) as f: |
|
|
|
|
for line in f: |
|
|
|
|
modmatch = modre.match(line) |
|
|
|
|
if modmatch is not None: |
|
|
|
|
modname = modmatch.group(1) |
|
|
|
|
if modname.lower() == 'procedure': |
|
|
|
|
# MODULE PROCEDURE construct |
|
|
|
|
continue |
|
|
|
|
if modname in module_files: |
|
|
|
|
raise InvalidArguments( |
|
|
|
|
'Namespace collision: module %s defined in ' |
|
|
|
|
'two files %s and %s.' % |
|
|
|
|
(modname, module_files[modname], s)) |
|
|
|
|
module_files[modname] = s |
|
|
|
|
self.fortran_deps[target.get_basename()] = module_files |
|
|
|
|
|
|
|
|
|
def get_fortran_deps(self, compiler, src, target): |
|
|
|
@ -1433,27 +1441,32 @@ rule FORTRAN_DEP_HACK |
|
|
|
|
usere = re.compile(r"\s*use\s+(\w+)", re.IGNORECASE) |
|
|
|
|
dirname = self.get_target_private_dir(target) |
|
|
|
|
tdeps= self.fortran_deps[target.get_basename()] |
|
|
|
|
for line in open(src): |
|
|
|
|
usematch = usere.match(line) |
|
|
|
|
if usematch is not None: |
|
|
|
|
usename = usematch.group(1) |
|
|
|
|
if usename not in tdeps: |
|
|
|
|
# The module is not provided by any source file. This is due to |
|
|
|
|
# a) missing file/typo/etc |
|
|
|
|
# b) using a module provided by the compiler, such as OpenMP |
|
|
|
|
# There's no easy way to tell which is which (that I know of) |
|
|
|
|
# so just ignore this and go on. Ideally we would print a |
|
|
|
|
# warning message to the user but this is a common occurrance, |
|
|
|
|
# which would lead to lots of distracting noise. |
|
|
|
|
continue |
|
|
|
|
mod_source_file = tdeps[usename] |
|
|
|
|
# Check if a source uses a module it exports itself. |
|
|
|
|
# Potential bug if multiple targets have a file with |
|
|
|
|
# the same name. |
|
|
|
|
if mod_source_file.fname == os.path.split(src)[1]: |
|
|
|
|
continue |
|
|
|
|
mod_name = compiler.module_name_to_filename(usematch.group(1)) |
|
|
|
|
mod_files.append(os.path.join(dirname, mod_name)) |
|
|
|
|
with open(src) as f: |
|
|
|
|
for line in f: |
|
|
|
|
usematch = usere.match(line) |
|
|
|
|
if usematch is not None: |
|
|
|
|
usename = usematch.group(1) |
|
|
|
|
if usename not in tdeps: |
|
|
|
|
# The module is not provided by any source file. This |
|
|
|
|
# is due to: |
|
|
|
|
# a) missing file/typo/etc |
|
|
|
|
# b) using a module provided by the compiler, such as |
|
|
|
|
# OpenMP |
|
|
|
|
# There's no easy way to tell which is which (that I |
|
|
|
|
# know of) so just ignore this and go on. Ideally we |
|
|
|
|
# would print a warning message to the user but this is |
|
|
|
|
# a common occurrence, which would lead to lots of |
|
|
|
|
# distracting noise. |
|
|
|
|
continue |
|
|
|
|
mod_source_file = tdeps[usename] |
|
|
|
|
# Check if a source uses a module it exports itself. |
|
|
|
|
# Potential bug if multiple targets have a file with |
|
|
|
|
# the same name. |
|
|
|
|
if mod_source_file.fname == os.path.split(src)[1]: |
|
|
|
|
continue |
|
|
|
|
mod_name = compiler.module_name_to_filename( |
|
|
|
|
usematch.group(1)) |
|
|
|
|
mod_files.append(os.path.join(dirname, mod_name)) |
|
|
|
|
return mod_files |
|
|
|
|
|
|
|
|
|
def get_cross_stdlib_args(self, target, compiler): |
|
|
|
|