10

I find myself going against the grain configuring cmake paths with ccmake over and over again as with every change of for ex. compiler some of my library paths get lost.

In particular paths to (unlinked) lapack, lapacke, gsl get either lost or set to system defaults instead the ones I've installed with brew.

There has to be a way to tell cmake to "ignore" system libraries and instead look in homebrew paths (say. /opt/homebrew/lib, /opt/homebrew/include etc.).

I'd prefer not to link those libraries as this is not recommend and I'm not experienced in switching environments.

[EDIT] MRE:

git clone https://gitlab.physik.uni-muenchen.de/AG-Scrinzi/tRecX.git
cd tRecX
cmake . -DCMAKE_BUILD_TYPE=Parallel
make -j 8

I add the following to .bash_profile/.zshrc:

export LDFLAGS="-L/opt/homebrew/opt/lapack/lib -L/opt/homebrew/opt/lapack/lib" 
export CPPFLAGS="-I/opt/homebrew/opt/lapack/include -I/opt/homebrew/opt/openblas/include" 
export PKG_CONFIG_PATH="/opt/homebrew/opt/lapack/lib/pkgconfig /opt/homebrew/opt/openblas/lib/pkgconfig"

then I try:

cmake . -DCMAKE_PREFIX_PATH=/opt/homebrew -DCMAKE_FIND_FRAMEWORK=NEVER -DCMAKE_FIND_APPBUNDLE=NEVER -DCMAKE_FIND_USE_CMAKE_SYSTEM_PATH=FALSE -DCMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH=FALSE -DMPI_CXX_COMPILER=/opt/homebrew/bin/mpicxx -DMPI_C_COMPILER=/opt/homebrew/bin/mpicc -DCMAKE_CXX_COMPILER=/opt/homebrew/bin/g++-11 -DCMAKE_C_COMPILER=/opt/homebrew/bin/gcc-11
Ranza
  • 294
  • 3
  • 10

1 Answers1

11

The most common solution is to just set CMAKE_PREFIX_PATH to /opt/homebrew. CMake will then look preferentially in /opt/homebrew for everything. Since you're on Apple, you might need to set CMAKE_FIND_FRAMEWORK and CMAKE_FIND_APPBUNDLE to LAST or NEVER, too.

You can skip the standard platform search paths by setting CMAKE_FIND_USE_CMAKE_SYSTEM_PATH to FALSE at the command line, in a preset, or in a toolchain file. You might also wish to disable looking at the PATH environment variable by setting CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH to FALSE.

Finally, if you're in a cross-compiling scenario or toolchain file, you can change the definition of the system directories by setting CMAKE_SYSROOT. Note that the sysroot will have to contain the language runtime libraries (e.g. glibc) and will be passed to the --sysroot flag (or equivalent). Just be aware of those effects, too.

All of this is documented here:


The following homebrew.cmake toolchain file worked for me:

set(HOMEBREW_PREFIX "/usr/local"
    CACHE PATH "Path to Homebrew installation")

set(CMAKE_C_COMPILER "${HOMEBREW_PREFIX}/bin/gcc-11")
set(CMAKE_CXX_COMPILER "${HOMEBREW_PREFIX}/bin/g++-11")

set(CMAKE_PREFIX_PATH
    "${HOMEBREW_PREFIX}"
    # These libraries are keg-only and not loaded into
    # the root prefix by default (to avoid clashes).
    "${HOMEBREW_PREFIX}/opt/lapack"
    "${HOMEBREW_PREFIX}/opt/openblas"
    "${HOMEBREW_PREFIX}/opt/gcc/lib/gcc/11"
)

list(TRANSFORM CMAKE_PREFIX_PATH APPEND "/include"
     OUTPUT_VARIABLE CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES)
set(CMAKE_C_STANDARD_INCLUDE_DIRECTORIES "${CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES}")

set(CMAKE_FIND_FRAMEWORK NEVER)
set(CMAKE_FIND_APPBUNDLE NEVER)

set(CMAKE_FIND_USE_CMAKE_SYSTEM_PATH FALSE)
set(CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH FALSE)

I built with the following commands:

$ ls 
tRecX  homebrew.cmake
$ cmake -G Ninja -S tRecX -B tRecX-build \
    -DCMAKE_TOOLCHAIN_FILE=$PWD/homebrew.cmake \
    -DCBLAS=/usr/local/opt/openblas/lib/libblas.dylib \
    -DCMAKE_EXE_LINKER_FLAGS="-Wl,-undefined,dynamic_lookup" \
    -DCMAKE_SHARED_LINKER_FLAGS="-Wl,-undefined,dynamic_lookup" \
    -DCMAKE_BUILD_TYPE=Parallel

[ ... output clipped ... ]

Boost found -- full functionality

Build "Parallel" with C++ flags  -D_USE_BOOST_ -O3  -pthread  -D_USE_FFTW_, return to default by -UCMAKE_BUILD_TYPE

            Compiler: /usr/local/bin/g++-11, change by -DCMAKE_CXX_COMPILER=[path_to_complier]

