How to check the static library dependencies in Windows? - c++

I have a dependency like this in a large project:
MyEXE --> MyDLL --> MyStaticLib
Which means that my executable (MyEXE) is dependent on a dll (MyDLL) and the dll uses an static lib (MyStaticLib). The problem is that I can call the MyStaticLib methods from MyEXE and it compiles and links without any issues. I checked the Linker/Input page on Visual Studio (2015) of MyEXE project, but I cannot find MyStaticLib as one of the dependencies of MyEXE.
Now the questions are:
How it is possible for MyEXEto call MyStaticLib methods without any explicit dependancies?
Is there any tools on Windows to list all of the static libs used by an executable? (here is a solution for Linux)
Update 1: There is no #pragma comment(lib, ...) directive in the headers of the MyStaticLib. So, the static lib cannot be linked to the .exe using this directive.

MSVC at least has a mechanism for implicit dependencies, done through the #pragma comment(lib, ...) directive. Check the headers for the static library and make sure that there is no such.
Also, if using a static library provided through 'vcpkg' and you have done "vcpkg integrate install" an MSBuild file is added to the project build system that automatically imports everything that vcpkg generates.
Also, link.exe has a /VERBOSE:LIB option that will print out the libraries that are searched, though it won't tell you why that particular library was added to the build.

Related

Cannot open curl/libcurl_a_debug.lib

In my current project I'm using the library libcurl, previously installed by powershell. I'm including it using #include "curl/curl.h" and compiling works but I have a linking error that says:
:LNK1104:cannot open file curl/libcurl_a_debug.lib
I dont have this file. In my current directory i found only libcurl.lib. I already added the path to the directory in Additional library directories and Additional include directories. I'd like to know is any other way to solve this error.
In release mode i have an error that linker cannot open file libcurl_a.lib. On the other hand in debug folder i have a libcurl-d.lib file.
According to Microsoft Docs, there are several common causes for this issue:
The path to your library file may be incorrect, or not wrapped in
double-quotes. Or, you may not have specified it to the linker.
You may have installed a 32-bit version of the library but you're
building for 64 bits, or the other way around.
The library may have dependencies on other libraries that aren't
installed.
By the way, could you add libcurl.lib in Properties->Linker->Additional Dependencies? If not, you could add it.
You could try to use compiled statements instead of settings.
#ifdef _DEBUG
#pragma comment(lib,"..\\debug\\lib name")
#else
#pragma comment(lib,"..\\release\\lib name")
#endif
Also, I read the official documentation of curl. There is a description of Windows link errors:
5.7 Link errors when building libcurl on Windows!
You need to make sure that your project, and all the libraries (both static and dynamic) that it links against, are compiled/linked against the same run time library.
This is determined by the /MD, /ML, /MT (and their corresponding /M?d) options to the command line compiler. /MD (linking against MSVCRT dll) seems to be the most commonly used option.
When building an application that uses the static libcurl library, you must add -DCURL_STATICLIB to your CFLAGS. Otherwise the linker will look for dynamic import symbols. If you're using Visual Studio, you need to instead add CURL_STATICLIB in the "Preprocessor Definitions" section.
If you get linker error like "unknown symbol __imp__curl_easy_init ..." you have linked against the wrong (static) library. If you want to use the libcurl.dll and import lib, you don't need any extra CFLAGS, but use one of the import libraries below. These are the libraries produced by the various lib/Makefile.* files:
Target: static lib. import lib for libcurl*.dll.
-----------------------------------------------------------
MingW: libcurl.a libcurldll.a
MSVC (release): libcurl.lib libcurl_imp.lib
MSVC (debug): libcurld.lib libcurld_imp.lib
Borland: libcurl.lib libcurl_imp.lib
I suggest that you could try the method.

How do I statically link FFTW on windows?

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.

how to add static lib from other cmake module

