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

CMake: Adding support for building multiple precisions at once #276

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
281 changes: 161 additions & 120 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,16 @@ option (ENABLE_OPENMP "Use OpenMP for multithreading" OFF)
option (ENABLE_THREADS "Use pthread for multithreading" OFF)
option (WITH_COMBINED_THREADS "Merge thread library" OFF)

option (ENABLE_FLOAT "single-precision" OFF)
option (ENABLE_LONG_DOUBLE "long-double precision" OFF)
option (ENABLE_QUAD_PRECISION "quadruple-precision" OFF)
option (ENABLE_FLOAT "Build the single precision library" OFF)
option (ENABLE_DOUBLE "Build the double precision library" ON)
option (ENABLE_LONG_DOUBLE "Build the long double precision library" OFF)
option (ENABLE_QUAD_PRECISION "Build the quadruple precision library" OFF)

option (ENABLE_SSE "Compile with SSE instruction set support" OFF)
option (ENABLE_SSE2 "Compile with SSE2 instruction set support" OFF)
option (ENABLE_AVX "Compile with AVX instruction set support" OFF)
option (ENABLE_AVX2 "Compile with AVX2 instruction set support" OFF)
option (ENABLE_NEON "Compile with NEON instruction set support" OFF)

option (DISABLE_FORTRAN "Disable Fortran wrapper routines" OFF)

Expand Down Expand Up @@ -192,9 +194,20 @@ if (ENABLE_AVX2)
endforeach ()
endif ()

if (ENABLE_NEON)
if (ENABLE_LONG_DOUBLE)
message (FATAL_ERROR "NEON only works in single or double precision, please disable long double support")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems contradictory to this PR. Shouldn't it be fine that NEON is only built for single and double, and we just give a warning that it doesn't work for the others?

endif ()
if (ENABLE_QUAD_PRECISION)
message (FATAL_ERROR "NEON only works in single or double precision, please disable quad precision support")
endif ()
set (HAVE_NEON TRUE)
endif ()

if (HAVE_SSE2 OR HAVE_AVX)
set (HAVE_SIMD TRUE)
endif ()

