Skip to content

Commit faa3e2a

Browse files
authored
Merge pull request #2599 from ocaisa/allow_dep_upgrades
Add ability to upgrade dependencies based on available easyconfigs
2 parents 33aa08a + ee63271 commit faa3e2a

File tree

15 files changed

+810
-127
lines changed

15 files changed

+810
-127
lines changed

easybuild/framework/easyconfig/format/one.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ def dump_dependency(dep, toolchain):
7171
if dep['external_module']:
7272
res = "(%s, EXTERNAL_MODULE)" % quote_py_str(dep['full_mod_name'])
7373
else:
74-
# mininal spec: (name, version)
74+
# minimal spec: (name, version)
7575
tup = (dep['name'], dep['version'])
7676
if dep['toolchain'] != toolchain:
7777
if dep[SYSTEM_TOOLCHAIN_NAME]:

easybuild/framework/easyconfig/tweak.py

Lines changed: 337 additions & 67 deletions
Large diffs are not rendered by default.

easybuild/tools/filetools.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -758,7 +758,8 @@ def find_easyconfigs(path, ignore_dirs=None):
758758
return files
759759

760760

761-
def search_file(paths, query, short=False, ignore_dirs=None, silent=False, filename_only=False, terse=False):
761+
def search_file(paths, query, short=False, ignore_dirs=None, silent=False, filename_only=False, terse=False,
762+
case_sensitive=False):
762763
"""
763764
Search for files using in specified paths using specified search query (regular expression)
764765
@@ -782,7 +783,11 @@ def search_file(paths, query, short=False, ignore_dirs=None, silent=False, filen
782783

783784
# compile regex, case-insensitive
784785
try:
785-
query = re.compile(query, re.I)
786+
if case_sensitive:
787+
query = re.compile(query)
788+
else:
789+
# compile regex, case-insensitive
790+
query = re.compile(query, re.I)
786791
except re.error as err:
787792
raise EasyBuildError("Invalid search query: %s", err)
788793

easybuild/tools/options.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,9 @@ def software_options(self):
318318

319319
opts['map-toolchains'] = ("Enable mapping of (sub)toolchains when --try-toolchain(-version) is used",
320320
None, 'store_true', True)
321+
opts['try-update-deps'] = ("Try to update versions of the dependencies of an easyconfig based on what is "
322+
"available in the robot path",
323+
None, 'store_true', False)
321324

322325
self.log.debug("software_options: descr %s opts %s" % (descr, opts))
323326
self.add_group_parser(opts, descr)
@@ -1481,6 +1484,7 @@ def process_software_build_specs(options):
14811484
'version': options.try_software_version,
14821485
'toolchain_name': options.try_toolchain_name,
14831486
'toolchain_version': options.try_toolchain_version,
1487+
'update_deps': options.try_update_deps
14841488
}
14851489

14861490
# process easy options

easybuild/tools/robot.py

Lines changed: 55 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -469,20 +469,36 @@ def resolve_dependencies(easyconfigs, modtool, retain_all_deps=False, raise_erro
469469
return ordered_ecs
470470

471471

472-
def search_easyconfigs(query, short=False, filename_only=False, terse=False):
473-
"""Search for easyconfigs, if a query is provided."""
472+
def search_easyconfigs(query, short=False, filename_only=False, terse=False, consider_extra_paths=True,
473+
print_result=True, case_sensitive=False):
474+
"""
475+
Search for easyconfigs, if a query is provided.
476+
477+
:param query: regex query string
478+
:param short: figure out common prefix of hits, use variable to factor it out
479+
:param filename_only: only print filenames, not paths
480+
:param terse: stick to terse (machine-readable) output, as opposed to pretty-printing
481+
:param consider_extra_paths: consider all paths when searching
482+
:param print_result: print the list of easyconfigs
483+
:param case_sensitive: boolean to decide whether search is case sensitive
484+
485+
:return: return a list of paths for the query
486+
"""
474487
search_path = build_option('robot_path')
475488
if not search_path:
476489
search_path = [os.getcwd()]
477490
extra_search_paths = build_option('search_paths')
478-
if extra_search_paths:
479-
search_path.extend(extra_search_paths)
491+
# If we're returning a list of possible resolutions by the robot, don't include the extra_search_paths
492+
if extra_search_paths and consider_extra_paths:
493+
# we shouldn't use += or .extend here but compose a new list,
494+
# to avoid adding a path to the list returned by build_option('robot_path') !
495+
search_path = search_path + extra_search_paths
480496

481497
ignore_dirs = build_option('ignore_dirs')
482498

483499
# note: don't pass down 'filename_only' here, we need the full path to filter out archived easyconfigs
484500
var_defs, _hits = search_file(search_path, query, short=short, ignore_dirs=ignore_dirs, terse=terse,
485-
silent=True, filename_only=False)
501+
silent=True, filename_only=False, case_sensitive=case_sensitive)
486502

487503
# filter out archived easyconfigs, these are handled separately
488504
hits, archived_hits = [], []
@@ -492,32 +508,42 @@ def search_easyconfigs(query, short=False, filename_only=False, terse=False):
492508
else:
493509
hits.append(hit)
494510

495-
# check whether only filenames should be printed
511+
# check whether only filenames should be used
496512
if filename_only:
497513
hits = [os.path.basename(hit) for hit in hits]
498514
archived_hits = [os.path.basename(hit) for hit in archived_hits]
499515

500-
# prepare output format
501-
if terse:
502-
lines, tmpl = [], '%s'
516+
if print_result:
517+
# prepare output format
518+
if terse:
519+
lines, tmpl = [], '%s'
520+
else:
521+
lines = ['%s=%s' % var_def for var_def in var_defs]
522+
tmpl = ' * %s'
523+
524+
# non-archived hits are shown first
525+
lines.extend(tmpl % hit for hit in hits)
526+
527+
# also take into account archived hits
528+
if archived_hits:
529+
if build_option('consider_archived_easyconfigs'):
530+
if not terse:
531+
lines.extend(['', "Matching archived easyconfigs:", ''])
532+
lines.extend(tmpl % hit for hit in archived_hits)
533+
elif not terse:
534+
cnt = len(archived_hits)
535+
lines.extend([
536+
'',
537+
"Note: %d matching archived easyconfig(s) found, use --consider-archived-easyconfigs to see them"
538+
% cnt,
539+
])
540+
541+
print('\n'.join(lines))
542+
543+
# if requested return the matches as a list
544+
if build_option('consider_archived_easyconfigs'):
545+
final_hits = hits + archived_hits
503546
else:
504-
lines = ['%s=%s' % var_def for var_def in var_defs]
505-
tmpl = ' * %s'
506-
507-
# non-archived hits are shown first
508-
lines.extend(tmpl % hit for hit in hits)
509-
510-
# also take into account archived hits
511-
if archived_hits:
512-
if build_option('consider_archived_easyconfigs'):
513-
if not terse:
514-
lines.extend(['', "Matching archived easyconfigs:", ''])
515-
lines.extend(tmpl % hit for hit in archived_hits)
516-
elif not terse:
517-
cnt = len(archived_hits)
518-
lines.extend([
519-
'',
520-
"Note: %d matching archived easyconfig(s) found, use --consider-archived-easyconfigs to see them" % cnt,
521-
])
522-
523-
print('\n'.join(lines))
547+
final_hits = hits
548+
549+
return final_hits

test/framework/easyblock.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1765,11 +1765,11 @@ def run_checks():
17651765

17661766
# full check also catches checksum issues with extensions
17671767
res = eb.check_checksums()
1768-
self.assertEqual(len(res), 5)
1768+
self.assertEqual(len(res), 4)
17691769
run_checks()
17701770

17711771
idx = 2
1772-
for ext in ['bar', 'barbar', 'toy']:
1772+
for ext in ['bar', 'barbar']:
17731773
expected = "Checksums missing for one or more sources/patches of extension %s in " % ext
17741774
self.assertTrue(res[idx].startswith(expected))
17751775
idx += 1
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
##
2+
# This file is an EasyBuild reciPY as per https://github.com/easybuilders/easybuild
3+
#
4+
# Copyright:: Copyright (c) 2012-2013 Cyprus Institute / CaSToRC
5+
# Authors:: Thekla Loizou <[email protected]>
6+
# License:: MIT/GPL
7+
# $Id$
8+
#
9+
# This work implements a part of the HPCBIOS project and is a component of the policy:
10+
# http://hpcbios.readthedocs.org/en/latest/HPCBIOS_06-19.html
11+
##
12+
easyblock = 'ConfigureMake'
13+
14+
name = 'gzip'
15+
version = '1.4'
16+
17+
homepage = "http://www.gzip.org/"
18+
description = "gzip (GNU zip) is a popular data compression program as a replacement for compress"
19+
20+
# test toolchain specification
21+
toolchain = {'name': 'GCC', 'version': '4.9.3-2.26'}
22+
23+
# source tarball filename
24+
sources = ['%(name)s-%(version)s.tar.gz']
25+
26+
# download location for source files
27+
source_urls = [GNU_SOURCE]
28+
29+
# make sure the gzip and gunzip binaries are available after installation
30+
sanity_check_paths = {
31+
'files': ["bin/gunzip", "bin/gzip"],
32+
'dirs': [],
33+
}
34+
35+
# run 'gzip -h' and 'gzip --version' after installation
36+
sanity_check_commands = [True, ('gzip', '--version')]
37+
38+
software_license = GPLv3
39+
40+
moduleclass = 'tools'
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
##
2+
# This file is an EasyBuild reciPY as per https://github.com/easybuilders/easybuild
3+
#
4+
# Copyright:: Copyright (c) 2012-2013 Cyprus Institute / CaSToRC
5+
# Authors:: Thekla Loizou <[email protected]>
6+
# License:: MIT/GPL
7+
# $Id$
8+
#
9+
# This work implements a part of the HPCBIOS project and is a component of the policy:
10+
# http://hpcbios.readthedocs.org/en/latest/HPCBIOS_06-19.html
11+
##
12+
easyblock = 'ConfigureMake'
13+
14+
name = 'gzip'
15+
version = '1.6'
16+
17+
homepage = "http://www.gzip.org/"
18+
description = "gzip (GNU zip) is a popular data compression program as a replacement for compress"
19+
20+
# test toolchain specification
21+
toolchain = {'name': 'iccifort', 'version': '2016.1.150-GCC-4.9.3-2.25'}
22+
23+
# source tarball filename
24+
sources = ['%(name)s-%(version)s.tar.gz']
25+
26+
# download location for source files
27+
source_urls = [GNU_SOURCE]
28+
29+
# make sure the gzip and gunzip binaries are available after installation
30+
sanity_check_paths = {
31+
'files': ["bin/gunzip", "bin/gzip"],
32+
'dirs': [],
33+
}
34+
35+
# run 'gzip -h' and 'gzip --version' after installation
36+
sanity_check_commands = [True, ('gzip', '--version')]
37+
38+
software_license = GPLv3
39+
40+
moduleclass = 'tools'

test/framework/easyconfigs/test_ecs/h/hwloc/hwloc-1.6.2-GCC-4.9.3-2.26.eb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@ toolchain = {'name': 'GCC', 'version': '4.9.3-2.26'}
1515

1616
source_urls = ['http://www.open-mpi.org/software/hwloc/v%(version_major_minor)s/downloads/']
1717
sources = [SOURCE_TAR_GZ]
18+
checksums = ['aa9d9ca75c7d7164f6bf3a52ecd77340eec02c18']
1819

1920
builddependencies = [('binutils', '2.26')]
2021

22+
# introduce fake dependency for testing dep upgrades
23+
dependencies = [('gzip', '1.4')]
24+
2125
moduleclass = 'system'

test/framework/easyconfigs/test_ecs/t/toy/toy-0.0-gompi-2018a-test.eb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ exts_list = [
4747
(name, version, {
4848
'sanity_check_paths': {'files': ['lib/libtoy.a'], 'dirs': []},
4949
'exts_filter': ("ls -l lib/libtoy.a", ''),
50+
'checksums': ['44332000aa33b99ad1e00cbd1a7da769220d74647060a10e807b916d73ea27bc']
5051
}),
5152
]
5253

0 commit comments

Comments
 (0)