Repository: spack/spack

Issue:
openfoam-org: support aarch64 platform
`openfoam-org` cannot support aarch64 now,
so we added a patch for aarch64-patch and create an issue for upstream:
https://github.com/OpenFOAM/OpenFOAM-7/issues/1




Discussion:
@olesenm can you review this PR?
> I don't think that this should be patched with a file. The change set corresponds to a git commit from their repository

Well, looks we should wait for a while and check if upstream receive this patch?
@darmac I think what @olesenm means is that if you change your patch statement to the sample he provided, it should be good to merge. That way we download the patch instead of storing it in the Spack repo.
@darmac - as @adamjstewart said, it is preferable to downloading the patch instead of storing it in the spack repo.
If you try to get this patched upstream, you stumble into the next dilemma. The patched upstream would then correspond to a different version with a different sha and you would need to update the spack recipe again.

... or just use "openfoam" instead. 
@adamjstewart  @olesenm 
Got it, I'll refine this patch later.
Ping @darmac, is this still a WIP?
@adamjstewart  We found some error by using a url patch, and we have not feedback to `openfoam-org` community yet.
I found `openfoam-8` can support ARM64 now, so we can update the version.
But there is still a issue for `openfoam-8` as below:
```
==> Installing openfoam-org
==> No binary for openfoam-org found: installing from source
==> Using cached archive: /home/xiaojun/spack/var/spack/cache/_source-cache/archive/94/94ba11cbaaa12fbb5b356e01758df403ac8832d69da309a5d79f76f42eb008fc.tar.gz
==> renamed spack-src -> OpenFOAM-8
==> Added file spack-Allwmake
==> Added file README-spack
==> Added file bin/foamEtcFile
==> openfoam-org: Executing phase: 'configure'
==> [2020-11-03-11:00:17.237558] FILTER FILE: etc/bashrc [replacing "^(\s*export\s+WM_COMPILER)=.*$"]
==> [2020-11-03-11:00:17.241145] FILTER FILE: etc/bashrc [replacing "^(\s*export\s+WM_LABEL_SIZE)=.*$"]
==> [2020-11-03-11:00:17.243734] FILTER FILE: etc/bashrc [replacing "^(\s*export\s+WM_PRECISION_OPTION)=.*$"]
==> [2020-11-03-11:00:17.246196] FILTER FILE: etc/bashrc [replacing "^(\s*export\s+WM_COMPILE_OPTION)=.*$"]
==> [2020-11-03-11:00:17.248756] FILTER FILE: etc/bashrc [replacing "^(\s*export\s+WM_MPLIB)=.*$"]
==> [2020-11-03-11:00:17.251205] FILTER FILE: etc/cshrc [replacing "^(\s*setenv\s+WM_COMPILER)\s+.*$"]
==> [2020-11-03-11:00:17.253741] FILTER FILE: etc/cshrc [replacing "^(\s*setenv\s+WM_LABEL_SIZE)\s+.*$"]
==> [2020-11-03-11:00:17.256363] FILTER FILE: etc/cshrc [replacing "^(\s*setenv\s+WM_PRECISION_OPTION)\s+.*$"]
==> [2020-11-03-11:00:17.258892] FILTER FILE: etc/cshrc [replacing "^(\s*setenv\s+WM_COMPILE_OPTION)\s+.*$"]
==> [2020-11-03-11:00:17.261437] FILTER FILE: etc/cshrc [replacing "^(\s*setenv\s+WM_MPLIB)\s+.*$"]
==> openfoam-org: Executing phase: 'build'
==> Error: InstallError: No wmake rule for linuxARM64 Gcc

/home/xiaojun/spack/var/spack/repos/builtin/packages/openfoam-org/package.py:303, in build:
        300        its environment first.
        301        Only build if the compiler is known to be supported.
        302        """
  >>    303        self.foam_arch.has_rule(self.stage.source_path)
        304        self.foam_arch.create_rules(self.stage.source_path, self)
        305
        306        args = []

See build log for details:
  /tmp/root/spack-stage/spack-stage-openfoam-org-8-zj5ojam67uyo7j434msadfkmrvs2b6xz/spack-build-out.txt
```

