Exe performs full link when Library changes, despite incremental linking - c++

I have an MSVC++ project consisting of an executable, several own static libraries and some precompiled static third party libraries. The exe uses incremental linking in order to speed up build time.
When I change a .cpp file within the executable project, compiling + linking is very quick (<10s).
However, when I change a .cpp file within one of my own libraries, the executable project appears to be doing a full link against every library it uses.
I'm not so sure anymore if it is a full link in fact, but from the "vc90.pdb not found" Linker Warnings, I can tell that it links against some external libraries which have not changed at all.
Here's an example of the project structure:
Precompiled third party libraries ExtLib1, ExtLib2 and ExtLib3
Own Library MyLib, using third party lib ExtLib1
Own Exe MyExe, using MyLib and ExtLib1-3
Changing a .cpp file in MyLib would then lead to MyExe being linked to MyLib, ExtLib1, ExtLib2 and ExtLib3, even if Incremental Linking is turned on.
A full link takes around 5 minutes in my project, so I'm asking: Is there any way to re-link only the changed library?

This is a introduction to incremental linking. It lists situations that will cause a full link. One of them is "An object that was compiled with the /Yu /Z7 option is changed.", check if your MyLib caught it.

When a static library changes there will always be a full link for the executable, at least in Visual Studio 2013, and you will probably get something like this in the output window:
2>Link:
2> LINK : library changed; performing full link
Good news though: I did a quick test in Visual Studio 2015 and incremental linking seemed to work as expected.
Source: lots of experimentation and looking around, having had the same problem. Also, this: http://www.pcreview.co.uk/threads/incremental-linking-and-multiple-projects.1431266/ , specifically:
This is by design. We can't incrementally link when a static lib changes.
That was never supported before either.
Ronald Laeremans, Visual C++ team
Edit - it's confirmed that VS 2015 has incremental linking when using static libraries: http://blogs.msdn.com/b/vcblog/archive/2014/11/12/speeding-up-the-incremental-developer-scenario-with-visual-studio-2015.aspx .

Related

Are lib files exclusively statically linked or do they need to be compiled specifically (VS2015)

I have some confusion about static and dynamic linked libraries and .lib and .dll files.
I have a project with two libraries, one I built myself and one is from an open source library.
The one I built myself is a separate project in the same solution (Visual Studio 2015, C++), and I don't need to copy over the .lib files or create a DLL for the executable to build and run
For the other open source library, I do need to copy over the .lib file and the DLL into the executable folder. However, I thought it would be possible to statically link a .lib file and not have to copy over the DLL.
Does this mean I need to compile the Open Source library differently? Like change the define __declspec(dllexport) to __declspec(dllimport) ? Or change /mD to /mT in compiler options?
I tried both of these, but it's still saying that it can't start without the .dll
Or can I get away with changing a setting in the executable project to link this library statically? If so, what are these settings?
EDIT: I know this is a standard question that can be looked up on google, but I haven't been able to find an exact answer for a while. Mainly, I'm confused about what settings need to be changed, and which project they need to be changed in. (The library or the executable).
I'm under assumption that static linking means the library is built into the executable, and dynamic linking means the library needs to be in a separate file, if this is incorrect, please let me know. Otherwise, I need to know how to build the library into the executable file.
And I can go ahead and change the build options in the open source library, and I tried this already.
Thanks,
-D
In Windows, dll files (dynamically linked libraries) need to be in the same directory as the application or on the search path. lib files (static libraries) need to be statically linked during linking (the last step of building the application). It's common in Windows so have a library come with both a dll and lib file. In this case, the lib file is an import library containing the information needed to easily link to the dll.
Place the dll file where your application will be built and statically link with the lib file. Go to 'Project->Properties->Link->Input->Additional Dependencies' and 'Project->Properties->Link->General->Additional Library Directories' to specify the static libraries you want to link.
Edit: It seems I misunderstood the question. The question is how to recompile a dynamic library as a static library. You need the source code of the library you are using along with it's Visual Studio Project file. Open the library and in `Project->Properties->General->Configuration Type' change it from Dynamic Library to Static Library.
Beware that Dynamic Library uses the Linker group of properties while the Static Library uses the Librarian group of properties. Changing between these types may cause the project to drop essential linker flags options. Since every library is different, I can't predict what you will have to do work around this. Make sure to backup the project file so you can see the original options and flags.
I had to change the setting for "Static Library" for All Configurations, not just Debug, although it was building in Debug. Not sure what may have caused this. Possibly because the debug and release builds for the library were set to the same folder, it may have been overwriting the debug builds with release builds when building

Visual Studio (C++) is automatically linking against an unwanted version of lib file