-- Linking to libraries Boost::system;Boost::filesystem;/usr/local/lib/libfftw3.dylib;/usr/local/opt/gcc/lib/gcc/11/libgfortran.dylib;alglib;/usr/local/lib/libarpack.dylib;Boost::system;Boost::filesystem;/usr/local/opt/lapack/lib/liblapacke.dylib;/usr/local/opt/openblas/lib/libblas.dylib;/usr/local/opt/lapack/lib/liblapack.dylib;/usr/local/opt/lapack/lib/libblas.dylib;m
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/alexreinking/Development/tRecX-build
$ cmake --build tRecX-build

I had to set CBLAS manually because libblas.dylib provides the OpenBLAS CBLAS interface, but the build system specifically looks for a library named libcblas. There's no other option in this case.

The code and build have issues with its linking model and dependencies. I was able to paper over these by setting -Wl,-undefined,dynamic_lookup. However, note that this will just defer linker errors to runtime and might impose a large startup cost.

If you can make commits to the project, I would store these settings in a preset, maybe name it homebrew-parallel or something:

    -DCMAKE_TOOLCHAIN_FILE=$PWD/homebrew.cmake \
    -DCBLAS=/usr/local/opt/openblas/lib/libblas.dylib \
    -DCMAKE_EXE_LINKER_FLAGS="-Wl,-undefined,dynamic_lookup" \
    -DCMAKE_SHARED_LINKER_FLAGS="-Wl,-undefined,dynamic_lookup" \
    -DCMAKE_BUILD_TYPE=Parallel

Then you could just run cmake --preset=homebrew-parallel

Alex Reinking
  • 16,724
  • 5
  • 52
  • 86
  • Thank you for the answer. I've run `cmake . -DCMAKE_PREFIX_PATH=/opt/homebrew -DCMAKE_FIND_FRAMEWORK=NEVER -DCMAKE_FIND_APPBUNDLE=NEVER -DCMAKE_FIND_USE_CMAKE_SYSTEM_PATH=FALSE -DCMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH=FALSE` yet it still uses Xcode gcc compiler rather than homebrew gcc by default... – Ranza Jun 23 '21 at 19:21
  • Ok, maybe it'd be better to try the other way around - is there a way to temporarily link all keg-only libraries from brew? – Ranza Jun 23 '21 at 19:37
  • @Ranza - it doesn't look like you set the compiler you want to use... You'll need to set `CMAKE_CXX_COMPILER` and `CMAKE_C_COMPILER`. Also, Xcode "gcc" isn't actually gcc, it's a symbolic link to Apple's clang. You'll need the full path to the Homebrew compilers. – Alex Reinking Jun 23 '21 at 19:40
  • Right, so I've tried: `cmake . -DCMAKE_PREFIX_PATH=/opt/homebrew -DCMAKE_FIND_FRAMEWORK=NEVER -DCMAKE_FIND_APPBUNDLE=NEVER -DCMAKE_FIND_USE_CMAKE_SYSTEM_PATH=FALSE -DCMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH=FALSE -DMPI_CXX_COMPILER=/opt/homebrew/bin/mpicxx -DMPI_C_COMPILER=/opt/homebrew/bin/mpicc -DCMAKE_CXX_COMPILER=/opt/homebrew/bin/g++-11 -DCMAKE_C_COMPILER=/opt/homebrew/bin/gcc-11` – Ranza Jun 23 '21 at 19:47
  • and also added `export LDFLAGS="-L/opt/homebrew/opt/lapack/lib -L/opt/homebrew/opt/lapack/lib" export CPPFLAGS="-I/opt/homebrew/opt/lapack/include -I/opt/homebrew/opt/openblas/include" export PKG_CONFIG_PATH="/opt/homebrew/opt/lapack/lib/pkgconfig /opt/homebrew/opt/openblas/lib/pkgconfig"` before to zshrc and restarted the shell but it still doesn't find BLAS, CBLAS, LAPACK nor LAPACKE – Ranza Jun 23 '21 at 19:49
  • Can you give an MRE so I can reproduce this locally? I think the right solution for you will be to create a toolchain file. – Alex Reinking Jun 23 '21 at 19:53
  • 1
    Sure, just added. – Ranza Jun 23 '21 at 19:57
  • 1
    @Ranza - I got pretty far, but get linker errors at the end. Not sure where the problem is. – Alex Reinking Jun 23 '21 at 21:38
  • Lapack related? I'm stuck at missing symbols like "_LAPACKE_zgbrfs" too. – Ranza Jun 23 '21 at 21:42
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/234133/discussion-between-alex-reinking-and-ranza). – Alex Reinking Jun 23 '21 at 21:43
  • @Ranza - please see the chat link above – Alex Reinking Jun 23 '21 at 21:56
  • thinking how to make old cmakefiles work that don't rely on find_package, and or use find_library instead and don't work on Apple M1 with homebrew. Would find_package be a preferable approach over cmake prefix path ? – hombre Jan 07 '23 at 01:27