Skip to content

Commit

Permalink
Merge pull request #406 from ParaToolsInc/compiler_none
Browse files Browse the repository at this point in the history
Allow a Compiler to be specified as None, so that MPI and CUDA compilers can be unset even if auto-detected
  • Loading branch information
nchaimov committed Jan 30, 2022
2 parents 8cd2631 + 7e6d091 commit e2b2098
Show file tree
Hide file tree
Showing 9 changed files with 212 additions and 5 deletions.
12 changes: 10 additions & 2 deletions packages/taucmdr/cf/compiler/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ class InstalledCompilerCreator(type):
and `icc` would be probed twice. With this metaclass, ``b is a == True`` and `icc` is only invoked once.
"""
def __call__(cls, absolute_path, info, **kwargs):
assert isinstance(absolute_path, str) and os.path.isabs(absolute_path)
assert absolute_path == '' or (isinstance(absolute_path, str) and os.path.isabs(absolute_path))
assert isinstance(info, _CompilerInfo)
# Don't allow unchecked values into the instance cache
if kwargs:
Expand Down Expand Up @@ -637,7 +637,10 @@ def probe(cls, command, family=None, role=None):
assert isinstance(role, _CompilerRole) or role is None
absolute_path = util.which(command)
if not absolute_path:
raise ConfigurationError("Compiler '%s' not found on PATH" % command)
if family is None:
absolute_path = ''
else:
raise ConfigurationError("Compiler '%s' not found on PATH" % command)
command = os.path.basename(absolute_path)
LOGGER.debug("Probe: command='%s', abspath='%s', family='%s', role='%s'",
command, absolute_path, family, role)
Expand Down Expand Up @@ -765,6 +768,11 @@ def __init__(self, family):
LOGGER.warning(err)
continue
self.members.setdefault(role, []).append(installed)
for role, info_list in family.members.items():
for info in info_list:
if family.name == 'None':
installed = InstalledCompiler(info.command, info)
self.members.setdefault(role, []).append(installed)
if not self.members:
cmds = [info.command for info_list in family.members.values() for info in info_list]
raise ConfigurationError(f"{self.family.name} {self.family.kbase.description} not found.",
Expand Down
2 changes: 2 additions & 0 deletions packages/taucmdr/cf/compiler/cuda.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,7 @@
IBM = CUDA_COMPILERS.add('IBM', family_regex=r'^IBM XL', version_flags=['-qversion'],
FC='xlcuf')

NONE = CUDA_COMPILERS.add('None', CXX='', FC='')

CUDA_CXX = CUDA_COMPILERS.roles['CXX']
CUDA_FC = CUDA_COMPILERS.roles['FC']
4 changes: 4 additions & 0 deletions packages/taucmdr/cf/compiler/mpi.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@
show_wrapper_flags=['-craype-verbose', '--version', '-E'],
CC='cc', CXX='CC', FC='ftn')

NONE = MPI_COMPILERS.add('None', #family_regex='',
CC='', CXX='', FC='')


MPI_CC = MPI_COMPILERS.roles['CC']
MPI_CXX = MPI_COMPILERS.roles['CXX']
MPI_FC = MPI_COMPILERS.roles['FC']
5 changes: 5 additions & 0 deletions packages/taucmdr/cli/commands/target/copy.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
from taucmdr.cf.compiler.host import HOST_COMPILERS
from taucmdr.cf.compiler.mpi import MPI_COMPILERS
from taucmdr.cf.compiler.shmem import SHMEM_COMPILERS
from taucmdr.cf.compiler.cuda import CUDA_COMPILERS
from taucmdr.cf.software.tau_installation import TauInstallation


Expand Down Expand Up @@ -96,6 +97,10 @@ def _construct_parser(self):

group = parser.add_argument_group('Symmetric Hierarchical Memory (SHMEM) arguments')
self._configure_argument_group(group, SHMEM_COMPILERS, '--shmem-compilers', 'shmem_family')

group = parser.add_argument_group('CUDA arguments')
self._configure_argument_group(group, CUDA_COMPILERS, '--cuda-compilers', 'cuda_family')

return parser

def main(self, argv):
Expand Down
4 changes: 4 additions & 0 deletions packages/taucmdr/cli/commands/target/edit.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
from taucmdr.cf.compiler.host import HOST_COMPILERS
from taucmdr.cf.compiler.mpi import MPI_COMPILERS
from taucmdr.cf.compiler.shmem import SHMEM_COMPILERS
from taucmdr.cf.compiler.cuda import CUDA_COMPILERS
from taucmdr.cf.software.tau_installation import TauInstallation


Expand Down Expand Up @@ -99,6 +100,9 @@ def _construct_parser(self):

group = parser.add_argument_group('Symmetric Hierarchical Memory (SHMEM) arguments')
self._configure_argument_group(group, SHMEM_COMPILERS, '--shmem-compilers', 'shmem_family')

group = parser.add_argument_group('CUDA arguments')
self._configure_argument_group(group, CUDA_COMPILERS, '--cuda-compilers', 'cuda_family')
return parser

def _update_record(self, store, data, key):
Expand Down
68 changes: 67 additions & 1 deletion packages/taucmdr/cli/commands/target/tests/test_copy.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"""


