Search code examples
visual-studio-2015mingwstatic-librariesvisual-studio-2019fftw

Build FFTW lib with Visual Studio 2015 [added: steps for VS 2019]


I'm trying to use Visual Studio 2015 to compile a project that uses FFTW. Unfortunately, the precompiled binaries from the FFTW website aren't compatible with VS 2015, due to this problem: unresolved external symbol __imp__fprintf and __imp____iob_func, SDL2. You get a link error when you try to compile.

I'm looking for any advice on how I can compile a compatible version. The obvious answer would be to recompile FFTW with VS 2015, but I can't find any instructions on how to compile it with Visual Studio at all, and lots of suggestions that it would be hard to do that. The standard version was compiled with MinGW, and they do provide instructions on how to do that. But can MinGW produce a library compatible with VS 2015? I haven't found any information about that either.


Solution

  • I eventually managed to figure this out myself. I don't promise I did it in the best way, since I'm not a Visual Studio expert, but it did work. So for the benefit of posterity, here's what I did.

    First, duplicate config.h.in. Call the new copy config.h. Now edit it by hand to set options for the library you're going to generate: what precision mode it should use, which vector instruction sets (if any) to compile for, the sizes of various types (which will depend on whether you plan to compile in 32 or 64 bit mode), whether to include threading support, etc.

    Now create an empty VS project. I recommend putting it at the top level of the source folder. Then in the Solution Explorer, click the "Show All Files" icon at the top. This will make the following steps easier, since you can add or exclude files directly from the Solution Explorer.

    Bring up the Project Properties window. There's a lot of options you'll need to set:

    In General, set "Configuration Type" to static library. (Or you can set it to dynamic library if you want a DLL, but then you'll need to figure out how to get it to export the necessary symbols. I didn't do that, since I wanted a static library.)

    In VC++ Directories, edit "Include Directories". Add the following directories (replacing "(source dir)" by the actual directory containing the source):

    (source dir)
    (source dir)\api
    (source dir)\dft
    (source dir)\rdft
    (source dir)\reodft
    (source dir)\kernel
    (source dir)\simd-support
    (source dir)\dft\simd
    (source dir)\dft\scalar
    (source dir)\rdft\simd
    (source dir)\rdft\scalar
    

    If you're including threading support, then in C/C++ > Language, set "Open MP Support" to yes.

    If you're including AVX support, then in C/C++ > Code Generation, set "Enable Enhanced Instruction Set" to AVX. This means the library you generate will not work on any computer that doesn't support AVX. You might be able to get around that restriction by only setting this option on the individual source files that use AVX. I'm not sure about that.

    In C/C++ > Output Files, set "Object File Name" to $(IntDir)/%(RelativeDir)/. (FFTW has a lot of files with the same names but in different directories, and by default VS puts all object files in the same directory, which won't work.)

    Now you're ready to add source files to the project, which you can do by right clicking in the Solution Explorer and choosing "Include In Project". You should add all .c files in the following folders:

    api
    dft
    dft/scalar
    kernel
    rdft
    rdft/scalar
    reodft
    

    If you want threading support, you should add all source files in "threads" except for threads.c. (That one contains the pthreads version.)

    If you want support for any vector instruction sets, you should include only the files relating to the particular instruction sets you want from the following folders:

    dft/simd
    rdft/simd
    simd-support
    

    Presumably if you want mpi support, you include the files in "mpi". I didn't do that, so I don't know if there's anything else you'll need to make that work.

    Be sure to set the configuration to "Release" and either "x86" or "x64", depending on what type of binary you want.

    And now, if I haven't forgotten anything critical, you should be able to compile a library.