Merge pull request #5524 from scivision/icl_ifort

Add ifort on Windows
pull/5555/head
Dylan Baker 6 years ago committed by GitHub
commit ec97bedd8a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      mesonbuild/backend/ninjabackend.py
  2. 27
      mesonbuild/compilers/fortran.py
  3. 6
      mesonbuild/dependencies/misc.py
  4. 6
      mesonbuild/environment.py
  5. 16
      mesonbuild/interpreter.py
  6. 8
      run_project_tests.py
  7. 8
      test cases/fortran/10 find library/meson.build
  8. 3
      test cases/fortran/13 coarray/meson.build
  9. 6
      test cases/fortran/6 dynamic/meson.build

@ -2164,7 +2164,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
# outdir argument instead. # outdir argument instead.
# https://github.com/mesonbuild/meson/issues/1348 # https://github.com/mesonbuild/meson/issues/1348
if not is_generated: if not is_generated:
abs_src = os.path.join(build_dir, rel_src) abs_src = Path(build_dir) / rel_src
extra_deps += self.get_fortran_deps(compiler, abs_src, target) extra_deps += self.get_fortran_deps(compiler, abs_src, target)
# Dependency hack. Remove once multiple outputs in Ninja is fixed: # Dependency hack. Remove once multiple outputs in Ninja is fixed:
# https://groups.google.com/forum/#!topic/ninja-build/j-2RfBIOd_8 # https://groups.google.com/forum/#!topic/ninja-build/j-2RfBIOd_8
@ -2802,7 +2802,7 @@ def _scan_fortran_file_deps(src: Path, srcdir: Path, dirname: Path, tdeps, compi
# a common occurrence, which would lead to lots of # a common occurrence, which would lead to lots of
# distracting noise. # distracting noise.
continue continue
srcfile = srcdir / tdeps[usename].fname srcfile = srcdir / tdeps[usename].fname # type: Path
if not srcfile.is_file(): if not srcfile.is_file():
if srcfile.name != src.name: # generated source file if srcfile.name != src.name: # generated source file
pass pass
@ -2824,7 +2824,7 @@ def _scan_fortran_file_deps(src: Path, srcdir: Path, dirname: Path, tdeps, compi
ancestor_child = '_'.join(parents) ancestor_child = '_'.join(parents)
if ancestor_child not in tdeps: if ancestor_child not in tdeps:
raise MesonException("submodule {} relies on ancestor module {} that was not found.".format(submodmatch.group(2).lower(), ancestor_child.split('_')[0])) raise MesonException("submodule {} relies on ancestor module {} that was not found.".format(submodmatch.group(2).lower(), ancestor_child.split('_')[0]))
submodsrcfile = srcdir / tdeps[ancestor_child].fname submodsrcfile = srcdir / tdeps[ancestor_child].fname # type: Path
if not submodsrcfile.is_file(): if not submodsrcfile.is_file():
if submodsrcfile.name != src.name: # generated source file if submodsrcfile.name != src.name: # generated source file
pass pass

@ -65,10 +65,14 @@ class FortranCompiler(CLikeCompiler, Compiler):
extra_flags = environment.coredata.get_external_args(self.for_machine, self.language) extra_flags = environment.coredata.get_external_args(self.for_machine, self.language)
extra_flags += environment.coredata.get_external_link_args(self.for_machine, self.language) extra_flags += environment.coredata.get_external_link_args(self.for_machine, self.language)
extra_flags += self.get_always_args() extra_flags += self.get_always_args()
# %% build the test executable # %% build the test executable "sanitycheckf"
pc = subprocess.Popen(self.exelist + extra_flags + [str(source_name), '-o', str(binary_name)]) # cwd=work_dir is necessary on Windows especially for Intel compilers to avoid error: cannot write on sanitycheckf.obj
pc.wait() # this is a defect with how Windows handles files and ifort's object file-writing behavior vis concurrent ProcessPoolExecutor.
if pc.returncode != 0: # This simple workaround solves the issue.
# FIXME: cwd=str(work_dir) is for Python 3.5 on Windows, when 3.5 is deprcated, this can become cwd=work_dir
returncode = subprocess.run(self.exelist + extra_flags + [str(source_name), '-o', str(binary_name)],
cwd=str(work_dir)).returncode
if returncode != 0:
raise EnvironmentException('Compiler %s can not compile programs.' % self.name_string()) raise EnvironmentException('Compiler %s can not compile programs.' % self.name_string())
if self.is_cross: if self.is_cross:
if self.exe_wrapper is None: if self.exe_wrapper is None:
@ -79,9 +83,8 @@ class FortranCompiler(CLikeCompiler, Compiler):
cmdlist = [str(binary_name)] cmdlist = [str(binary_name)]
# %% Run the test executable # %% Run the test executable
try: try:
pe = subprocess.Popen(cmdlist, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) returncode = subprocess.run(cmdlist, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL).returncode
pe.wait() if returncode != 0:
if pe.returncode != 0:
raise EnvironmentException('Executables created by Fortran compiler %s are not runnable.' % self.name_string()) raise EnvironmentException('Executables created by Fortran compiler %s are not runnable.' % self.name_string())
except OSError: except OSError:
raise EnvironmentException('Executables created by Fortran compiler %s are not runnable.' % self.name_string()) raise EnvironmentException('Executables created by Fortran compiler %s are not runnable.' % self.name_string())
@ -137,9 +140,7 @@ class FortranCompiler(CLikeCompiler, Compiler):
return filename return filename
def find_library(self, libname, env, extra_dirs, libtype: LibType = LibType.PREFER_SHARED): def find_library(self, libname, env, extra_dirs, libtype: LibType = LibType.PREFER_SHARED):
code = '''program main code = '''stop; end program'''
call exit(0)
end program main'''
return self.find_library_impl(libname, env, extra_dirs, code, libtype) return self.find_library_impl(libname, env, extra_dirs, code, libtype)
def has_multi_arguments(self, args, env): def has_multi_arguments(self, args, env):
@ -158,7 +159,7 @@ class FortranCompiler(CLikeCompiler, Compiler):
'the compiler you are using. has_link_argument or ' 'the compiler you are using. has_link_argument or '
'other similar method can be used instead.' 'other similar method can be used instead.'
.format(arg)) .format(arg))
code = 'program main\ncall exit(0)\nend program main' code = 'stop; end program'
return self.has_arguments(args, env, code, mode='compile') return self.has_arguments(args, env, code, mode='compile')
@ -271,8 +272,8 @@ class IntelClFortranCompiler(IntelVisualStudioLikeCompiler, FortranCompiler):
'custom': [], 'custom': [],
} }
def __init__(self, exelist, version, is_cross, target: str, exe_wrapper=None): def __init__(self, exelist, for_machine: MachineChoice, version, is_cross, target: str, exe_wrapper=None):
FortranCompiler.__init__(self, exelist, version, is_cross, exe_wrapper) FortranCompiler.__init__(self, exelist, for_machine, version, is_cross, exe_wrapper)
IntelVisualStudioLikeCompiler.__init__(self, target) IntelVisualStudioLikeCompiler.__init__(self, target)
default_warn_args = ['/warn:general', '/warn:truncated_source'] default_warn_args = ['/warn:general', '/warn:truncated_source']