from taucmdr import tests
from taucmdr import tests, util
from taucmdr.cli.commands.target import copy

class CopyTest(tests.TestCase):
Expand Down Expand Up @@ -76,3 +76,69 @@ def test_compilerarg(self):
stdout, stderr = self.assertCommandReturnValue(0, copy.COMMAND, argv)
self.assertIn('Added target \'targ2\' to project configuration', stdout)
self.assertFalse(stderr)

@tests.skipUnless(util.which('mpicc'), "MPI compilers required for this test")
def test_no_mpi(self):
self.reset_project_storage()
argv = ['targ1', 'targ2', '--mpi-wrappers', 'None']
stdout, stderr = self.assertCommandReturnValue(0, copy.COMMAND, argv)
self.assertIn("Added target \'targ2\' to project configuration", stdout)
self.assertFalse(stderr)
from taucmdr.cf.compiler.mpi import MPI_CC, MPI_CXX, MPI_FC
from taucmdr.cf.storage.levels import PROJECT_STORAGE
from taucmdr.model.target import Target
ctrl = Target.controller(PROJECT_STORAGE)
targ2 = ctrl.one({'name': 'targ2'})
for role, expected in (MPI_CC, ''), (MPI_CXX, ''), (MPI_FC, ''):
path = targ2.populate(role.keyword)['path']
self.assertEqual(path, expected, f"Target[{role}] is '{path}', not '{expected}'")


@tests.skipUnless(util.which('mpicc'), "MPI compilers required for this test")
def test_no_mpi_cc(self):
self.reset_project_storage()
argv = ['targ1', 'targ2', '--mpi-cc', 'None']
stdout, stderr = self.assertCommandReturnValue(0, copy.COMMAND, argv)
self.assertIn("Added target \'targ2\' to project configuration", stdout)
self.assertFalse(stderr)
from taucmdr.cf.compiler.mpi import MPI_CC, MPI_CXX, MPI_FC
from taucmdr.cf.storage.levels import PROJECT_STORAGE
from taucmdr.model.target import Target
ctrl = Target.controller(PROJECT_STORAGE)
targ2 = ctrl.one({'name': 'targ2'})
path = targ2.populate(MPI_CC.keyword)['path']
self.assertEqual(path, '', f"Target[MPI_CC] is '{path}', not ''")

@tests.skipUnless(util.which('nvcc'), "CUDA compilers required for this test")
def test_no_cuda_cxx(self):
self.reset_project_storage()
argv = ['targ1', 'targ2', '--cuda-cxx', 'None']
stdout, stderr = self.assertCommandReturnValue(0, copy.COMMAND, argv)
self.assertIn("Added target \'targ2\' to project configuration", stdout)
self.assertFalse(stderr)
from taucmdr.cf.compiler.cuda import CUDA_CXX, CUDA_FC
from taucmdr.cf.storage.levels import PROJECT_STORAGE
from taucmdr.model.target import Target
ctrl = Target.controller(PROJECT_STORAGE)
targ2 = ctrl.one({'name': 'targ2'})
role = CUDA_CXX
expected = ''
path = targ2.populate(role.keyword)['path']
self.assertEqual(path, expected, f"Target[{role}] is '{path}', not '{expected}'")

