Interesting LNK1104 error when using the static version of boost::filesystem - c++

I'm trying to test out some code which makes use of boost::filesystem for various things.
I built the static version of boost 1.51 for vc11, and the intended libraries came out as expected.
Here are the flags I used:
b2 --with-filesystem --build-type=complete --build-dir=.\build link=static runtime-link=static
And here's the list of files it generated:
libboost_filesystem-vc110-mt-s-1_51.lib
libboost_filesystem-vc110-mt-sgd-1_51.lib
libboost_filesystem-vc110-s-1_51.lib
libboost_filesystem-vc110-sgd-1_51.lib
libboost_system-vc110-mt-s-1_51.lib
libboost_system-vc110-mt-sgd-1_51.lib
libboost_system-vc110-s-1_51.lib
libboost_system-vc110-sgd-1_51.lib
I then created a new Win32 DLL project and added the proper include/lib directories.
But when I try to compile, I get the following output:
LNK1104: cannot open file 'libboost_filesystem-vc110-mt-gd-1_51.lib
But this file does not exist because (afaik) it IS NOT the static version of the library...
Which is odd because I never asked to link against the DLL version anywhere in my project!
So why is my project complaining about a library which I never asked to use?
Do the boost headers automatically try to link against their corresponding libs?
Is there some sort of preprocessor flag I should be setting to tell boost I want to use the static, single-threaded version of boost::filesystem?
UPDATE:
I have been informed in the comments that boost does in fact try to auto-link for compilers which support it, via <boost/config/auto_link.hpp>...
After several attempts to properly configure these headers to use the static, /MDd (debug) & /MD (release) versions of boost, I am still getting this error.
So if anyone could tell me how to properly configure OR disable this feature, I will mark it as the answer.
Also, am I correct in assuming that libboost_filesystem-vc110-s-1_51.lib and libboost_filesystem-vc110-sgd-1_51.lib are the proper /MD and /MDd libs?
Thanks!

To disable auto-link you need to define BOOST_ALL_NO_LIB. From the boost documentation:
// BOOST_ALL_NO_LIB: Tells the config system not to automatically select
// which libraries to link against.
// Normally if a compiler supports #pragma lib, then the correct library
// build variant will be automatically selected and linked against,
// simply by the act of including one of that library's headers.
// This macro turns that feature off.
But don't do that - it will not solve your problem. Auto-link is usually right, i.e. you are either linking to the wrong libraries or you have incorrectly configured your preprocessor macros. If linker wants to link to the shared libraries I would guess that you defined BOOST_ALL_DYN_LINK or BOOST_FILE_SYSTEM_DYN_LINK and BOOST_SYSTEM_DYN_LINK. Remove it and it should link just fine.

Related

How do I setup a Codeblocks project on Windows 10 to compile and link a static SFML project?

