def cxx11_flag(self): if self.version < ver('11.1'): tty.die("Only intel 11.1 and above support c++11.") elif self.version < ver('13'): return "-std=c++0x" else: return "-std=c++11"
def default_version(cls, cc): """Older versions of gcc use the ``-dumpversion`` option. Output looks like this:: 4.4.7 In GCC 7, this option was changed to only return the major version of the compiler:: 7 A new ``-dumpfullversion`` option was added that gives us what we want:: 7.2.0 """ # Skip any gcc versions that are actually clang, like Apple's gcc. # Returning "unknown" makes them not detected by default. # Users can add these manually to compilers.yaml at their own risk. if spack.compilers.clang.Clang.default_version(cc) != 'unknown': return 'unknown' version = super(Gcc, cls).default_version(cc) if ver(version) >= ver('7'): version = get_compiler_version(cc, '-dumpfullversion') return version
def test_find_versions_of_archive_3(): versions = find_versions_of_archive(root_tarball, root, list_depth=3) assert ver('0.0.0') in versions assert ver('1.0.0') in versions assert ver('2.0.0') in versions assert ver('3.0') in versions assert ver('4.5') in versions
def cxx11_flag(self): if self.version < ver('4.3'): tty.die("Only gcc 4.3 and above support c++11.") elif self.version < ver('4.7'): return "-std=c++0x" else: return "-std=c++11"
def fc_version(cls, fc): """Older versions of gfortran use the ``-dumpversion`` option. Output looks like this:: GNU Fortran (GCC) 4.4.7 20120313 (Red Hat 4.4.7-18) Copyright (C) 2010 Free Software Foundation, Inc. or:: 4.8.5 In GCC 7, this option was changed to only return the major version of the compiler:: 7 A new ``-dumpfullversion`` option was added that gives us what we want:: 7.2.0 """ version = get_compiler_version( fc, '-dumpversion', r'(?:GNU Fortran \(GCC\) )?([\d.]+)') if ver(version) >= ver('7'): version = get_compiler_version(fc, '-dumpfullversion') return version
def cxx14_flag(self): if self.version < ver('4.8'): tty.die("Only gcc 4.8 and above support c++14.") elif self.version < ver('4.9'): return "-std=c++1y" else: return "-std=c++14"
def test_version_ranges(): assert_ver_lt('1.2:1.4', '1.6') assert_ver_gt('1.6', '1.2:1.4') assert_ver_eq('1.2:1.4', '1.2:1.4') assert ver('1.2:1.4') != ver('1.2:1.6') assert_ver_lt('1.2:1.4', '1.5:1.6') assert_ver_gt('1.5:1.6', '1.2:1.4')
def cxx14_flag(self): # Adapted from CMake's Intel-CXX rules. if self.version < ver('15'): tty.die("Only intel 15.0 and above support c++14.") elif self.version < ver('15.0.2'): return "-std=c++1y" else: return "-std=c++14"
def assert_ver_gt(a, b): """Asserts the results of comparisons when 'a' is greater than 'b'.""" a, b = ver(a), ver(b) assert a > b assert a >= b assert a != b assert not a == b assert not a < b assert not a <= b
def assert_ver_eq(a, b): """Asserts the results of comparisons when 'a' is equal to 'b'.""" a, b = ver(a), ver(b) assert not a > b assert a >= b assert not a != b assert a == b assert not a < b assert a <= b
def cxx11_flag(self): if self.version < ver('4.3'): raise UnsupportedCompilerFlag(self, "the C++11 standard", "cxx11_flag", " < 4.3") elif self.version < ver('4.7'): return "-std=c++0x" else: return "-std=c++11"
def cxx17_flag(self): if self.version < ver('5.0'): raise UnsupportedCompilerFlag(self, "the C++17 standard", "cxx17_flag", "< 5.0") elif self.version < ver('6.0'): return "-std=c++1z" else: return "-std=c++17"
def cxx14_flag(self): # Adapted from CMake's Intel-CXX rules. if self.version < ver('15'): raise UnsupportedCompilerFlag(self, "the C++14 standard", "cxx14_flag", "< 15") elif self.version < ver('15.0.2'): return "-std=c++1y" else: return "-std=c++14"
def cxx14_flag(self): if self.version < ver('4.8'): raise UnsupportedCompilerFlag(self, "the C++14 standard", "cxx14_flag", "< 4.8") elif self.version < ver('4.9'): return "-std=c++1y" elif self.version < ver('6.0'): return "-std=c++14" else: return ""
def cxx17_flag(self): if self.is_apple: # Adapted from CMake's rules for AppleClang if self.version < ver('6.1.0'): tty.die("Only Apple LLVM 6.1 and above support c++17.") else: return "-std=c++1z" else: if self.version < ver('3.5'): tty.die("Only Clang 3.5 and above support c++17.") else: return "-std=c++1z"
def cxx11_flag(self): if self.is_apple: # Adapted from CMake's AppleClang-CXX rules # Spack's AppleClang detection only valid form Xcode >= 4.6 if self.version < ver('4.0.0'): tty.die("Only Apple LLVM 4.0 and above support c++11") else: return "-std=c++11" else: if self.version < ver('3.3'): tty.die("Only Clang 3.3 and above support c++11.") else: return "-std=c++11"
def try_fetch(self, rev, test_file, args): """Tries to: 1. Fetch the repo using a fetch strategy constructed with supplied args. 2. Check if the test_file is in the checked out repository. 3. Assert that the repository is at the revision supplied. 4. Add and remove some files, then reset the repo, and ensure it's all there again. """ self.pkg.versions[ver('git')] = args self.pkg.do_stage() self.assert_rev(rev) file_path = join_path(self.pkg.stage.source_path, test_file) self.assertTrue(os.path.isdir(self.pkg.stage.source_path)) self.assertTrue(os.path.isfile(file_path)) os.unlink(file_path) self.assertFalse(os.path.isfile(file_path)) untracked_file = 'foobarbaz' touch(untracked_file) self.assertTrue(os.path.isfile(untracked_file)) self.pkg.do_restage() self.assertFalse(os.path.isfile(untracked_file)) self.assertTrue(os.path.isdir(self.pkg.stage.source_path)) self.assertTrue(os.path.isfile(file_path)) self.assert_rev(rev)
def checksum(parser, args): # Make sure the user provided a package and not a URL if not valid_fully_qualified_module_name(args.package): tty.die("`spack checksum` accepts package names, not URLs.") # Get the package we're going to generate checksums for pkg = spack.repo.get(args.package) if args.versions: # If the user asked for specific versions, use those url_dict = {} for version in args.versions: version = ver(version) if not isinstance(version, Version): tty.die("Cannot generate checksums for version lists or " "version ranges. Use unambiguous versions.") url_dict[version] = pkg.url_for_version(version) else: # Otherwise, see what versions we can find online url_dict = pkg.fetch_remote_versions() if not url_dict: tty.die("Could not find any versions for {0}".format(pkg.name)) version_lines = spack.util.web.get_checksums_for_versions( url_dict, pkg.name, keep_stage=args.keep_stage) print() print(version_lines)
def cxx11_flag(self): if self.version < ver('13.1'): raise UnsupportedCompilerFlag(self, "the C++11 standard", "cxx11_flag", "< 13.1") else: return "-qlanglvl=extended0x"
def cxx11_flag(self): if self.is_apple: # FIXME: figure out from which version Apple's clang supports c++11 return "-std=c++11" else: if self.version < ver('3.3'): tty.die("Only Clang 3.3 and above support c++11.") else: return "-std=c++11"
def cxx11_flag(self): if self.is_apple: # Adapted from CMake's AppleClang-CXX rules # Spack's AppleClang detection only valid from Xcode >= 4.6 if self.version < ver('4.0.0'): raise UnsupportedCompilerFlag(self, "the C++11 standard", "cxx11_flag", "Xcode < 4.0.0") else: return "-std=c++11" else: if self.version < ver('3.3'): raise UnsupportedCompilerFlag(self, "the C++11 standard", "cxx11_flag", "< 3.3") else: return "-std=c++11"
def cxx17_flag(self): if self.is_apple: # Adapted from CMake's rules for AppleClang if self.version < ver('6.1.0'): raise UnsupportedCompilerFlag(self, "the C++17 standard", "cxx17_flag", "Xcode < 6.1.0") else: return "-std=c++1z" else: if self.version < ver('3.5'): raise UnsupportedCompilerFlag(self, "the C++17 standard", "cxx17_flag", "< 5.0") elif self.version < ver('5.0'): return "-std=c++1z" else: return "-std=c++17"
def test_fetch( type_of_test, secure, mock_git_repository, config, refresh_builtin_mock ): """Tries to: 1. Fetch the repo using a fetch strategy constructed with supplied args (they depend on type_of_test). 2. Check if the test_file is in the checked out repository. 3. Assert that the repository is at the revision supplied. 4. Add and remove some files, then reset the repo, and ensure it's all there again. """ # Retrieve the right test parameters t = mock_git_repository.checks[type_of_test] h = mock_git_repository.hash # Construct the package under test spec = Spec('git-test') spec.concretize() pkg = spack.repo.get(spec, new=True) pkg.versions[ver('git')] = t.args # Enter the stage directory and check some properties with pkg.stage: try: spack.insecure = secure pkg.do_stage() finally: spack.insecure = False assert h('HEAD') == h(t.revision) file_path = join_path(pkg.stage.source_path, t.file) assert os.path.isdir(pkg.stage.source_path) assert os.path.isfile(file_path) os.unlink(file_path) assert not os.path.isfile(file_path) untracked_file = 'foobarbaz' touch(untracked_file) assert os.path.isfile(untracked_file) pkg.do_restage() assert not os.path.isfile(untracked_file) assert os.path.isdir(pkg.stage.source_path) assert os.path.isfile(file_path) assert h('HEAD') == h(t.revision)
def test_fetch( type_of_test, secure, mock_hg_repository, config, mutable_mock_packages ): """Tries to: 1. Fetch the repo using a fetch strategy constructed with supplied args (they depend on type_of_test). 2. Check if the test_file is in the checked out repository. 3. Assert that the repository is at the revision supplied. 4. Add and remove some files, then reset the repo, and ensure it's all there again. """ # Retrieve the right test parameters t = mock_hg_repository.checks[type_of_test] h = mock_hg_repository.hash # Construct the package under test spec = Spec('hg-test') spec.concretize() pkg = spack.repo.get(spec) pkg.versions[ver('hg')] = t.args # Enter the stage directory and check some properties with pkg.stage: with spack.config.override('config:verify_ssl', secure): pkg.do_stage() with working_dir(pkg.stage.source_path): assert h() == t.revision file_path = os.path.join(pkg.stage.source_path, t.file) assert os.path.isdir(pkg.stage.source_path) assert os.path.isfile(file_path) os.unlink(file_path) assert not os.path.isfile(file_path) untracked_file = 'foobarbaz' touch(untracked_file) assert os.path.isfile(untracked_file) pkg.do_restage() assert not os.path.isfile(untracked_file) assert os.path.isdir(pkg.stage.source_path) assert os.path.isfile(file_path) assert h() == t.revision
def fetch(self): self.stage.chdir() if self.stage.source_path: tty.msg("Already fetched %s." % self.stage.source_path) return args = [] if self.commit: args.append('at commit %s' % self.commit) elif self.tag: args.append('at tag %s' % self.tag) elif self.branch: args.append('on branch %s' % self.branch) tty.msg("Trying to clone git repository:", self.url, *args) if self.commit: # Need to do a regular clone and check out everything if # they asked for a particular commit. self.git('clone', self.url) self.stage.chdir_to_source() self.git('checkout', self.commit) else: # Can be more efficient if not checking out a specific commit. args = ['clone'] # If we want a particular branch ask for it. if self.branch: args.extend(['--branch', self.branch]) # Try to be efficient if we're using a new enough git. # This checks out only one branch's history if self.git_version > ver('1.7.10'): args.append('--single-branch') args.append(self.url) self.git(*args) self.stage.chdir_to_source()
def test_fetch( mock_archive, secure, checksum_type, config, mutable_mock_packages ): """Fetch an archive and make sure we can checksum it.""" mock_archive.url mock_archive.path algo = crypto.hash_fun_for_algo(checksum_type)() with open(mock_archive.archive_file, 'rb') as f: algo.update(f.read()) checksum = algo.hexdigest() # Get a spec and tweak the test package with new chcecksum params spec = Spec('url-test') spec.concretize() pkg = spack.repo.get('url-test') pkg.url = mock_archive.url pkg.versions[ver('test')] = {checksum_type: checksum, 'url': pkg.url} pkg.spec = spec # Enter the stage directory and check some properties with pkg.stage: with spack.config.override('config:verify_ssl', secure): pkg.do_stage() with working_dir(pkg.stage.source_path): assert os.path.exists('configure') assert is_exe('configure') with open('configure') as f: contents = f.read() assert contents.startswith('#!/bin/sh') assert 'echo Building...' in contents
def concretize_difficult_packages(self, a, b): """Test a couple of large packages that are often broken due to current limitations in the concretizer""" s = Spec(a + '@' + b) s.concretize() assert s[a].version == ver(b)
def test_concretize_preferred_version(self): spec = check_concretize('python') assert spec.versions == ver('2.7.11') spec = check_concretize('[email protected]') assert spec.versions == ver('3.5.1')
def concretize_multi_provider(self): s = Spec('mpileaks ^[email protected]') s.concretize() assert s['mpi'].version == ver('1.10.3')
def test_find_versions_of_archive_1(): versions = spack.util.web.find_versions_of_archive( root_tarball, root, list_depth=1) assert ver('0.0.0') in versions assert ver('1.0.0') in versions
def cxx98_flag(self): if self.version < ver('6.0'): return "" else: return "-std=c++98"
def c99_flag(self): if self.version < ver('12'): raise UnsupportedCompilerFlag(self, "the C99 standard", "c99_flag", "< 12") else: return "-std=c99"
def get_best_target(microarch, compiler_name, compiler_version): for compiler_entry in microarch.compilers[compiler_name]: if compiler_version.satisfies(ver(compiler_entry["versions"])): return compiler_entry.get("name", microarch.name) raise InstallError("Could not find a target architecture")
def assert_overlaps(v1, v2): """Asserts that two version ranges overlaps.""" assert ver(v1).overlaps(ver(v2))
def test_find_versions_of_archive_2(): versions = find_versions_of_archive(root_tarball, root, list_depth=2) assert ver('0.0.0') in versions assert ver('1.0.0') in versions assert ver('2.0.0') in versions
def test_empty_version_range_raises(): with pytest.raises(ValueError): assert VersionRange('2', '1.0') with pytest.raises(ValueError): assert ver('2:1.0')
def assert_canonical(canonical_list, version_list): """Asserts that a redundant list is reduced to canonical form.""" assert ver(canonical_list) == ver(version_list)
def c11_flag(self): if self.version < ver('4.7'): raise UnsupportedCompilerFlag(self, "the C11 standard", "c11_flag", "< 4.7") return "-std=c11"
def fetch(self): self.stage.chdir() if self.stage.source_path: tty.msg("Already fetched %s" % self.stage.source_path) return args = [] if self.commit: args.append('at commit %s' % self.commit) elif self.tag: args.append('at tag %s' % self.tag) elif self.branch: args.append('on branch %s' % self.branch) tty.msg("Trying to clone git repository:", self.url, *args) if self.commit: # Need to do a regular clone and check out everything if # they asked for a particular commit. self.git('clone', self.url) self.stage.chdir_to_source() self.git('checkout', self.commit) else: # Can be more efficient if not checking out a specific commit. args = ['clone'] # If we want a particular branch ask for it. if self.branch: args.extend(['--branch', self.branch]) elif self.tag and self.git_version >= ver('1.8.5.2'): args.extend(['--branch', self.tag]) # Try to be efficient if we're using a new enough git. # This checks out only one branch's history if self.git_version > ver('1.7.10'): args.append('--single-branch') cloned = False # Yet more efficiency, only download a 1-commit deep tree if self.git_version >= ver('1.7.1'): try: self.git(*(args + ['--depth', '1', self.url])) cloned = True except spack.error.SpackError: # This will fail with the dumb HTTP transport # continue and try without depth, cleanup first pass if not cloned: args.append(self.url) self.git(*args) self.stage.chdir_to_source() # For tags, be conservative and check them out AFTER # cloning. Later git versions can do this with clone # --branch, but older ones fail. if self.tag and self.git_version < ver('1.8.5.2'): # pull --tags returns a "special" error code of 1 in # older versions that we have to ignore. # see: https://github.com/git/git/commit/19d122b self.git('pull', '--tags', ignore_errors=1) self.git('checkout', self.tag)
def c11_flag(self): if self.version < ver('16'): raise UnsupportedCompilerFlag(self, "the C11 standard", "c11_flag", "< 16") else: return "-std=c1x"
def concretize_version(self, spec): """If the spec is already concrete, return. Otherwise take the preferred version from spackconfig, and default to the package's version if there are no available versions. TODO: In many cases we probably want to look for installed versions of each package and use an installed version if we can link to it. The policy implemented here will tend to rebuild a lot of stuff becasue it will prefer a compiler in the spec to any compiler already- installed things were built with. There is likely some better policy that finds some middle ground between these two extremes. """ # return if already concrete. if spec.versions.concrete: return False # List of versions we could consider, in sorted order pkg_versions = spec.package_class.versions usable = [ v for v in pkg_versions if any( v.satisfies(sv) for sv in spec.versions) ] yaml_prefs = PackagePrefs(spec.name, 'version') # The keys below show the order of precedence of factors used # to select a version when concretizing. The item with # the "largest" key will be selected. # # NOTE: When COMPARING VERSIONS, the '@develop' version is always # larger than other versions. BUT when CONCRETIZING, # the largest NON-develop version is selected by default. keyfn = lambda v: ( # ------- Special direction from the user # Respect order listed in packages.yaml -yaml_prefs(v), # The preferred=True flag (packages or packages.yaml or both?) pkg_versions.get(Version(v)).get('preferred', False), # ------- Regular case: use latest non-develop version by default. # Avoid @develop version, which would otherwise be the "largest" # in straight version comparisons not v.isdevelop(), # Compare the version itself # This includes the logic: # a) develop > everything (disabled by "not v.isdevelop() above) # b) numeric > non-numeric # c) Numeric or string comparison v) usable.sort(key=keyfn, reverse=True) if usable: spec.versions = ver([usable[0]]) else: # We don't know of any SAFE versions that match the given # spec. Grab the spec's versions and grab the highest # *non-open* part of the range of versions it specifies. # Someone else can raise an error if this happens, # e.g. when we go to fetch it and don't know how. But it # *might* work. if not spec.versions or spec.versions == VersionList([':']): raise NoValidVersionError(spec) else: last = spec.versions[-1] if isinstance(last, VersionRange): if last.end: spec.versions = ver([last.end]) else: spec.versions = ver([last.start]) else: spec.versions = ver([last]) return True # Things changed
def test_find_exotic_versions_of_archive_2(): versions = spack.util.web.find_versions_of_archive( root_tarball, root, list_depth=2) # up for grabs to make this better. assert ver('2.0.0b2') in versions
def cxx11_flag(self): if self.version < ver('13.1'): tty.die("Only xlC 13.1 and above have some c++11 support.") else: return "-qlanglvl=extended0x"
def openmp_flag(self): if self.version < ver('16.0'): return "-openmp" else: return "-qopenmp"
def fetch(self): self.stage.chdir() if self.stage.source_path: tty.msg("Already fetched %s" % self.stage.source_path) return args = '' if self.commit: args = 'at commit %s' % self.commit elif self.tag: args = 'at tag %s' % self.tag elif self.branch: args = 'on branch %s' % self.branch tty.msg("Trying to clone git repository: %s %s" % (self.url, args)) if self.commit: # Need to do a regular clone and check out everything if # they asked for a particular commit. if spack.debug: self.git('clone', self.url) else: self.git('clone', '--quiet', self.url) self.stage.chdir_to_source() if spack.debug: self.git('checkout', self.commit) else: self.git('checkout', '--quiet', self.commit) else: # Can be more efficient if not checking out a specific commit. args = ['clone'] if not spack.debug: args.append('--quiet') # If we want a particular branch ask for it. if self.branch: args.extend(['--branch', self.branch]) elif self.tag and self.git_version >= ver('1.8.5.2'): args.extend(['--branch', self.tag]) # Try to be efficient if we're using a new enough git. # This checks out only one branch's history if self.git_version > ver('1.7.10'): args.append('--single-branch') cloned = False # Yet more efficiency, only download a 1-commit deep tree if self.git_version >= ver('1.7.1'): try: self.git(*(args + ['--depth', '1', self.url])) cloned = True except spack.error.SpackError: # This will fail with the dumb HTTP transport # continue and try without depth, cleanup first pass if not cloned: args.append(self.url) self.git(*args) self.stage.chdir_to_source() # For tags, be conservative and check them out AFTER # cloning. Later git versions can do this with clone # --branch, but older ones fail. if self.tag and self.git_version < ver('1.8.5.2'): # pull --tags returns a "special" error code of 1 in # older versions that we have to ignore. # see: https://github.com/git/git/commit/19d122b if spack.debug: self.git('pull', '--tags', ignore_errors=1) self.git('checkout', self.tag) else: self.git('pull', '--quiet', '--tags', ignore_errors=1) self.git('checkout', '--quiet', self.tag) # Init submodules if the user asked for them. if self.submodules: if spack.debug: self.git('submodule', 'update', '--init', '--recursive') else: self.git('submodule', '--quiet', 'update', '--init', '--recursive')
def test_find_exotic_versions_of_archive_3(): versions = spack.util.web.find_versions_of_archive( root_tarball, root, list_depth=3) assert ver('2.0.0b2') in versions assert ver('3.0a1') in versions assert ver('4.5-rc5') in versions
def check_union(expected, a, b): """Asserts that 'a' union 'b' == 'expected'.""" assert ver(expected) == ver(a).union(ver(b))
def assert_no_overlap(v1, v2): """Asserts that two version ranges do not overlap.""" assert not ver(v1).overlaps(ver(v2))
def c99_flag(self): if self.version < ver('4.5'): raise UnsupportedCompilerFlag(self, "the C99 standard", "c99_flag", "< 4.5") return "-std=c99"
def assert_satisfies(v1, v2): """Asserts that 'v1' satisfies 'v2'.""" assert ver(v1).satisfies(ver(v2))
def assert_does_not_satisfy(v1, v2): """Asserts that 'v1' does not satisfy 'v2'.""" assert not ver(v1).satisfies(ver(v2))
def is_clang_based(self): version = self._real_version or self.version return version >= ver('9.0') and 'classic' not in str(version)
def check_intersection(expected, a, b): """Asserts that 'a' intersect 'b' == 'expected'.""" assert ver(expected) == ver(a).intersection(ver(b))
def test_isdevelop(): assert ver('develop').isdevelop() assert ver('develop.1').isdevelop() assert ver('develop.local').isdevelop() assert ver('master').isdevelop() assert ver('head').isdevelop() assert ver('trunk').isdevelop() assert ver('1.develop').isdevelop() assert ver('1.develop.2').isdevelop() assert not ver('1.1').isdevelop() assert not ver('1.mydevelopmentnightmare.3').isdevelop() assert not ver('mydevelopmentnightmare.3').isdevelop()
def cxx17_flag(self): if self.version < ver('5.0'): tty.die("Only gcc 5.0 and above support c++17.") else: return "-std=c++1z"
def assert_not_in(needle, haystack): """Asserts that 'needle' is not in 'haystack'.""" assert ver(needle) not in ver(haystack)
def test_concretize_preferred_version(self): spec = self.check_concretize('python') self.assertEqual(spec.versions, ver('2.7.11')) spec = self.check_concretize('[email protected]') self.assertEqual(spec.versions, ver('3.5.1'))
def test_version_range_nonempty(): assert Version('1.2.9') in VersionRange('1.2.0', '1.2') assert Version('1.1.1') in ver('1.0:1')