@tests.skipUnless(util.which('xlcuf'), "CUDA compilers required for this test")
def test_no_cuda_fc(self):
self.reset_project_storage()
argv = ['targ1', 'targ2', '--cuda-fc', 'None']
stdout, stderr = self.assertCommandReturnValue(0, copy.COMMAND, argv)
self.assertIn("Added target \'targ2\' to project configuration", stdout)
self.assertFalse(stderr)
from taucmdr.cf.compiler.cuda import CUDA_FC
from taucmdr.cf.storage.levels import PROJECT_STORAGE
from taucmdr.model.target import Target
ctrl = Target.controller(PROJECT_STORAGE)
targ2 = ctrl.one({'name': 'targ2'})
role = CUDA_FC
expected = ''
path = targ2.populate(role.keyword)['path']
self.assertEqual(path, expected, f"Target[{role}] is '{path}', not '{expected}'")
48 changes: 48 additions & 0 deletions packages/taucmdr/cli/commands/target/tests/test_create.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,54 @@ def test_cxx_as_cc_flag(self):
cxx_cmd = self.assertCompiler(CXX)
self.assertRaises(ConfigurationError, self.exec_command, create_cmd, ['test_targ', '--cc', cxx_cmd])

@tests.skipUnless(util.which('mpicc'), "MPI compilers required for this test")
def test_no_mpi(self):
self.reset_project_storage()
stdout, stderr = self.assertCommandReturnValue(0, create_cmd, ['test_targ', '--mpi-wrappers', 'None'])
self.assertIn("Added target", stdout)
self.assertIn("test_targ", stdout)
self.assertFalse(stderr)
from taucmdr.cf.compiler.mpi import MPI_CC, MPI_CXX, MPI_FC
from taucmdr.cf.storage.levels import PROJECT_STORAGE
from taucmdr.model.target import Target
ctrl = Target.controller(PROJECT_STORAGE)
test_targ = ctrl.one({'name': 'test_targ'})
for role, expected in (MPI_CC, ''), (MPI_CXX, ''), (MPI_FC, ''):
path = test_targ.populate(role.keyword)['path']
self.assertEqual(path, expected, f"Target[{role}] is '{path}', not '{expected}'")


@tests.skipUnless(util.which('mpicc'), "MPI compilers required for this test")
def test_no_mpi_cc(self):
self.reset_project_storage()
stdout, stderr = self.assertCommandReturnValue(0, create_cmd, ['test_targ', '--mpi-cc', 'None'])
self.assertIn("Added target", stdout)
self.assertIn("test_targ", stdout)
self.assertFalse(stderr)
from taucmdr.cf.compiler.mpi import MPI_CC, MPI_CXX, MPI_FC
from taucmdr.cf.storage.levels import PROJECT_STORAGE
from taucmdr.model.target import Target
ctrl = Target.controller(PROJECT_STORAGE)
test_targ = ctrl.one({'name': 'test_targ'})
path = test_targ.populate(MPI_CC.keyword)['path']
self.assertEqual(path, '', f"Target[{MPI_CC}] is '{path}', not ''")

@tests.skipUnless(util.which('nvcc') or util.which('xlcuf'), "CUDA compilers required for this test")
def test_no_cuda(self):
self.reset_project_storage()
argv = ['targ2', '--cuda-compilers', 'None']
stdout, stderr = self.assertCommandReturnValue(0, create_cmd, argv)
self.assertIn("Added target \'targ2\' to project configuration", stdout)
self.assertFalse(stderr)
from taucmdr.cf.compiler.cuda import CUDA_CXX, CUDA_FC
from taucmdr.cf.storage.levels import PROJECT_STORAGE
from taucmdr.model.target import Target
ctrl = Target.controller(PROJECT_STORAGE)
targ2 = ctrl.one({'name': 'targ2'})
for role, expected in (CUDA_CXX, ''), (CUDA_FC, ''):
path = targ2.populate(role.keyword)['path']
self.assertEqual(path, expected, f"Target[{role}] is '{path}', not '{expected}'")

