So I am building my c++ project from the command line (just quicker for me to develop in) by doing "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" and then using the cl compiler. So with my project, I need to link in a static library to my project that has static global initializers in it (that have side effects). I found that I can use -WHOLEARCHIVE:libname.lib to get it to work however this bloats the .exe file. When doing my research I found in the properties settings of any c++ project in the linker setting there is a Use Library Dependency Inputs option which you can set to true (which if I understand right actually understands the dependency chain on global constructors and doesn't just dump every single thing from the library into the .exe).
So what cl compiler option/flag is equivalent to the linker option Use Library Dependency Inputs?
Related
I have a project that I would like to unit test in Visual Studio 2013. I have changed the project type to a static library (lib) after getting some linker errors and reading the answer to this question.
I do not understand the underlying mechanisms of compiling and linking in c++. In changing my project to a static library, it seems I have lost the ability to specify additional dependencies, which is a pain because I need three libs for my main project that I would like to test.
What should I do to test this project, is there a way to make my project a static library and still specify additional dependencies?
Static library is a collection of object files. No linker involved. Dependencies are not being resolved. It only requires headers to build.
Now, when you finally create an executable (or a dynamic library), you should link all the necessary dependencies.
However, note that additionally to the "classic" build process described above, Visual Studio IDE provides abstractions (convenient, but sometimes a bit misleading, especially for novices), called "Project references" and "Project dependencies". There are options to make a static library "depend" on other static libraries. Also, executable can depend on that first static library. When "Link dependencies" is enabled, Visual Studio will resolve entire dependency chain recursively and link all the necessary into your executable.
See also:
What does the “Link Library Dependency” linker option actually do in Visual Studio 2010?
MSDN - C/C++ Building Reference
MSDN - Walkthrough: Creating and Using a Static Library (C++)
What is an undefined reference/unresolved external symbol error and how do I fix it?
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.
My friend wanted me to make him this program and he is not very tech savvy. How can I make the .exe run without making him download anything extra? It was coded in C++ on Visual Studio.
If your program uses anything from the standard library, it will need the Visual C++ runtime library, which is typically loaded from the library DLLs (something like msvcr110.dll).
However you can instruct the compiler (the linker, rather) to include (I do not mean #include-ing the header file) the library as part of your executable (exe file). (I guess you thought of ISO because an archive file would include all the necessary DLLs) According to https://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx, use the /MT compiler option will cause the "multithreaded, static version" of the Visual C++ runtime library (which is the library in pre-compiled code) to be included in your program during linking (in contrast to the default /MD option, which only causes code that helps your program link to the main library DLL to be included).
Correction: The program will be larger, but since the linker does not actually add everything to the output program, the size of the output file depends on what the program uses. Microsoft Visual Studio ~ C/C++ Runtime Library ~ Static/dynamic linking This might be helpful. (If you are interested, look into Program Files (x86)\Microsoft Visual Studio 12.0\VC\lib (don't forget to replace the version number).)
Go to project settings -> configuration properties -> C/C++ -> code generation and set runtime library to Multi-threaded (MT).
Correction: it seems directly setting the compiler flag will work even with the default /MD or /MDd flag left in the command line.
EDIT: be sure to clean the solution (build -> clean solution) after applying these settings. Otherwise the linker may still try to use the old files.
There is any preprocessor trick or something in which you can compile both, a lib and dll version, at the same time of a set of functions?
The compiler doesn't have to know whether you're making a static or dynamic library -- it just makes object files.
You can then take those object files and pass them to the library manager (creating a static library) or the linker (and create a shared object / DLL), and yes you can do both with the same object files, as long as you use a linker definition file to control DLL exports.
A convenient way to do with with Visual Studio is to set up a DLL project dependent on the static library, and select the "Use Library Dependency Inputs" option for that dependency, in order to ensure that all global objects are included and not just those defined in the same compilation unit as an export. Then the files will only be compiled once, but used to build two libraries. (Of course, if you're running into issues with global objects, your static library is likely broken for other consumers anyway.)
I'm not certain of the details on how to do this in Visual Studio, but basically you'll just have to set up two build products that build from the same source code, but with different build settings, such as a macro that enables/disables the declspec() attributes used in dlls.
I think in Visual Studio this might manifest as having two projects in your solution.
To my best knowledge, you need to create two independent projects sharing the same source files. And qualify the references you want to expose with a preprocessor symbol such as _DLL, substituted with empty for a static lib or with dll_export/dll_import when building or invoking the dynamic lib.
Since the library/DLL option is per-configuration and a single project may have multiple configurations, you can do this by adding (for example) static-debug, dynamic-debug, and so on. This is similar to how the CRT is handled, with static and dynamic, debug and not, and in the past threaded and not.
In order to do this, you'll need to use the configuration manager to add additional configurations for your projects, then you can do a batch build and select any combination of those you like.
You may want to use a text editor to copy the existing configurations and rename them, if you have many custom settings which are in the project/configuration itself (instead of global project or in a split properties file).
Outputting static library or dynamic library does not depend on compiler. It is linker's job. Compiler generates .obj files which are linked by linker into (when conditions are met, such as you need entry point for .exe) what you want.
Specifically, MS linker link.exe has several output flags:
no flag: .exe is produced;
/LIB: static library .lib produced;
/DLL: dynamic library .dll and import library .lib produced;
In case of /DLL you also want to decorate your exported functions/classes with __declspec(dllexport), so linker will put them in the import library. Also, note that static library and import library are NOT equivalent, even though they both have .lib extension. There are also additional files can be produced by the linker: here is link to MSDN article on link.exe options.
EDIT: As Ben pointed out, link.exe /LIB really invokes lib.exe for static library. Running link /LIB yields (Windows SDK 7.1 SP1):
D:\Programs\Windows SDK 7.1>link /lib
Microsoft (R) Library Manager Version 10.00.40219.01
Copyright (C) Microsoft Corporation. All rights reserved.
usage: LIB [options] [files]
options:
/DEF[:filename]
/ERRORREPORT:{NONE|PROMPT|QUEUE|SEND}
/EXPORT:symbol
/EXTRACT:membername
/INCLUDE:symbol
/LIBPATH:dir
/LIST[:filename]
/LTCG
/MACHINE:{ARM|EBC|IA64|MIPS|MIPS16|MIPSFPU|MIPSFPU16|
SH4|THUMB|X64|X86}
/NAME:filename
/NODEFAULTLIB[:library]
/NOLOGO
/OUT:filename
/REMOVE:membername
/SUBSYSTEM:{BOOT_APPLICATION|CONSOLE|EFI_APPLICATION|
EFI_BOOT_SERVICE_DRIVER|EFI_ROM|EFI_RUNTIME_DRIVER|
NATIVE|POSIX|WINDOWS|WINDOWSCE}[,#[.##]]
/VERBOSE
/WX[:NO]
How do you specify, in Visual Studio 2010, the order in which library files should be linked?
I have a project that links against libexpat and against another library. This library (not under my control) seems to also include libexpat. The problem is that 'we' use a different version of the library (XML_UNICODE vs not). In Visual Studio 2008 things seemed to work out okay (might have been a coincidence), but in Visual Studio 2010 the wrong instance of libexpat is linked. I was thinking that if I could specify the order in which these two libraries should be linked that then I could circumvent the problem.
A few years back I discovered a hack that allows you to force Visual C++ to link libraries with a specific precedence. This is not elegant, but it is functional.
It seems that the linker for Visual C++ generates link order on the fly based on symbol dependencies. By adding a symbol reference up-front, you can force the linker to include the first library specified in the linker input. Please note, I have only tested this with Visual C++ 6 and 8 (2005).
Let's say for example that you have two libraries with the symbol XML_ParserCreate:
libexpat.lib - XML_ParserCreate
someother.lib - OtherSymbolsYouNeed, XML_ParserCreate
First, order your library dependencies as you would expect, libexpat.lib and then someother.lib. Via command line these would be options to link.exe. In Visual Studio 2005, they would be options under the project's Configuration Properties -> Linker -> Input -> Additional Dependencies. I would imagine Visual C++ 2010 has a similar menu.
Next, add a command line option that defines a known repeated symbol up-front, by using the /INCLUDE linker option. In Visual Studio 2005, this can be added under the project's Configuration Properties -> Linker -> Command Line -> Additional options:
/out some.exe ... libexpat.lib someother.lib
/include:XML_ParserCreate
The definition of this symbol will cause the linker to immediately prefer the first library that terminates (realizes) it. In general Visual C++ will generate an error with repeated symbols; if you haven't already, make sure you are also specifying the /FORCE:MULTIPLE linker option.
My specific need for this was using the DUMA memory debugging library. It defines a variety of memory functions that are also defined in libcmtd.lib. The following would incorrectly link libcmtd's version of _malloc, despite a library order that seems to the contrary:
/out some.exe ... duma.lib libcmtd.lib
/FORCE:MULTIPLE
This was resolved by manually adding the symbol, and has worked reliably for years:
/out some.exe ... duma.lib libcmtd.lib
/INCLUDE:_malloc /FORCE:MULTIPLE
I have found 'a' solution: if you add the libraries through #pragma comment(lib... the order of linking is the same as the order in which you type those pragma's. I'm still keeping the question open for a solution when the libraries are added through the project file instead of through pragma statements.
You could create a DLL with the third party library and link it against the static version of expat that it needs and then link your code against the version of expat you need.
However, the fact that it worked before might mean that one library has all the functionality of the other plus some extra. I don't know the details of expat. If that is the case, you need to make sure that you only have the version you want to use in your library search path. A different search directory order in the other version of the compiler could explain the change in behaviour.
I think you can change the order in which library files are linked bij adding them in the project file in linker -> input -> additional dependencies. The library files will be linked in the order in which they are specified.