When `spack` build `openfoam-org@8`, it will check `wmake/rules/linuxARM64Gcc/` dir, but unfortunately, what `openfoam-org` has is a `wmake/rules/linuxArm64Gcc/`, the upper case `ARM` makes it build fail.

I tried move the `wmake/rules/linuxArm64Gcc/` to `wmake/rules/linuxARM64Gcc/` then it will install successfully.
I think we should not supply any patch to `openfoam-org`, we can just change `spack` code to fix the build issue:
```
[root@Estuary-CentOS8 packages]# git diff openfoam/package.py
diff --git a/var/spack/repos/builtin/packages/openfoam/package.py b/var/spack/repos/builtin/packages/openfoam/package.py
index 8947decc1..0910789ae 100644
--- a/var/spack/repos/builtin/packages/openfoam/package.py
+++ b/var/spack/repos/builtin/packages/openfoam/package.py
@@ -892,7 +892,7 @@ def __init__(self, spec, **kwargs):
             elif target == 'armv7l':
                 platform += 'ARM7'
             elif target == 'aarch64':
-                platform += 'ARM64'
+                platform += 'Arm64'
             elif target == 'ppc64':
                 platform += 'PPC64'
             elif target == 'ppc64le':
```

Which means we can abandon the patch `var/spack/repos/builtin/packages/openfoam-org/70-linuxARM64Gcc.patch`
> I think we should not supply any patch to `openfoam-org`, we can just change `spack` code to fix the build issue:
> 
> [root@Estuary-CentOS8 packages]# git diff openfoam/package.py
> -                platform += 'ARM64'
> +                platform += 'Arm64'

No, do **not** do that. This will break the openfoam.com (spack openfoam package) in favour of patching up the openfoam.org (spack openfoam-org package).  The openfoam/package.py is filled with numerous commonly used routines, which is why it is much larger than the openfoam-org package. It is also leveraged for the foam-extend package too.

- Dec-2017 :  `ARM64` support was added to openfoam.com (for the v1712 release)
- Jan-2018 : added support for ARM64 to the spack package.
- Jun-2020 : `Arm64` support was added to openfoam.org

I don't know why they (openfoam.org) decided for "Arm64" instead of "ARM64" - maybe they didn't want to look like they were copying from the openfoam.com, maybe they just don't care about people who need to package things. In any case, I see no justification in breaking things after 2-1/2 years to accommodate their choices. 
So, how about we copy the `Arm64` to `ARM64` in spack `openfoam-org` package (only at version 8 and arm64 platform)?
> So, how about we copy the `Arm64` to `ARM64` in spack `openfoam-org` package (only at version 8 and arm64 platform)?

This is close to what I had suggested. Make a **symlink** (not a copy) from `ARM64` to `Arm64` for the _openfoam-org_ package. This is a cheap operation - can do it for any/all versions that have wmake linuxArm64xxx directories.

@darmac 
just looked at the settings in their code base. Not really consist naming I'd say:

- aarch64 : WM_ARCH=linuxArm64
- armv7l : WM_ARCH=linuxARM7
My following fix was incorrect.
https://github.com/spack/spack/pull/19622

Please wait for a while as I will redo the fix.
I fixed it again with the following pull request.
https://github.com/spack/spack/pull/19743
> I fixed it again with the following pull request.
> #19743

@t-nojiri  Thanks for your help, so we can just waiting your patch and then close this PR?

Resolving patch:
diff --git a/var/spack/repos/builtin/packages/openfoam-org/package.py b/var/spack/repos/builtin/packages/openfoam-org/package.py
--- a/var/spack/repos/builtin/packages/openfoam-org/package.py
+++ b/var/spack/repos/builtin/packages/openfoam-org/package.py
@@ -174,7 +174,7 @@ def projectdir(self):
     @property
     def foam_arch(self):
         if not self._foam_arch:
-            self._foam_arch = OpenfoamArch(self.spec, **self.config)
+            self._foam_arch = OpenfoamOrgArch(self.spec, **self.config)
         return self._foam_arch
 
     @property
@@ -390,3 +390,17 @@ def install_links(self):
                 if os.path.isfile(f)
             ]:
                 os.symlink(f, os.path.basename(f))
+
+
+# -----------------------------------------------------------------------------
+
+class OpenfoamOrgArch(OpenfoamArch):
+    """An openfoam-org variant of OpenfoamArch
+    """
+    def update_arch(self, spec):
+        """Handle differences in WM_ARCH naming
+        """
+        OpenfoamArch.update_arch(self, spec)
+
+        # ARM64 (openfoam) -> Arm64 (openfoam-org)
+        self.arch = self.arch.replace("ARM64", "Arm64")
diff --git a/var/spack/repos/builtin/packages/openfoam/package.py b/var/spack/repos/builtin/packages/openfoam/package.py
--- a/var/spack/repos/builtin/packages/openfoam/package.py
+++ b/var/spack/repos/builtin/packages/openfoam/package.py
@@ -861,12 +861,13 @@ def __init__(self, spec, **kwargs):
         self.options          = None
         self.mplib            = kwargs.get('mplib', 'USERMPI')
 
-        # Normally support WM_LABEL_OPTION, but not yet for foam-extend
+        # WM_LABEL_OPTION, but perhaps not yet for foam-extend
         if '+int64' in spec:
             self.label_size = '64'
         elif kwargs.get('label-size', True):
             self.label_size = '32'
 
+        # WM_PRECISION_OPTION
         if '+spdp' in spec:
             self.precision_option = 'SPDP'
         elif '+float32' in spec:
@@ -876,6 +877,20 @@ def __init__(self, spec, **kwargs):
         if '+knl' in spec:
             self.arch_option = '-march=knl'
 
+        # Capitalize first letter of compiler name to obtain the
+        # OpenFOAM naming (eg, gcc -> Gcc, clang -> Clang, etc).
+        # Use compiler_mapping[] for special cases
+        comp = spec.compiler.name
+        if comp in self.compiler_mapping:
+            comp = self.compiler_mapping[comp]
+
+        self.compiler = comp.capitalize()
+        self.update_arch(spec)
+        self.update_options()
+
+    def update_arch(self, spec):
+        """Set WM_ARCH string corresponding to spack platform/target
+        """
         # spec.architecture.platform is like `uname -s`, but lower-case
         platform = str(spec.architecture.platform)
 
@@ -883,7 +898,6 @@ def __init__(self, spec, **kwargs):
         target = str(spec.target.family)
 
         # No spack platform family for ia64 or armv7l
-
         if platform == 'linux':
             if target == 'x86_64':
                 platform += '64'
@@ -901,21 +915,12 @@ def __init__(self, spec, **kwargs):
             if target == 'x86_64':
                 platform += '64'
         # ... and others?
-
         self.arch = platform
 
-        # Capitalize first letter of compiler name, which corresponds
-        # to how OpenFOAM handles things (eg, gcc -> Gcc).
-        # Use compiler_mapping for special cases.
-        comp = spec.compiler.name
-
-        if comp in self.compiler_mapping:
-            comp = self.compiler_mapping[comp]
-        comp = comp.capitalize()
-
-        self.compiler = comp
-
-        # Build WM_OPTIONS
+    def update_options(self):
+        """Set WM_OPTIONS string consistent with current settings
+        """
+        # WM_OPTIONS
         # ----
         # WM_LABEL_OPTION=Int$WM_LABEL_SIZE
         # WM_OPTIONS_BASE=$WM_ARCH$WM_COMPILER$WM_PRECISION_OPTION


Test patch: