How to add FFTW to an Android project using CMAKE

2020-05-09 22:44发布

问题:

I'm trying to add FFTW to my Android project using CMAKE, but I haven't been able to do so. If anyone has successfully added FFTW to their Android project, I would greatly appreciate any help, especially if it is done through cmake and not ndk-build.

Here is the code that I currently have in my CMakeLists.txt file for adding FFTW to the project:

set(buildDir ${CMAKE_CURRENT_BINARY_DIR}/build)
add_subdirectory(C:/Users/reyna/Documents/HMC/Clinic/Test/fftw-3.3.8 ${buildDir})
set(
        FFTW3_DIR ${buildDir}
        CACHE PATH "Path to internally built FFTW3Config.cmake"
        FORCE
)

find_package(FFTW3 CONFIG REQUIRED)

I get the following error message:

CMake Error at .cxx/cmake/debug/armeabi-v7a/build/FFTW3Config.cmake:13 (include):
The file C:/Users/reyna/Documents/HMC/Clinic/AmazonAppTest/Test2/app/.cxx/cmake/debug/armeabi-v7a/build/FFTW3LibraryDepends.cmake was generated by the export() command. It may not be used as the argument to the include() command. Use ALIAS targets instead to refer to targets by alternative names.

>

Call Stack (most recent call first):
CMakeLists.txt:69 (find_package)
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 1s
6 actionable tasks: 1 executed, 5 up-to-date

Anyone have any idea how to fix the error? I am not sure how to approach this, since it seems like it is coming from the FFTW Cmake files.

EDIT

So, I was able to get FFTW working with double precision (the default), using the following commands in my CMAKE:

set(CMAKE_INSTALL_PREFIX C:/Users/reyna/Documents/HMC/Clinic/FFTW_Install)
set( FFTW3_DIR C:/Users/reyna/Documents/HMC/Clinic/fftw/fftw-3.3.8)
add_subdirectory(${FFTW3_DIR} ${CMAKE_CURRENT_BINARY_DIR}/fftw_build)
include_directories(C:/Users/reyna/Documents/HMC/Clinic/FFTW_Install/include/)
target_link_libraries (native-lib fftw3 AudioEngine log oboe android)

From the little I know about CMake, what I think happens is the following:

  1. The first set() command just sets the CMAKE_INSTALL_PREFIX variable to a place of my choice. I am not using this now, but it could be useful later. More on this below...

  2. The second set() command sets a variable to the installation location of FFTW in my computer.

  3. The add_subdirectory() command runs the CMakeList.txt file located in the FTTW install directory, which builds the project into the directory specified by ${CMAKE_CURRENT_BINARY_DIR}/fftw_build, which is located in app/.cxx/cmake/debug/${abi}/fftw_build. Since the CMakeList.txt file has an add_library() command in it that makes a .so library (for x86 it makes a .a library for some reason), I can link my native-lib against that target. I found that these libraries are added to the app/build/intermediates/cmake/obj/${abi} folder (except x86, which for some reason adds it in the fftw_build folder). The linking is done using the target_link_libraries() command show above.

  4. The include_directories() command makes the fftw3.h file visible to the project. However, the fftw3.h file will not be copied anywhere within the Android project, unless you run an install command. The FFTW3 CMakeList.txt file has multiple install commands that don't get run during build time. These commands get executed if the cmake_install.cmake file that is located within the build folder is run. You can do this using the include() command. Not sure if this is what is generally done, but this is how I found you can do it. I did not run the install command because I found it was not necessary.

The problem is, I want single precision, which I thought I could get if I just set the ENABLE_FLOAT option in the FFTW3 CMakeList.txt file to ON. If I do that, and do steps 1-3 above (while linking to fftw3f instead of fftw3), I get the following error:

Build command failed.
Error while executing process C:\Users\reyna\AppData\Local\Android\Sdk\cmake\3.6.4111459\bin\cmake.exe with arguments {--build C:\Users\reyna\Documents\HMC\Clinic\AmazonAppTest\Test2\app.cxx\cmake\debug\armeabi-v7a --target native-lib} [1/1] Linking CXX shared library ........\build\intermediates\cmake\debug\obj\armeabi-v7a\libnative-lib.so FAILED: cmd.exe /C "cd . && C:\Users\reyna\AppData\Local\Android\Sdk\ndk\20.0.5594570\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe --target=armv7-none-linux-androideabi16 --gcc-toolchain=C:/Users/reyna/AppData/Local/Android/Sdk/ndk/20.0.5594570/toolchains/llvm/prebuilt/windows-x86_64 --sysroot=C:/Users/reyna/AppData/Local/Android/Sdk/ndk/20.0.5594570/toolchains/llvm/prebuilt/windows-x86_64/sysroot -fPIC -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -fno-addrsig -march=armv7-a -mthumb -Wa,--noexecstack -Wformat -Werror=format-security -O0 -fno-limit-debug-info -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libatomic.a -static-libstdc++ -Wl,--build-id -Wl,--warn-shared-textrel -Wl,--fatal-warnings -Wl,--exclude-libs,libunwind.a -Wl,--no-undefined -Qunused-arguments -Wl,-z,noexecstack -shared -Wl,-soname,libnative-lib.so -o ........\build\intermediates\cmake\debug\obj\armeabi-v7a\libnative-lib.so CMakeFiles/native-lib.dir/src/main/cpp/native-lib.cpp.o -lfftw3f ../../../../build/intermediates/cmake/debug/obj/armeabi-v7a/libAudioEngine.so -llog -landroid ../../../../build/intermediates/cmake/debug/obj/armeabi-v7a/libCallback.so -llog ../../../../build/intermediates/cmake/debug/obj/armeabi-v7a/liboboe.so -latomic -lm && cd ." C:/Users/reyna/AppData/Local/Android/Sdk/ndk/20.0.5594570/toolchains/llvm/prebuilt/windows-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin\ld: error: cannot find -lfftw3f

clang++: error: linker command failed with exit code 1 (use -v to see invocation)

ninja: build stopped: subcommand failed.

回答1:

I got the single precision build to work, but its not a great solution, since I think that if I do stuff like "Clean Project" or "Refresh Linked C++ Projects" it will not work anymore and I would have to repeat the process I will describe below:

1) The CMake arguments that I specified in the question are still the same. However, I went into the CMakeLists.txt of FFTW3 and set the ENABLE_FLOAT option to ON. At this point in the process, the single precision change would only be reflected for the x86 ABI build. So, when I tried to build the project, Android Studio would complain about not finding the fftw3f library for the armeabi-v7a build.
2) I went with an idea I had seen before that we needed to build FFTW3 for each ABI, so I added the following to my build.gradle file inside of defaultConfig{}:

externalNativeBuild {
            cmake {
                arguments "-DANDROID_ABI=x86_64"
                abiFilters "armeabi-v7a", "arm64-v8a", "x86", "x86_64"

            }
            ndk {
                abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'

            }

where I would change the -DANDROID_ABI flag to the ABI I wanted to build. I am really not sure whether the abiFilters stuff is needed or not, but I'm pretty confident that the argument flag is needed. I currently have commented out the abiFilter stuff because I would get errors after installing my app into my phone about not finding my native-lib.
3) I built the Android Project with each ABI flag, which is kind of a hassle, so maybe I would need do the build multiple apks method.