How to Enforce C++ compiler to use specific CRT version? - c++

I am using VS2008 for developing a COM dll which by default uses CRT version 9
but I am using TSF (Text service framework) that is not compatible with the new CRT. I think the solution is to use the compatible one so how can I specify the CRT version?

I whole heartily join the recommendation not to manually change the CRT version you link against. If however, for some reason (which I cannot imagine) this is the right course of action for you, the way to do so is change the manifest for your project.
First make sure a manifest is not generated on every build (on VS2005: Configuration properties/Linker/Manifest file/Generate manifest), as it would overwrite your manual changes. Also make sure there that isolation is enabled.
Next, locate the manifest file - should be at the $(IntDir) (e.g., Debug). You should see a section similar to -
<dependency>
<dependentAssembly>
<assemblyIdentity type='win32' name='Microsoft.VC80.DebugCRT' version='8.0.50727.762' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' />
</dependentAssembly>
</dependency>
(For debug builds, of course). You need to edit the version and publicKeyToken attributes of the CRT element.
You can inspect the files at your local WINDOWS\WinSxS folder to see the versions available. Check here how to extract the publicKeyToken once you find the version you want. (Although I'd first try and look directly into manifests of other projects, linking against your desired CRT version).
If you do go there, expect some rough water. You may have some luck if your application is a console app that does not link against other Side-by-Side components (MFC, OpenMP, etc.). If your application is non-trivial, I'd be surprised if there aren't some intricate version dependencies amont the SxS components.
(edit) You'd also need to distribute with your application the specific CRT you're using. Here's someone who did that.

The easiest way will be to build your DLL with a VC++ version that uses the CRT that is compatible with TFS.
I don't think that it is a good idea just to link your DLL with a different version of the CRT, unless you also use the same version of the header files. And the easiest way to do that will be to use the right VC++ version...
If you still want to try, you can:
go to "Configuration settings->Linker->Input->Ignore specific library" and enter the crt you are using (libc.lib, libcmt.lib, etc. see this code project article for details).
Enter the name of the crt version you want to use in "Configuration settings->Linker->Input->Additional dependencies", and its path in "Configuration settings->Linker->General->Additional library directories".
You can also try to change the default directories in "Tools->Options->Projects and solution->VC++ directories->library files". Maybe changing $(VCInstallDir)lib to the path where you other version of the CRT resides will do the trick

Don't try to use VS9 and link to another version of the CRT.
If you need your app to link to another CRT, say VS8's CRT, then you must compile & link your app in that version of VS.

The solution worked for me with Visual Studio Express 2013 x64 + OpenCV 2.4.9 x64 compiled, debug (I integrated that in LV2013 x64), but it should work for any other VS-version:
1) Right-click on your Solution > Properties > Debug Source Files ...
2) There are maybe two entires (depending on your VS-install-directory)...
C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\vc7\atlmfc
C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\vc7\crt
With these it would work for Visual Studio 2013 Express but should also work for other 2013. If you've got Visual Studio 10 or 11 just type "Microsoft Visual Studio 11.0" or 10.0 in each. You can also just add them.
These entries you can get from your OpenCV.sln under Solution > Properties > Debug Source Files (as described above). And as already decribed: CRT needs to match... and this happens in that place.

Related

Specifying Correct VS 2012 VC/MFC Runtime Using Manifest Files in Visual Studio

We've recently converted a large MFC-based suite of projects from Visual Studio 2005/2008 to Visual Studio 2012 (Update 5). Our projects previously used a set of configuration-specific manifest files, embedded as resources, to specify the exact version of the side-by-side (SxS) assemblies to load. As an example, below here is a snippet from one of our old manifest files for the VC90 runtime:
<assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.30729.1" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
Previously, I could associate the identity above with a folder at C:\Windows\WinSxS. An example would be the folder "x86_microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.30729.1_none_e163563597edeada" which contains the correct binaries.
As you can see, the folder name contains all the information necessary to populate the assemblyIdentity node's attributes. Unfortunately, this (outdated) article confirms my findings that Microsoft no longer stores VC2010+ SxS files in this manner. I want to tell our projects to run against the latest Microsoft Visual C++ 2012 Redistributable (installer v11.0.61030.0). How do I locate the correct name/version/publicKeyToken information for these binaries? I could not find an MSDN listing or similar.
Note that I've been using sxstrace.exe / Dependency Walker and the like to investigate this issue. I can confirm the manifest files are being appropriately embedded in our executables; the issue is only the manifest files are specified incorrectly.
Thanks in advance!
Look at this. As I remember correctly by default your application will be linked to libs as in your Windows SDK. And to make project use default libs just delete info about them inside your project file or recreate project with default settings.

