Repository: NVIDIA/hpc-container-maker

Issue:
LLVM package: make OpenMP installation optinal
For our CI we install different versions of Clang/LLVM in parallel in a container. Unfortunately there is a dependency between `lipomp5-7` and `lipomp5-8`:

```bash
Step 20/28 : RUN apt-get update -y &&     DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends         clang-8         libomp-8-dev &&     rm -rf /var/lib/apt/lists/*
 ---> Running in c82cf74f02b3
Get:2 http://archive.ubuntu.com/ubuntu bionic InRelease [242 kB]
Get:1 https://apt.llvm.org/bionic llvm-toolchain-bionic InRelease [4232 B]
Get:3 https://apt.llvm.org/bionic llvm-toolchain-bionic-10 InRelease [4232 B]
Get:4 https://apt.llvm.org/bionic llvm-toolchain-bionic-11 InRelease [4232 B]
Get:5 http://archive.ubuntu.com/ubuntu bionic-updates InRelease [88.7 kB]
Get:6 http://security.ubuntu.com/ubuntu bionic-security InRelease [88.7 kB]
Get:7 http://archive.ubuntu.com/ubuntu bionic-backports InRelease [74.6 kB]
Get:8 https://apt.llvm.org/bionic llvm-toolchain-bionic/main Sources [2193 B]
Get:9 https://apt.llvm.org/bionic llvm-toolchain-bionic/main amd64 Packages [10.6 kB]
Get:10 http://archive.ubuntu.com/ubuntu bionic/restricted amd64 Packages [13.5 kB]
Get:11 http://archive.ubuntu.com/ubuntu bionic/main amd64 Packages [1344 kB]
Get:12 http://archive.ubuntu.com/ubuntu bionic/universe amd64 Packages [11.3 MB]
Get:13 https://apt.llvm.org/bionic llvm-toolchain-bionic-10/main Sources [1665 B]
Get:14 https://apt.llvm.org/bionic llvm-toolchain-bionic-10/main amd64 Packages [8762 B]
Get:15 http://archive.ubuntu.com/ubuntu bionic/multiverse amd64 Packages [186 kB]
Get:16 https://apt.llvm.org/bionic llvm-toolchain-bionic-11/main Sources [1666 B]
Get:17 https://apt.llvm.org/bionic llvm-toolchain-bionic-11/main amd64 Packages [8738 B]
Get:18 http://archive.ubuntu.com/ubuntu bionic-updates/multiverse amd64 Packages [44.6 kB]
Get:19 http://archive.ubuntu.com/ubuntu bionic-updates/restricted amd64 Packages [220 kB]
Get:20 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 Packages [2110 kB]
Get:21 http://archive.ubuntu.com/ubuntu bionic-updates/universe amd64 Packages [2095 kB]
Get:22 http://archive.ubuntu.com/ubuntu bionic-backports/main amd64 Packages [11.3 kB]
Get:23 http://archive.ubuntu.com/ubuntu bionic-backports/universe amd64 Packages [11.4 kB]
Get:24 http://security.ubuntu.com/ubuntu bionic-security/universe amd64 Packages [1332 kB]
Get:25 http://security.ubuntu.com/ubuntu bionic-security/restricted amd64 Packages [193 kB]
Get:26 http://security.ubuntu.com/ubuntu bionic-security/main amd64 Packages [1693 kB]
Get:27 http://security.ubuntu.com/ubuntu bionic-security/multiverse amd64 Packages [14.6 kB]
Fetched 21.1 MB in 2s (8756 kB/s)
Reading package lists...
Reading package lists...
Building dependency tree...
Reading state information...
The following additional packages will be installed:
  libclang-common-8-dev libclang1-8 libllvm8 libomp5-8
Suggested packages:
  clang-8-doc libomp-8-doc
Recommended packages:
  llvm-8-dev python
The following NEW packages will be installed:
  clang-8 libclang-common-8-dev libclang1-8 libllvm8 libomp-8-dev libomp5-8
0 upgraded, 6 newly installed, 0 to remove and 18 not upgraded.
Need to get 31.9 MB of archives.
After this operation, 173 MB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libllvm8 amd64 1:8-3~ubuntu18.04.2 [13.6 MB]
Get:2 http://archive.ubuntu.com/ubuntu bionic-updates/universe amd64 libclang-common-8-dev amd64 1:8-3~ubuntu18.04.2 [3802 kB]
Get:3 http://archive.ubuntu.com/ubuntu bionic-updates/universe amd64 libclang1-8 amd64 1:8-3~ubuntu18.04.2 [6225 kB]
Get:4 http://archive.ubuntu.com/ubuntu bionic-updates/universe amd64 clang-8 amd64 1:8-3~ubuntu18.04.2 [7940 kB]
Get:5 http://archive.ubuntu.com/ubuntu bionic-updates/universe amd64 libomp5-8 amd64 1:8-3~ubuntu18.04.2 [299 kB]
Get:6 http://archive.ubuntu.com/ubuntu bionic-updates/universe amd64 libomp-8-dev amd64 1:8-3~ubuntu18.04.2 [56.2 kB]
debconf: delaying package configuration, since apt-utils is not installed
Fetched 31.9 MB in 1s (35.2 MB/s)
Selecting previously unselected package libllvm8:amd64.
(Reading database ... 14420 files and directories currently installed.)
Preparing to unpack .../0-libllvm8_1%3a8-3~ubuntu18.04.2_amd64.deb ...
Unpacking libllvm8:amd64 (1:8-3~ubuntu18.04.2) ...
Selecting previously unselected package libclang-common-8-dev.
Preparing to unpack .../1-libclang-common-8-dev_1%3a8-3~ubuntu18.04.2_amd64.deb ...
Unpacking libclang-common-8-dev (1:8-3~ubuntu18.04.2) ...
Selecting previously unselected package libclang1-8.
Preparing to unpack .../2-libclang1-8_1%3a8-3~ubuntu18.04.2_amd64.deb ...
Unpacking libclang1-8 (1:8-3~ubuntu18.04.2) ...
Selecting previously unselected package clang-8.
Preparing to unpack .../3-clang-8_1%3a8-3~ubuntu18.04.2_amd64.deb ...
Unpacking clang-8 (1:8-3~ubuntu18.04.2) ...
Selecting previously unselected package libomp5-8:amd64.
Preparing to unpack .../4-libomp5-8_1%3a8-3~ubuntu18.04.2_amd64.deb ...
Unpacking libomp5-8:amd64 (1:8-3~ubuntu18.04.2) ...
dpkg: error processing archive /tmp/apt-dpkg-install-04VwC3/4-libomp5-8_1%3a8-3~ubuntu18.04.2_amd64.deb (--unpack):
 trying to overwrite '/usr/lib/x86_64-linux-gnu/libomp.so.5', which is also in package libomp5-7:amd64 1:7-3~ubuntu0.18.04.1
Selecting previously unselected package libomp-8-dev.
Preparing to unpack .../5-libomp-8-dev_1%3a8-3~ubuntu18.04.2_amd64.deb ...
Unpacking libomp-8-dev (1:8-3~ubuntu18.04.2) ...
Errors were encountered while processing:
 /tmp/apt-dpkg-install-04VwC3/4-libomp5-8_1%3a8-3~ubuntu18.04.2_amd64.deb
E: Sub-process /usr/bin/dpkg returned an error code (1)
The command '/bin/sh -c apt-get update -y &&     DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends         clang-8         libomp-8-dev &&     rm -rf /var/lib/apt/lists/*' returned a non-zero code: 100
```
For us it is not necessary to install different OpenMP versions in parallel. Can you please make the OpenMP installation optional.

