FFTW / fftw3

DO NOT CHECK OUT THESE FILES FROM GITHUB UNLESS YOU KNOW WHAT YOU ARE DOING. (See below.)
GNU General Public License v2.0
2.76k stars 667 forks source link

Q: Is FFTW3 transpilable to Webassembly (WASM via emscripten)? #293

Closed RalphSteinhagen closed 1 year ago

RalphSteinhagen commented 2 years ago

First, thanks a lot for all the effort you put into the de-facto backbone of most numerical tools on the internet! Kudos :+1:

We have some libraries/applications that rely on fftw3 and which we would eventually like to also deploy to the web. In order to keep the same API, it would be great if fftw3 would transpile to webassembly (e.g. using emscripten).

Did anybody have success transpiling the fftw code to WASM? Are there plans?

Thanks in advance for a

latermarch commented 1 year ago

I build the .a lib via emscripten like this: emconfigure ./configure --disable-fortran --enable-static --disable-single --enable-threads --prefix=$EM_PATH CFLAGS="-s WASM=1" CXXFLAGS="-s WASM=1" LDFLAGS="-s WASM=1"

but when run the web application,it stucked: image

image I don't know how to fix it

RalphSteinhagen commented 1 year ago

Meanwhile, we found a solution to integrate and compile FFTW3 to WASM. See here and the FFT block for example.

Here is the specific cmake example:

# FFTW3 is build 2 times for float and double precisions
SET(FFTW_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/fftw)
SET(FFTW_CFLAGS "${CFLAGS} -w")
if (EMSCRIPTEN)
    SET(FFTW_CONFIG cd ${FFTW_PREFIX}/src/ && emconfigure ./configure --enable-silent-rules --quiet --disable-fortran --prefix=${FFTW_PREFIX}/install)
    SET(FFTW_BUILD emmake make -j CFLAGS=${FFTW_CFLAGS} --silent V=0 && emmake make install --silent V=0 && emmake make clean --silent V=0)
else ()
    SET(FFTW_CONFIG ${FFTW_PREFIX}/src/configure --enable-silent-rules --quiet --disable-fortran --prefix=${FFTW_PREFIX}/install)
    SET(FFTW_BUILD make -j CFLAGS=${FFTW_CFLAGS} --silent V=0 && make install --silent V=0 && make clean --silent V=0)
endif ()
SET(FFTW_INSTALL_COMMAND
        ${FFTW_CONFIG} && ${FFTW_BUILD} &&
        ${FFTW_CONFIG} --enable-float && ${FFTW_BUILD})

include(ExternalProject)
ExternalProject_Add(fftw_ext
        PREFIX ${FFTW_PREFIX}
        SOURCE_DIR ${FFTW_PREFIX}/src
        BINARY_DIR ${FFTW_PREFIX}/build
        INSTALL_DIR ${FFTW_INSTALL_DIR}
        STAMP_DIR ${FFTW_PREFIX}/stamp
        TMP_DIR ${FFTW_PREFIX}/tmp
        DOWNLOAD_DIR ${FFTW_PREFIX}/download
        LOG_DIR ${FFTW_PREFIX}/log
        URL "https://fftw.org/fftw-3.3.10.tar.gz"
        URL_MD5 8ccbf6a5ea78a16dbc3e1306e234cc5c
        CONFIGURE_COMMAND ${FFTW_INSTALL_COMMAND}
        BUILD_COMMAND ""
        INSTALL_COMMAND ""
        LOG_DOWNLOAD ON
)

include_directories(${FFTW_PREFIX}/install/include)

add_library(fftw INTERFACE)
target_link_libraries(fftw INTERFACE fftw3 INTERFACE fftw3f INTERFACE m)
target_include_directories(fftw INTERFACE ${FFTW_PREFIX}/install/include)
target_link_directories(fftw INTERFACE ${FFTW_PREFIX}/install/lib ${FFTW_PREFIX}/install/lib64)
add_dependencies(fftw fftw_ext)

or a more basic bash-style version:

#/bin/bash

if [ -z ${EM_PATH+x} ]; then 
        echo "EM_PATH is unset"; 
        export EM_PATH="$(PWD)/test"
else 
        echo "EM_PATH is set to '$EM_PATH'"; 
fi

wget "http://fftw.org/fftw-3.3.10.tar.gz"
tar -xf fftw-3.3.6-pl2.tar.gz
cd fftw-3.3.6-pl2
emconfigure ./configure --disable-fortran --enable-float --prefix=$EM_PATH CFLAGS="-s WASM=1" CXXFLAGS="-s WASM=1"  LDFLAGS="-s WASM=1"  #--with-combined-threads
emmake make -j
emmake make install

Certainly! Below is a revised version of your comment:

Note: The GPLv2 license of FFTW, without linking/WebAssembly (WASM) exceptions, makes its use in commercial settings challenging. While this is fine for us as a public organization, it's a hurdle for some industry and governmental library co-users. As a solution, we're developing a more straightforward, albeit possibly slower, alternative using std::simd. This approach aims to minimize maintenance, reduce external dependencies, ease cross-compilation to WASM, and encourage a more public adoption of our prototype library, envisioned as a stepping stone towards 'GNU Radio 4.0'.