My advance appologies for being hopeless at Windows development. I am by no means a Windows developer and my understanding of how to write, compile and link C++ code on a Windows system is limited to say the least.
I am having difficulty trying to compile and link a SFML project on a Windows 10 system with the CodeBlocks IDE.
I am trying to link this project with static linking, not dynamic linking. Again I have virtually no idea how the two different methods work in detail, I just know that if I ship a static linked binary to another Windows 10 user it is much more likely to "just work" on their system.
List of things I did:
Downloaded the latest version of CodeBlocks with MINGW integration.
Installed, default options
Downloaded the latest version of SFML (32bit MINGW version)
Extracted the zip file (SFML) to my home directory
Created a new codeblocks project (console application) and followed the instructions to set the compiler and linker options
https://www.sfml-dev.org/tutorials/2.5/start-cb.php
It works fine for dynamic linking, but requires me to copy the .dll files to the same dir as the produced executable file (produced from compilation of my C++ code).
I tried to change to static linking, changing the names of the linker libs with the -s or -s-d suffix, and adding the define SMFL_STATIC option to global (release and debug) options. I also added the opengl32, freetype, winmm and gdi32 link libs, before their respective sfml link libs.
When trying to compile I get the following linker errors
cannot find -lfreetype
cannot find -lsfml-graphics-s-d
cannot find -lsfml-window-s-d
cannot find -lsfml-system-s-d
in Release mode, similar errors are produced.
What am I doing wrong?
My hunch would be that you either have the wrong compiler (see below) or you haven't defined the library directory as mentioned in the linked tutorial.
There are four common things to consider when using SFML (and essentially any other C++ library) on Windows.
Compiler versions have to fully match
Make sure to not mix x86 and x64
Settings need to be specified for the correct configuration
When linking libraries statically, you also need to link the dependencies
Compiler versions have to fully match
Since C++ doesn't have a standardized ABI, the generated libraries will never be reusable between compilers. Yes, sometimes "it works", but it can break at any point and there's no guarantee.
We strongly recommend to either use the compilers linked on the SFML Download page or build SFML from source with your current compiler.
If you got the latest stable Code::Blocks version with MinGW as stated, you should also be able to get a snapshot build of SFML, which should be using the same compiler.
Note: One exception to this rule is Visual Studio, where VS 2017 binaries are compatible with VS 2019 (and maybe VS 2022?).
Make sure to not mix x86 and x64
When you download a 32-bits (x86) version of SFML, you also need a 32-bits version of your compiler. When you download a 64-bits (x64) version of SFML, you also need a 64-bits version of your compiler.
Make sure you double check your compiler configuration that you've selected the correct bit-ness.
Note: For Visual Studio you need to select the correct compiler architecture in the IDE, usually positioned right next to the run button.
Settings need to be specified for the correct configuration
Project configurations are usually spread across the matrix built from the types:
Debug / Release / All
x86 / x64 (for VS)
Make sure when you add the settings for library paths and include paths that it's not just set for debug or release and ends up missing in either or the other configuration.
Also make sure you're not setting up debug libraries (with the -d suffix) in release mode or release libraries (without any suffix) in debug mode.
When linking libraries statically, you also need to link the dependencies
The SFML static libraries don't contain any symbols of any of its dependencies, that means, in your final application you have to link static SFML and all its dependencies.
As a short summary you can think of static libraries like an archive of object files. These object files will directly be linking into your application, like you link your own source file object files. As such, the SFML static libraries only contain object files of SFML itself and not of other libraries as well.
Troubleshooting
If nothing seems to help, then you should enable verbose compiler & linker output, that we you see exactly which commands are invoked and one can quickly spot the missing statements.

CMake: Override libraries added by target_link_libraries