Cheers,
Simeon

Discussion:
samcmill: @SimeonEhrig does this address your issue?
SimeonEhrig: > @SimeonEhrig does this address your issue?

This is exactly what I wanted. I have also successfully tested it my system. Thank you very much.

Patch:
diff --git a/docs/building_blocks.md b/docs/building_blocks.md
index e50a59c..8a15602 100644
--- a/docs/building_blocks.md
+++ b/docs/building_blocks.md
@@ -2163,6 +2163,9 @@ include the LLVM compilers when necessary. The default is True.
 - __extra_tools__: Boolean flag to specify whether to also install
 `clang-format` and `clang-tidy`.  The default is False.
 
+- __openmp__: Boolean flag to specify whether to also install OpenMP
+support.  The default is True.
+
 - __toolset__: Boolean flag to specify whether to also install the
 full LLVM toolset.  The default is False.
 
diff --git a/hpccm/building_blocks/llvm.py b/hpccm/building_blocks/llvm.py
index 5f1d143..2ad8b86 100644
--- a/hpccm/building_blocks/llvm.py
+++ b/hpccm/building_blocks/llvm.py
@@ -51,6 +51,9 @@ class llvm(bb_base, hpccm.templates.envvars):
     extra_tools: Boolean flag to specify whether to also install
     `clang-format` and `clang-tidy`.  The default is False.
 
+    openmp: Boolean flag to specify whether to also install OpenMP
+    support.  The default is True.
+
     toolset: Boolean flag to specify whether to also install the
     full LLVM toolset.  The default is False.
 
@@ -97,6 +100,7 @@ class llvm(bb_base, hpccm.templates.envvars):
         self.__compiler_debs = []  # Filled in below
         self.__compiler_rpms = []  # Filled in below
         self.__extra_tools = kwargs.get('extra_tools', False)
+        self.__openmp = kwargs.get('openmp', True)
         self.__ospackages = kwargs.get('ospackages', []) # Filled in below
         self.__runtime_debs = []   # Filled in below
         self.__runtime_ospackages = [] # Filled in below
@@ -129,21 +133,26 @@ class llvm(bb_base, hpccm.templates.envvars):
 
             if self.__version:
                 if LooseVersion(self.__version) <= LooseVersion('6.0'):
+                    self.__compiler_debs = ['clang-{}'.format(self.__version)]
+                    self.__runtime_debs = [
+                        'libclang1-{}'.format(self.__version)]
+
                     # Versioned OpenMP libraries do not exist for
                     # older versions