Release .exe for vs2012 c++ requesting MSVCR110.dll

I'm attempting to compile a release executable using vs2012 Express. However, whenever I try to run the .exe on other computers, I get a warning that I need msvcr110.dll. I could simply copy the dll over, but I'm looking for a more long term solution.
In my attempts to isolate what is causing the error, I have reverted back to a new c++ project using the default settings, except for changing the configuration to release in the configuration manager.
I've been trying to solve this on my own for over a week now without any progress, so any suggestions would be appreciated.
Link to the CRT statically. Choose "Multithreaded", and not the DLL option in the Runtime Library dropdown in the project properties.
In your project properties choose option Configuration Properties/C/C++/Code Generation/Runtime Library and pick option 'Multi-threaded (/MT)' (or 'Multi-threaded Debug (/MTd)' for your debug configuration).
For dynamically linked applications, the Visual C++ Redistributable for Visual Studio 2012 must be installed in target machines. Be sure to choose the architecture that matches your application.
Statically linking will obviously work, too, but I tend to classify this as a workaround.

Distributing the Visual C++ Runtime Libraries (MSVCRT)

I have an ATL/WTL project developed using Visual Studio 2008 and up until now I have been statically linking with the CRT libraries, avoiding the need to ship them. However, I now need to consider using the dynamic libraries (DLL) instead - in order to reduce the size of the code and because I want to use the excellent crashrpt tool (which requires you dynamically link to the CRT.)
Now, MS supply both a stand-alone installer (vcredist_x86.exe) and an MSM package but this is no good for me for two reasons:
I am not using an MSI based installer (I am using InnoSetup).
My application installs on a limited user account and the vcredist_x86.exe installer will not work.
Therefore I want to ship the CRT DLLs and install then in my applications program folder. Now, this is something you can do as I found the following blog post by Martyn Lovell, the MSVC Libraries Development Lead that says:
However, if you want to
install-applocal, you should make sure
that your application has a manifest,
and then copy the whole of this folder
into your EXE directory:
X:\Program Files\Microsoft Visual
Studio
8\VC\redist\x86\Microsoft.VC80.CRT
and other folders if you use more than
the CRT. Make sure you include the
manifest.
Just want I am after - except I don't understand this part:
make sure that your application has a manifest
My question is - how do I create an application manifest that references the CRT DLLs I want to use? The only manifest information my projects currently use is the following (which ensures the app uses v6 of the Common Controls):
/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"
Can someone provide me with instructions on how to work the manifest magic using Visual Studio 2008? There is a Microsoft.VC90.CRT.manifest file in my Visual Studio VC\redist\x86\Microsoft.VC90.CRT folder - do I need to use this somehow?
Note: This is a similar - but different - question to this one.
Visual Studio will generate the correct manifest for you when you pass the /MD flag.

How to select the version of the VC 2008 DLLs the application should be linked to?