assuming I have 2 cmake modules
MyStaticLib which is after compilation will be a static library
Connector which is a shared lib or executable, and it's should use MyStaticLib inside.
So, I want to add MyStaticLib inside Connector but not simply put myStaticLib.a + headers in some folder, but reference MyStaticLib module from Connector, so when Connector compile it will build lib from sources and use it.
What is a proper way to do that in cmake?
In case of independent projects (MyStaticLib is used by other projects to, has it's own release cycle), you can use:
find_library:
Build, test and install MyStaticLib into your file system
add find_library into Connector's CMakeList.txt
find_package
Similary to above but MyStaticLib provides additional information
ExternalProject
In case you want to trigger any additional actions (build, patch) on MyStaticLib before usage by Connector
Gives you the most possibilities
In case of dependent projects (MyStaticLib is a subproject of Connector), just add it as subdirectory of Connector (It must be a subdirectory).

Qt 3rd Party Library Static Linking (QtSerialPort)

Turns out static linking was working, but only for Qt libraries. My 3rd party library QtSerialPort is not linking statically. After some reasearch, I've found that I either have to build this library statically or I have to link directly to a .pri file in my .pro file.
I'm not sure how to do either since it seems QtSerialPort has not been designed for static linking.
The .pri method I really don't understand and has been vaguely described in these two links:
http://qt-project.org/forums/viewthread/15223
http://www.qtcentre.org/archive/index.php/t-54505.html
Does anyone have any adivce on how to get either of these methods to work? Or possibly another method?
Also, MSVCP100.dll is not linking statically if anyone could give me any advice on that.
==================================================================================
I am trying to get Qt to statically link libraries so that I can make a standalone application. I have followed various tutorials on how to build Qt statically then building a static application but I am not having much luck. I believe I have succesfully built Qt with static linking because the application has grown in size from 79KB to 7+MB but I am still getting errors saying QtCore4.dll and QtSerialPort.dll are missing. Also, another issue I'm having when using this static configuration, which isn't too serious, is that when I close my program Windows thinks it has crashed and gives me a window saying MyProgram.exe has stopped working...
I am on a Windows machine using MSVC 2010 with Qt 4.8.5 and am using the third party library QtSerialPort.
What I've done accoring to the guides I've been reading is:
Download and extract qt-everywhere-opensource-src-4.8.5.zip
Open /mkspec/mwin32-msvc2010/qmake.conf and change the follwing lines to
CONFIG += qt warn_on release incremental flat link_prl precompile_header autogen_precompile_source copy_dir_files debug_and_release debug_and_release_target
and
QMAKE_CLFAGS_RELEASE = -O2 -MT
I then open the MSVC2010 command prompt and cd to this . I then enter the commands
configure -static -release -platform win32-msvc2010
nmake sub-src
After this is done I open my project and add
CONFIG += static
to the .pro file. In QtCreator I then go into Projects, Manage Kits then to Qt Versions and browse to the qMake I just generated. I add a new Kit with this version of qMake. I then clean all and switch to this new kit and run qmake from QtCreator. I then use msvc2010 command prompt to go to the directory where the files are generated and then
nmake release
This generates a rather large .exe but like I said, it's still depending on a couple .dll's.
For static linking of external library one have a couple options, both have their pros and cons.
I. Compile the library for static linking yourself. Link to it.
Look for possible existing configuration switches for static linking. There can be something like QTSERIALPORT_STATIC = no, etc. in the library's .pro/.pri files. Just say yes for the library to compile for static linking and go to the step 4!
In .pro/.pri file replace CONFIG += dll with CONFIG += static.
Remove export declarations from the library. Typically Qt library symbols are declared with some definition like QTSERIALPORT_EXPORT which expands to Q_DECL_EXPORT/Q_DECL_IMPORT in shared library build / its header files usage when linking. You'll need to find where this QTSERIALPORT_EXPORT is defined and replace it with empty definition:
#define QTSERIALPORT_EXPORT // in source file
or
DEFINES += QTSERIALPORT_EXPORT # in .pro/.pri file
Build the library.
Link to the library .lib/.a file, use the library header files for symbol declarations in your project.
II. Include the library source files into your project and compile them within it (no linking at all).
Include all the source files of the library into your project (add to SOURCES in qmake project file)
Determine all the stuff the library depends on (other libraries, Qt options, etc.) and include it also into your .pro file.
OR
Include the proper .pri file into your .pro if the library author provides it for in-project compilation (i.e. include(QtSerialPort.pri) or something.)
Remove export/import declarations from the library source code — as described in the item 3 of part I.
Build your project.

The library file name with "lib" head can't be recognized in codeblocks and vs9 compiler

This environment is win7, codeblocks,vs9,boost1.52,
I have installed boost library with python library.It generates some library files.Such as "libboost_python-vc90-mt-gd-1_52.lib".
Then I write a test code to compile and link.But an error has occurred: can not open file "boost_python-vc90-mt-gd-1_52.lib".
The VS compiler don't recognized a library file name with "lib" head?How to do it better.
Adding a lib prefix at the start of the name is a Linux thing. On Windows there is a .lib at the end instead.
If the library is named "libboost_python-vc90-mt-gd-1_52", you have to give exactly that name to the linker.
First of all, Boost uses auto-linking under Windows. Thus, you only need to provide the location of the boost libraries, but not the names themselves.
Second, Boost uses different filenames for statically and dynamically linked libraries. The ones with lib prefix are for static linking, the ones without for dynamic linking.
By default, Boost uses static linking on Windows. Defining BOOST_ALL_DYN_LINK (there are library specific macros as well if you only want to dynamically link certain libraries) will enable dynamic linking.
From your error message, it seems that your project has BOOST_ALL_DYN_LINK enabled (either in the project settings, as a #define or in <boost/config/user.hpp>. If you prefer static linking, make sure to change/remove this setting.
Either way, make sure that the respective binaries are available and that their location (just the directory) is known to the linker.