-                    self.__compiler_debs = [
-                        'clang-{}'.format(self.__version),
-                        'libomp-dev']
-                    self.__runtime_debs = [
-                        'libclang1-{}'.format(self.__version),
-                        'libomp5']
+                    if self.__openmp:
+                        self.__compiler_debs.append('libomp-dev')
+                        self.__runtime_debs.append('libomp5')
+
                 else:
-                    self.__compiler_debs = [
-                        'clang-{}'.format(self.__version),
-                        'libomp-{}-dev'.format(self.__version)]
+                    self.__compiler_debs = ['clang-{}'.format(self.__version)]
                     self.__runtime_debs = [
-                        'libclang1-{}'.format(self.__version),
-                        'libomp5-{}'.format(self.__version)]
+                        'libclang1-{}'.format(self.__version)]
+
+                    if self.__openmp:
+                        self.__compiler_debs.append(
+                            'libomp-{}-dev'.format(self.__version))
+                        self.__runtime_debs.append(
+                            'libomp5-{}'.format(self.__version))
 
                 if self.__upstream:
                     # Upstream packages from apt.llvm.org
@@ -196,8 +205,12 @@ class llvm(bb_base, hpccm.templates.envvars):
 
             else:
                 # Distro default
-                self.__compiler_debs = ['clang', 'libomp-dev']
-                self.__runtime_debs = ['libclang1', 'libomp5']
+                self.__compiler_debs = ['clang']
+                self.__runtime_debs = ['libclang1']
+
+                if self.__openmp:
+                    self.__compiler_debs.append('libomp-dev')
+                    self.__runtime_debs.append('libomp5')
 
                 if self.__toolset or self.__extra_tools:
                     self.__compiler_debs.extend(['clang-format', 'clang-tidy'])
@@ -224,10 +237,14 @@ class llvm(bb_base, hpccm.templates.envvars):
             if self.__version:
                 if hpccm.config.g_linux_version >= StrictVersion('8.0'):
                     # Multiple versions are not available for CentOS 8
-                    self.__compiler_rpms = ['clang', 'llvm-libs', 'libomp']
-                    self.__runtime_rpms = ['llvm-libs', 'libomp']
+                    self.__compiler_rpms = ['clang', 'llvm-libs']
+                    self.__runtime_rpms = ['llvm-libs']
                     compiler_version = '8'
 
+                    if self.__openmp:
+                        self.__compiler_rpms.append('libomp')
+                        self.__runtime_rpms.append('libomp')
+
                     if self.__toolset or self.__extra_tools:
                         self.__compiler_rpms.append('clang-tools-extra')
 
@@ -236,14 +253,18 @@ class llvm(bb_base, hpccm.templates.envvars):
                 else:
                     # CentOS 7
                     self.__compiler_rpms = [
-                        'llvm-toolset-{}-clang'.format(self.__version),
-                        'llvm-toolset-{}-libomp-devel'.format(self.__version)]
+                        'llvm-toolset-{}-clang'.format(self.__version)]
                     self.__runtime_rpms = [
                         'llvm-toolset-{}-runtime'.format(self.__version),
-                        'llvm-toolset-{}-libomp'.format(self.__version),
                         'llvm-toolset-{}-compiler-rt'.format(self.__version)]
                     compiler_version = '4.8.2'
 
+                    if self.__openmp:
+                        self.__compiler_rpms.append(
+                            'llvm-toolset-{}-libomp-devel'.format(self.__version))
+                        self.__runtime_rpms.append(
+                            'llvm-toolset-{}-libomp'.format(self.__version))
+
                     if self.__toolset or self.__extra_tools:
                         self.__compiler_rpms.append('llvm-toolset-{}-clang-tools-extra'.format(self.__version))
 
@@ -258,9 +279,12 @@ class llvm(bb_base, hpccm.templates.envvars):
                 self.__compiler_rpms = ['clang']
                 if hpccm.config.g_linux_version >= StrictVersion('8.0'):
                     # CentOS 8
-                    self.__runtime_rpms = ['llvm-libs', 'libomp']
+                    self.__runtime_rpms = ['llvm-libs']
                     compiler_version = '8'
 
+                    if self.__openmp:
+                        self.__runtime_rpms.append('libomp')
+
                     if self.__toolset or self.__extra_tools:
                         self.__compiler_rpms.append('clang-tools-extra')
 


Test patch:
diff --git a/test/test_llvm.py b/test/test_llvm.py
index 693be94..f8a246b 100644
--- a/test/test_llvm.py
+++ b/test/test_llvm.py
@@ -169,6 +169,19 @@ ENV COMPILER_PATH=/usr/lib/gcc/aarch64-redhat-linux/8:$COMPILER_PATH \
         with self.assertRaises(RuntimeError):
             llvm()
 
+    @x86_64
+    @ubuntu
+    @docker
+    def test_openmp_ubuntu(self):
+        """openmp disabled"""
+        l = llvm(openmp=False)
+        self.assertEqual(str(l),
+r'''# LLVM compiler
+RUN apt-get update -y && \
+    DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
+        clang && \
+    rm -rf /var/lib/apt/lists/*''')
+
     @x86_64
     @ubuntu
     @docker