'How to use FFTW library in cmake?

I have C++ code which uses FFTW 3.3.4. Ubuntu 16.04, cmake version 3.7.2

$ locate *fftw*.so

/usr/lib/libsfftw.so
/usr/lib/libsfftw_mpi.so
/usr/lib/libsfftw_threads.so
/usr/lib/libsrfftw.so
/usr/lib/libsrfftw_mpi.so
/usr/lib/libsrfftw_threads.so
/usr/lib/x86_64-linux-gnu/libfftw3.so
/usr/lib/x86_64-linux-gnu/libfftw3_mpi.so
/usr/lib/x86_64-linux-gnu/libfftw3_omp.so
/usr/lib/x86_64-linux-gnu/libfftw3_threads.so
/usr/lib/x86_64-linux-gnu/libfftw3f.so
/usr/lib/x86_64-linux-gnu/libfftw3f_mpi.so
/usr/lib/x86_64-linux-gnu/libfftw3f_omp.so
/usr/lib/x86_64-linux-gnu/libfftw3f_threads.so
/usr/lib/x86_64-linux-gnu/libfftw3l.so
/usr/lib/x86_64-linux-gnu/libfftw3l_mpi.so
/usr/lib/x86_64-linux-gnu/libfftw3l_omp.so
/usr/lib/x86_64-linux-gnu/libfftw3l_threads.so
/usr/lib/x86_64-linux-gnu/libfftw3q.so
/usr/lib/x86_64-linux-gnu/libfftw3q_omp.so
/usr/lib/x86_64-linux-gnu/libfftw3q_threads.so


$ locate fftw3.h
/usr/include/fftw3.h

I can compile it in this way:

g++ main.cpp -o main -lfftw3

but I have a problem with cmake.

This is my CMakeLists.txt:

cmake_minimum_required(VERSION 3.5.1)
project (main)
SET(CMAKE_C_COMPILER gcc)
SET(CMAKE_CXX_COMPILER g++)
file(GLOB SOURCES "*.cpp") 
SET(CMAKE_CXX_FLAGS "-lm -lfftw3")
SET(CMAKE_C_FLAGS   "-lm -lfftw3")
INCLUDE_DIRECTORIES(/usr/include)
LINK_DIRECTORIES(/usr/lib/x86_64-linux-gnu)
add_library(fftw3 STATIC IMPORTED)
set(CMAKE_C_OUTPUT_EXTENSION_REPLACE 1) 
set(CMAKE_CXX_OUTPUT_EXTENSION_REPLACE 1)
add_executable(main ${SOURCES})

cmake . && make

gives

undefined reference to `fftw_malloc'

and the same for the other fftw functions.



Solution 1:[1]

We delegate this to pkg-config:

find_package(PkgConfig REQUIRED)
pkg_search_module(FFTW REQUIRED fftw3 IMPORTED_TARGET)
include_directories(PkgConfig::FFTW)
link_libraries     (PkgConfig::FFTW)

This works with cmake 3.11 (at least, it may work with earlier versions too).


NOTE: This doesn't work with fftw3_thread component because they don't have a separate .pc file. (see https://github.com/FFTW/fftw3/issues/180).

This may work to add the component (not tested, doesn't work in Macs --see comments--):

link_libraries     (PkgConfig::FFTW -lfftw3_thread)

NOTE 2: I am pasting here @OlafWilkocx solution to get the thread component as well

    cmake_minimum_required(VERSION 3.20)
...
    set(CMAKE_CXX_FLAGS_RELEASE "-O3 -fno-math-errno -ffinite-math-only") # clang
    find_package(OpenMP    REQUIRED)

    find_package(PkgConfig REQUIRED)     
    pkg_check_modules(FFTW IMPORTED_TARGET REQUIRED fftw3)
          
    if( NOT FFTW_ROOT AND DEFINED ENV{FFTWDIR} )
        set( FFTW_ROOT $ENV{FFTWDIR} )
    endif()
          
    find_library(
            FFTW_DOUBLE_THREADS_LIB
            NAMES "fftw3_threads"
            PATHS ${PKG_FFTW_LIBRARY_DIRS} ${LIB_INSTALL_DIR}
            )
          
    if (FFTW_DOUBLE_THREADS_LIB)
        set(FFTW_DOUBLE_THREADS_LIB_FOUND TRUE)
        set(FFTW_LIBRARIES ${FFTW_LIBRARIES} ${FFTW_DOUBLE_THREADS_LIB})
        add_library(FFTW::DoubleThreads INTERFACE IMPORTED)
        set_target_properties(FFTW::DoubleThreads
            PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${FFTW_INCLUDE_DIRS}"
            INTERFACE_LINK_LIBRARIES "${FFTW_DOUBLE_THREADS_LIB}"
            )
    else()
        set(FFTW_DOUBLE_THREADS_LIB_FOUND FALSE)
    endif()
     
    include_directories(PkgConfig::FFTW)
     
    add_executable(solver_step src/solver_step.cc)
    target_link_libraries(solver_step PRIVATE OpenMP::OpenMP_CXX ${VTK_LIBRARIES} PkgConfig::FFTW ${FFTW_DOUBLE_THREADS_LIB})

NOTE 3

I am told that the line include_directories(PkgConfig::FFTW) is always incorrect and suggested to either only use link_libraries(PkgConfig::FFTW) or target_link_libraries(target_name PRIVATE PkgConfig::FFTW).

see here: Avoid bad include paths in CMake's pkg-config fallback

Solution 2:[2]

The command add_library will create a library in your project (CMake - add_library). I assume that is not what you want.

The command: g++ main.cpp -o main -lfftw3 will link the executable to the fftw library. In CMake you can reproduce the linking with:

add_executable(main ${SOURCES})
target_link_libraries(main fftw3)

Docu: CMake - target_link_libraries
Notice: It is important that the add_executable command comes before the linking.
Have fun with FFTW :)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2