file(GLOB fftw_api_SOURCE api/*.c api/*.h)
file(GLOB fftw_dft_SOURCE dft/*.c dft/*.h)
file(GLOB fftw_dft_scalar_SOURCE dft/scalar/*.c dft/scalar/*.h)
Expand All @@ -204,6 +217,7 @@ file(GLOB fftw_dft_simd_SOURCE dft/simd/*.c dft/simd
file(GLOB fftw_dft_simd_sse2_SOURCE dft/simd/sse2/*.c dft/simd/sse2/*.h)
file(GLOB fftw_dft_simd_avx_SOURCE dft/simd/avx/*.c dft/simd/avx/*.h)
file(GLOB fftw_dft_simd_avx2_SOURCE dft/simd/avx2/*.c dft/simd/avx2/*.h dft/simd/avx2-128/*.c dft/simd/avx2-128/*.h)
file(GLOB fftw_dft_simd_neon_SOURCE dft/simd/neon/*.c dft/simd/neon/*.h)
file(GLOB fftw_kernel_SOURCE kernel/*.c kernel/*.h)
file(GLOB fftw_rdft_SOURCE rdft/*.c rdft/*.h)
file(GLOB fftw_rdft_scalar_SOURCE rdft/scalar/*.c rdft/scalar/*.h)
Expand All @@ -219,6 +233,7 @@ file(GLOB fftw_rdft_simd_SOURCE rdft/simd/*.c rdft/sim
file(GLOB fftw_rdft_simd_sse2_SOURCE rdft/simd/sse2/*.c rdft/simd/sse2/*.h)
file(GLOB fftw_rdft_simd_avx_SOURCE rdft/simd/avx/*.c rdft/simd/avx/*.h)
file(GLOB fftw_rdft_simd_avx2_SOURCE rdft/simd/avx2/*.c rdft/simd/avx2/*.h rdft/simd/avx2-128/*.c rdft/simd/avx2-128/*.h)
file(GLOB fftw_rdft_simd_neon_SOURCE rdft/simd/neon/*.c rdft/simd/neon/*.h)

file(GLOB fftw_reodft_SOURCE reodft/*.c reodft/*.h)
file(GLOB fftw_simd_support_SOURCE simd-support/*.c simd-support/*.h)
Expand Down Expand Up @@ -279,94 +294,138 @@ if (HAVE_AVX2)
list (APPEND SOURCEFILES ${fftw_dft_simd_avx2_SOURCE} ${fftw_rdft_simd_avx2_SOURCE})
endif ()

set (FFTW_VERSION 3.3.9)

set (PREC_SUFFIX)
if (ENABLE_FLOAT)
set (FFTW_SINGLE TRUE)
set (BENCHFFT_SINGLE TRUE)
set (PREC_SUFFIX f)
if (HAVE_NEON)
list (APPEND SOURCEFILES ${fftw_dft_simd_neon_SOURCE} ${fftw_rdft_simd_neon_SOURCE})
endif ()

if (ENABLE_LONG_DOUBLE)
set (FFTW_LDOUBLE TRUE)
set (BENCHFFT_LDOUBLE TRUE)
set (PREC_SUFFIX l)
endif ()
set (FFTW_VERSION 3.3.10)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is rather archaic. We should move this into project(FFTW VERSION 3.3.10)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also in the project, only C language should be enabled


if (ENABLE_QUAD_PRECISION)
set (FFTW_QUAD TRUE)
set (BENCHFFT_QUAD TRUE)
set (PREC_SUFFIX q)
endif ()
set (fftw3_lib fftw3${PREC_SUFFIX})
set (PRECISIONS SINGLE DOUBLE LDOUBLE QUAD)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about passing this as a list via set(CACHE), then if any flags are added, simply add to the list.

foreach (PRECISION ${PRECISIONS})
# Initialize all parameters to false:
foreach (TMPPRECISION ${PRECISIONS})
set (FFTW_${TMPPRECISION} FALSE)
set (BENCHFFT_${TMPPRECISION} FALSE)
endforeach ()

configure_file (cmake.config.h.in config.h @ONLY)
include_directories (${CMAKE_CURRENT_BINARY_DIR})
if ("${PRECISION}" STREQUAL "SINGLE")
if (NOT "${ENABLE_FLOAT}")
continue ()
endif()
set (PREC_SUFFIX f)
elseif ("${PRECISION}" STREQUAL "DOUBLE")
if (NOT "${ENABLE_DOUBLE}")
continue ()
endif()
set (PREC_SUFFIX)
elseif ("${PRECISION}" STREQUAL "LDOUBLE")
if (NOT "${ENABLE_LONG_DOUBLE}")
continue ()
endif()
set (PREC_SUFFIX l)
elseif ("${PRECISION}" STREQUAL "QUAD")
if (NOT "${ENABLE_QUAD_PRECISION}")
continue ()
endif()
set (PREC_SUFFIX q)
endif ()

if (BUILD_SHARED_LIBS)
add_definitions (-DFFTW_DLL)
endif ()
# Enable only one precision per iteration:
set (FFTW_${PRECISION} TRUE)
set (BENCHFFT_${PRECISION} TRUE)

add_library (${fftw3_lib} ${SOURCEFILES})
target_include_directories (${fftw3_lib} INTERFACE $<INSTALL_INTERFACE:include>)
if (MSVC AND NOT (CMAKE_C_COMPILER_ID STREQUAL "Intel"))
target_compile_definitions (${fftw3_lib} PRIVATE /bigobj)
endif ()
if (HAVE_SSE)
target_compile_options (${fftw3_lib} PRIVATE ${SSE_FLAG})
endif ()
if (HAVE_SSE2)
target_compile_options (${fftw3_lib} PRIVATE ${SSE2_FLAG})
endif ()
if (HAVE_AVX)
target_compile_options (${fftw3_lib} PRIVATE ${AVX_FLAG})
endif ()
if (HAVE_AVX2)
target_compile_options (${fftw3_lib} PRIVATE ${AVX2_FLAG})
endif ()
if (HAVE_FMA)
target_compile_options (${fftw3_lib} PRIVATE ${FMA_FLAG})
endif ()
if (HAVE_LIBM)
target_link_libraries (${fftw3_lib} m)
endif ()

set (subtargets ${fftw3_lib})

if (Threads_FOUND)
if (WITH_COMBINED_THREADS)
target_link_libraries (${fftw3_lib} ${CMAKE_THREAD_LIBS_INIT})
else ()
add_library (${fftw3_lib}_threads ${fftw_threads_SOURCE})
target_include_directories (${fftw3_lib}_threads INTERFACE $<INSTALL_INTERFACE:include>)
target_link_libraries (${fftw3_lib}_threads ${fftw3_lib})
target_link_libraries (${fftw3_lib}_threads ${CMAKE_THREAD_LIBS_INIT})
list (APPEND subtargets ${fftw3_lib}_threads)
set (fftw3_lib fftw3${PREC_SUFFIX})
add_library (${fftw3_lib} ${SOURCEFILES})
list (APPEND FFTW3_LIBRARIES "${fftw3_lib}")

configure_file (cmake.config.h.in "${PRECISION}/config.h" @ONLY)
target_include_directories (${fftw3_lib} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/${PRECISION}")

target_include_directories (${fftw3_lib} INTERFACE $<INSTALL_INTERFACE:include>)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>

Copy link

@LecrisUT LecrisUT Jan 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, I understood this tutorial the other way around.

This is still recommended. Just don't use ${CMAKE_INSTALL_FULL_INCLUDEDIR}


if (BUILD_SHARED_LIBS)
target_compile_definitions (${fftw3_lib} PRIVATE -DFFTW_DLL)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this specific to windows?

endif ()
endif ()

if (OPENMP_FOUND)
add_library (${fftw3_lib}_omp ${fftw_omp_SOURCE})
target_include_directories (${fftw3_lib}_omp INTERFACE $<INSTALL_INTERFACE:include>)
target_link_libraries (${fftw3_lib}_omp ${fftw3_lib})
target_link_libraries (${fftw3_lib}_omp ${CMAKE_THREAD_LIBS_INIT})
list (APPEND subtargets ${fftw3_lib}_omp)
target_compile_options (${fftw3_lib}_omp PRIVATE ${OpenMP_C_FLAGS})
endif ()
if (MSVC AND NOT (CMAKE_C_COMPILER_ID STREQUAL "Intel"))
target_compile_definitions (${fftw3_lib} PRIVATE /bigobj)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For readability, how about moving these common ones to a base_fftw interface target (and maybe a separate compiler.cmake)?

endif ()
if (HAVE_SSE)
target_compile_options (${fftw3_lib} PRIVATE ${SSE_FLAG})
endif ()
if (HAVE_SSE2)
target_compile_options (${fftw3_lib} PRIVATE ${SSE2_FLAG})
endif ()
if (HAVE_AVX)
target_compile_options (${fftw3_lib} PRIVATE ${AVX_FLAG})
endif ()
if (HAVE_AVX2)
target_compile_options (${fftw3_lib} PRIVATE ${AVX2_FLAG})
endif ()
if (HAVE_FMA)
target_compile_options (${fftw3_lib} PRIVATE ${FMA_FLAG})
endif ()
if (HAVE_LIBM)
target_link_libraries (${fftw3_lib} m)
endif ()

set (subtargets ${fftw3_lib})

if (Threads_FOUND)
if (WITH_COMBINED_THREADS)
target_link_libraries (${fftw3_lib} ${CMAKE_THREAD_LIBS_INIT})
else ()
add_library (${fftw3_lib}_threads ${fftw_threads_SOURCE})
target_include_directories (${fftw3_lib}_threads PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/${PRECISION}")
target_include_directories (${fftw3_lib}_threads INTERFACE $<INSTALL_INTERFACE:include>)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems these can be generalized in an interface target as well. Can combine with depends to link to appropriate config.h as well.

target_link_libraries (${fftw3_lib}_threads ${fftw3_lib})
target_link_libraries (${fftw3_lib}_threads ${CMAKE_THREAD_LIBS_INIT})
list (APPEND subtargets ${fftw3_lib}_threads)
endif ()
endif ()

if (OPENMP_FOUND)
add_library (${fftw3_lib}_omp ${fftw_omp_SOURCE})
target_include_directories (${fftw3_lib}_omp PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/${PRECISION}")
target_include_directories (${fftw3_lib}_omp INTERFACE $<INSTALL_INTERFACE:include>)
target_link_libraries (${fftw3_lib}_omp ${fftw3_lib})
target_link_libraries (${fftw3_lib}_omp ${CMAKE_THREAD_LIBS_INIT})
list (APPEND subtargets ${fftw3_lib}_omp)
target_compile_options (${fftw3_lib}_omp PRIVATE ${OpenMP_C_FLAGS})
endif ()

foreach(subtarget ${subtargets})
set_target_properties (${subtarget} PROPERTIES SOVERSION 3.6.9 VERSION 3)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are SOVERSIONs not in sync with PROJECT_VERSION?

install (TARGETS ${subtarget}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should be exported as well

LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
endforeach ()

if (BUILD_TESTS)
add_executable (bench${PREC_SUFFIX} ${fftw_libbench2_SOURCE} tests/bench.c tests/hook.c tests/fftw-bench.c)
target_include_directories (bench${PREC_SUFFIX} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/${PRECISION}")

if (ENABLE_THREADS AND NOT WITH_COMBINED_THREADS)
target_link_libraries (bench${PREC_SUFFIX} ${fftw3_lib}_threads)
else ()
target_link_libraries (bench${PREC_SUFFIX} ${fftw3_lib})
endif ()

enable_testing ()

if (Threads_FOUND)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Either move this together with condition BUILD_TESTS, or enable the testing altogether. Also bench is not a good name for this purpose. Preferably move these to tests subfolder

macro (fftw_add_test problem)
add_test (NAME ${problem}${PREC_SUFFIX} COMMAND bench${PREC_SUFFIX} -s ${problem})
endmacro ()

foreach(subtarget ${subtargets})
set_target_properties (${subtarget} PROPERTIES SOVERSION 3.6.9 VERSION 3)
install (TARGETS ${subtarget}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
fftw_add_test (32x64)
fftw_add_test (ib256)
endif ()
endif ()
endforeach ()
install(TARGETS ${fftw3_lib}
EXPORT FFTW3LibraryDepends
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})

install (FILES api/fftw3.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/api/fftw3.f)
Expand All @@ -380,30 +439,11 @@ if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/api/fftw3.f03.in)
install (FILES ${CMAKE_CURRENT_BINARY_DIR}/fftw3.f03 DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
endif ()

if (BUILD_TESTS)

add_executable (bench ${fftw_libbench2_SOURCE} tests/bench.c tests/hook.c tests/fftw-bench.c)

if (ENABLE_THREADS AND NOT WITH_COMBINED_THREADS)
target_link_libraries (bench ${fftw3_lib}_threads)
else ()
target_link_libraries (bench ${fftw3_lib})
endif ()


enable_testing ()

if (Threads_FOUND)

macro (fftw_add_test problem)
add_test (NAME ${problem} COMMAND bench -s ${problem})
endmacro ()

fftw_add_test (32x64)
fftw_add_test (ib256)

endif ()
endif ()
install(TARGETS ${FFTW3_LIBRARIES}
EXPORT FFTW3LibraryDepends
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})

# pkgconfig file
set (prefix ${CMAKE_INSTALL_PREFIX})
Expand All @@ -413,22 +453,23 @@ set (includedir ${CMAKE_INSTALL_FULL_INCLUDEDIR})
set (VERSION ${FFTW_VERSION})
configure_file (fftw.pc.in fftw3${PREC_SUFFIX}.pc @ONLY)
install (FILES
${CMAKE_CURRENT_BINARY_DIR}/fftw3${PREC_SUFFIX}.pc
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
COMPONENT Development)

# cmake file
set (FFTW3_LIBRARIES "FFTW3::${fftw3_lib}")
configure_file (FFTW3Config.cmake.in FFTW3${PREC_SUFFIX}Config.cmake @ONLY)
configure_file (FFTW3ConfigVersion.cmake.in FFTW3${PREC_SUFFIX}ConfigVersion.cmake @ONLY)
install (FILES
${CMAKE_CURRENT_BINARY_DIR}/FFTW3${PREC_SUFFIX}Config.cmake
${CMAKE_CURRENT_BINARY_DIR}/FFTW3${PREC_SUFFIX}ConfigVersion.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/fftw3${PREC_SUFFIX}
COMPONENT Development)
${CMAKE_CURRENT_BINARY_DIR}/fftw3${PREC_SUFFIX}.pc

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should be in the loop

DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
COMPONENT Development)

export (TARGETS ${fftw3_lib} NAMESPACE FFTW3:: FILE ${PROJECT_BINARY_DIR}/FFTW3LibraryDepends.cmake)
# cmake configuration file
configure_file (FFTW3Config.cmake.in FFTW3Config.cmake @ONLY)
configure_file (FFTW3ConfigVersion.cmake.in FFTW3ConfigVersion.cmake @ONLY)
install (FILES
"${CMAKE_CURRENT_BINARY_DIR}/FFTW3Config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/FFTW3ConfigVersion.cmake"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/fftw3"
COMPONENT Development)

export (TARGETS ${FFTW3_LIBRARIES}
NAMESPACE FFTW3::
FILE "${PROJECT_BINARY_DIR}/FFTW3LibraryDepends.cmake")
install(EXPORT FFTW3LibraryDepends
NAMESPACE FFTW3::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/fftw3${PREC_SUFFIX}
COMPONENT Development)
NAMESPACE FFTW3::
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/fftw3"
COMPONENT Development)
2 changes: 1 addition & 1 deletion cmake.config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@
/* #undef HAVE_MPI */

/* Define to enable ARM NEON optimizations. */
/* #undef HAVE_NEON */
#cmakedefine HAVE_NEON 1

/* Define if OpenMP is enabled */
#cmakedefine HAVE_OPENMP
Expand Down