@ -66,6 +66,10 @@ class CoarrayDependency(ExternalDependency):
self.is_found = True self.is_found = True
self.link_args = ['-coarray=shared'] self.link_args = ['-coarray=shared']
self.compile_args = self.link_args self.compile_args = self.link_args
elif cid == 'intel-cl':
""" Coarrays are built into Intel compilers, no external library needed """
self.is_found = True
self.compile_args = ['/Qcoarray:shared']
elif cid == 'nagfor': elif cid == 'nagfor':
""" NAG doesn't require any special arguments for Coarray """ """ NAG doesn't require any special arguments for Coarray """
self.is_found = True self.is_found = True
@ -213,7 +217,7 @@ class MPIDependency(ExternalDependency):
if not self.is_found and mesonlib.is_windows(): if not self.is_found and mesonlib.is_windows():
# only Intel Fortran compiler is compatible with Microsoft MPI at this time. # only Intel Fortran compiler is compatible with Microsoft MPI at this time.
if language == 'fortran' and environment.detect_fortran_compiler(self.for_machine).name_string() != 'intel': if language == 'fortran' and environment.detect_fortran_compiler(self.for_machine).name_string() != 'intel-cl':
return return
result = self._try_msmpi() result = self._try_msmpi()
if result is not None: if result is not None:

@ -792,7 +792,7 @@ class Environment:
else: else:
compiler_type = CompilerType.PGI_STANDARD compiler_type = CompilerType.PGI_STANDARD
cls = PGICCompiler if lang == 'c' else PGICPPCompiler cls = PGICCompiler if lang == 'c' else PGICPPCompiler
return cls(ccache + compiler, version, compiler_type, for_machine, is_cross, compiler_type, exe_wrap) return cls(ccache + compiler, version, compiler_type, for_machine, is_cross, exe_wrap)
if '(ICC)' in out: if '(ICC)' in out:
if self.machines[for_machine].is_darwin(): if self.machines[for_machine].is_darwin():
compiler_type = CompilerType.ICC_OSX compiler_type = CompilerType.ICC_OSX
@ -854,7 +854,7 @@ class Environment:
return cls(ccache + compiler, version, for_machine, exe_wrap) return cls(ccache + compiler, version, for_machine, exe_wrap)
raise EnvironmentException('Could not find suitable CUDA compiler: "' + ' '.join(compilers) + '"') raise EnvironmentException('Could not find suitable CUDA compiler: "' + ' '.join(compilers) + '"')
def detect_fortran_compiler(self, for_machine): def detect_fortran_compiler(self, for_machine: MachineChoice):
popen_exceptions = {} popen_exceptions = {}
compilers, ccache, exe_wrap = self._get_compilers('fortran', for_machine) compilers, ccache, exe_wrap = self._get_compilers('fortran', for_machine)
is_cross = not self.machines.matches_build_machine(for_machine) is_cross = not self.machines.matches_build_machine(for_machine)
@ -901,7 +901,7 @@ class Environment:
if 'Intel(R) Visual Fortran' in err: if 'Intel(R) Visual Fortran' in err:
version = search_version(err) version = search_version(err)
target = 'x86' if 'IA-32' in err else 'x86_64' target = 'x86' if 'IA-32' in err else 'x86_64'
return IntelClFortranCompiler(compiler, version, is_cross, target, exe_wrap) return IntelClFortranCompiler(compiler, version, for_machine, is_cross, target, exe_wrap)
if 'ifort (IFORT)' in out: if 'ifort (IFORT)' in out:
return IntelFortranCompiler(compiler, version, for_machine, is_cross, exe_wrap, full_version=full_version) return IntelFortranCompiler(compiler, version, for_machine, is_cross, exe_wrap, full_version=full_version)

@ -40,7 +40,7 @@ from collections import namedtuple
from itertools import chain from itertools import chain
from pathlib import PurePath from pathlib import PurePath
import functools import functools
import typing from typing import Sequence, List, Union, Optional, Iterator, Dict, Any
import importlib import importlib
@ -874,10 +874,10 @@ class RunTargetHolder(InterpreterObject, ObjectHolder):
return r.format(self.__class__.__name__, h.get_id(), h.command) return r.format(self.__class__.__name__, h.get_id(), h.command)
class Test(InterpreterObject): class Test(InterpreterObject):
def __init__(self, name: str, project: str, suite: typing.List[str], exe: build.Executable, def __init__(self, name: str, project: str, suite: List[str], exe: build.Executable,
depends: typing.List[typing.Union[build.CustomTarget, build.BuildTarget]], depends: List[Union[build.CustomTarget, build.BuildTarget]],
is_parallel: bool, cmd_args: typing.List[str], env: build.EnvironmentVariables, is_parallel: bool, cmd_args: List[str], env: build.EnvironmentVariables,
should_fail: bool, timeout: int, workdir: typing.Optional[str], protocol: str): should_fail: bool, timeout: int, workdir: Optional[str], protocol: str):
InterpreterObject.__init__(self) InterpreterObject.__init__(self)
self.name = name self.name = name
self.suite = suite self.suite = suite
@ -2773,7 +2773,7 @@ external dependencies (including libraries) must go to "dependencies".''')
self.validate_arguments(args, 0, []) self.validate_arguments(args, 0, [])
raise Exception() raise Exception()
def add_languages(self, args, required): def add_languages(self, args: Sequence[str], required: bool) -> bool:
success = self.add_languages_for(args, required, MachineChoice.BUILD) success = self.add_languages_for(args, required, MachineChoice.BUILD)
success &= self.add_languages_for(args, required, MachineChoice.HOST) success &= self.add_languages_for(args, required, MachineChoice.HOST)
return success return success
@ -3831,7 +3831,7 @@ different subdirectory.
# TODO make cross agnostic, just taking into account for_machine # TODO make cross agnostic, just taking into account for_machine
# TODO PerMachine[T], Iterator[T] # TODO PerMachine[T], Iterator[T]
def get_argdict_on_crossness(self, dicts_per_machine: PerMachine, kwargs) -> typing.Iterator: def get_argdict_on_crossness(self, dicts_per_machine: PerMachine, kwargs) -> Iterator:
for_native = kwargs.get('native', not self.environment.is_cross_build()) for_native = kwargs.get('native', not self.environment.is_cross_build())
if not isinstance(for_native, bool): if not isinstance(for_native, bool):
raise InterpreterException('Keyword native must be a boolean.') raise InterpreterException('Keyword native must be a boolean.')
@ -4218,7 +4218,7 @@ This will become a hard error in the future.''', location=self.current_node)
return varname in self.variables return varname in self.variables
@staticmethod @staticmethod
def machine_from_native_kwarg(kwargs: typing.Dict[str, typing.Any]) -> MachineChoice: def machine_from_native_kwarg(kwargs: Dict[str, Any]) -> MachineChoice:
native = kwargs.get('native', False) native = kwargs.get('native', False)
if not isinstance(native, bool): if not isinstance(native, bool):
raise InvalidArguments('Argument to "native" must be a boolean.') raise InvalidArguments('Argument to "native" must be a boolean.')

