diff --git a/.github/workflows/cuda.yml b/.github/workflows/cuda.yml index f572cf83799..f5c113c8921 100644 --- a/.github/workflows/cuda.yml +++ b/.github/workflows/cuda.yml @@ -46,7 +46,7 @@ jobs: nvidia-smi source toolchain/install/setup rm -rf build - cmake -B build -G Ninja -DUSE_CUDA=ON -DBUILD_TESTING=ON + cmake -B build -G Ninja -DUSE_CUDA=ON -DBUILD_TESTING=ON -DENABLE_FLOAT_FFTW=ON cmake --build build -j4 cmake --install build diff --git a/CMakeLists.txt b/CMakeLists.txt index 23583375bb3..9fd317c146c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -420,10 +420,8 @@ endif() if(ENABLE_MPI) find_package(MPI COMPONENTS CXX REQUIRED) - target_include_directories(abacus_external_deps INTERFACE ${MPI_CXX_INCLUDE_PATH}) - target_link_libraries(${ABACUS_BIN_NAME} PRIVATE MPI::MPI_CXX) + target_link_libraries(abacus_external_deps INTERFACE MPI::MPI_CXX) abacus_add_feature_definitions(__MPI) - list(APPEND math_libs MPI::MPI_CXX) endif() @@ -438,47 +436,6 @@ if (USE_DSP) endif() -if(USE_KML) - abacus_add_feature_definitions(__KML) - message(STATUS "Huawei KML support enabled. Defining __KML.") -# TODO: Create FindKML.cmake -# if(NOT DEFINED KML_ROOT) -# if(DEFINED ENV{KML_ROOT}) -# set(KML_ROOT $ENV{KML_ROOT}) -# else() -# message(WARNING "KML_ROOT is not set. Trying default system paths for KML.") -# endif() -# endif() -# -# find_library(KML_BLAS_LIB NAMES kblas PATHS ${KML_ROOT}/lib ${KML_ROOT}/lib64 NO_DEFAULT_PATH) -# find_library(KML_LAPACK_LIB NAMES klapack_full PATHS ${KML_ROOT}/lib ${KML_ROOT}/lib64 NO_DEFAULT_PATH) -# find_library(KML_SCALAPACK_LIB NAMES kscalapack_full PATHS ${KML_ROOT}/lib ${KML_ROOT}/lib64 NO_DEFAULT_PATH) -# find_library(KML_FFTW_LIB NAMES fftw3 PATHS ${KML_ROOT}/lib ${KML_ROOT}/lib64 NO_DEFAULT_PATH) -# -# set(KML_LIBS_FOUND TRUE) -# foreach(LIB_VAR KML_BLAS_LIB KML_LAPACK_LIB KML_SCALAPACK_LIB KML_FFTW_LIB) -# if(NOT ${LIB_VAR}) -# message(WARNING "${LIB_VAR} not found in KML_ROOT! Please check your KML installation.") -# set(KML_LIBS_FOUND FALSE) -# endif() -# endforeach() -# -# if(KML_LIBS_FOUND) -# target_link_libraries(abacus PUBLIC -# ${KML_BLAS_LIB} -# ${KML_LAPACK_LIB} -# ${KML_SCALAPACK_LIB} -# ${KML_FFTW_LIB} -# ) -# message(STATUS "Huawei KML libraries found and linked successfully.") -# else() -# message(FATAL_ERROR "Failed to find all required KML libraries. Aborting.") -# endif() -# -# set(BLAS_libraries ${KML_BLAS_LIB}) -# set(LAPACK_libraries ${KML_LAPACK_LIB}) -endif(USE_KML) - if (USE_SW) abacus_add_feature_definitions(__SW) @@ -694,32 +651,45 @@ endif() if(DEFINED ENV{MKLROOT} AND NOT DEFINED MKLROOT) set(MKLROOT "$ENV{MKLROOT}") endif() -if(MKLROOT) +if(USE_KML) + set(_kml_components BLAS LAPACK FFTW3) + if(ENABLE_MPI) + list(APPEND _kml_components ScaLAPACK) + endif() + if(ENABLE_FLOAT_FFTW) + list(APPEND _kml_components FFTW3_FLOAT) + endif() + + find_package(KML REQUIRED COMPONENTS ${_kml_components}) + if(ENABLE_MPI) + target_link_libraries(abacus_external_deps INTERFACE KML::ScaLAPACK) + else() + target_link_libraries(abacus_external_deps INTERFACE KML::LAPACK) + endif() + target_link_libraries(abacus_external_deps INTERFACE KML::FFTW3) + if(ENABLE_FLOAT_FFTW) + target_link_libraries(abacus_external_deps INTERFACE KML::FFTW3_FLOAT) + endif() + abacus_add_feature_definitions(__KML) +elseif(MKLROOT) set(MKL_INTERFACE lp64) set(ENABLE_SCALAPACK ON) find_package(MKL REQUIRED) abacus_add_feature_definitions(__MKL) - target_include_directories(abacus_external_deps INTERFACE ${MKL_INCLUDE} ${MKL_INCLUDE}/fftw) - list(APPEND math_libs MKL::MKL) + target_include_directories(abacus_external_deps INTERFACE ${MKL_INCLUDE}/fftw) + target_link_libraries(abacus_external_deps INTERFACE MKL::MKL) if(CMAKE_CXX_COMPILER_ID MATCHES Intel) list(APPEND math_libs ifcore) endif() elseif(NOT USE_SW) - find_package(FFTW3 REQUIRED) find_package(Lapack REQUIRED) - list(APPEND math_libs FFTW3::FFTW3 LAPACK::LAPACK BLAS::BLAS) + target_link_libraries(abacus_external_deps INTERFACE LAPACK::LAPACK BLAS::BLAS) # ScaLAPACK is a distributed-memory library and is only needed for the # MPI build. A serial build (e.g. the native Windows serial version) # must not require it. if(ENABLE_MPI) find_package(ScaLAPACK REQUIRED) - list(APPEND math_libs ScaLAPACK::ScaLAPACK) - endif() - if(USE_OPENMP) - list(APPEND math_libs FFTW3::FFTW3_OMP) - endif() - if(ENABLE_FLOAT_FFTW) - list(APPEND math_libs FFTW3::FFTW3_FLOAT) + target_link_libraries(abacus_external_deps INTERFACE ScaLAPACK::ScaLAPACK) endif() if(CMAKE_CXX_COMPILER_ID MATCHES GNU) list(APPEND math_libs gfortran) @@ -732,6 +702,17 @@ elseif(NOT USE_SW) endif() endif() +if(NOT USE_KML AND NOT MKLROOT AND NOT USE_SW) + find_package(FFTW3 REQUIRED) + target_link_libraries(abacus_external_deps INTERFACE FFTW3::FFTW3) + if(USE_OPENMP) + target_link_libraries(abacus_external_deps INTERFACE FFTW3::FFTW3_OMP) + endif() + if(ENABLE_FLOAT_FFTW) + target_link_libraries(abacus_external_deps INTERFACE FFTW3::FFTW3_FLOAT) + endif() +endif() + if(ENABLE_FLOAT_FFTW) abacus_add_feature_definitions(__ENABLE_FLOAT_FFTW) endif() @@ -768,7 +749,7 @@ if(ENABLE_MLALGO OR DEFINED Torch_DIR) set_if_higher(CMAKE_CXX_STANDARD 14) endif() target_include_directories(abacus_external_deps INTERFACE ${TORCH_INCLUDE_DIRS}) - list(APPEND math_libs ${TORCH_LIBRARIES}) + target_link_libraries(abacus_external_deps INTERFACE ${TORCH_LIBRARIES}) add_compile_options(${TORCH_CXX_FLAGS}) endif() diff --git a/cmake/FindFFTW3.cmake b/cmake/FindFFTW3.cmake index b79f97013ca..6491aebf136 100644 --- a/cmake/FindFFTW3.cmake +++ b/cmake/FindFFTW3.cmake @@ -16,29 +16,35 @@ find_library(FFTW3_LIBRARY HINTS ${FFTW3_DIR} PATH_SUFFIXES "lib" ) -find_library(FFTW3_FLOAT_LIBRARY - NAMES fftw3f - HINTS ${FFTW3_DIR} - PATH_SUFFIXES "lib" - ) -# both libfftw3.so and libfftw3_omp.so should be link in multi-thread term +if(ENABLE_FLOAT_FFTW) + find_library(FFTW3_FLOAT_LIBRARY + NAMES fftw3f + HINTS ${FFTW3_DIR} + PATH_SUFFIXES "lib" + ) +endif() + +# Both libfftw3.so and libfftw3_omp.so are required for OpenMP builds. if (USE_OPENMP) -find_library(FFTW3_OMP_LIBRARY - NAMES fftw3_omp - HINTS ${FFTW3_DIR} - PATH_SUFFIXES "lib" - ) + find_library(FFTW3_OMP_LIBRARY + NAMES fftw3_omp + HINTS ${FFTW3_DIR} + PATH_SUFFIXES "lib" + ) endif() # Handle the QUIET and REQUIRED arguments and # set FFTW3_FOUND to TRUE if all variables are non-zero. include(FindPackageHandleStandardArgs) -if (USE_OPENMP) -find_package_handle_standard_args(FFTW3 DEFAULT_MSG FFTW3_OMP_LIBRARY FFTW3_LIBRARY FFTW3_FLOAT_LIBRARY FFTW3_INCLUDE_DIR) -else() -find_package_handle_standard_args(FFTW3 DEFAULT_MSG FFTW3_LIBRARY FFTW3_FLOAT_LIBRARY FFTW3_INCLUDE_DIR) +set(_fftw3_required_vars FFTW3_LIBRARY FFTW3_INCLUDE_DIR) +if(USE_OPENMP) + list(APPEND _fftw3_required_vars FFTW3_OMP_LIBRARY) +endif() +if(ENABLE_FLOAT_FFTW) + list(APPEND _fftw3_required_vars FFTW3_FLOAT_LIBRARY) endif() +find_package_handle_standard_args(FFTW3 DEFAULT_MSG ${_fftw3_required_vars}) # Copy the results to the output variables and target. if(FFTW3_FOUND) @@ -64,7 +70,7 @@ if(FFTW3_FOUND) IMPORTED_LOCATION "${FFTW3_LIBRARY}" INTERFACE_INCLUDE_DIRECTORIES "${FFTW3_INCLUDE_DIRS}") endif() - if(NOT TARGET FFTW3::FFTW3_FLOAT) + if(ENABLE_FLOAT_FFTW AND NOT TARGET FFTW3::FFTW3_FLOAT) add_library(FFTW3::FFTW3_FLOAT UNKNOWN IMPORTED) set_target_properties(FFTW3::FFTW3_FLOAT PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES "C" diff --git a/cmake/FindKML.cmake b/cmake/FindKML.cmake new file mode 100644 index 00000000000..09301fe8e74 --- /dev/null +++ b/cmake/FindKML.cmake @@ -0,0 +1,279 @@ +# - Find Huawei Kunpeng Math Library (KML) +# +# This module finds the KML linear-algebra libraries. KML installs optimized +# variants below architecture- and threading-specific directories, so those +# choices are made here rather than at each consumer. +# +# Imported targets: +# KML::BLAS KML BLAS +# KML::LAPACK KML LAPACK, with KML::BLAS transitively linked +# KML::ScaLAPACK KML ScaLAPACK, with KML::LAPACK transitively linked +# KML::FFTW3 KML FFTW-compatible double-precision FFT interface +# KML::FFTW3_FLOAT KML FFTW-compatible single-precision FFT interface +# +# If libkml_rt is present, KML::BLAS also propagates it as a runtime +# dependency. +# +# Cache variables: +# KML_ROOT KML installation prefix +# KML_ARCH KML library variant: neon, sve, or sve512 +# KML_BLAS_THREADING kblas variant: auto, multi, locking, or nolocking +# (default: auto) +# +# The default threading selection uses the caller's USE_OPENMP option when it +# is available: multi for OpenMP builds and nolocking otherwise. Projects can +# select a KML_BLAS_THREADING variant explicitly. +# +# KML_ARCH=sve512 uses the lib/sme KBLAS directory; the remaining KML +# libraries use lib/sve512. + +include(FindPackageHandleStandardArgs) + +set(KML_ROOT "" CACHE PATH "KML installation prefix") + +set(KML_ARCH "neon" CACHE STRING "KML library variant (neon, sve, or sve512)") +set_property(CACHE KML_ARCH PROPERTY STRINGS neon sve sve512) + +set(KML_BLAS_THREADING "auto" CACHE STRING + "KML kblas variant (auto, multi, locking, or nolocking)") +set_property(CACHE KML_BLAS_THREADING PROPERTY STRINGS + auto multi locking nolocking) + +set(_kml_arch_variants neon sve sve512) +if(NOT KML_ARCH IN_LIST _kml_arch_variants) + message(FATAL_ERROR "KML_ARCH must be one of: ${_kml_arch_variants}") +endif() + +set(_kml_thread_variants multi locking nolocking) +if(KML_BLAS_THREADING STREQUAL "auto") + if(DEFINED USE_OPENMP AND USE_OPENMP) + set(_kml_blas_threading multi) + else() + set(_kml_blas_threading nolocking) + endif() +else() + set(_kml_blas_threading "${KML_BLAS_THREADING}") +endif() + +if(NOT _kml_blas_threading IN_LIST _kml_thread_variants) + message(FATAL_ERROR + "KML_BLAS_THREADING must be auto or one of: ${_kml_thread_variants}") +endif() + +set(_kml_blas_arch "${KML_ARCH}") +if(KML_ARCH STREQUAL "sve512") + set(_kml_blas_arch sme) +endif() + +set(_kml_prefix_hints) +if(KML_ROOT) + list(APPEND _kml_prefix_hints "${KML_ROOT}") +endif() +if(DEFINED ENV{KML_ROOT}) + list(APPEND _kml_prefix_hints "$ENV{KML_ROOT}") +endif() +list(APPEND _kml_prefix_hints /usr/local/kml) + +# Check if an explicitly selected compiler-specific KML prefix matches the compiler. +set(_kml_explicit_root "${KML_ROOT}") +if(NOT _kml_explicit_root AND DEFINED ENV{KML_ROOT}) + set(_kml_explicit_root "$ENV{KML_ROOT}") +endif() +get_filename_component(_kml_root_name "${_kml_explicit_root}" NAME) +if(_kml_root_name STREQUAL "gcc") + if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + message(FATAL_ERROR + "KML_ROOT points to the GCC KML bundle, but the C++ compiler is " + "${CMAKE_CXX_COMPILER_ID}.") + endif() +elseif(_kml_root_name STREQUAL "bisheng") + if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + message(FATAL_ERROR + "KML_ROOT points to the BiShengLLVM KML bundle, but the C++ compiler is " + "${CMAKE_CXX_COMPILER_ID}.") + endif() +endif() + +find_path(KML_INCLUDE_DIR + NAMES kblas.h klapack.h kscalapack.h + HINTS ${_kml_prefix_hints} + PATH_SUFFIXES include) + +if(KML_INCLUDE_DIR) + get_filename_component(_kml_prefix "${KML_INCLUDE_DIR}" DIRECTORY) + + find_library(KML_RUNTIME_LIBRARY + NAMES kml_rt + HINTS "${_kml_prefix}" + PATH_SUFFIXES lib + NO_DEFAULT_PATH) + + find_library(KML_BLAS_LIBRARY + NAMES kblas + HINTS "${_kml_prefix}" + PATH_SUFFIXES "lib/${_kml_blas_arch}/kblas/${_kml_blas_threading}" + NO_DEFAULT_PATH) + + find_library(KML_LAPACK_LIBRARY + NAMES klapack_full + HINTS "${_kml_prefix}" + PATH_SUFFIXES "lib/${KML_ARCH}" + NO_DEFAULT_PATH) + + find_library(KML_SCALAPACK_LIBRARY + NAMES kscalapack_full + HINTS "${_kml_prefix}" + PATH_SUFFIXES "lib/${KML_ARCH}" + NO_DEFAULT_PATH) + + find_library(KML_FFTW3_LIBRARY + NAMES fftw3 + HINTS "${_kml_prefix}" + PATH_SUFFIXES lib/noarch + NO_DEFAULT_PATH) + + find_library(KML_KFFT_LIBRARY + NAMES kfft + HINTS "${_kml_prefix}" + PATH_SUFFIXES "lib/${KML_ARCH}" + NO_DEFAULT_PATH) + + find_library(KML_FFTW3_FLOAT_LIBRARY + NAMES fftw3f + HINTS "${_kml_prefix}" + PATH_SUFFIXES lib/noarch + NO_DEFAULT_PATH) + + find_library(KML_KFFTF_LIBRARY + NAMES kfftf + HINTS "${_kml_prefix}" + PATH_SUFFIXES "lib/${KML_ARCH}" + NO_DEFAULT_PATH) +endif() + +set(KML_BLAS_FOUND FALSE) +if(KML_INCLUDE_DIR AND KML_BLAS_LIBRARY) + set(KML_BLAS_FOUND TRUE) +endif() + +set(KML_LAPACK_FOUND FALSE) +if(KML_BLAS_FOUND AND KML_LAPACK_LIBRARY) + set(KML_LAPACK_FOUND TRUE) +endif() + +set(KML_ScaLAPACK_FOUND FALSE) +if(KML_LAPACK_FOUND AND KML_SCALAPACK_LIBRARY) + set(KML_ScaLAPACK_FOUND TRUE) +endif() +set(KML_SCALAPACK_FOUND "${KML_ScaLAPACK_FOUND}") + +set(KML_FFTW3_FOUND FALSE) +if(KML_INCLUDE_DIR AND EXISTS "${KML_INCLUDE_DIR}/fftw3.h" AND + KML_FFTW3_LIBRARY AND KML_KFFT_LIBRARY) + set(KML_FFTW3_FOUND TRUE) +endif() + +set(KML_FFTW3_FLOAT_FOUND FALSE) +if(KML_INCLUDE_DIR AND EXISTS "${KML_INCLUDE_DIR}/fftw3.h" AND + KML_FFTW3_FLOAT_LIBRARY AND KML_KFFTF_LIBRARY) + set(KML_FFTW3_FLOAT_FOUND TRUE) +endif() + +set(_kml_required_vars KML_INCLUDE_DIR) +if(KML_FIND_COMPONENTS) + foreach(_kml_component IN LISTS KML_FIND_COMPONENTS) + if(_kml_component STREQUAL "BLAS") + list(APPEND _kml_required_vars KML_BLAS_LIBRARY) + elseif(_kml_component STREQUAL "LAPACK") + list(APPEND _kml_required_vars KML_LAPACK_LIBRARY KML_BLAS_LIBRARY) + elseif(_kml_component STREQUAL "ScaLAPACK" OR _kml_component STREQUAL "SCALAPACK") + set(KML_${_kml_component}_FOUND "${KML_ScaLAPACK_FOUND}") + list(APPEND _kml_required_vars + KML_SCALAPACK_LIBRARY KML_LAPACK_LIBRARY KML_BLAS_LIBRARY) + elseif(_kml_component STREQUAL "FFTW3") + list(APPEND _kml_required_vars KML_FFTW3_LIBRARY KML_KFFT_LIBRARY) + elseif(_kml_component STREQUAL "FFTW3_FLOAT") + list(APPEND _kml_required_vars + KML_FFTW3_FLOAT_LIBRARY KML_KFFTF_LIBRARY) + else() + set(KML_${_kml_component}_FOUND FALSE) + endif() + endforeach() +else() + list(APPEND _kml_required_vars KML_BLAS_LIBRARY KML_LAPACK_LIBRARY) +endif() +list(REMOVE_DUPLICATES _kml_required_vars) + +find_package_handle_standard_args(KML + REQUIRED_VARS ${_kml_required_vars} + HANDLE_COMPONENTS) + +if(KML_FOUND) + set(KML_INCLUDE_DIRS "${KML_INCLUDE_DIR}") + + if(KML_RUNTIME_LIBRARY AND NOT TARGET KML::Runtime) + add_library(KML::Runtime UNKNOWN IMPORTED) + set_target_properties(KML::Runtime PROPERTIES + IMPORTED_LOCATION "${KML_RUNTIME_LIBRARY}") + endif() + + if(KML_BLAS_FOUND AND NOT TARGET KML::BLAS) + add_library(KML::BLAS UNKNOWN IMPORTED) + set_target_properties(KML::BLAS PROPERTIES + IMPORTED_LOCATION "${KML_BLAS_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${KML_INCLUDE_DIR}") + if(TARGET KML::Runtime) + set_property(TARGET KML::BLAS APPEND PROPERTY + INTERFACE_LINK_LIBRARIES KML::Runtime) + endif() + endif() + + if(KML_LAPACK_FOUND AND NOT TARGET KML::LAPACK) + add_library(KML::LAPACK UNKNOWN IMPORTED) + set_target_properties(KML::LAPACK PROPERTIES + IMPORTED_LOCATION "${KML_LAPACK_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${KML_INCLUDE_DIR}" + INTERFACE_LINK_LIBRARIES KML::BLAS) + endif() + + if(KML_ScaLAPACK_FOUND AND NOT TARGET KML::ScaLAPACK) + add_library(KML::ScaLAPACK UNKNOWN IMPORTED) + set_target_properties(KML::ScaLAPACK PROPERTIES + IMPORTED_LOCATION "${KML_SCALAPACK_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${KML_INCLUDE_DIR}" + INTERFACE_LINK_LIBRARIES KML::LAPACK) + endif() + + if(KML_FFTW3_FOUND AND NOT TARGET KML::FFTW3) + add_library(KML::FFTW3 UNKNOWN IMPORTED) + set_target_properties(KML::FFTW3 PROPERTIES + IMPORTED_LOCATION "${KML_FFTW3_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${KML_INCLUDE_DIR}" + INTERFACE_LINK_LIBRARIES "${KML_KFFT_LIBRARY}") + endif() + + if(KML_FFTW3_FLOAT_FOUND AND NOT TARGET KML::FFTW3_FLOAT) + add_library(KML::FFTW3_FLOAT UNKNOWN IMPORTED) + set_target_properties(KML::FFTW3_FLOAT PROPERTIES + IMPORTED_LOCATION "${KML_FFTW3_FLOAT_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${KML_INCLUDE_DIR}" + INTERFACE_LINK_LIBRARIES "${KML_KFFTF_LIBRARY}") + endif() + + if(TARGET KML::LAPACK) + set(KML_LIBRARIES KML::LAPACK) + elseif(TARGET KML::BLAS) + set(KML_LIBRARIES KML::BLAS) + endif() +endif() + +mark_as_advanced( + KML_INCLUDE_DIR + KML_RUNTIME_LIBRARY + KML_BLAS_LIBRARY + KML_LAPACK_LIBRARY + KML_SCALAPACK_LIBRARY + KML_FFTW3_LIBRARY + KML_KFFT_LIBRARY + KML_FFTW3_FLOAT_LIBRARY + KML_KFFTF_LIBRARY) diff --git a/toolchain/scripts/stage3/install_fftw.sh b/toolchain/scripts/stage3/install_fftw.sh index 766e8badbe0..4ad04705574 100755 --- a/toolchain/scripts/stage3/install_fftw.sh +++ b/toolchain/scripts/stage3/install_fftw.sh @@ -127,7 +127,6 @@ if [ "$with_fftw" != "__DONTUSE__" ]; then prepend_path LD_LIBRARY_PATH "${pkg_install_dir}/lib" prepend_path LD_RUN_PATH "${pkg_install_dir}/lib" prepend_path LIBRARY_PATH "${pkg_install_dir}/lib" -prepend_path CPATH "${pkg_install_dir}/include" prepend_path PKG_CONFIG_PATH "${pkg_install_dir}/lib/pkgconfig" prepend_path CMAKE_PREFIX_PATH "${pkg_install_dir}" EOF @@ -139,9 +138,6 @@ export FFTW3_LIBS="${FFTW_LIBS}" export FFTW_CFLAGS="${FFTW_CFLAGS}" export FFTW_LDFLAGS="${FFTW_LDFLAGS}" export FFTW_LIBS="${FFTW_LIBS}" -export CP_DFLAGS="\${CP_DFLAGS} -D__FFTW3 IF_COVERAGE(IF_MPI(|-U__FFTW3)|)" -export CP_CFLAGS="\${CP_CFLAGS} ${FFTW_CFLAGS}" -export CP_LDFLAGS="\${CP_LDFLAGS} ${FFTW_LDFLAGS}" export CP_LIBS="${FFTW_LIBS} \${CP_LIBS}" export FFTW_ROOT=${FFTW_ROOT:-${pkg_install_dir}} export FFTW3_ROOT=${pkg_install_dir}