I'm using Visual Studio 2008 SP1 for C++. When compiling, Visual Studio needs to choose against which version of the CRT and MFC DLLs the application should be linked, version 9.0.21022.8 (= RTM), 9.0.30729.17 (= SP1) or 9.0.30729.4148 (= SP1 with security update). I'd like to know how you can choose which of both versions will be linked against. Does anyone know?
Note: this is important when using a private assembly, because you need to know which versions of the VC 9.0 DLLs to copy along with the .exe.
Note that the _BIND_TO_CURRENT_VCLIBS_VERSION flag only makes sure that the right version is included in the manifest. The DLL version selection at runtime is apparently not done based upon the version that is included in the manifest file. Even if the manifest file says that v21022 should be used, the .exe uses the v30729 .DLLs. I know this, because it uses std::tr1::weakptr, which is not present in v21022.
_BIND_TO_CURRENT_VCLIBS_VERSION sets the current version in the manifest - or the RTM version if not.
And setting it in the manifest is the correct way to do this.
What you are seeing however is the effects of an assembly policy file :- When the VCRedist package containing the 2008 SP1 runtime is installed, it installs a policy file into the WinSxS store with a bindingRedirect entry that redirects attempts to load the RTM runtime to the SP1 runtime.
So applications that specify the RTM runtime in their manifest will load the SP1 runtime, and applications that specify the SP1 runtime, will load the SP1 runtime.
If you actually DO want to use the RTM runtime, even when the SP1 runtime and policy files are installed, then you need to specify the RTM version in your manifest, AND make use of an application configuration file. Basically "yourappname.exe.config" ( or "yourdllname.dll.2.config" if its an isolation aware dll causing grief).
Application congifuration files can supply a bindingRedirect element that overrides any assembly version specified in the manifest, or policy files.
This config file will tell the OS to load the RTM runtime even if the SP1 runtime is installed :-
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<configuration>
<windows>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.VC90.CRT" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"/>
<bindingRedirect oldVersion="9.0.30729.1" newVersion="9.0.21022.8"/>
</dependentAssembly>
</assemblyBinding>
</windows>
</configuration>
Note: oldVersion is allowed to be a range: oldVersion="9.0.30729.1-9.1.0.0"
See: Application Configuration Files documented on MSDN.
By defining
#define _CRT_ASSEMBLY_VERSION "9.0.30729.1"
or
#define _MFC_ASSEMBLY_VERSION "9.0.30729.1"
you can link against a specified version.
The compiler uses the .h and .lib files to determine what CRT code to use. Change your include and lib search directory build settings for your project to look in the directories where the appropriate .lib and .h files exist.
That said, why do you feel the need to use anything but the latest CRT?

A C++ Application Compiled With VS2008 Doesn't Run In Other Computer

I have created a wn32 project with Visual Studio 2008 and Visual C++ language, it uses the ws2_32.lib library and then I compiled in Release mode.
It runs very good in the same computer, but when I copy the exe file to other computer (that doesn't have installed Visual Studio), it doesn't run.
The message I see is:
This application has failed to start because the application configuration is incorrect. Reinstalling the application may fix this problem.
But, if I compile my application using DEV C++, it generates a bigger executable (738KB) compared with the Visual Studio 2008 executable (9.5 KB). However, the DEV C++ executable runs in the other computer.
I have add the library ws2_32.lib to the linker properties of my project, in the Additional Dependencies field.
How can I fix it to work with Visual Studio 2008?
My code is the following: http://www.stan.com.mx/yupi/udpserver.cpp
The problem is almost certainly that the other computer does not have version 9 of the C++ CRT installed.
The default setting for compiling against the CRT in VS2008 is to dynamically link vs. statically linking. If you want to deploy your program with a real setup project you'll need to include the CRT redistributable.
However if you want to do an XCOPY deployment follow the steps on the following page.
http://msdn.microsoft.com/en-us/library/ms235291.aspx
Try installing the Visual C++ redistributables. If that doesn't work, use DependencyWalker to find out what DLLs are missing.
I agree with JaredPar. The application you build with VS2008 is using dynamic linking, whereas the DEV C++ is linking statically, hence the larger size and why one works and not the other.
However, if its a plain win32 application project you've got (and you don't want/need to distribute it with a setup), you may be able to get it to run on another machine without redistributing the CRT by getting VS2008 to link statically for you (if its just the standard lib you're missing). I don't have a copy of VS2008 to hand, so I'll describe how to do it in VS2005 and hopefully it'll translate across.
Bring up configuration properties for the project (right click the project name, then select "properties" from the menu)
Expand "Configuration Properties", then "C/C++", then click "Code Generation"
Under the "Runtime Library" item, for your particular configuration select the non-DLL version of the library i.e. for debug builds you want "Multi-threaded Debug (/MTd) and for release builds you want "Multi-threaded (/MT)"
Try and see if that works. You'll obviously get a much bigger final binary now the library is statically linked.
You may be missing an external dependency required by your program. Check the project settings to see if you are linking against MFC dynamically for example. You can also run Depends utility to check for missing dependencies.