Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve handling of OpenMP switch to support Apple Clang with brew-installed libomp #3395

Open
heplesser opened this issue Jan 16, 2025 · 5 comments
Assignees
Labels
I: No breaking change Previously written code will work as before, no one should note anything changing (aside the fix) S: Normal Handle this with default priority T: Maintenance Work to keep up the quality of the code and documentation.

Comments

@heplesser
Copy link
Contributor

Apple Clang does not support the -fopenmp switch out of the box. Therefore, to build NEST with Apple Clang and without conda environments, one needs to install libomp (and some other tools) with Homebrew and then pass file paths and compiler options either as environment variables or cmake options explicitly.

A typical Homebrew setup can be

brew install llvm libomp gcc boost gsl cmake libtool readline open-mpi graphviz

but I have not checked if llvm and gcc are strictly needed (graphvis is only needed for one test until #3390 is fixed).

One can then configure NEST with

CFLAGS="-I/opt/homebrew/opt/libomp/include -Xclang -fopenmp" CXXFLAGS="-I/opt/homebrew/opt/libomp/include -Xclang -fopenmp" LDFLAGS="-L/opt/homebrew/opt/libomp/lib" cmake -DCMAKE_INSTALL_PREFIX:PATH=`pwd`/install -Dwith-openmp=ON -Dwith-mpi=ON ../../../src/main
``` 

On Intel Macs, replace `/opt/homebrew` with `/usr/local/opt`.

Alternatively, one can use

cmake -DCMAKE_INSTALL_PREFIX:PATH=pwd/install -Dwith-openmp="-I/opt/homebrew/opt/libomp/include -Xclang -fopenmp -L/opt/homebrew/opt/libomp/lib -lomp" -Dwith-mpi=ON ../../../src/main


but this will cause many compiler warnings as linker flags are passed to the compiler.

The main problem is that when anything except `ON` or `OFF` is passed to `-Dwith-openmp`, the string passed will be directly used as compiler flags ([see code here](https://github.com/nest/nest-simulator/blob/c201d6718a31ff46e1eb64af0dde73115dbb207f/cmake/ProcessOptions.cmake#L383)).
@heplesser heplesser added I: No breaking change Previously written code will work as before, no one should note anything changing (aside the fix) S: Normal Handle this with default priority T: Maintenance Work to keep up the quality of the code and documentation. labels Jan 16, 2025
@terhorstd terhorstd moved this from To do to In progress in Build system and CI Feb 10, 2025
@steffengraber
Copy link
Contributor

@heplesser With brew link --force libomp after installing the brew packages, I was able to get cmake to work with -Dwith-openmp=ON. Could you maybe test that?

@lekshmideepu
Copy link
Contributor

lekshmideepu commented Feb 17, 2025

@steffengraber I could confirm your suggestion.
`$ brew link --force libomp
Linking /usr/local/Cellar/libomp/19.1.7... 6 symlinks created.

(nest-venv) $ cmake -DCMAKE_INSTALL_PREFIX:PATH=pwd/install -Dwith-openmp=ON -Dwith-mpi=ON -DCYTHON_EXECUTABLE=$(which cython) ../nest-simulator/
-- Info: Host triple: x86_64-apple-darwin
-- Info: Target triple: x86_64-apple-darwin
-- Could NOT find Readline (missing: READLINE_LIBRARY) (found version "4.2")
-- Found OpenMP_C: -Xclang -fopenmp (found version "5.1")
-- Found OpenMP_CXX: -Xclang -fopenmp (found version "5.1")
-- Found OpenMP: TRUE (found version "5.1")
-- Found MPI_C: /usr/local/Cellar/open-mpi/5.0.7/lib/libmpi.dylib (found version "3.1")
-- Found MPI_CXX: /usr/local/Cellar/open-mpi/5.0.7/lib/libmpi.dylib (found version "3.1")
-- Found MPI: TRUE (found version "3.1")`

Homebrew installs libomp separately but it doesn't symlink it because of the possible conflicts with other tools. This command (brew link --force libomp) forces Homebrew to create symbolic links for libomp in /usr/local, thus making it available system-wide.

$ brew list libomp
/usr/local/Cellar/libomp/19.1.7/include/ (4 files)
/usr/local/Cellar/libomp/19.1.7/lib/libomp.dylib
/usr/local/Cellar/libomp/19.1.7/lib/libomp.a
/usr/local/Cellar/libomp/19.1.7/sbom.spdx.json

@lekshmideepu
Copy link
Contributor

$ echo | clang -Xpreprocessor -fopenmp -I$(brew --prefix libomp)/include -dM -E - | grep OPENMP
#define _OPENMP 202011

As per my understanding, if no output appears for the above command, clang may not support OpenMP. Then we may need to install and use llvm instead.

@lekshmideepu
Copy link
Contributor

lekshmideepu commented Feb 19, 2025

@heplesser I haven't explicitly installed gcc via Homebrew during the NEST installation steps.

As gcc is actually a symlink to Clang, the version check gives the following output. ie. Clang and not Homebrew installed gcc.

$ gcc --version
Apple clang version 16.0.0 (clang-1600.0.26.6)
Target: x86_64-apple-darwin23.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

On my system I had gcc-14 installed via Homebrew. (Homebrew always installs GCC with versioned names, not just gcc)

$ gcc-14 --version
gcc-14 (Homebrew GCC 14.2.0_1) 14.2.0
Copyright (C) 2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

If we need to use Hombrew GCC, then we need to either set the alias alias gcc=gcc-14 for gcc or update the PATH

In short, I don't think gcc and llvm are strictly needed.

@heplesser
Copy link
Contributor Author

@steffengraber The brew link --force libomp works for me as well, I hope there won't be any side-effects of linking. But I would recommend this approach as it is rather straightforward. Although it would be even better if we could hint to CMake where it can find libomp, so one could pass a --with-openmp=/here/you/find/libomp.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
I: No breaking change Previously written code will work as before, no one should note anything changing (aside the fix) S: Normal Handle this with default priority T: Maintenance Work to keep up the quality of the code and documentation.
Projects
Status: In progress
Development

No branches or pull requests

3 participants