Repository: NVIDIA/hpc-container-maker (language: python)

Issue:
Incompatible with python 3.12
The very recently released python 3.12 no longer ships with distutils, which this package depends on for `LooseVersion` and `StrictVersion`.

Authors are apparently [recommended](https://setuptools.pypa.io/en/latest/deprecated/distutils-legacy.html#) to use similar functionality from the `packaging` package, but it does not appear to be a drop-in replacement


Discussion / hints:

Fix patch:
diff --git a/.github/workflows/python3.yml b/.github/workflows/python3.yml
index c3e3665f..6e756ef8 100644
--- a/.github/workflows/python3.yml
+++ b/.github/workflows/python3.yml
@@ -8,7 +8,7 @@ jobs:
     strategy:
       matrix:
         os: [ubuntu-latest, macos-latest, windows-latest]
-        python-version: ['3.7', '3.8', '3.9', '3.10', '3.11']
+        python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12']
         include:
           - os: macos-latest
             python-version: '3.5'
@@ -34,7 +34,7 @@ jobs:
         else
           python -m pip install --upgrade pip
         fi
-        pip install six archspec
+        pip install six archspec packaging
       shell: bash
 
     - name: Run unit tests
diff --git a/docs/tutorial.md b/docs/tutorial.md
index abaf2084..e9c37e4f 100644
--- a/docs/tutorial.md
+++ b/docs/tutorial.md
@@ -308,15 +308,15 @@ specified using this option are inserted into a Python dictionary
 named `USERARG` that can be accessed inside a recipe.
 
 ```python
-from distutils.version import StrictVersion
+from packaging.version import Version
 
 cuda_version = USERARG.get('cuda', '9.1')
-if StrictVersion(cuda_version) < StrictVersion('9.0'):
+if Version(cuda_version) < Version('9.0'):
   raise RuntimeError('invalid CUDA version: {}'.format(cuda_version))
 Stage0 += baseimage(image='nvidia/cuda:{}-devel-ubuntu16.04'.format(cuda_version))
 
 ompi_version = USERARG.get('ompi', '3.1.2')
-if not StrictVersion(ompi_version):
+if not Version(ompi_version):
   raise RuntimeError('invalid OpenMPI version: {}'.format(ompi_version))
 Stage0 += openmpi(infiniband=False, version=ompi_version)
 ```
@@ -353,7 +353,7 @@ provide equivalent functionality.
 #!/usr/bin/env python
 
 from __future__ import print_function
-from distutils.version import StrictVersion
+from packaging.version import Version
 
 import argparse
 import hpccm
@@ -372,11 +372,11 @@ args = parser.parse_args()
 
 Stage0 = hpccm.Stage()
 
-if StrictVersion(args.cuda) < StrictVersion('9.0'):
+if Version(args.cuda) < Version('9.0'):
   raise RuntimeError('invalid CUDA version: {}'.format(args.cuda))
 Stage0 += baseimage(image='nvidia/cuda:{}-devel-ubuntu16.04'.format(args.cuda))
 
-if not StrictVersion(args.ompi):
+if not Version(args.ompi):
   raise RuntimeError('invalid OpenMPI version: {}'.format(args.ompi))
 Stage0 += openmpi(infiniband=False, version=args.ompi)
 
diff --git a/hpccm/building_blocks/arm_allinea_studio.py b/hpccm/building_blocks/arm_allinea_studio.py
index 2865c336..6de4a3ca 100644
--- a/hpccm/building_blocks/arm_allinea_studio.py
+++ b/hpccm/building_blocks/arm_allinea_studio.py
@@ -21,7 +21,7 @@
 from __future__ import unicode_literals
 from __future__ import print_function
 
-from distutils.version import StrictVersion
+from packaging.version import Version
 import logging
 import posixpath
 import re
@@ -168,11 +168,11 @@ def __distro(self):
         specified value overrides any defaults."""
 
         if hpccm.config.g_linux_distro == linux_distro.UBUNTU:
-            if StrictVersion(self.__version) <= StrictVersion('20.3'):
+            if Version(self.__version) <= Version('20.3'):
                 self.__directory_string = 'Ubuntu-16.04'
                 self.__package_string = 'Ubuntu-16.04'
                 self.__url_string = 'Ubuntu16.04'
-            elif hpccm.config.g_linux_version <= StrictVersion('18.04'):
+            elif hpccm.config.g_linux_version <= Version('18.04'):
                 self.__directory_string = 'Ubuntu-18.04'
                 self.__package_string = 'Ubuntu-18.04'
                 self.__url_string = "ACfL"
@@ -182,7 +182,7 @@ def __distro(self):
                 self.__url_string = "ACfL"
 
             self.__installer_template = 'arm-compiler-for-linux_{{}}_{0}.sh'.format(self.__directory_string)
-            if  hpccm.config.g_linux_version >= StrictVersion('22.04'):
+            if  hpccm.config.g_linux_version >= Version('22.04'):
                 python2_package = "python2"
             else:
                 python2_package = "python"
@@ -191,17 +191,17 @@ def __distro(self):
                                      'tcl', 'wget']
 
         elif hpccm.config.g_linux_distro == linux_distro.CENTOS:
-            if hpccm.config.g_linux_version >= StrictVersion('8.0'):
+            if hpccm.config.g_linux_version >= Version('8.0'):
                 self.__directory_string = 'RHEL-8'
                 self.__package_string = 'RHEL-8'
-                if StrictVersion(self.__version) <= StrictVersion('20.3'):
+                if Version(self.__version) <= Version('20.3'):
                     self.__url_string = 'RHEL8'
                 else:
                     self.__url_string = 'ACfL'
             else:
                 self.__directory_string = 'RHEL-7'
                 self.__package_string = 'RHEL-7'
-                if StrictVersion(self.__version) <= StrictVersion('20.3'):
+                if Version(self.__version) <= Version('20.3'):
                     self.__url_string = 'RHEL7'
                 else:
                     self.__url_string = 'ACfL'
@@ -252,10 +252,10 @@ def __setup(self):
         install_args = ['--install-to {}'.format(self.__prefix)]
         if self.__eula:
             install_args.append('--accept')
-        if self.__microarchitectures and StrictVersion(self.__version) <= StrictVersion('20.3'):
+        if self.__microarchitectures and Version(self.__version) <= Version('20.3'):
             install_args.append('--only-install-microarchitectures={}'.format(
                 ','.join(self.__microarchitectures)))
-        if StrictVersion(self.__version) >= StrictVersion("21.1"):
+        if Version(self.__version) >= Version("21.1"):
             arch_string = ""
         else:
             arch_string = "_aarch64"
diff --git a/hpccm/building_blocks/charm.py b/hpccm/building_blocks/charm.py
index f943054d..d3a26d21 100644
--- a/hpccm/building_blocks/charm.py
+++ b/hpccm/building_blocks/charm.py
@@ -21,7 +21,7 @@
 from __future__ import unicode_literals
 from __future__ import print_function
 
-from distutils.version import LooseVersion
+from packaging.version import Version
 import posixpath
 
 import hpccm.config
@@ -118,7 +118,7 @@ def __init__(self, **kwargs):
         self.__version = kwargs.get('version', '6.10.2')
 
         # Version 6.9.0 dropped the 'v' from directory name
-        if LooseVersion(self.__version) >= LooseVersion('6.9.0'):
+        if Version(self.__version) >= Version('6.9.0'):
             self.__installdir = posixpath.join(
                 self.__prefix, 'charm-{}'.format(self.__version))
         else:
diff --git a/hpccm/building_blocks/cmake.py b/hpccm/building_blocks/cmake.py
index 7d6eb92a..3fdbc65f 100644
--- a/hpccm/building_blocks/cmake.py
+++ b/hpccm/building_blocks/cmake.py
@@ -33,7 +33,7 @@
 from hpccm.building_blocks.base import bb_base
 from hpccm.building_blocks.packages import packages
 from hpccm.common import cpu_arch, linux_distro
-from distutils.version import LooseVersion
+from packaging.version import Version
 from hpccm.primitives.comment import comment
 from hpccm.primitives.shell import shell
 from hpccm.primitives.environment import environment
@@ -122,7 +122,7 @@ def __setup(self):
         if not self.__source and hpccm.config.g_cpu_arch == cpu_arch.X86_64:
             # Use the pre-compiled x86_64 binary
             self.__binary()
-        elif not self.__source and hpccm.config.g_cpu_arch == cpu_arch.AARCH64 and LooseVersion(self.__version) >= LooseVersion('3.20'):
+        elif not self.__source and hpccm.config.g_cpu_arch == cpu_arch.AARCH64 and Version(self.__version) >= Version('3.20'):
             # Use the pre-compiled aarch64 binary
             self.__binary()
         else:
@@ -135,11 +135,11 @@ def __binary(self):
         runfile = 'cmake-{}-linux-x86_64.sh'
         if hpccm.config.g_cpu_arch == cpu_arch.AARCH64:
             runfile = 'cmake-{}-linux-aarch64.sh'
-        elif hpccm.config.g_cpu_arch == cpu_arch.X86_64 and LooseVersion(self.__version) < LooseVersion('3.20'):
+        elif hpccm.config.g_cpu_arch == cpu_arch.X86_64 and Version(self.__version) < Version('3.20'):
             runfile = 'cmake-{}-Linux-x86_64.sh'
 
         runfile = runfile.format(self.__version)
-        if LooseVersion(self.__version) < LooseVersion('3.1'):
+        if Version(self.__version) < Version('3.1'):
             runfile = 'cmake-{}-Linux-i386.sh'.format(self.__version)
             # CMake releases of versions < 3.1 are only include 32-bit
             # binaries:
diff --git a/hpccm/building_blocks/conda.py b/hpccm/building_blocks/conda.py
index f2348353..8fd2a458 100644
--- a/hpccm/building_blocks/conda.py
+++ b/hpccm/building_blocks/conda.py
@@ -21,7 +21,7 @@
 from __future__ import unicode_literals
 from __future__ import print_function
 
-from distutils.version import LooseVersion
+from packaging.version import Version
 import logging
 import posixpath
 
@@ -152,7 +152,7 @@ def __setup(self):
         """Construct the series of shell commands, i.e., fill in
            self.__commands"""
 
-        if LooseVersion(self.__version) >= LooseVersion('4.8'):
+        if Version(self.__version) >= Version('4.8'):
             miniconda = 'Miniconda{0}-{1}_{2}-Linux-{3}.sh'.format(
                 self.__python_version, self.__python_subversion,
                 self.__version, self.__arch_pkg)
diff --git a/hpccm/building_blocks/gdrcopy.py b/hpccm/building_blocks/gdrcopy.py
index e818868f..538a6642 100644
--- a/hpccm/building_blocks/gdrcopy.py
+++ b/hpccm/building_blocks/gdrcopy.py
@@ -23,7 +23,7 @@
 
 import posixpath
 from six.moves import shlex_quote
-from distutils.version import LooseVersion
+from packaging.version import Version
 
 import hpccm.templates.envvars
 import hpccm.templates.ldconfig
@@ -96,7 +96,7 @@ def __init__(self, **kwargs):
             make_opts['COMMONCFLAGS'] = make_opts.pop('CFLAGS')
 
         # Version 2.2 changed the flag to lowercase prefix and the lib directory
-        if LooseVersion(self.__version) >= LooseVersion('2.2'):
+        if Version(self.__version) >= Version('2.2'):
             make_opts['prefix'] = self.__prefix
             libdir = 'lib'
         else:
diff --git a/hpccm/building_blocks/gnu.py b/hpccm/building_blocks/gnu.py
index 6be35a0b..d241353d 100644
--- a/hpccm/building_blocks/gnu.py
+++ b/hpccm/building_blocks/gnu.py
@@ -20,7 +20,7 @@
 from __future__ import unicode_literals
 from __future__ import print_function
 
-from distutils.version import StrictVersion
+from packaging.version import Version
 import posixpath
 
 import hpccm.config
@@ -345,11 +345,11 @@ def __distro(self):
             # Set libfortran version depending on the Ubuntu version
             if self.__fortran:
                 if hpccm.config.g_linux_distro == linux_distro.UBUNTU:
-                    if hpccm.config.g_linux_version >= StrictVersion('20.0'):
+                    if hpccm.config.g_linux_version >= Version('20.0'):
                         self.__runtime_debs.append('libgfortran5')
-                    elif hpccm.config.g_linux_version >= StrictVersion('18.0'):
+                    elif hpccm.config.g_linux_version >= Version('18.0'):
                         self.__runtime_debs.append('libgfortran4')
-                    elif hpccm.config.g_linux_version >= StrictVersion('16.0'):
+                    elif hpccm.config.g_linux_version >= Version('16.0'):
                         self.__runtime_debs.append('libgfortran3')
                     else: # pragma: no cover
                         raise RuntimeError('Unrecognized Ubuntu version')
@@ -374,7 +374,7 @@ def __distro(self):
                     # Default for CentOS 7
                     toolset_path = '/opt/rh/devtoolset-{}/root/usr/bin'.format(
                         self.__version)
-                    if hpccm.config.g_linux_version >= StrictVersion('8.0'):
+                    if hpccm.config.g_linux_version >= Version('8.0'):
                         # CentOS 8
                         toolset_path = '/opt/rh/gcc-toolset-{}/root/usr/bin'.format(self.__version)
 
@@ -447,7 +447,7 @@ def __repository(self):
                 '{0}-{1}'.format(x, self.__version)
                 for x in self.__compiler_debs]
 
-            if hpccm.config.g_linux_version >= StrictVersion('8.0'):
+            if hpccm.config.g_linux_version >= Version('8.0'):
                 # CentOS 8
                 self.__compiler_rpms = [
                     'gcc-toolset-{1}-{0}'.format(x, self.__version)
diff --git a/hpccm/building_blocks/hpcx.py b/hpccm/building_blocks/hpcx.py
index df7ef65b..c3473c95 100644
--- a/hpccm/building_blocks/hpcx.py
+++ b/hpccm/building_blocks/hpcx.py
@@ -21,7 +21,7 @@
 from __future__ import unicode_literals
 from __future__ import print_function
 
-from distutils.version import StrictVersion
+from packaging.version import Version
 import posixpath
 import re
 
@@ -152,25 +152,25 @@ def __init__(self, **kwargs):
         self.__wd = kwargs.get('wd', hpccm.config.g_wd) # working directory
 
         if not self.__buildlabel:
-            if StrictVersion(self.__version) >= StrictVersion('2.16'):
+            if Version(self.__version) >= Version('2.16'):
                 self.__buildlabel = 'cuda12-gdrcopy2-nccl2.18'
-            elif StrictVersion(self.__version) >= StrictVersion('2.15'):
+            elif Version(self.__version) >= Version('2.15'):
                 self.__buildlabel = 'cuda12-gdrcopy2-nccl2.17'
-            elif StrictVersion(self.__version) >= StrictVersion('2.14'):
+            elif Version(self.__version) >= Version('2.14'):
                 self.__buildlabel = 'cuda11-gdrcopy2-nccl2.16'
-            elif StrictVersion(self.__version) >= StrictVersion('2.12'):
+            elif Version(self.__version) >= Version('2.12'):
                 self.__buildlabel = 'cuda11-gdrcopy2-nccl2.12'
-            elif StrictVersion(self.__version) >= StrictVersion('2.10'):
+            elif Version(self.__version) >= Version('2.10'):
                 self.__buildlabel = 'cuda11-gdrcopy2-nccl2.11'
 
         if not self.__mlnx_ofed:
-            if StrictVersion(self.__version) >= StrictVersion('2.10'):
+            if Version(self.__version) >= Version('2.10'):
                 self.__mlnx_ofed = '5'
             else:
                 self.__mlnx_ofed = '5.2-2.2.0.0'
 
         if not self.__ofedlabel:
-            if StrictVersion(self.__version) >= StrictVersion('2.16'):
+            if Version(self.__version) >= Version('2.16'):
                 self.__ofedlabel = 'gcc-mlnx_ofed'
             else:
                 self.__ofedlabel = 'gcc-MLNX_OFED_LINUX-{}'.format(self.__mlnx_ofed)
@@ -202,11 +202,11 @@ def __distro(self):
 
         if hpccm.config.g_linux_distro == linux_distro.UBUNTU:
             if not self.__oslabel:
-                if hpccm.config.g_linux_version >= StrictVersion('22.0'):
+                if hpccm.config.g_linux_version >= Version('22.0'):
                     self.__oslabel = 'ubuntu22.04'
-                elif hpccm.config.g_linux_version >= StrictVersion('20.0'):
+                elif hpccm.config.g_linux_version >= Version('20.0'):
                     self.__oslabel = 'ubuntu20.04'
-                elif hpccm.config.g_linux_version >= StrictVersion('18.0'):
+                elif hpccm.config.g_linux_version >= Version('18.0'):
                     self.__oslabel = 'ubuntu18.04'
                 else:
                     self.__oslabel = 'ubuntu16.04'
@@ -218,13 +218,13 @@ def __distro(self):
 
         elif hpccm.config.g_linux_distro == linux_distro.CENTOS:
             if not self.__oslabel:
-                if hpccm.config.g_linux_version >= StrictVersion('8.0'):
-                    if StrictVersion(self.__version) >= StrictVersion('2.10'):
+                if hpccm.config.g_linux_version >= Version('8.0'):
+                    if Version(self.__version) >= Version('2.10'):
                         self.__oslabel = 'redhat8'
                     else:
                         self.__oslabel = 'redhat8.0'
                 else:
-                    if StrictVersion(self.__version) >= StrictVersion('2.10'):
+                    if Version(self.__version) >= Version('2.10'):
                         self.__oslabel = 'redhat7'
                     else:
                         self.__oslabel = 'redhat7.6'
@@ -246,7 +246,7 @@ def __setup(self):
         # MAJOR.MINOR.REVISION, so pull apart the full version to get
         # the individual components.
         version_string = self.__version
-        if StrictVersion(self.__version) <= StrictVersion('2.8'):
+        if Version(self.__version) <= Version('2.8'):
             match = re.match(r'(?P<major>\d+)\.(?P<minor>\d+)\.(?P<revision>\d+)',
                              self.__version)
             version_string = '{0}.{1}'.format(match.groupdict()['major'],
@@ -254,7 +254,7 @@ def __setup(self):
 
         if self.__inbox:
             # Use inbox OFED
-            if StrictVersion(self.__version) >= StrictVersion('2.10'):
+            if Version(self.__version) >= Version('2.10'):
                 # Version 2.11 and later include an extra label
                 self.__label = 'hpcx-v{0}-gcc-inbox-{1}-{2}-{3}'.format(
                     self.__version, self.__oslabel, self.__buildlabel,
@@ -264,7 +264,7 @@ def __setup(self):
                     self.__version, self.__oslabel, self.__arch)
         else:
             # Use MLNX OFED
-            if StrictVersion(self.__version) >= StrictVersion('2.10'):
+            if Version(self.__version) >= Version('2.10'):
                 # Version 2.10 and later include an extra label
                 self.__label = 'hpcx-v{0}-{1}-{2}-{3}-{4}'.format(
                     self.__version, self.__ofedlabel, self.__oslabel, self.__buildlabel, self.__arch)
@@ -311,7 +311,7 @@ def __setup(self):
             hpcx_mpi_dir = posixpath.join(hpcx_dir, 'ompi')
             hpcx_oshmem_dir = hpcx_mpi_dir
             hpcx_mpi_tests_dir = posixpath.join(hpcx_mpi_dir, 'tests')
-            if StrictVersion(self.__version) >= StrictVersion('2.7'):
+            if Version(self.__version) >= Version('2.7'):
                 hpcx_osu_dir = posixpath.join(hpcx_mpi_tests_dir,
                                               'osu-micro-benchmarks-5.6.2')
                 hpcx_osu_cuda_dir = posixpath.join(
diff --git a/hpccm/building_blocks/intel_mpi.py b/hpccm/building_blocks/intel_mpi.py
index 388b6733..d95c1737 100644
--- a/hpccm/building_blocks/intel_mpi.py
+++ b/hpccm/building_blocks/intel_mpi.py
@@ -21,7 +21,7 @@
 from __future__ import unicode_literals
 from __future__ import print_function
 
-from distutils.version import LooseVersion
+from packaging.version import Version
 import logging
 
 import hpccm.config
@@ -143,7 +143,7 @@ def __instructions(self):
             # subsequent build steps and when starting the container,
             # but this may miss some things relative to the mpivars
             # environment script.
-            if LooseVersion(self.__version) >= LooseVersion('2019.0'):
+            if Version(self.__version) >= Version('2019.0'):
               self.environment_variables={
                   'FI_PROVIDER_PATH': '/opt/intel/compilers_and_libraries/linux/mpi/intel64/libfabric/lib/prov',
                   'I_MPI_ROOT': '/opt/intel/compilers_and_libraries/linux/mpi',
diff --git a/hpccm/building_blocks/intel_psxe_runtime.py b/hpccm/building_blocks/intel_psxe_runtime.py
index 79740dee..96c00917 100644
--- a/hpccm/building_blocks/intel_psxe_runtime.py
+++ b/hpccm/building_blocks/intel_psxe_runtime.py
@@ -21,7 +21,7 @@
 from __future__ import unicode_literals
 from __future__ import print_function
 
-from distutils.version import LooseVersion
+from packaging.version import Version
 import logging # pylint: disable=unused-import
 import posixpath
 
@@ -256,7 +256,7 @@ def __environment(self):
                                                   'lib'))
             path.append(posixpath.join(basepath, 'mpi', 'intel64', 'bin'))
 
-            if LooseVersion(self.__version) >= LooseVersion('2019'):
+            if Version(self.__version) >= Version('2019'):
                 env['FI_PROVIDER_PATH'] = posixpath.join(
                     basepath, 'mpi', 'intel64', 'libfabric', 'lib', 'prov')
                 ld_library_path.append(posixpath.join(
@@ -264,7 +264,7 @@ def __environment(self):
                 path.append(posixpath.join(basepath, 'mpi', 'intel64',
                                            'libfabric', 'bin'))
 
-            if LooseVersion(self.__version) >= LooseVersion('2020'):
+            if Version(self.__version) >= Version('2020'):
                 ld_library_path.append(posixpath.join(
                     basepath, 'mpi', 'intel64', 'lib', 'release'))
 
diff --git a/hpccm/building_blocks/kokkos.py b/hpccm/building_blocks/kokkos.py
index a5aa8729..592c893c 100644
--- a/hpccm/building_blocks/kokkos.py
+++ b/hpccm/building_blocks/kokkos.py
@@ -21,7 +21,7 @@
 from __future__ import unicode_literals
 from __future__ import print_function
 
-from distutils.version import StrictVersion
+from packaging.version import Version
 
 import hpccm.config
 import hpccm.templates.downloader
@@ -194,7 +194,7 @@ def __distro(self):
             if not self.__ospackages:
                 self.__ospackages = ['hwloc-devel', 'make']
 
-            if hpccm.config.g_linux_version >= StrictVersion('8.0'):
+            if hpccm.config.g_linux_version >= Version('8.0'):
                 # hwloc-devel is in the CentOS powertools repository
                 self.__powertools = True
         else: # pragma: no cover
diff --git a/hpccm/building_blocks/llvm.py b/hpccm/building_blocks/llvm.py
index 5897a997..6458df41 100644
--- a/hpccm/building_blocks/llvm.py
+++ b/hpccm/building_blocks/llvm.py
@@ -20,7 +20,7 @@
 from __future__ import unicode_literals
 from __future__ import print_function
 
-from distutils.version import LooseVersion, StrictVersion
+from packaging.version import Version
 import logging
 
 import hpccm.config
@@ -133,7 +133,7 @@ def __setup(self):
                 self.__version = self.__trunk_version
 
             if self.__version:
-                if LooseVersion(self.__version) <= LooseVersion('6.0'):
+                if Version(self.__version) <= Version('6.0'):
                     self.__compiler_debs = ['clang-{}'.format(self.__version)]
                     self.__runtime_debs = [
                         'libclang1-{}'.format(self.__version)]
@@ -236,7 +236,7 @@ def __setup(self):
             compiler_version = ''
 
             if self.__version:
-                if hpccm.config.g_linux_version >= StrictVersion('8.0'):
+                if hpccm.config.g_linux_version >= Version('8.0'):
                     # Multiple versions are not available for CentOS 8
                     self.__compiler_rpms = ['clang', 'llvm-libs']
                     self.__runtime_rpms = ['llvm-libs']
@@ -278,7 +278,7 @@ def __setup(self):
             else:
                 # Distro default
                 self.__compiler_rpms = ['clang']
-                if hpccm.config.g_linux_version >= StrictVersion('8.0'):
+                if hpccm.config.g_linux_version >= Version('8.0'):
                     # CentOS 8
                     self.__runtime_rpms = ['llvm-libs']
                     compiler_version = '8'
@@ -342,29 +342,29 @@ def __upstream_package_repos(self):
         codename = 'xenial'
         codename_ver = 'xenial'
 
-        if (hpccm.config.g_linux_version >= StrictVersion('22.0') and
-            hpccm.config.g_linux_version < StrictVersion('23.0')):
+        if (hpccm.config.g_linux_version >= Version('22.0') and
+            hpccm.config.g_linux_version < Version('23.0')):
             codename = 'jammy'
             if self.__version == self.__trunk_version:
                 codename_ver = 'jammy'
             else:
                 codename_ver = 'jammy-{}'.format(self.__version)
-        elif (hpccm.config.g_linux_version >= StrictVersion('20.0') and
-            hpccm.config.g_linux_version < StrictVersion('21.0')):
+        elif (hpccm.config.g_linux_version >= Version('20.0') and
+            hpccm.config.g_linux_version < Version('21.0')):
             codename = 'focal'
             if self.__version == self.__trunk_version:
                 codename_ver = 'focal'
             else:
                 codename_ver = 'focal-{}'.format(self.__version)
-        elif (hpccm.config.g_linux_version >= StrictVersion('18.0') and
-            hpccm.config.g_linux_version < StrictVersion('19.0')):
+        elif (hpccm.config.g_linux_version >= Version('18.0') and
+            hpccm.config.g_linux_version < Version('19.0')):
             codename = 'bionic'
             if self.__version == self.__trunk_version:
                 codename_ver = 'bionic'
             else:
                 codename_ver = 'bionic-{}'.format(self.__version)
-        elif (hpccm.config.g_linux_version >= StrictVersion('16.0') and
-              hpccm.config.g_linux_version < StrictVersion('17.0')):
+        elif (hpccm.config.g_linux_version >= Version('16.0') and
+              hpccm.config.g_linux_version < Version('17.0')):
             codename = 'xenial'
             if self.__version == self.__trunk_version:
                 codename_ver = 'xenial'
diff --git a/hpccm/building_blocks/mlnx_ofed.py b/hpccm/building_blocks/mlnx_ofed.py
index 8b8a88bd..8f2f1707 100644
--- a/hpccm/building_blocks/mlnx_ofed.py
+++ b/hpccm/building_blocks/mlnx_ofed.py
@@ -20,7 +20,7 @@
 from __future__ import unicode_literals
 from __future__ import print_function
 
-from distutils.version import LooseVersion, StrictVersion
+from packaging.version import Version
 import posixpath
 
 import hpccm.config
@@ -163,22 +163,29 @@ def __distro(self):
         """Based on the Linux distribution, set values accordingly.  A user
            specified value overrides any defaults."""
 
+        # packaging.version.Version cannot handle version strings like
+        # 5.0-1.2.3.4.  Only the part before the dash is needed, so
+        # get the first half.
+        version_nodash = self.__version
+        if '-' in self.__version:
+            version_nodash = self.__version.split('-')[0]
+
         if hpccm.config.g_linux_distro == linux_distro.UBUNTU:
             self.__deppackages = ['libnl-3-200', 'libnl-route-3-200',
                                  'libnuma1']
 
             if not self.__oslabel:
-                if hpccm.config.g_linux_version >= StrictVersion('22.0'):
+                if hpccm.config.g_linux_version >= Version('22.0'):
                     self.__oslabel = 'ubuntu22.04'
-                elif hpccm.config.g_linux_version >= StrictVersion('20.0'):
+                elif hpccm.config.g_linux_version >= Version('20.0'):
                     self.__oslabel = 'ubuntu20.04'
-                elif hpccm.config.g_linux_version >= StrictVersion('18.0'):
+                elif hpccm.config.g_linux_version >= Version('18.0'):
                     self.__oslabel = 'ubuntu18.04'
                 else:
                     self.__oslabel = 'ubuntu16.04'
 
             if not self.__packages:
-                if LooseVersion(self.__version) >= LooseVersion('5.0'):
+                if Version(version_nodash) >= Version('5.0'):
                     # Uses UPSTREAM libs
                     self.__packages = ['libibverbs1', 'libibverbs-dev',
                                        'ibverbs-providers', 'ibverbs-utils',
@@ -196,13 +203,13 @@ def __distro(self):
                                        'librdmacm-dev', 'librdmacm1']
 
         elif hpccm.config.g_linux_distro == linux_distro.CENTOS:
-            if hpccm.config.g_linux_version >= StrictVersion('8.0'):
+            if hpccm.config.g_linux_version >= Version('8.0'):
                 self.__deppackages = ['libnl3', 'numactl-libs']
             else:
                 self.__deppackages = ['libnl', 'libnl3', 'numactl-libs']
 
             if not self.__oslabel:
-                if hpccm.config.g_linux_version >= StrictVersion('8.0'):
+                if hpccm.config.g_linux_version >= Version('8.0'):
                     self.__oslabel = 'rhel8.0'
                 else:
                     if hpccm.config.g_cpu_arch == cpu_arch.AARCH64:
@@ -211,7 +218,7 @@ def __distro(self):
                         self.__oslabel = 'rhel7.2'
 
             if not self.__packages:
-                if LooseVersion(self.__version) >= LooseVersion('5.0'):
+                if Version(version_nodash) >= Version('5.0'):
                     # Uses UPSTREAM libs
                     self.__packages = ['libibverbs', 'libibverbs-utils',
                                        'libibumad', 'librdmacm',
diff --git a/hpccm/building_blocks/multi_ofed.py b/hpccm/building_blocks/multi_ofed.py
index 745e63f3..c7cce017 100644
--- a/hpccm/building_blocks/multi_ofed.py
+++ b/hpccm/building_blocks/multi_ofed.py
@@ -20,7 +20,7 @@
 from __future__ import unicode_literals
 from __future__ import print_function
 
-from distutils.version import StrictVersion
+from packaging.version import Version
 import posixpath
 
 import hpccm.config
@@ -120,7 +120,7 @@ def __distro(self):
                                      'libnuma1']
         elif hpccm.config.g_linux_distro == linux_distro.CENTOS:
             if not self.__ospackages:
-                if hpccm.config.g_linux_version >= StrictVersion('8.0'):
+                if hpccm.config.g_linux_version >= Version('8.0'):
                     self.__ospackages = ['libnl3', 'numactl-libs']
                 else:
                     self.__ospackages = ['libnl', 'libnl3', 'numactl-libs']
diff --git a/hpccm/building_blocks/nccl.py b/hpccm/building_blocks/nccl.py
index 1c8ca174..be86250a 100644
--- a/hpccm/building_blocks/nccl.py
+++ b/hpccm/building_blocks/nccl.py
@@ -21,7 +21,7 @@
 from __future__ import unicode_literals
 from __future__ import print_function
 
-from distutils.version import StrictVersion
+from packaging.version import Version
 import posixpath
 
 import hpccm.templates.downloader
@@ -192,13 +192,13 @@ def __distro(self):
                 self.__ospackages = ['apt-transport-https', 'ca-certificates',
                                      'gnupg', 'wget']
 
-            if hpccm.config.g_linux_version >= StrictVersion('18.0'):
+            if hpccm.config.g_linux_version >= Version('18.0'):
                 self.__distro_label = 'ubuntu1804'
             else:
                 self.__distro_label = 'ubuntu1604'
 
         elif hpccm.config.g_linux_distro == linux_distro.CENTOS:
-            if hpccm.config.g_linux_version >= StrictVersion('8.0'):
+            if hpccm.config.g_linux_version >= Version('8.0'):
                 self.__distro_label = 'rhel8'
             else:
                 self.__distro_label = 'rhel7'
diff --git a/hpccm/building_blocks/netcdf.py b/hpccm/building_blocks/netcdf.py
index 399d1d25..23440cd7 100644
--- a/hpccm/building_blocks/netcdf.py
+++ b/hpccm/building_blocks/netcdf.py
@@ -21,7 +21,7 @@
 from __future__ import unicode_literals
 from __future__ import print_function
 
-from distutils.version import LooseVersion
+from packaging.version import Version
 import posixpath
 
 import hpccm.config
@@ -230,7 +230,7 @@ def __download(self):
         """Set download source based on user parameters"""
 
         # Version 4.3.1 changed the package name
-        if LooseVersion(self.__version) >= LooseVersion('4.3.1'):
+        if Version(self.__version) >= Version('4.3.1'):
             pkgname = 'netcdf-c'
             tarball = 'v{0}.tar.gz'.format(self.__version)
         else:
diff --git a/hpccm/building_blocks/nsight_compute.py b/hpccm/building_blocks/nsight_compute.py
index 58ebac02..c4898c46 100644
--- a/hpccm/building_blocks/nsight_compute.py
+++ b/hpccm/building_blocks/nsight_compute.py
@@ -22,7 +22,7 @@
 from __future__ import print_function
 import os
 
-from distutils.version import StrictVersion
+from packaging.version import Version
 import posixpath
 
 import hpccm.config
@@ -149,11 +149,11 @@ def __distro(self):
                     self.__ospackages = ['apt-transport-https',
                                          'ca-certificates', 'gnupg', 'wget']
 
-            if hpccm.config.g_linux_version >= StrictVersion('22.04'):
+            if hpccm.config.g_linux_version >= Version('22.04'):
                 self.__distro_label = 'ubuntu2204'
-            elif hpccm.config.g_linux_version >= StrictVersion('20.04'):
+            elif hpccm.config.g_linux_version >= Version('20.04'):
                 self.__distro_label = 'ubuntu2004'
-            elif hpccm.config.g_linux_version >= StrictVersion('18.0'):
+            elif hpccm.config.g_linux_version >= Version('18.0'):
                 self.__distro_label = 'ubuntu1804'
             else:
                 self.__distro_label = 'ubuntu1604'
@@ -163,7 +163,7 @@ def __distro(self):
                 if self.__runfile:
                     self.__ospackages = ['perl', 'perl-Env', 'wget']
 
-            if hpccm.config.g_linux_version >= StrictVersion('8.0'):
+            if hpccm.config.g_linux_version >= Version('8.0'):
                 self.__distro_label = 'rhel8'
             else:
                 self.__distro_label = 'rhel7'
diff --git a/hpccm/building_blocks/nsight_systems.py b/hpccm/building_blocks/nsight_systems.py
index be733ae9..20f2f173 100644
--- a/hpccm/building_blocks/nsight_systems.py
+++ b/hpccm/building_blocks/nsight_systems.py
@@ -21,7 +21,7 @@
 from __future__ import unicode_literals
 from __future__ import print_function
 
-from distutils.version import StrictVersion
+from packaging.version import Version
 
 import hpccm.config
 
@@ -122,17 +122,17 @@ def __distro(self):
                 self.__ospackages = ['apt-transport-https', 'ca-certificates',
                                      'gnupg', 'wget']
 
-            if hpccm.config.g_linux_version >= StrictVersion('22.04'):
+            if hpccm.config.g_linux_version >= Version('22.04'):
                 self.__distro_label = 'ubuntu2204'
-            elif hpccm.config.g_linux_version >= StrictVersion('20.04'):
+            elif hpccm.config.g_linux_version >= Version('20.04'):
                 self.__distro_label = 'ubuntu2004'
-            elif hpccm.config.g_linux_version >= StrictVersion('18.0'):
+            elif hpccm.config.g_linux_version >= Version('18.0'):
                 self.__distro_label = 'ubuntu1804'
             else:
                 self.__distro_label = 'ubuntu1604'
 
         elif hpccm.config.g_linux_distro == linux_distro.CENTOS:
-            if hpccm.config.g_linux_version >= StrictVersion('8.0'):
+            if hpccm.config.g_linux_version >= Version('8.0'):
                 self.__distro_label = 'rhel8'
             else:
                 self.__distro_label = 'rhel7'
diff --git a/hpccm/building_blocks/nvhpc.py b/hpccm/building_blocks/nvhpc.py
index 64d30beb..e4e71d80 100644
--- a/hpccm/building_blocks/nvhpc.py
+++ b/hpccm/building_blocks/nvhpc.py
@@ -20,7 +20,7 @@
 from __future__ import unicode_literals
 from __future__ import print_function
 
-from distutils.version import StrictVersion
+from packaging.version import Version
 import logging
 import re
 import posixpath
@@ -182,27 +182,27 @@ def __init__(self, **kwargs):
         self.toolchain = toolchain(CC='nvc', CXX='nvc++', F77='nvfortran',
                                    F90='nvfortran', FC='nvfortran')
 
-        if StrictVersion(self.__version) >= StrictVersion('23.7'):
+        if Version(self.__version) >= Version('23.7'):
             self.__cuda_version_default = '12.2'
-        elif StrictVersion(self.__version) >= StrictVersion('23.5'):
+        elif Version(self.__version) >= Version('23.5'):
             self.__cuda_version_default = '12.1'
-        if StrictVersion(self.__version) >= StrictVersion('23.1'):
+        if Version(self.__version) >= Version('23.1'):
             self.__cuda_version_default = '12.0'
-        elif StrictVersion(self.__version) >= StrictVersion('22.11'):
+        elif Version(self.__version) >= Version('22.11'):
             self.__cuda_version_default = '11.8'
-        elif StrictVersion(self.__version) >= StrictVersion('22.5'):
+        elif Version(self.__version) >= Version('22.5'):
             self.__cuda_version_default = '11.7'
-        elif StrictVersion(self.__version) >= StrictVersion('22.2'):
+        elif Version(self.__version) >= Version('22.2'):
             self.__cuda_version_default = '11.6'
-        elif StrictVersion(self.__version) >= StrictVersion('21.11'):
+        elif Version(self.__version) >= Version('21.11'):
             self.__cuda_version_default = '11.5'
-        elif StrictVersion(self.__version) >= StrictVersion('21.7'):
+        elif Version(self.__version) >= Version('21.7'):
             self.__cuda_version_default = '11.4'
-        elif StrictVersion(self.__version) >= StrictVersion('21.5'):
+        elif Version(self.__version) >= Version('21.5'):
             self.__cuda_version_default = '11.3'
-        elif StrictVersion(self.__version) >= StrictVersion('21.2'):
+        elif Version(self.__version) >= Version('21.2'):
             self.__cuda_version_default = '11.2'
-        elif StrictVersion(self.__version) >= StrictVersion('20.11'):
+        elif Version(self.__version) >= Version('20.11'):
             self.__cuda_version_default = '11.1'
         else:
             self.__cuda_version_default = '11.0'
@@ -249,7 +249,7 @@ def __instructions(self):
             self += shell(commands=self.__commands)
         else:
             # repository install
-            if StrictVersion(self.__version) >= StrictVersion('22.9'):
+            if Version(self.__version) >= Version('22.9'):
                 # signed packages
                 self += packages(
                     apt_keys=['https://developer.download.nvidia.com/hpc-sdk/ubuntu/DEB-GPG-KEY-NVIDIA-HPC-SDK'],
@@ -292,7 +292,7 @@ def __cpu_arch(self):
                 self.__arch_label = 'arm64'
             else:
                 self.__arch_label = 'aarch64'
-            if StrictVersion(self.__version) < StrictVersion('20.11'):
+            if Version(self.__version) < Version('20.11'):
                 self.__cuda_multi = False # CUDA multi packages not available
         elif hpccm.config.g_cpu_arch == cpu_arch.PPC64LE:
             self.__arch_directory = 'Linux_ppc64le'
@@ -395,20 +395,20 @@ def __environment(self):
                 posixpath.join(self.__basepath, 'comm_libs', 'mpi', 'lib'))
             path.append(
                 posixpath.join(self.__basepath, 'comm_libs', 'mpi', 'bin'))
-        elif self.__hpcx and StrictVersion(self.__version) >= StrictVersion('23.5'):
+        elif self.__hpcx and Version(self.__version) >= Version('23.5'):
             path.append(
                 posixpath.join(self.__basepath, 'comm_libs', 'hpcx', 'bin'))
         elif self.__hpcx:
             # Set environment for HPC-X
-            if StrictVersion(self.__version) >= StrictVersion('22.2'):
+            if Version(self.__version) >= Version('22.2'):
                 hpcx_version = 'latest'
-            elif StrictVersion(self.__version) >= StrictVersion('21.11'):
+            elif Version(self.__version) >= Version('21.11'):
                 hpcx_version = 'hpcx-2.10.beta'
-            elif StrictVersion(self.__version) >= StrictVersion('21.9'):
+            elif Version(self.__version) >= Version('21.9'):
                 hpcx_version = 'hpcx-2.9.0'
-            elif StrictVersion(self.__version) >= StrictVersion('21.7'):
+            elif Version(self.__version) >= Version('21.7'):
                 hpcx_version = 'hpcx-2.8.1'
-            elif StrictVersion(self.__version) < StrictVersion('21.5'):
+            elif Version(self.__version) < Version('21.5'):
               hpcx_version = 'hpcx-2.7.4'
             hpcx_dir = posixpath.join(self.__basepath, 'comm_libs', 'hpcx',
                                       hpcx_version)
diff --git a/hpccm/building_blocks/ofed.py b/hpccm/building_blocks/ofed.py
index fbae5de4..a3b90b50 100644
--- a/hpccm/building_blocks/ofed.py
+++ b/hpccm/building_blocks/ofed.py
@@ -20,7 +20,7 @@
 from __future__ import unicode_literals
 from __future__ import print_function
 
-from distutils.version import StrictVersion
+from packaging.version import Version
 import posixpath
 
 import hpccm.config
@@ -110,12 +110,12 @@ def __distro(self):
             self.__deppackages = ['libnl-3-200', 'libnl-route-3-200',
                                  'libnuma1']
 
-            if hpccm.config.g_linux_version >= StrictVersion('18.0'):
+            if hpccm.config.g_linux_version >= Version('18.0'):
                 # Give priority to packages from the Ubuntu repositories over
                 # vendor repositories
-                if hpccm.config.g_linux_version >= StrictVersion('22.0'):
+                if hpccm.config.g_linux_version >= Version('22.0'):
                     self.__extra_opts = ['-t jammy']
-                elif hpccm.config.g_linux_version >= StrictVersion('20.0'):
+                elif hpccm.config.g_linux_version >= Version('20.0'):
                     self.__extra_opts = ['-t focal']
                 else:
                     self.__extra_opts = ['-t bionic']
@@ -158,7 +158,7 @@ def __distro(self):
         elif hpccm.config.g_linux_distro == linux_distro.CENTOS:
             self.__extra_opts = [r'--disablerepo=mlnx\*']
 
-            if hpccm.config.g_linux_version >= StrictVersion('8.0'):
+            if hpccm.config.g_linux_version >= Version('8.0'):
                 self.__deppackages = ['libnl3', 'numactl-libs']
                 self.__ospackages = ['libibmad', 'libibmad-devel',
                                      'libibumad', 'libibverbs',
diff --git a/hpccm/building_blocks/pgi.py b/hpccm/building_blocks/pgi.py
index b4ad08f4..2f24e6ff 100644
--- a/hpccm/building_blocks/pgi.py
+++ b/hpccm/building_blocks/pgi.py
@@ -20,7 +20,7 @@
 from __future__ import unicode_literals
 from __future__ import print_function
 
-from distutils.version import LooseVersion
+from packaging.version import Version
 import logging # pylint: disable=unused-import
 import re
 import posixpath
@@ -219,7 +219,7 @@ def __environment(self, runtime=False):
 
         pgi_path = posixpath.join(self.__basepath, self.__version)
         mpi_path = posixpath.join(pgi_path, 'mpi', 'openmpi')
-        if LooseVersion(self.__version) >= LooseVersion('19.4'):
+        if Version(self.__version) >= Version('19.4'):
             mpi_path = posixpath.join(pgi_path, 'mpi', 'openmpi-3.1.3')
 
         if runtime:
@@ -396,7 +396,7 @@ def runtime(self, _from='0'):
 
         pgi_path = posixpath.join(self.__basepath, self.__version)
         src_path = pgi_path
-        if (LooseVersion(self.__version) >= LooseVersion('19.4') and
+        if (Version(self.__version) >= Version('19.4') and
             hpccm.config.g_cpu_arch == cpu_arch.X86_64):
             # Too many levels of symlinks for the Docker builder to
             # handle, so use the real path
@@ -407,8 +407,8 @@ def runtime(self, _from='0'):
 
         # REDIST workaround for incorrect libcudaforwrapblas.so
         # symlink
-        if (LooseVersion(self.__version) >= LooseVersion('18.10') and
-            LooseVersion(self.__version) < LooseVersion('19.10') and
+        if (Version(self.__version) >= Version('18.10') and
+            Version(self.__version) < Version('19.10') and
             hpccm.config.g_cpu_arch == cpu_arch.X86_64):
             self.rt += copy(_from=_from,
                             src=posixpath.join(pgi_path, 'lib',
@@ -418,7 +418,7 @@ def runtime(self, _from='0'):
 
         if self.__mpi:
             mpi_path = posixpath.join(pgi_path, 'mpi', 'openmpi')
-            if LooseVersion(self.__version) >= LooseVersion('19.4'):
+            if Version(self.__version) >= Version('19.4'):
                 mpi_path = posixpath.join(pgi_path, 'mpi', 'openmpi-3.1.3')
             self.rt += copy(_from=_from, src=mpi_path, dest=mpi_path)
 
diff --git a/hpccm/building_blocks/pip.py b/hpccm/building_blocks/pip.py
index f1587141..b1ba4a0d 100644
--- a/hpccm/building_blocks/pip.py
+++ b/hpccm/building_blocks/pip.py
@@ -21,7 +21,7 @@
 from __future__ import unicode_literals
 from __future__ import print_function
 
-from distutils.version import StrictVersion
+from packaging.version import Version
 import logging
 import posixpath
 
@@ -109,11 +109,11 @@ def __init__(self, **kwargs):
                                     'python-wheel'])
                 self.__rpms.append('python2-pip')
                 if (hpccm.config.g_linux_distro == linux_distro.CENTOS and
-                    hpccm.config.g_linux_version < StrictVersion('8.0')):
+                    hpccm.config.g_linux_version < Version('8.0')):
                     # python2-pip is an EPEL package in CentOS 7.x
                     self.__epel = True
                 elif (hpccm.config.g_linux_distro == linux_distro.UBUNTU and
-                      hpccm.config.g_linux_version >= StrictVersion('20.0')):
+                      hpccm.config.g_linux_version >= Version('20.0')):
                     # python-pip is not supported in Ubuntu 20.04
                     logging.warning('pip2 is not supported in Ubuntu 20.04.  Use pip3.')
         elif self.__ospackages:
diff --git a/hpccm/building_blocks/pnetcdf.py b/hpccm/building_blocks/pnetcdf.py
index 8bf05fb9..f67ee640 100644
--- a/hpccm/building_blocks/pnetcdf.py
+++ b/hpccm/building_blocks/pnetcdf.py
@@ -21,7 +21,7 @@
 from __future__ import unicode_literals
 from __future__ import print_function
 
-from distutils.version import LooseVersion
+from packaging.version import Version
 import posixpath
 
 import hpccm.config
@@ -183,7 +183,7 @@ def __download(self):
         """Set download source based on user parameters"""
 
         # Version 1.11.0 changed the package name
-        if LooseVersion(self.__version) >= LooseVersion('1.11.0'):
+        if Version(self.__version) >= Version('1.11.0'):
             pkgname = 'pnetcdf'
         else:
             pkgname = 'parallel-netcdf'
diff --git a/hpccm/building_blocks/python.py b/hpccm/building_blocks/python.py
index 62843c28..08430eae 100644
--- a/hpccm/building_blocks/python.py
+++ b/hpccm/building_blocks/python.py
@@ -21,7 +21,7 @@
 from __future__ import unicode_literals
 from __future__ import print_function
 
-from distutils.version import StrictVersion
+from packaging.version import Version
 
 import hpccm.config
 
@@ -75,7 +75,7 @@ def __init__(self, **kwargs):
 
         if self.__python2:
             if (hpccm.config.g_linux_distro == linux_distro.UBUNTU and
-                hpccm.config.g_linux_version >= StrictVersion('22.0')):
+                hpccm.config.g_linux_version >= Version('22.0')):
                 self.__debs.append('python2')
             else:
                 self.__debs.append('python')
@@ -83,7 +83,7 @@ def __init__(self, **kwargs):
 
             if self.__devel:
                 if (hpccm.config.g_linux_distro == linux_distro.UBUNTU and
-                    hpccm.config.g_linux_version >= StrictVersion('22.0')):
+                    hpccm.config.g_linux_version >= Version('22.0')):
                     self.__debs.append('python2-dev')
                 else:
                     self.__debs.append('python-dev')
diff --git a/hpccm/building_blocks/rdma_core.py b/hpccm/building_blocks/rdma_core.py
index 6bb47807..33cf6b12 100644
--- a/hpccm/building_blocks/rdma_core.py
+++ b/hpccm/building_blocks/rdma_core.py
@@ -23,7 +23,7 @@
 
 from six import string_types
 
-from distutils.version import StrictVersion
+from packaging.version import Version
 import posixpath
 
 import hpccm.config
@@ -190,7 +190,7 @@ def __distro(self):
                 self.__ospackages = ['libnl3-devel', 'libudev-devel', 'make',
                                      'pkgconfig', 'pandoc', 'wget']
 
-                if hpccm.config.g_linux_version >= StrictVersion('8.0'):
+                if hpccm.config.g_linux_version >= Version('8.0'):
                     self.__ospackages.append('python3-docutils')
                 else:
                     self.__ospackages.append('python-docutils')
diff --git a/hpccm/building_blocks/ucx.py b/hpccm/building_blocks/ucx.py
index 3c82a161..f95edb66 100644
--- a/hpccm/building_blocks/ucx.py
+++ b/hpccm/building_blocks/ucx.py
@@ -23,7 +23,7 @@
 
 from six import string_types
 
-from distutils.version import StrictVersion
+from packaging.version import Version
 import posixpath
 
 import hpccm.config
@@ -347,7 +347,7 @@ def __distro(self):
                                               'ca-certificates', 'git',
                                               'libtool'])
 
-            if hpccm.config.g_linux_version >= StrictVersion('18.0'):
+            if hpccm.config.g_linux_version >= Version('18.0'):
                 self.__runtime_ospackages = ['libbinutils']
             else:
                 self.__runtime_ospackages = ['binutils']
diff --git a/hpccm/building_blocks/yum.py b/hpccm/building_blocks/yum.py
index 26fd6879..7063c1ef 100644
--- a/hpccm/building_blocks/yum.py
+++ b/hpccm/building_blocks/yum.py
@@ -20,7 +20,7 @@
 from __future__ import unicode_literals
 from __future__ import print_function
 
-from distutils.version import StrictVersion
+from packaging.version import Version
 import logging # pylint: disable=unused-import
 import posixpath
 
@@ -153,7 +153,7 @@ def __setup(self):
         # Use yum version 4 is requested.  yum 4 is the default on
         # CentOS 8.
         yum = 'yum'
-        if self.__yum4 and hpccm.config.g_linux_version < StrictVersion('8.0'):
+        if self.__yum4 and hpccm.config.g_linux_version < Version('8.0'):
             self.__commands.append('yum install -y nextgen-yum4')
             yum = 'yum4'
 
@@ -163,7 +163,7 @@ def __setup(self):
 
         if self.__repositories:
             # Need yum-config-manager
-            if hpccm.config.g_linux_version >= StrictVersion('8.0'):
+            if hpccm.config.g_linux_version >= Version('8.0'):
                 # CentOS 8
                 self.__commands.append('yum install -y dnf-utils')
             else:
@@ -184,7 +184,7 @@ def __setup(self):
             self.__commands.append('yum install -y epel-release')
 
         if (self.__powertools and
-            hpccm.config.g_linux_version >= StrictVersion('8.0')):
+            hpccm.config.g_linux_version >= Version('8.0')):
             # This needs to be a discrete, preliminary step so that
             # packages from PowerTools are available to be installed.
             if not self.__repositories:
@@ -194,13 +194,13 @@ def __setup(self):
             self.__commands.append('yum-config-manager --set-enabled powertools')
 
         if (self.__release_stream and
-            hpccm.config.g_linux_version >= StrictVersion('8.0')):
+            hpccm.config.g_linux_version >= Version('8.0')):
             # This needs to be a discrete, preliminary step so that
             # packages from release stream are available to be installed.
             self.__commands.append('yum install -y centos-release-stream')
 
         if (self.__scl and
-            hpccm.config.g_linux_version < StrictVersion('8.0')):
+            hpccm.config.g_linux_version < Version('8.0')):
             # This needs to be a discrete, preliminary step so that
             # packages from SCL are available to be installed.
             self.__commands.append('yum install -y centos-release-scl')
diff --git a/hpccm/config.py b/hpccm/config.py
index 4023ed3e..b14e6164 100644
--- a/hpccm/config.py
+++ b/hpccm/config.py
@@ -22,7 +22,7 @@
 
 from __future__ import absolute_import
 
-from distutils.version import StrictVersion
+from packaging.version import Version
 import archspec.cpu
 import logging
 import platform
@@ -41,8 +41,8 @@
 g_cpu_target = None                  # CPU optimization target
 g_ctype = container_type.DOCKER      # Container type
 g_linux_distro = linux_distro.UBUNTU # Linux distribution
-g_linux_version = StrictVersion('16.04') # Linux distribution version
-g_singularity_version = StrictVersion('2.6') # Singularity version
+g_linux_version = Version('16.04') # Linux distribution version
+g_singularity_version = Version('2.6') # Singularity version
 g_wd = '/var/tmp' # Working directory
 
 def get_cpu_architecture():
@@ -182,44 +182,44 @@ def set_linux_distro(distro):
   this = sys.modules[__name__]
   if distro == 'centos':
     this.g_linux_distro = linux_distro.CENTOS
-    this.g_linux_version = StrictVersion('7.0')
+    this.g_linux_version = Version('7.0')
   elif distro == 'centos7':
     this.g_linux_distro = linux_distro.CENTOS
-    this.g_linux_version = StrictVersion('7.0')
+    this.g_linux_version = Version('7.0')
   elif distro == 'centos8':
     this.g_linux_distro = linux_distro.CENTOS
-    this.g_linux_version = StrictVersion('8.0')
+    this.g_linux_version = Version('8.0')
   elif distro == 'rhel':
     this.g_linux_distro = linux_distro.RHEL
-    this.g_linux_version = StrictVersion('7.0')
+    this.g_linux_version = Version('7.0')
   elif distro == 'rhel7':
     this.g_linux_distro = linux_distro.RHEL
-    this.g_linux_version = StrictVersion('7.0')
+    this.g_linux_version = Version('7.0')
   elif distro == 'rhel8':
     this.g_linux_distro = linux_distro.RHEL
-    this.g_linux_version = StrictVersion('8.0')
+    this.g_linux_version = Version('8.0')
   elif distro == 'rockylinux8':
     this.g_linux_distro = linux_distro.ROCKYLINUX
-    this.g_linux_version = StrictVersion('8.0')
+    this.g_linux_version = Version('8.0')
   elif distro == 'ubuntu':
     this.g_linux_distro = linux_distro.UBUNTU
-    this.g_linux_version = StrictVersion('16.04')
+    this.g_linux_version = Version('16.04')
   elif distro == 'ubuntu16':
     this.g_linux_distro = linux_distro.UBUNTU
-    this.g_linux_version = StrictVersion('16.04')
+    this.g_linux_version = Version('16.04')
   elif distro == 'ubuntu18':
     this.g_linux_distro = linux_distro.UBUNTU
-    this.g_linux_version = StrictVersion('18.04')
+    this.g_linux_version = Version('18.04')
   elif distro == 'ubuntu20':
     this.g_linux_distro = linux_distro.UBUNTU
-    this.g_linux_version = StrictVersion('20.04')
+    this.g_linux_version = Version('20.04')
   elif distro == 'ubuntu22':
     this.g_linux_distro = linux_distro.UBUNTU
-    this.g_linux_version = StrictVersion('22.04')
+    this.g_linux_version = Version('22.04')
   else:
     logging.warning('Unable to determine the Linux distribution, defaulting to Ubuntu')
     this.g_linux_distro = linux_distro.UBUNTU
-    this.g_linux_version = StrictVersion('16.04')
+    this.g_linux_version = Version('16.04')
 
 def set_singularity_version(ver):
   """Set the Singularity definition file format version
@@ -234,7 +234,7 @@ def set_singularity_version(ver):
 
   """
   this = sys.modules[__name__]
-  this.g_singularity_version = StrictVersion(ver)
+  this.g_singularity_version = Version(ver)
 
 def set_working_directory(wd):
   """Set the working directory to use for staging inside the container
diff --git a/hpccm/primitives/baseimage.py b/hpccm/primitives/baseimage.py
index ec315624..dd3e47a4 100644
--- a/hpccm/primitives/baseimage.py
+++ b/hpccm/primitives/baseimage.py
@@ -20,7 +20,7 @@
 from __future__ import unicode_literals
 from __future__ import print_function
 
-from distutils.version import StrictVersion
+from packaging.version import Version
 import logging # pylint: disable=unused-import
 import re
 
@@ -175,7 +175,7 @@ def __str__(self):
                                                        self.image)
 
             if (self.__as and
-                hpccm.config.g_singularity_version >= StrictVersion('3.2')):
+                hpccm.config.g_singularity_version >= Version('3.2')):
                 image = image + '\nStage: {}'.format(self.__as)
 
                 image = str(comment('NOTE: this definition file depends on features only available in Singularity 3.2 and later.')) + '\n' + image
diff --git a/hpccm/primitives/copy.py b/hpccm/primitives/copy.py
index 3101cfef..11b6bfc9 100644
--- a/hpccm/primitives/copy.py
+++ b/hpccm/primitives/copy.py
@@ -20,7 +20,7 @@
 from __future__ import unicode_literals
 from __future__ import print_function
 
-from distutils.version import StrictVersion
+from packaging.version import Version
 import logging  # pylint: disable=unused-import
 import posixpath
 
@@ -174,7 +174,7 @@ def __str__(self):
             if (not self.__from and
                 any(f['dest'].startswith(('/var/tmp', '/tmp')) for f in files)):
                 msg = 'Singularity 3.6 and later no longer allow a temporary directory to be used to stage files into the container image.  Modify the recipe or, in many cases, use --working-directory or hpccm.config.set_working_directory() to specify another location.'
-                if hpccm.config.g_singularity_version >= StrictVersion('3.6'):
+                if hpccm.config.g_singularity_version >= Version('3.6'):
                     raise RuntimeError(msg)
                 else:
                     logging.warning(msg)
@@ -190,7 +190,7 @@ def __str__(self):
             #     src3 dest3
             section = '%files'
             if (self.__from and
-                hpccm.config.g_singularity_version >= StrictVersion('3.2')):
+                hpccm.config.g_singularity_version >= Version('3.2')):
                 section = section + ' from {}'.format(self.__from)
 
             if self._app:
diff --git a/hpccm/recipe.py b/hpccm/recipe.py
index 9de65ff8..b6f59b4d 100644
--- a/hpccm/recipe.py
+++ b/hpccm/recipe.py
@@ -21,7 +21,7 @@
 from __future__ import print_function
 from six import raise_from
 
-from distutils.version import StrictVersion
+from packaging.version import Version
 import logging
 import os
 import sys
@@ -139,7 +139,7 @@ def recipe(recipe_file, cpu_target=None, ctype=container_type.DOCKER,
     hpccm.config.g_ctype = ctype
 
     # Set the global Singularity version
-    hpccm.config.g_singularity_version = StrictVersion(singularity_version)
+    hpccm.config.g_singularity_version = Version(singularity_version)
 
     # Set the global working directory
     hpccm.config.g_wd = working_directory
@@ -158,7 +158,7 @@ def recipe(recipe_file, cpu_target=None, ctype=container_type.DOCKER,
         del stages[1:]
     elif len(Stage1) > 0:
         if (ctype == container_type.SINGULARITY and
-            hpccm.config.g_singularity_version < StrictVersion('3.2')):
+            hpccm.config.g_singularity_version < Version('3.2')):
             # Singularity prior to version 3.2 did not support
             # multi-stage builds.  If the Singularity version is not
             # sufficient to support multi-stage, provide advice to
diff --git a/recipes/lammps/lammps.py b/recipes/lammps/lammps.py
index c2085a9c..b9be02b3 100644
--- a/recipes/lammps/lammps.py
+++ b/recipes/lammps/lammps.py
@@ -15,10 +15,10 @@
 #  ucx (default: 1.6.1)
 ########
 
-from distutils.version import StrictVersion
+from packaging.version import Version
 import hpccm.version
 
-if StrictVersion(hpccm.__version__) < StrictVersion('19.11.0'):
+if Version(hpccm.__version__) < Version('19.11.0'):
   raise Exception('requires HPCCM version 19.11.0 or later')
 
 # Use appropriate container base images based on the CPU architecture
diff --git a/recipes/nvhpc.py b/recipes/nvhpc.py
index e8135ba2..4f7534ff 100644
--- a/recipes/nvhpc.py
+++ b/recipes/nvhpc.py
@@ -5,11 +5,11 @@
 
 $ hpccm --recipe nvhpc.py --userarg eula=yes cuda_multi=no arch=x86_64
 """
-from distutils.version import StrictVersion
+from packaging.version import Version
 import platform
 
 # Verify correct version of HPCCM is used
-if StrictVersion(hpccm.__version__) < StrictVersion('21.7.0'):
+if Version(hpccm.__version__) < Version('21.7.0'):
   raise RuntimeError('requires HPCCM version 21.7.0 or later')
 
 arch = USERARG.get('arch', platform.machine())
diff --git a/setup.py b/setup.py
index d70b9011..2f4067f3 100644
--- a/setup.py
+++ b/setup.py
@@ -39,7 +39,8 @@
       "Programming Language :: Python :: 3.6"
     ],
     # Make hpccm.cli.main available from the command line as `hpccm`.
-    install_requires=['archspec', "enum34; python_version < '3.4'", 'six'],
+    install_requires=['archspec', "enum34; python_version < '3.4'", 
+                      'packaging', 'six'],
     entry_points={
         'console_scripts': [
             'hpccm=hpccm.cli:main']})


Test patch:
diff --git a/test/helpers.py b/test/helpers.py
index 1659ebc5..3e9d706d 100644
--- a/test/helpers.py
+++ b/test/helpers.py
@@ -19,7 +19,7 @@
 from __future__ import unicode_literals
 from __future__ import print_function
 
-from distutils.version import StrictVersion
+from packaging.version import Version
 import logging # pylint: disable=unused-import
 
 import hpccm.config
@@ -54,7 +54,7 @@ def centos(function):
     """Decorator to set the Linux distribution to CentOS 7"""
     def wrapper(*args, **kwargs):
         hpccm.config.g_linux_distro = linux_distro.CENTOS
-        hpccm.config.g_linux_version = StrictVersion('7.0')
+        hpccm.config.g_linux_version = Version('7.0')
         return function(*args, **kwargs)
 
     return wrapper
@@ -63,7 +63,7 @@ def centos8(function):
     """Decorator to set the Linux distribution to CentOS 8"""
     def wrapper(*args, **kwargs):
         hpccm.config.g_linux_distro = linux_distro.CENTOS
-        hpccm.config.g_linux_version = StrictVersion('8.0')
+        hpccm.config.g_linux_version = Version('8.0')
         return function(*args, **kwargs)
 
     return wrapper
@@ -136,7 +136,7 @@ def singularity26(function):
     """Decorator to set the global singularity version"""
     def wrapper(*args, **kwargs):
         hpccm.config.g_ctype = container_type.SINGULARITY
-        hpccm.config.g_singularity_version = StrictVersion('2.6')
+        hpccm.config.g_singularity_version = Version('2.6')
         return function(*args, **kwargs)
 
     return wrapper
@@ -145,7 +145,7 @@ def singularity32(function):
     """Decorator to set the global singularity version"""
     def wrapper(*args, **kwargs):
         hpccm.config.g_ctype = container_type.SINGULARITY
-        hpccm.config.g_singularity_version = StrictVersion('3.2')
+        hpccm.config.g_singularity_version = Version('3.2')
         return function(*args, **kwargs)
 
     return wrapper
@@ -154,7 +154,7 @@ def singularity37(function):
     """Decorator to set the global singularity version"""
     def wrapper(*args, **kwargs):
         hpccm.config.g_ctype = container_type.SINGULARITY
-        hpccm.config.g_singularity_version = StrictVersion('3.7')
+        hpccm.config.g_singularity_version = Version('3.7')
         return function(*args, **kwargs)
 
     return wrapper
@@ -171,7 +171,7 @@ def ubuntu(function):
     """Decorator to set the Linux distribution to Ubuntu 16.04"""
     def wrapper(*args, **kwargs):
         hpccm.config.g_linux_distro = linux_distro.UBUNTU
-        hpccm.config.g_linux_version = StrictVersion('16.04')
+        hpccm.config.g_linux_version = Version('16.04')
         return function(*args, **kwargs)
 
     return wrapper
@@ -180,7 +180,7 @@ def ubuntu18(function):
     """Decorator to set the Linux distribution to Ubuntu 18.04"""
     def wrapper(*args, **kwargs):
         hpccm.config.g_linux_distro = linux_distro.UBUNTU
-        hpccm.config.g_linux_version = StrictVersion('18.04')
+        hpccm.config.g_linux_version = Version('18.04')
         return function(*args, **kwargs)
 
     return wrapper
@@ -189,7 +189,7 @@ def ubuntu20(function):
     """Decorator to set the Linux distribution to Ubuntu 20.04"""
     def wrapper(*args, **kwargs):
         hpccm.config.g_linux_distro = linux_distro.UBUNTU
-        hpccm.config.g_linux_version = StrictVersion('20.04')
+        hpccm.config.g_linux_version = Version('20.04')
         return function(*args, **kwargs)
 
     return wrapper
@@ -198,7 +198,7 @@ def ubuntu22(function):
     """Decorator to set the Linux distribution to Ubuntu 22.04"""
     def wrapper(*args, **kwargs):
         hpccm.config.g_linux_distro = linux_distro.UBUNTU
-        hpccm.config.g_linux_version = StrictVersion('22.04')
+        hpccm.config.g_linux_version = Version('22.04')
         return function(*args, **kwargs)
 
     return wrapper
diff --git a/test/test_baseimage.py b/test/test_baseimage.py
index 1ae0083c..4774f427 100644
--- a/test/test_baseimage.py
+++ b/test/test_baseimage.py
@@ -24,7 +24,7 @@
 
 from helpers import bash, docker, invalid_ctype, singularity, singularity26, singularity32
 
-from distutils.version import StrictVersion
+from packaging.version import Version
 import hpccm.config
 
 from hpccm.primitives.baseimage import baseimage
@@ -144,91 +144,91 @@ def test_detect_ubuntu(self):
         """Base image Linux distribution detection"""
         b = baseimage(image='ubuntu:sixteen')
         self.assertEqual(hpccm.config.g_linux_distro, linux_distro.UBUNTU)
-        self.assertEqual(hpccm.config.g_linux_version, StrictVersion('16.04'))
+        self.assertEqual(hpccm.config.g_linux_version, Version('16.04'))
 
     @docker
     def test_detect_ubuntu16(self):
         """Base image Linux distribution detection"""
         b = baseimage(image='nvidia/cuda:9.0-devel-ubuntu16.04')
         self.assertEqual(hpccm.config.g_linux_distro, linux_distro.UBUNTU)
-        self.assertEqual(hpccm.config.g_linux_version, StrictVersion('16.04'))
+        self.assertEqual(hpccm.config.g_linux_version, Version('16.04'))
 
     @docker
     def test_detect_ubuntu18(self):
         """Base image Linux distribution detection"""
         b = baseimage(image='nvidia/cuda:9.2-devel-ubuntu18.04')
         self.assertEqual(hpccm.config.g_linux_distro, linux_distro.UBUNTU)
-        self.assertEqual(hpccm.config.g_linux_version, StrictVersion('18.04'))
+        self.assertEqual(hpccm.config.g_linux_version, Version('18.04'))
 
     @docker
     def test_detect_ubuntu20(self):
         """Base image Linux distribution detection"""
         b = baseimage(image='nvidia/cuda:11.0-devel-ubuntu20.04')
         self.assertEqual(hpccm.config.g_linux_distro, linux_distro.UBUNTU)
-        self.assertEqual(hpccm.config.g_linux_version, StrictVersion('20.04'))
+        self.assertEqual(hpccm.config.g_linux_version, Version('20.04'))
 
     @docker
     def test_detect_ubuntu_16(self):
         """Base image Linux distribution detection"""
         b = baseimage(image='ubuntu:16.04')
         self.assertEqual(hpccm.config.g_linux_distro, linux_distro.UBUNTU)
-        self.assertEqual(hpccm.config.g_linux_version, StrictVersion('16.04'))
+        self.assertEqual(hpccm.config.g_linux_version, Version('16.04'))
 
     @docker
     def test_detect_ubuntu_18(self):
         """Base image Linux distribution detection"""
         b = baseimage(image='ubuntu:18.04')
         self.assertEqual(hpccm.config.g_linux_distro, linux_distro.UBUNTU)
-        self.assertEqual(hpccm.config.g_linux_version, StrictVersion('18.04'))
+        self.assertEqual(hpccm.config.g_linux_version, Version('18.04'))
 
     @docker
     def test_detect_ubuntu_20(self):
         """Base image Linux distribution detection"""
         b = baseimage(image='ubuntu:20.04')
         self.assertEqual(hpccm.config.g_linux_distro, linux_distro.UBUNTU)
-        self.assertEqual(hpccm.config.g_linux_version, StrictVersion('20.04'))
+        self.assertEqual(hpccm.config.g_linux_version, Version('20.04'))
 
     @docker
     def test_detect_centos(self):
         """Base image Linux distribution detection"""
         b = baseimage(image='nvidia/cuda:9.0-devel-centos7')
         self.assertEqual(hpccm.config.g_linux_distro, linux_distro.CENTOS)
-        self.assertEqual(hpccm.config.g_linux_version, StrictVersion('7.0'))
+        self.assertEqual(hpccm.config.g_linux_version, Version('7.0'))
 
     @docker
     def test_detect_centos_7(self):
         """Base image Linux distribution detection"""
         b = baseimage(image='centos:7')
         self.assertEqual(hpccm.config.g_linux_distro, linux_distro.CENTOS)
-        self.assertEqual(hpccm.config.g_linux_version, StrictVersion('7.0'))
+        self.assertEqual(hpccm.config.g_linux_version, Version('7.0'))
 
     @docker
     def test_detect_centos_8(self):
         """Base image Linux distribution detection"""
         b = baseimage(image='centos:8')
         self.assertEqual(hpccm.config.g_linux_distro, linux_distro.CENTOS)
-        self.assertEqual(hpccm.config.g_linux_version, StrictVersion('8.0'))
+        self.assertEqual(hpccm.config.g_linux_version, Version('8.0'))
 
     @docker
     def test_detect_rockylinux_8(self):
         """Base image Linux distribution detection"""
         b = baseimage(image='rockylinux/rockylinux:8')
         self.assertEqual(hpccm.config.g_linux_distro, linux_distro.ROCKYLINUX)
-        self.assertEqual(hpccm.config.g_linux_version, StrictVersion('8.0'))
+        self.assertEqual(hpccm.config.g_linux_version, Version('8.0'))
 
     @docker
     def test_detect_ubi7(self):
         """Base image Linux distribution detection"""
         b = baseimage(image='nvidia/cuda:10.1-devel-ubi7')
         self.assertEqual(hpccm.config.g_linux_distro, linux_distro.RHEL)
-        self.assertEqual(hpccm.config.g_linux_version, StrictVersion('7.0'))
+        self.assertEqual(hpccm.config.g_linux_version, Version('7.0'))
 
     @docker
     def test_detect_ubi8(self):
         """Base image Linux distribution detection"""
         b = baseimage(image='nvidia/cuda:10.1-devel-ubi8')
         self.assertEqual(hpccm.config.g_linux_distro, linux_distro.RHEL)
-        self.assertEqual(hpccm.config.g_linux_version, StrictVersion('8.0'))
+        self.assertEqual(hpccm.config.g_linux_version, Version('8.0'))
 
     @docker
     def test_detect_nonexistent(self):
@@ -243,7 +243,7 @@ def test_detect_nonexistent(self):
 
         b = baseimage(image='nonexistent')
         self.assertEqual(hpccm.config.g_linux_distro, linux_distro.UBUNTU)
-        self.assertEqual(hpccm.config.g_linux_version, StrictVersion('16.04'))
+        self.assertEqual(hpccm.config.g_linux_version, Version('16.04'))
         self.assertEqual(hpccm.config.g_cpu_arch, gold)
 
     @docker
@@ -251,56 +251,56 @@ def test_distro_ubuntu(self):
         """Base image Linux distribution specification"""
         b = baseimage(image='foo', _distro='ubuntu')
         self.assertEqual(hpccm.config.g_linux_distro, linux_distro.UBUNTU)
-        self.assertEqual(hpccm.config.g_linux_version, StrictVersion('16.04'))
+        self.assertEqual(hpccm.config.g_linux_version, Version('16.04'))
 
     @docker
     def test_distro_ubuntu16(self):
         """Base image Linux distribution specification"""
         b = baseimage(image='foo', _distro='ubuntu16')
         self.assertEqual(hpccm.config.g_linux_distro, linux_distro.UBUNTU)
-        self.assertEqual(hpccm.config.g_linux_version, StrictVersion('16.04'))
+        self.assertEqual(hpccm.config.g_linux_version, Version('16.04'))
 
     @docker
     def test_distro_ubuntu18(self):
         """Base image Linux distribution specification"""
         b = baseimage(image='foo', _distro='ubuntu18')
         self.assertEqual(hpccm.config.g_linux_distro, linux_distro.UBUNTU)
-        self.assertEqual(hpccm.config.g_linux_version, StrictVersion('18.04'))
+        self.assertEqual(hpccm.config.g_linux_version, Version('18.04'))
 
     @docker
     def test_distro_ubuntu20(self):
         """Base image Linux distribution specification"""
         b = baseimage(image='foo', _distro='ubuntu20')
         self.assertEqual(hpccm.config.g_linux_distro, linux_distro.UBUNTU)
-        self.assertEqual(hpccm.config.g_linux_version, StrictVersion('20.04'))
+        self.assertEqual(hpccm.config.g_linux_version, Version('20.04'))
 
     @docker
     def test_distro_centos(self):
         """Base image Linux distribution specification"""
         b = baseimage(image='foo', _distro='centos')
         self.assertEqual(hpccm.config.g_linux_distro, linux_distro.CENTOS)
-        self.assertEqual(hpccm.config.g_linux_version, StrictVersion('7.0'))
+        self.assertEqual(hpccm.config.g_linux_version, Version('7.0'))
 
     @docker
     def test_distro_centos7(self):
         """Base image Linux distribution specification"""
         b = baseimage(image='foo', _distro='centos7')
         self.assertEqual(hpccm.config.g_linux_distro, linux_distro.CENTOS)
-        self.assertEqual(hpccm.config.g_linux_version, StrictVersion('7.0'))
+        self.assertEqual(hpccm.config.g_linux_version, Version('7.0'))
 
     @docker
     def test_distro_centos8(self):
         """Base image Linux distribution specification"""
         b = baseimage(image='foo', _distro='centos8')
         self.assertEqual(hpccm.config.g_linux_distro, linux_distro.CENTOS)
-        self.assertEqual(hpccm.config.g_linux_version, StrictVersion('8.0'))
+        self.assertEqual(hpccm.config.g_linux_version, Version('8.0'))
 
     @docker
     def test_distro_nonexistent(self):
         """Base image Linux distribution specification"""
         b = baseimage(image='foo', _distro='nonexistent')
         self.assertEqual(hpccm.config.g_linux_distro, linux_distro.UBUNTU)
-        self.assertEqual(hpccm.config.g_linux_version, StrictVersion('16.04'))
+        self.assertEqual(hpccm.config.g_linux_version, Version('16.04'))
 
     @docker
     def test_detect_aarch64(self):
diff --git a/test/test_config.py b/test/test_config.py
index e54c735d..bd714962 100644
--- a/test/test_config.py
+++ b/test/test_config.py
@@ -19,7 +19,7 @@
 from __future__ import unicode_literals
 from __future__ import print_function
 
-from distutils.version import StrictVersion
+from packaging.version import Version
 import logging # pylint: disable=unused-import
 import unittest
 
@@ -56,17 +56,17 @@ def test_set_linux_distro_ubuntu(self):
         hpccm.config.set_linux_distro('ubuntu')
         self.assertEqual(hpccm.config.g_linux_distro,
                          hpccm.linux_distro.UBUNTU)
-        self.assertEqual(hpccm.config.g_linux_version, StrictVersion('16.04'))
+        self.assertEqual(hpccm.config.g_linux_version, Version('16.04'))
 
         hpccm.config.set_linux_distro('ubuntu16')
         self.assertEqual(hpccm.config.g_linux_distro,
                          hpccm.linux_distro.UBUNTU)
-        self.assertEqual(hpccm.config.g_linux_version, StrictVersion('16.04'))
+        self.assertEqual(hpccm.config.g_linux_version, Version('16.04'))
 
         hpccm.config.set_linux_distro('ubuntu18')
         self.assertEqual(hpccm.config.g_linux_distro,
                          hpccm.linux_distro.UBUNTU)
-        self.assertEqual(hpccm.config.g_linux_version, StrictVersion('18.04'))
+        self.assertEqual(hpccm.config.g_linux_version, Version('18.04'))
 
     @docker
     def test_set_linux_distro_centos(self):
@@ -74,17 +74,17 @@ def test_set_linux_distro_centos(self):
         hpccm.config.set_linux_distro('centos')
         self.assertEqual(hpccm.config.g_linux_distro,
                          hpccm.linux_distro.CENTOS)
-        self.assertEqual(hpccm.config.g_linux_version, StrictVersion('7.0'))
+        self.assertEqual(hpccm.config.g_linux_version, Version('7.0'))
 
         hpccm.config.set_linux_distro('centos7')
         self.assertEqual(hpccm.config.g_linux_distro,
                          hpccm.linux_distro.CENTOS)
-        self.assertEqual(hpccm.config.g_linux_version, StrictVersion('7.0'))
+        self.assertEqual(hpccm.config.g_linux_version, Version('7.0'))
 
         hpccm.config.set_linux_distro('centos8')
         self.assertEqual(hpccm.config.g_linux_distro,
                          hpccm.linux_distro.CENTOS)
-        self.assertEqual(hpccm.config.g_linux_version, StrictVersion('8.0'))
+        self.assertEqual(hpccm.config.g_linux_version, Version('8.0'))
 
     @docker
     def test_set_linux_distro_rhel(self):
@@ -92,17 +92,17 @@ def test_set_linux_distro_rhel(self):
         hpccm.config.set_linux_distro('rhel')
         self.assertEqual(hpccm.config.g_linux_distro,
                          hpccm.linux_distro.RHEL)
-        self.assertEqual(hpccm.config.g_linux_version, StrictVersion('7.0'))
+        self.assertEqual(hpccm.config.g_linux_version, Version('7.0'))
 
         hpccm.config.set_linux_distro('rhel7')
         self.assertEqual(hpccm.config.g_linux_distro,
                          hpccm.linux_distro.RHEL)
-        self.assertEqual(hpccm.config.g_linux_version, StrictVersion('7.0'))
+        self.assertEqual(hpccm.config.g_linux_version, Version('7.0'))
 
         hpccm.config.set_linux_distro('rhel8')
         self.assertEqual(hpccm.config.g_linux_distro,
                          hpccm.linux_distro.RHEL)
-        self.assertEqual(hpccm.config.g_linux_version, StrictVersion('8.0'))
+        self.assertEqual(hpccm.config.g_linux_version, Version('8.0'))
 
     @docker
     def test_set_linux_distro_rockylinux(self):
@@ -110,7 +110,7 @@ def test_set_linux_distro_rockylinux(self):
         hpccm.config.set_linux_distro('rockylinux8')
         self.assertEqual(hpccm.config.g_linux_distro,
                          hpccm.linux_distro.ROCKYLINUX)
-        self.assertEqual(hpccm.config.g_linux_version, StrictVersion('8.0'))
+        self.assertEqual(hpccm.config.g_linux_version, Version('8.0'))
 
     @docker
     def test_set_linux_distro_invalid(self):
@@ -118,14 +118,13 @@ def test_set_linux_distro_invalid(self):
         hpccm.config.set_linux_distro('invalid')
         self.assertEqual(hpccm.config.g_linux_distro,
                          hpccm.linux_distro.UBUNTU)
-        self.assertEqual(hpccm.config.g_linux_version, StrictVersion('16.04'))
+        self.assertEqual(hpccm.config.g_linux_version, Version('16.04'))
 
     @singularity
     def test_set_singularity_version(self):
         """Set Singularity version"""
         hpccm.config.set_singularity_version('10.0')
-        self.assertEqual(hpccm.config.g_singularity_version,
-                         StrictVersion('10.0'))
+        self.assertEqual(hpccm.config.g_singularity_version, Version('10.0'))
 
     @docker
     def test_set_cpu_architecture_aarch64(self):