I am trying to create a C++ project in Visual Studio 2013 that has CGAL and Boost (and a couple of other libraries) as dependencies. I preferably like to link to these libraries dynamically. Also, I'd like to link to the "Release" versions of these libraries for performance reasons (not the "Debug" versions).
Starting from an empty C++ project, I added the path to header files of the aforementioned libraries as shown in the image below:
Inside the linker options, I then added the directories that contain the DLL and lib files of the external libraries. (CGAL directory contains CGAL's compiled DLL files along with lib files).
At this point, I have not added a single "lib" file "Additional Dependencies" dialog:
Now something weird is going on and I cannot explain why. If I try to build the project as-is (under the "Debug" configuration), I get a LNK1104 error about the linker not being able to find CGAL-vc120-mt-gd-4.7.lib. I know that the error means I should add the lib file in "Additional Dependencies" dialog...
But wait... WHAT...?!!
How does Visual Studio know how to automatically link against this lib file?! Worse yet, how does it know it needs the "debug" version of the library? (With the gd suffix). Also, how does it know I compiled CGAL with VS2013!!??
At first, I though the project was inheriting properties from some preset property sheets somewhere in my system. But I am certain that's not the case as this behavior shows even with a project created from scratch.
My main question is, how would you force Visual Studio to link against the "Release" version of this library? (eg. CGAL-vc120-mt-4.7.lib)
Side question but related: Am I even linking against the DLL files? How can I be certain that I am in deed doing dynamic linking and not static linking?
This is probably happening due to the #pragma comment(lib) mechanism - eg see What does "#pragma comment" mean?
This is a way of the compiler emitting instructions for the linker so that it can decide between multiple versions of a library depending on the compiler version. In this case it means that it can automatically pick up the correct version of the library (debug vs release, vs2013 vs vs2015, MT vs MD, etc). When you added the explicit reference to the library in Additional Dependencies then it is now trying to look for two files.
So, to fix the problem, remove it from Additional Dependencies and let VS pick the right library. If you are getting the LNK1104 error then it suggests that either the link library path isn't set up correctly, or you don't have the CGAL library file it's looking for. You can increase the verbosity settings for the linker in the Project Options to get more detail about what's happening.

How can a static release lib be linked into a debug build?

The Gameplay Project distributes a set of static libraries of all it's dependencies. The libraries they include will link in a debug or release build of an application. I ran the strings command on their lib and compared it to one I compiled. The linker directive /FAILIFMISMATCH:"RuntimeLibrary=MD_DynamicRelease" is set in my library, but not theirs.
How did they compile their library this way?
Edit: Clarification
I failed to mention that this occurs on the next branch, which uses libs compiled for VS2012. The _MSC_VER of the libraries is 1700.
I am aware that you shouldn't link different versions of the CRT, but I'm wondering how they were even able to compile it this way.
It seems MS has started adding /FAILIFMISMATCH:"RuntimeLibrary line from vs2012. /FAILIFMISMATCH itself is introduced in vs2010. I've chekced Gameplay Project sln file and it is using vs2010. Try to use vs2010 and see if the directive is gone.
I think you already know this but it doesn't really matter if the directive is there or not because you must match the runtime library compile option anyway.

Build C++ project to include ALL msvc dlls

I have a simple C++ program. I want to just build the exe and give it to a person on another complete non-development box. Is there a way to build such a simple, single-source file to an executable in Visual Studio without needing all the crap ? I have changed the program to compile in MT mode, instead of MTD which statically linked the msvcr.dll file, but now it is looking for msvcp.dll file. How can I compile so that my executable either 1) doesnt include all this junk or 2) statically links it all so that I have exactly one file to transfer to another Windows PC to run
Thanks
If compiling with /MT is requiring msvcr100.dll, something included in your application is probably trying to link with it, possibly a third party component. I would check any third party libraries and related.
MSVCP100.DLL is the C++ standard library. You might want to double check that it's not looking for MSVCP100D.DLL, which is the debug version; mixing release and debug mode libraries could cause this.
MSVCRT100.DLL is the C run-time library, and MSVCP100.DLL is the C++ standard library. Both should go away if you build with /MT, in that case static versions of these libraries should have been used.
My guess is that you either did not fully rebuild your app after switching to /MT, or that one or more files in your project have custom settings that include /MD. You may want to open the properties dialog box on the page that shows the /MT and then click on all your source files one by one to verify that none of them still show /MD.

Why is VisualStudio looking for this lib file? LNK1104 error

We have a large project using VS2008 and boost 1_42. I'm trying to upgrade to VS2010 and boost 1_44. I installed VS2010 and boost 1_44 and converted the project. Now I am trying to build, and everything compiles, but fails when linking:
LINK : fatal error LNK1104: cannot open file 'libboost_thread-vc90-mt-1_42.lib'
I have changed the include and lib directories to point to the new boost 1_44 files and I have renamed the old boost 1_42 directory.
Why is the linker still looking for a vc90-1_42 file, when it is only using 1_44 headers? Is there a way that I can determine WHY the linker wants this file? The linker obviously thinks it needs the file, but why?
I have cleaned the project and I am re-building to ensure any old build files are erased.
I've run into exactly this problem a couple of times too. It's usually been some old temporary files but like in your case cleaning didn't always do the trick straight away. Does your project include any static libs that might have been built with 1.42?
Something you can try which may or may not be helpful in tracking down your issue:
Rename the old boost directory back to it's original name
Clean the solution
Under C/C++->Command Line->Additional Options add "/showIncludes"
Under Linker->Command Line->Additional Options add "/verbose:lib"
Rebuild all
Then when you build you'll be able to see at which point 1.42 headers are included, etc. in the output window. Somehow doing this helped me in tracking down where the problem was.
Along with changing the lib directory, you need to change the name of the boost library. That's in the Linker | Input section of the project settings.
Your added comment makes it clear that the dependency on the Boost 1.42 library was being created indirectly by another library that hadn't been rebuilt.
For this you basically have two choices: either add that library as a project to your main solution, and make sure it has enough dependency information that it'll be re-built when you upgrade Boost, or use the /Zl compiler switch when you build your library. This tells the compiler you're building a library so you do not want to embed library dependencies like this.
Boost uses
#pragma comment(lib)
command to inform the linker of libraries it needs to link with. It is not an error. If Boost says you need it, it's likely you do.
On How can I find out why the linker wants this file?
There are programs which will go through your app and dlls/libs and report the content of manifests and what the binaries report they depend on. You could then scan the report for the unexpected libraries being included. We used this mainly to find libs including the previous version of the VC runtime.
Have not used the one we had in about 5 years though, now if only I could remember the name of the app!
DependancyWalker (depends.exe) will allow you to see dependancies of dll/exe but not static libs.
You could open each binary as a 'file' in MSVS and look at the manifest content by hand, but I imaging this would be a bit painful. I've not tried this with a static lib.