So I am running into a pretty large headache building my software with CMake.
I am building a third party library statically (dlib) which requires zlib and libpng (both also static, I prebuilt these) libraries to support PNG functionality. The CMakeFile provided by the COTS dlib library is doing a basic:
target_link_libraries( dlib ${dlib_required_libs})
This is making all of its libraries configured as "general" libraries, which end up being used for both Release and Debug builds.
This isn't an issue in Linux, but Windows has a lovely "feature" of specifying the runtime library (/MT or /MD or /MTd or /MDd). Any mismatches between these flags cause multiple symbol definition errors at link time. i.e. If libpng was built with /MT and my software is using /MTd, they will be incompatible.
To alleviate this, I have two built versions of zlib and libpng. One set using the /MT flag for Release builds and the other /MTd for Debug builds. These happily link into my own software using optimized/debug flags on target_link_libraries where they are used. HOWEVER, dlib (3rd party) is only linking the Release set of the zlib and libpng libs by the way it's CMakeFile has been written.
My main question is, is there a way I can 'override' what dlib is linking without modifying it's provided CMakeFile?
I attempted overwriting dlib_LIB_DEPENDS and forcing it into the cache out of desperation, to no avail.
FindPNG.cmake script, like many other Find*.cmake scripts used by find_package(), does not care about multiconfig builds. So it just searched single library, while multiconfig builds naturally want library-per-config.
For make searched PNG library to be per-config, one can to write own FindPNG.cmake script (and set CMAKE_MODULE_PATH to point to the directory with this script).
But for concrete usage it is simpler to just rewrite output of the original script, that is set PNG_LIBRARY cache variable pointed to library-per-config:
optimized png-lib-release debug png-lib-debug
or, using generator expressions,
$<$<CONFIG:Release>:png-lib-release>$<$<CONFIG:Debug>:png-lib-debug>`
(instead of png-lib-release and png-lib-debug should be paths to the release and debug version of the library conrrespondingly).
Both these values are expected to be used with target_link_libraries command,
producing per-config linkage.
Dlib comes with copies of libpng and zlib in dlib/external. By default, dlib's CMakeLists.txt will build them the correct way and statically link them into your program. So the solution is to let it do that. Don't try to create a separate static library because, as you noted, that causes a lot of trouble on windows.

Linker error LNK1104 with 'libboost_filesystem-vc100-mt-s-1_49.lib'

During the process of linking my program to the boost::filesystem module in release mode I get the next error:
error LNK1104: cannot open file
'libboost_filesystem-vc100-mt-s-1_49.lib'
However, in the boost\stage\lib directory I only have the next libraries referred to filesystem module:
libboost_filesystem-vc100-mt-1_49.lib
libboost_filesystem-vc100-mt-gd-1_49.lib
My questions are:
Why does the VC++ is asking for 'libboost_filesystem-vc100-mt-s-1_49.lib?
Which compiler/linking properties should I change to get the compiler to ask for libboost_filesystem-vc100-mt-1_49.lib?
UPDATE: My VC2010++ solution has 2 projects that include the previous boost library: x is a library and y (the main program) which invokes to x.
When I build x with Configuration type=Static library and RuntimeLibrary=Multi-threaded (/MT), it is ok.
When I build y with Configuration type=Application (.exe) and RuntimeLibrary=Multi-threaded (/MT), it issues the error I indicated, if I change to Configuration type=Static library it builds ok, but my main program has .lib extension and not the expected .exe.
You are using /MT or /MTd option in C/C++/Code Generation/Runtime Library which require static library, boost default build with shared library output. You can switch Runtime Library to /MD or /MDd. An other option is recompile boost with static library output and you'll get 'libboost_filesystem-vc100-mt-s-1_49.lib'..
I had a similar problem with a recent project (inherited from a long legacy).
Here is a "poor man's" solution to this issue:
Rebuild the boost libraries with all variants, to be sure that you have the correct variant for your needs.
Run:
.\b2 --build-type=complete
Note that the boost build time will obviously be longer with this option.
This is not an elegant solution, but I didn't have time to mess about figuring out which exact option I needed for my project, so I just built them all.
You can paste the following characters into you control console (win+r----cmd , then go to boost src directory , find the bjam.exe)
ps:double click the bootstrap.bat can get bjam.exe
bjam --toolset=msvc-1.0 --stagedir=./lib_x64 --builddir=./ address-model=32 link=static variant=release runtime-link=static threading=multi stage debug releasde
libboost_filesystem-vc100-mt-s-1_49.lib
"link=static" correspond to -s-
"threading=multi" correspond to -mt-
"runtime-link=static" correspond to lib prefix
"variant=release" make sure libboost_filesystem-vc100-mt-s-1_49.lib don't contain -gd-
The boost libraries that you have in your boost\stage\lib directory are linking dynamically to the standard C++ libraries. See the following post:
boost lib build configuraton variations
Your code is linking statically to the standard C++ libraries, hence a mismatch. Try linking your code dynamically to the standard libraries. (Project Settings->General->Configuration Type)
run below command to rebuild boost in static in VS2013 x86 Native Tools Command Prompt.
b2 -link=static
Add your linker library paths in your project link path in VS.
Then, rebuild your project, error gone.

How to link Boost in a dependent static library

In MS Visual C++ 2010
I had a single C++ project in my solution which used boost and worked perfectly.
I then decided to convert this project into a static library and create a new project which depends on this static library.
Now, my converted static library builds without errors and warnings (compiler and linker)
but the new project compiles but does not link.
I am getting:
1>LINK : fatal error LNK1104: cannot open file 'libboost_thread-vc100-mt-1_45.lib'
As a test I added the full directory path to the linker options for this library... and then it complained about
1>LINK : fatal error LNK1104: cannot open file 'libboost_date_time-vc100-mt-1_45.lib'
I have now added complete paths to all the libraries and it now builds and run.
I am not happy with this solution because:
I don't want users of the library to
have to worry about linking in
boost.
It is messy
I know an answer would be to create a DLL but is there a way to do this statically and keep the linking at my static library level.
Edit:
If I tell the .exe linker to ignore the boost libs explicitly then it all is ok except the .exe should not have to worry about boost at all.
/NODEFAULTLIB:"libboost_thread-vc100-mt-1_45.lib" /NODEFAULTLIB:"libboost_date_time-vc100-mt-1_45.lib"
Apparently you don't need the .libs, as your exe also links without them. You seem to be using boost header-only methods and classes. So just tell boost to disable auto linking by defining the preprocessor symbol BOOST_ALL_NO_LIB in your project.
If you want to make your .lib unnecessary big by including all of boost, this question seems to hold an answer (which I never really tried myself): Linking static libraries to other static libraries
When building your library, you can include the boost libraries in yours. To do so, in VisualStudio's Librarian > General property page, list your boost libraries as Additional Dependencies.
However, there may be a problem if your clients use boost themselves, and statically link to it (especially a different version than the one you are using).
Did you build boost library? There are certain libraries in Boost that needs to be compiled. In case if you haven't done that, refer to "Getting started in Windows" on how to build the Boost library.
EDIT-1: Boost can be built both as a static and dynamically loadable (dll) libraries.
EDIT-2: If you have already built Boost, then the answer by #Daniel Gehriger tells you how to add it in VS.

Boost autolinks libraries which are not built by Boost, but the intended ones are built

I am developing a Math application which can be extended by writing python scripts.
I am using Qt 4.6.3 (built as static library, debug and release versions) and Boost 1.43.0 (built as static library, runtime-link also set to static, multi-threaded version, debug and release). Everything is built with MSVC++2008. Boost built the following libraries:
libboost_python-vc90-mt-s-1_43.lib
libboost_python-vc90-mt-s.lib
libboost_python-vc90-mt-sgd-1_43.lib
libboost_python-vc90-mt-sgd.lib
My project compiles, but gives the following error during the linking phase:
1>Linking...
1>LINK : fatal error LNK1104: cannot open file 'boost_python-vc90-mt-gd-1_43.lib'
Why is it not selecting one of my compiled libraries?
I think the s in the library names stands for static, but then the auto-linking feature seems to select a dynamic library, and I want it all linked statically in one executable.
The same happens with the regex library: I have the same 4 regex libraries compiled and a quick test shows this linking error:
1>LINK : fatal error LNK1104: cannot open file 'libboost_regex-vc90-mt-gd-1_43.lib'
What to do?
You can define BOOST_ALL_NO_LIB. This prevents automatic linking of boost libraries and you must then link the required boost libs manually.
If 's' stands indeed for static (I don't know all those modifiers by heart), define the BOOST_ALL_DYN_LINK symbol while compiling (add it to the command line options). It tells boost to link to the DLL libraries. Alternatively, compile/install static boost libraries.
The problem is fixed, during the compilation of the boost libraries, I selected the link=static option. Which creates static libraries. I also selected runtime-link=static option, and this was wrong!
The solution for this problem was compiling boost with runtime-link=shared. Now some extra libraries are added, with the correct filenames, so the linker can find them. At first the compiler still searches for the dll library (boost_python-vc90-mt-gd-1_43.lib, instead of libboost_python-vc90-mt-gd-1_43.lib), everything else from boost links automatically to a static library, but because boost.python has a different auto-linkage set up, when you provide BOOST_PYTHON_STATIC_LIB, it finally links to the right library and it works!