How do I statically link FFTW on windows? - c++

During the setup of my project - when I knew even less than I do now about cmake - I was trying my hardest to link the FFTW library.
C:\\path\\to\\fftw-3.3.5-dll64 contains the .h files, .lib files (generated from .def files) and .dll files.
What I ended up doing was adding these links to my CMakeLists.txt:
add_executable(${TargetName} PRIVATE main.cpp)
target_include_directories(${TargetName} PRIVATE "C:\\path\\to\\fftw-3.3.5-dll64")
target_link_directories(${TargetName} PRIVATE "C:\\path\\to\\fftw-3.3.5-dll64")
target_link_libraries(${TargetName} PRIVATE libfftwf3-3)
After building this, the application was still not working. Eventually, I figured out that on opening the executable, windows was looking for the libfftw3-3 dll file. At the time I just wanted to get it working, so I copied the .dll files that are included with the library - even though this is shared/dynamic linking, not static linking.
I'm now trying to properly statically link the library; I removed the dll's from my build folder and filtered my CMakeLists.txt file down to:
add_executable(${TargetName} PRIVATE main.cpp)
target_include_directories(${TargetName} PRIVATE "C:\\path\\to\\fftw-3.3.5-dll64")
target_link_libraries(${TargetName} PRIVATE libfftwf3-3)
This builds, as I would expect it would. However, even though, in my CMakeLists.txt file, I've taken the steps to statically link the library, I'm still required to copy the dll's over in order for the executable to run (its dynamically linking still).
(Successful) verbose build output: https://pastebin.com/bbrZdd7r

The LIB files you generated from the DEF files are "stubs". They contain just enough code to load the DLL and call functions from it. They do not contain the actual FFTW code. You cannot statically link with these pre-built FFTW LIBs.
You will need to compile FFTW into a static library yourself first. It comes with a CMake build file where you can turn off BUILD_SHARED_LIBS.
edit: on review, your question is nearly identical to this one, with the same answer.

libs can be either static or dynamic. The one's generated (following the instructions in the README-WINDOWS file) are shared (they link to the .dll files inside the same folder.
With the windows binaries provided by FFTW, you cannot statically link (because all they provide are the dynamic libraries (.dlls). If you look at the file size of the .lib file, it's very small, because it's just a reference to the .dlls.
Follow the instructions on FFTW's windows page, for building the library from the source. Because you're now building the library yourself, you have the option to turn of "shared-library" and make a "static" lib.

Related

decoupling app and libraries in CMake project

I had a project that was configured to be:
CMake Project
static Lib A src (depends on B)
static Lib B src (depends on Qt)
App src (statically links with LibA)
Each of these folders had its own CMakeLists.txt but all were part of the same CMake project. Things were working fine.
Then for the purpose of more easily separating the library source and the app source into different source code repositories, I started to learn about the creation of CMake packages and performing find_package on LibA. I rearranged things so that now the libraries are their own CMake project, which requires I run "cmake --build . --target install" to put the packages in a common area (not in the build folder).
The app similarly became its own CMake package, and I thought I would only need to find_package(LibA). It turned out I also needed to find_package on LibB because there was one header that the App needed. But the unexpected part is that the App needed to find_package on Qt5Widgets, Qt5Core, and Qt5Gui just as LibB did. That's the part that I don't quite understand. When everything was one giant project, the App's CMakeLists.txt only needed to link against LibA. Was all of the other stuff just taken care of without me knowing? Am I naive to think that performing find_package on LibA and LibB would somehow cause the Qt libs to be linked in to the App as well?
This might be a lousy question, because I have things working again. I just want to make sure I understand the why.
Using static libraries in C++ does not pull in their dependencies, so they have to be specified explicitly while linking the executable (as compared to dynamic ones).
A static library is essentially a pre-compiled archive of functions (an object file), which get linked into your applications by your C++ linker in a similar way as any other object file would. As such, it does not include information about its dependencies.
A shared (dynamic) library is a more complex (and generic) thing, allowing to load and link code run-time. This is done by a dynamic linker, which will also bring it any dependencies of the loaded library recursively.
For this reason, if you want to avoid specifying the dependencies explicitly, a dynamic library might be a better choice (it might be a better choice for a variety of other reasons as well :) ).

creating a static library and linking using Cmake

I have a application which need to use two libraries (pugixml and lua) and need to be an multi-platform build capable. I am trying to use Cmake for this. Since I have three different solution (two for creating static libraries and one solution which actually uses that libraries). So far what I do is run Cmake for those two libraries and copy those static libraries manually to the lib folder into application and run cmake again.
I need to reduce the three step and make it as a single step so that I can handle the multi-platform build in a single shot.
I need to know, should we need to create a dynamic link library or shared library or static library for these kind of operation?
And need help on how to do it. I tried creating the source folder of pugixml and copy the cpp/hpp/h file and wrote a cmakelists file like
set(HEADERS pugixml.hpp pugiconfig.hpp)
set(SOURCES ${HEADERS} pugixml.cpp)
add_library(pugixmlLib STATIC ${SOURCES})
target_link_libraries(pugixmlLib pugixml)
On the solution I could see my application project and pugixml project, but on my application project linker property I could find pugixml library.