# @tests.skipUnless(util.which('python'), "Python 2 or 3 required for this test")
# def test_python_init(self):
# self.reset_project_storage(['--python', 'T', '--python-interpreter', 'python'])
Expand Down
67 changes: 66 additions & 1 deletion packages/taucmdr/cli/commands/target/tests/test_edit.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"""


from taucmdr import tests
from taucmdr import tests, util
from taucmdr.cli.commands.target import edit

class EditTest(tests.TestCase):
Expand Down Expand Up @@ -69,3 +69,68 @@ def test_ambiguousarg(self):
_, stderr = self.assertNotCommandReturnValue(0, edit.COMMAND, argv)
self.assertIn('target edit <target_name> [arguments]', stderr)
self.assertIn('target edit: error: ambiguous option: --mpi could match --mpi-', stderr)

@tests.skipUnless(util.which('mpicc'), "MPI compilers required for this test")
def test_no_mpi(self):
self.reset_project_storage()
argv = ['targ1', '--mpi-wrappers', 'None']
stdout, stderr = self.assertCommandReturnValue(0, edit.COMMAND, argv)
self.assertIn("Updated target \'targ1\'", stdout)
self.assertFalse(stderr)
from taucmdr.cf.compiler.mpi import MPI_CC, MPI_CXX, MPI_FC
from taucmdr.cf.storage.levels import PROJECT_STORAGE
from taucmdr.model.target import Target
ctrl = Target.controller(PROJECT_STORAGE)
targ1 = ctrl.one({'name': 'targ1'})
for role, expected in (MPI_CC, ''), (MPI_CXX, ''), (MPI_FC, ''):
path = targ1.populate(role.keyword)['path']
self.assertEqual(path, expected, f"Target[{role}] is '{path}', not '{expected}'")

@tests.skipUnless(util.which('mpicc'), "MPI compilers required for this test")
def test_no_mpi_cc(self):
self.reset_project_storage()
argv = ['targ1', '--mpi-cc', 'None']
stdout, stderr = self.assertCommandReturnValue(0, edit.COMMAND, argv)
self.assertIn("Updated target \'targ1\'", stdout)
self.assertFalse(stderr)
from taucmdr.cf.compiler.mpi import MPI_CC, MPI_CXX, MPI_FC
from taucmdr.cf.storage.levels import PROJECT_STORAGE
from taucmdr.model.target import Target
ctrl = Target.controller(PROJECT_STORAGE)
targ1 = ctrl.one({'name': 'targ1'})
path = targ1.populate(MPI_CC.keyword)['path']
self.assertEqual(path, '', f"Target[{MPI_CC}] is '{path}', not ''")

@tests.skipUnless(util.which('nvcc'), "CUDA CXX compiler required for this test")
def test_no_cuda_cxx(self):
self.reset_project_storage()
argv = ['targ1', '--cuda-cxx', 'None']
stdout, stderr = self.assertCommandReturnValue(0, edit.COMMAND, argv)
self.assertIn("Updated target \'targ1\'", stdout)
self.assertFalse(stderr)
from taucmdr.cf.compiler.cuda import CUDA_CXX
from taucmdr.cf.storage.levels import PROJECT_STORAGE
from taucmdr.model.target import Target
ctrl = Target.controller(PROJECT_STORAGE)
targ1 = ctrl.one({'name': 'targ1'})
role = CUDA_CXX
expected = ''
path = targ1.populate(role.keyword)['path']
self.assertEqual(path, expected, f"Target[{role}] is '{path}', not '{expected}'")

@tests.skipUnless(util.which('xlcuf'), "CUDA CXX compiler required for this test")
def test_no_cuda_fc(self):
self.reset_project_storage()
argv = ['targ1', '--cuda-fc', 'None']
stdout, stderr = self.assertCommandReturnValue(0, edit.COMMAND, argv)
self.assertIn("Updated target \'targ1\'", stdout)
self.assertFalse(stderr)
from taucmdr.cf.compiler.cuda import CUDA_FC
from taucmdr.cf.storage.levels import PROJECT_STORAGE
from taucmdr.model.target import Target
ctrl = Target.controller(PROJECT_STORAGE)
targ1 = ctrl.one({'name': 'targ1'})
role = CUDA_FC
expected = ''
path = targ1.populate(role.keyword)['path']
self.assertEqual(path, expected, f"Target[{role}] is '{path}', not '{expected}'")
7 changes: 6 additions & 1 deletion packages/taucmdr/model/target.py
Original file line number Diff line number Diff line change
Expand Up @@ -576,12 +576,17 @@ def on_update(self, changes):
"Delete experiment '%s' and try again." % expr['name'])
if self.is_selected():
for attr, change in changes.items():
message = {}
props = self.attributes[attr]
if props.get('rebuild_required'):
if props.get('model', None) == Compiler:
old_comp = Compiler.controller(self.storage).one(change[0])
new_comp = Compiler.controller(self.storage).one(change[1])
message = {attr: (old_comp['path'], new_comp['path'])}
if old_comp is None:
if new_comp['path'] != '':
message = {attr: ('', new_comp['path'])}
else:
message = {attr: (old_comp['path'], new_comp['path'])}
else:
message = {attr: change}
self.controller(self.storage).push_to_topic('rebuild_required', message)
Expand Down

0 comments on commit e2b2098

Please sign in to comment.