@ -600,6 +600,12 @@ def detect_tests_to_run(only: List[str]) -> List[Tuple[str, List[Path], bool]]:
gathered_tests: list of tuple of str, list of pathlib.Path, bool gathered_tests: list of tuple of str, list of pathlib.Path, bool
tests to run tests to run
""" """
ninja_fortran_compiler = shutil.which('gfortran') or shutil.which('flang') or shutil.which('pgfortran') or (not mesonlib.is_windows() and shutil.which('ifort'))
ninja_fortran = backend is Backend.ninja and ninja_fortran_compiler
vs_fortran = mesonlib.is_windows() and backend is Backend.vs and shutil.which('ifort')
skip_fortran = not(ninja_fortran or vs_fortran)
# Name, subdirectory, skip condition. # Name, subdirectory, skip condition.
all_tests = [ all_tests = [
('cmake', 'cmake', not shutil.which('cmake') or (os.environ.get('compiler') == 'msvc2015' and under_ci)), ('cmake', 'cmake', not shutil.which('cmake') or (os.environ.get('compiler') == 'msvc2015' and under_ci)),
@ -621,7 +627,7 @@ def detect_tests_to_run(only: List[str]) -> List[Tuple[str, List[Path], bool]]:
('d', 'd', backend is not Backend.ninja or not have_d_compiler()), ('d', 'd', backend is not Backend.ninja or not have_d_compiler()),
('objective c', 'objc', backend not in (Backend.ninja, Backend.xcode) or not have_objc_compiler()), ('objective c', 'objc', backend not in (Backend.ninja, Backend.xcode) or not have_objc_compiler()),
('objective c++', 'objcpp', backend not in (Backend.ninja, Backend.xcode) or not have_objcpp_compiler()), ('objective c++', 'objcpp', backend not in (Backend.ninja, Backend.xcode) or not have_objcpp_compiler()),
('fortran', 'fortran', backend is not Backend.ninja or not shutil.which('gfortran')), ('fortran', 'fortran', skip_fortran),
('swift', 'swift', backend not in (Backend.ninja, Backend.xcode) or not shutil.which('swiftc')), ('swift', 'swift', backend not in (Backend.ninja, Backend.xcode) or not shutil.which('swiftc')),
('cuda', 'cuda', backend not in (Backend.ninja, Backend.xcode) or not shutil.which('nvcc')), ('cuda', 'cuda', backend not in (Backend.ninja, Backend.xcode) or not shutil.which('nvcc')),
('python3', 'python3', backend is not Backend.ninja), ('python3', 'python3', backend is not Backend.ninja),

@ -1,9 +1,13 @@
project('find fortran library', 'fortran') project('find fortran library', 'fortran')
fortranc = meson.get_compiler('fortran') fc = meson.get_compiler('fortran')
sources = ['main.f90', 'gzip.f90'] sources = ['main.f90', 'gzip.f90']
zlib = fortranc.find_library('z') zlib = fc.find_library('z', required: false)
if not zlib.found()
error('MESON_SKIP_TEST: Z library not available.')
endif
exe = executable('zlibtest', sources, dependencies : zlib) exe = executable('zlibtest', sources, dependencies : zlib)
test('testzlib', exe) test('testzlib', exe)

@ -1,4 +1,5 @@
project('Fortran coarray', 'fortran') project('Fortran coarray', 'fortran',
meson_version: '>=0.50')
# coarray is required because single-image fallback is an intrinsic feature # coarray is required because single-image fallback is an intrinsic feature
coarray = dependency('coarray', required : true) coarray = dependency('coarray', required : true)

@ -1,5 +1,11 @@
project('dynamic_fortran', 'fortran') project('dynamic_fortran', 'fortran')
if meson.get_compiler('fortran').get_id() == 'intel-cl'
error('MESON_SKIP_TEST: Windows ifort does not use shared_library in a sane way')
# !DEC$ ATTRIBUTES DLLEXPORT must be used!
# https://software.intel.com/en-us/node/535306
endif
dynamic = shared_library('dynamic', 'dynamic.f90') dynamic = shared_library('dynamic', 'dynamic.f90')
exe = executable('test_exe', 'main.f90', link_with : dynamic) exe = executable('test_exe', 'main.f90', link_with : dynamic)
test('dynamic-fortran', exe) test('dynamic-fortran', exe)

Loading…
Cancel
Save