Add option to internally build FFTW if selected
authorChristoph Junghans <junghans@votca.org>
Mon, 12 Nov 2012 02:40:38 +0000 (19:40 -0700)
committerGerrit Code Review <gerrit@gerrit.gromacs.org>
Wed, 28 Nov 2012 15:08:54 +0000 (16:08 +0100)
Fixes #1031

Change-Id: If9d7cee68f4ced26e931b9a7c5595df47185bb66

CMakeLists.txt
src/contrib/fftw/CMakeLists.txt [new file with mode: 0644]
src/mdlib/CMakeLists.txt

index 833abf71639e8068ab735323a925022431835de9..e34e87e5277879452c312b8b82927845f1e13a76 100644 (file)
@@ -187,6 +187,8 @@ set(GMX_CPU_ACCELERATION "@GMX_SUGGESTED_CPU_ACCELERATION@"
 
 set(GMX_FFT_LIBRARY "fftw3" 
     CACHE STRING "FFT library choices: fftw3,mkl,fftpack[built-in]")
+option(GMX_BUILD_OWN_FFTW "Download and build FFTW 3 during the GROMACS build process, rather than fall back on the really slow fftpack." OFF)
+mark_as_advanced(GMX_BUILD_OWN_FFTW)
 option(GMX_DISABLE_FFTW_MEASURE 
        "Do not optimize FFTW setups (not needed with SSE)" OFF)
 mark_as_advanced(GMX_DISABLE_FFTW_MEASURE)
@@ -936,23 +938,29 @@ set(PKG_FFT_LIBS "")
 if(${GMX_FFT_LIBRARY} STREQUAL "FFTW3")
     if(GMX_DOUBLE)
         set(FFTW fftw)
-    else(GMX_DOUBLE)
+    else()
         set(FFTW fftwf)
-    endif(GMX_DOUBLE)
-    find_package(FFTW COMPONENTS ${FFTW})
+    endif()
+
+    if(GMX_BUILD_OWN_FFTW)
+      add_subdirectory(src/contrib/fftw)
+    else()
+      find_package(FFTW COMPONENTS ${FFTW})
+    endif()
+
     string(TOUPPER "${FFTW}" FFTW)
     set(PKG_FFT "${${FFTW}_PKG}")
     include_directories(${${FFTW}_INCLUDE_DIRS})
     set(FFT_LIBRARIES ${${FFTW}_LIBRARIES})
     if(NOT ${FFTW}_FOUND)
-      MESSAGE(FATAL_ERROR "Cannot find FFTW3 (with correct precision - libfftw3f for single precision GROMACS or libfftw3 for double precision GROMACS). Fix it, choose another FFT library, or use the Gromacs built-in fftpack (slower)!")
-    endif(NOT ${FFTW}_FOUND)
+      MESSAGE(FATAL_ERROR "Cannot find FFTW 3 (with correct precision - libfftw3f for single-precision GROMACS or libfftw3 for double-precision GROMACS). Either choose the right precision, choose another FFT(W) library, enable the advanced option to let GROMACS build FFTW 3 for you, or use the really slow GROMACS built-in fftpack library.")
+    endif()
 
     set(GMX_FFT_FFTW3 1)
 
     if (NOT ${GMX_CPU_ACCELERATION} STREQUAL "NONE" AND NOT ${FFTW}_HAVE_SIMD) 
       message(WARNING "The fftw library found is compiled without SIMD support, which makes it slow. Consider recompiling it or contact your admin")
-    endif (NOT ${GMX_CPU_ACCELERATION} STREQUAL "NONE" AND NOT ${FFTW}_HAVE_SIMD) 
+    endif()
 
 elseif(${GMX_FFT_LIBRARY} STREQUAL "MKL")
 #    MESSAGE(STATUS "Using external FFT library - Intel MKL")
diff --git a/src/contrib/fftw/CMakeLists.txt b/src/contrib/fftw/CMakeLists.txt
new file mode 100644 (file)
index 0000000..6787c83
--- /dev/null
@@ -0,0 +1,60 @@
+# Download and build a suitable copy of FFTW.
+# The GROMACS team won't distribute source or binaries linked to FFTW
+# because we are choosing to be very clear about distributing only
+# LGPL-licensed code, to suit requirements from our funding source.
+#
+# Input: FFTW variable contains the FFTW component to build,
+#        either fftw or fftwf for double or single precision
+
+set(GMX_BUILD_OWN_FFTW_OPTIMIZATION_CONFIGURATION "" CACHE INTERNAL "Optimization flags for FFTW compilation")
+if(${CMAKE_CURRENT_BINARY_DIR} MATCHES ".*[[:space:]].*")
+    message(FATAL_ERROR "An internal limitation of FFTW means GROMACS cannot build FFTW in a directory with whitespace in its name. Either use a system FFTW, build it yourself, or build GROMACS in a different location.")
+endif()
+
+if(NOT GMX_DOUBLE)
+    set(GMX_BUILD_OWN_FFTW_PREC --enable-float)
+endif()
+
+# Always build a static lib, so it gets added to libmd and doesn't need to be installed
+set(GMX_BUILD_OWN_FFTW_SHARED_FLAG --disable-shared --enable-static)
+if (CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" AND BUILD_SHARED_LIBS) # FFTW doesn't use -DPIC by default
+    set(GMX_BUILD_OWN_FFTW_SHARED_FLAG ${GMX_BUILD_OWN_FFTW_SHARED_FLAG} --with-pic)
+endif()
+
+# Testing shows FFTW configured with --enable-avx is never better than --enable-sse2, so we do the latter always.
+if(${GMX_CPU_ACCELERATION} MATCHES "^(SSE|AVX)")
+    set(GMX_BUILD_OWN_FFTW_OPTIMIZATION_CONFIGURATION --enable-sse2 CACHE INTERNAL "Optimization flags for FFTW compilation")
+endif()
+
+# Machinery for running the external project
+set(EXTERNAL_FFTW_VERSION 3.3.2)
+set(EXTERNAL_FFTW_VERSION_MD5_SUM 6977ee770ed68c85698c7168ffa6e178)
+include(ExternalProject)
+if(CMAKE_VERSION VERSION_LESS 2.8.3)
+    # Can't check MD5 sum with this CMake version
+    message(WARNING "GROMACS is downloading FFTW ${EXTERNAL_FFTW_VERSION}, but your version of CMake is too old to allow GROMACS to check that the archive it receives is correct. GROMACS will build and link to FFTW anyway, but there is a security risk if you execute a GROMACS tool that calls this library. Either build your own FFTW, or update CMake to at least version 2.8.3.")
+        ExternalProject_add(gmxfftw
+            URL "http://www.fftw.org/fftw-${EXTERNAL_FFTW_VERSION}.tar.gz"
+            CONFIGURE_COMMAND <SOURCE_DIR>/configure --prefix=<INSTALL_DIR>
+            ${GMX_BUILD_OWN_FFTW_SHARED_FLAG} ${GMX_BUILD_OWN_FFTW_OPTIMIZATION_CONFIGURATION}
+            ${GMX_BUILD_OWN_FFTW_PREC})
+else()
+    ExternalProject_add(gmxfftw
+        URL "http://www.fftw.org/fftw-${EXTERNAL_FFTW_VERSION}.tar.gz"
+        URL_MD5 ${EXTERNAL_FFTW_VERSION_MD5_SUM}
+        CONFIGURE_COMMAND <SOURCE_DIR>/configure --prefix=<INSTALL_DIR>
+        ${GMX_BUILD_OWN_FFTW_SHARED_FLAG} ${GMX_BUILD_OWN_FFTW_OPTIMIZATION_CONFIGURATION}
+        ${GMX_BUILD_OWN_FFTW_PREC})
+endif()
+externalproject_get_property(gmxfftw INSTALL_DIR)
+# The dependency that triggers building the gmxfftw target gets made where libmd is constructed
+
+string(TOUPPER "${FFTW}" UPPERFFTW)
+string(TOLOWER "${FFTW}" LOWERFFTW)
+string(REGEX REPLACE "fftw" "fftw3" FFTW_LIBNAME ${LOWERFFTW})
+set(${UPPERFFTW}_LIBRARIES ${CMAKE_BINARY_PREFIX}/${INSTALL_DIR}/lib/lib${FFTW_LIBNAME}${CMAKE_STATIC_LIBRARY_SUFFIX} PARENT_SCOPE)
+set(${UPPERFFTW}_INCLUDE_DIRS ${CMAKE_BINARY_PREFIX}/${INSTALL_DIR}/include PARENT_SCOPE)
+set(${UPPERFFTW}_FOUND TRUE PARENT_SCOPE)
+set(${UPPERFFTW}_HAVE_SIMD TRUE PARENT_SCOPE)
+
+message(STATUS "The GROMACS-managed build of FFTW 3 will configure with the following optimizations: ${GMX_BUILD_OWN_FFTW_OPTIMIZATION_CONFIGURATION}")
index 87194ee47f912019a7115c8ac75e40afd4f449cd..cce39574e7c1c99a0e9e0d05613515010423bdd4 100644 (file)
@@ -24,7 +24,14 @@ endif()
 add_library(md ${MDLIB_SOURCES})
 
 target_link_libraries(md ${GMX_GPU_LIBRARIES} gmx ${GMX_EXTRA_LIBRARIES} ${FFT_LIBRARIES} ${OpenMP_SHARED_LINKER_FLAGS})
-
+if(GMX_BUILD_OWN_FFTW)
+    # This dependency has to be made here rather than the CMakeLists.txt that
+    # does the FFTW build, because of the order in which
+    # add_subdirectory() calls are made in the top-level CMakeLists.txt; the
+    # md library target does not necessarily exist yet. Also enabling and
+    # disabling GMX_BUILD_OWN_FFTW changes dependencies correctly.
+    add_dependencies(md gmxfftw)
+endif()
 set_target_properties(md PROPERTIES OUTPUT_NAME "md${GMX_LIBS_SUFFIX}" SOVERSION ${SOVERSION} INSTALL_NAME_DIR "${LIB_INSTALL_DIR}"
     COMPILE_FLAGS "${OpenMP_C_FLAGS}")