Statically linking to libarchive on Windows with MinGW

I've been using libarchive in my project for some time now and it's working great, at the moment I am dynamically linking to it, so on Windows the libarchive.dll file has to present on the system.
I would now like to statically link to the library so I don't have to bother distributing the DLL, but I'm having real trouble trying to achieve this!
Currently, in my make file, I have something like this:
-Lpath/to//libarchive/ -larchive
And this works, but it does a dynamic link. I don't know how to enforce a static link.
I can see in the libarchive directory there are two a files, libarchive.dll.a and libarchive_static.a. I suppose I want to link to libarchive_static.a but I can't seem to specify this, doing -larchive_static in the make file results in linker errors.
I was under the impression that static libraries under windows are lib files, but I get no such file type when I build libarchive.
How can I make a .lib file from libarchive. Also, as an extra question, what is the difference between an a file and a lib file?
Update
To statically link to libarchive, your library command for make should contain:
-Lpath/to//libarchive/ -larchive_static
This will link to the libarchive_static.a file. However, you also need to define LIBARCHIVE_STATIC in your code.
Now the problem is that libarchive depends on the bzip2 libraries (as well as others), and if you do not have a static build of them you will get linker errors something like:
undefined reference to `BZ2_bzCompressInit'
You need a static build of the dependent libraries and a similar command to the linker after the libarchive command:
-Lpath/to/bzip2/ -lbzip2
You can either build bzip2 from source, or do it the easy way and get a pre-built binary from the Gnu32Win project here: http://gnuwin32.sourceforge.net/packages.html
Just add libarchive_static.a explicitly to your link command.
gcc -o YourApp.exe $(OBJS) path/to/libarchive_static.a $(OtherLibs)
".lib" files differ from compiler to compiler (Borland, Microsoft etc.), ".a" is an old "archive" format from UNIX's ar tool. It is now used only for the bundling of static libraries.
Currently, in my make file, I have something ...
And this works, but it does a dynamic link
The .a file actually contains some code for dynamic linking to the .dll file, not the libarchive itself. On the startup the pointers to functions are allocated and dynamic linking is done.

QtCreator - use static dll lib

I want to make my app without any dependancies for the users. It works well when I put the dll files into the same folder as my exe.
I'm trying to set all those libraries to static use the following code in my pro file (Qt 4.8.1):
QMAKE_LFLAGS += -static-libgcc
CONFIG += static
The previous code doesn't change anything.
Here are the dll file I have included into my project folder:
libgcc_s_dw2-1.dll
mingwm10.dll
QtCore4.dll
QtGui4.dll
The fact is I don't want my app be more than a file and I don't want the users to download libs files, which are heavy (9mB for the last one).
Is there a way to compile a Qt project and use static libs?
I've tried to read some tutorials I've found on the Internet but they are all outdated. For what I read too, the solution would be to rebuild the Qt source code staticaly.
To be able to fully statically compile against Qt you need to rebuild the framework as static, using the pre-compiled framework isn't enough - unless you have a commercial license and can get the static binaries.
See: http://www.formortals.com/how-to-statically-link-qt-4/, http://www.formortals.com/build-qt-static-small-microsoft-intel-gcc-compiler/ and http://doc.qt.nokia.com/4.7-snapshot/deployment.html#static-vs-shared-libraries for more information.
Download already compiled libraries. If you are building against a platform, use cross-compiled libraries of that. You can link those libraries in Makefile statically [in #INCLUDE and LIBS variable in makefile]. The only drawback is your exe size will be increased.

Compiling libraries with CMake under Cygwin

I have been trying to compile TinyXML using CMake as a sort of mini project, trying to learn CMake. As an addition I am trying to make it compile into a dynamic library and install itself so it works.
So far I have managed to get it to compile and install BUT it compiles into a .dll and a .dll.a and the only way to get it to work is to have it install into both /bin and /lib, which makes it install both files in both folders. This setup works but I'm guessing the .dll should be in /bin and the .dll.a should be in /lib. Is this some sort of Cygwin-specific problem or am I doing something wrong?
The .dll is the runtime library file, which must be present on the target system on run time (and be in $PATH there). The .dll.a file is the import library for the .dll, which must be present on the compiling machine at link time. You need to distribute the .dll file to the places where the program should run, and both .dll and .dll.a to places where the library is used to link other programs. you don't need the .dll.a file on the machines running the program only.
When you don't want to create a shared library, you can tell this to cmake with the static keyword in the add_library command:
add_library(mylib STATIC foo.c bar.cpp)
This way there will no shared library created, but the code from the library will be added by the linker into the final executable file.
What you need is to specify a destination for each type of file.
The .dll is considered a RUNTIME library and the .a is an ARCHIVE. Just in case, for other platforms, you probably want the LIBRARY entry (for .so files).
install( TARGETS ${PROJECT_NAME}
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin
)