How to Enforce C++ Compiler to Use Specific Crt Version

How to Enforce C++ compiler to use specific 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.

How to execute some code before entering the main() routine in VC?

There's some information here (search for CRT). The significance of variable pinit is none, it's just a piece of data placed in the executable, where the runtime can find it. However, I would advise you to give it a type, like this:

_CRTALLOC(".CRT$XIC") static void (*pinit)()=...

The linker warning probably just warns you you have a function that has int return type, but doesn't return anything (probably you'd better change the return type to void).

How can I target a specific version of the C++ runtime?

While I'm pretty sure that Christopher's answer and code sample (thank you, Christopher!) is part of a more elegant solution, we were under the gun to get this out the door and found a very similar, but different, solution.

The first step is to create a manifest for the assembly:

<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
<dependency>
<dependentAssembly>
<assemblyIdentity type='win32' name='Microsoft.VC80.DebugCRT' version='8.0.50608.0' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' />
</dependentAssembly>
</dependency>
<dependency>
<dependentAssembly>
<assemblyIdentity type='win32' name='Microsoft.VC80.CRT' version='8.0.50608.0' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' />
</dependentAssembly>
</dependency>
</assembly>

Next you have to set the 'Generate Manifest' option to 'No' under Configuration Properties -> Linker -> Manifest File, and set the 'Embed Manifest' option to 'No' under Configuration Properties -> Manifest Tool -> Input and Output.

Finally, to get your new manifest into the assembly add the following command to the project's post-build step:

mt.exe /manifest "$(ProjectDir)cppassembly.dll.manifest" /outputresource:"$(TargetDir)\cppassembly.dll";#2 -out:"$(TargetDir)\cppassembly.dll.manifest"

Once built we can open the dll in Visual Studio to view the manifest under RT_MANIFEST and confirm that it has our manifest!

When I put Christopher's code in the stdafx.h it ended up adding it as an additional dependency...the manifest was still looking for v8.0.50727.762. The manifest it generated looked like this:

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.VC80.DebugCRT" version="8.0.50608.0" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
</dependentAssembly>
</dependency>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.VC80.DebugCRT" version="8.0.50727.762" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
</dependentAssembly>
</dependency>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.VC80.CRT" version="8.0.50727.762" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
</dependentAssembly>
</dependency>
</assembly>

I could not track down another switch that would remove or clear existing dependencies. I like Christopher's approach better than a post-build step, but for now this works. If anyone has any additional input on how to clear out any existing dependencies that'd be great.

Thanks!

Visual Studio 2015: Compile C/C++ without a runtime library

To compile your app without C-Runtime Library (CRT) use /MT, /NODEFAULTLIB linker options and redefine entry point at Linker -> Advanced -> Entry Point to function defined in your code, e.g. rawMain. The signature is:

DWORD CALLBACK rawMain();

Without C-runtime library you are not allowed to use it's functions, like malloc, free, memset, etc. You should implement all the used CRT functions by yourself. E.g. you can replace usage of malloc by VirtualAlloc() and free by VirtualFree().

To check that C-runtime is not linked to your application use Dependency Walker.

How can I force MSVC++ to ignore CRT dependencies of a static library?

A .lib does not have any linker settings because you don't link it, you link to it. A .lib is just an archive of .obj files, sort of like an uncompressed .zip file - that's why you have to put the setting on all projects that link to it.

If you're using VS2005+ you could use property sheets so that you only have to put the setting in one place and then use that property sheet in all projects.

However, OpenSSL is just that - Open Source, so you should be able to get the source for the version you are using and build it again (and add it to your version control system of course). I thought OpenSSL could be built as a DLL or LIB, which would solve your problem as the DLL would not interfere with the linking of your code.

Failing that, you always have the option of slitting your functionality out into a separate DLL so that you only have issues with one project.

Can I use Visual Studio 2010's C++ compiler with Visual Studio 2008's C++ Runtime Library?

Suma's solution looked pretty promising, but it doesn't work: the __imp__*@4 symbols need to be pointers to functions, rather than the functions themselves. Unfortunately, I don't know how to make Visual C++ spit out a pointer with that kind of name generation... (well, __declspec(naked) combined with __stdcall does the trick, but then I don't know how to emit a pointer).

If using an assembler at build-time is OK, the solution is pretty trivial - assemble the following code with FASM and link against the produced object file, and presto - no EncodePointer/DecodePointer references in the exe:

use32
format ms coff

section ".data" data
public __imp__DecodePointer@4
__imp__DecodePointer@4 dd dummy

public __imp__EncodePointer@4
__imp__EncodePointer@4 dd dummy

section ".text" code
dummy:
mov eax, [esp+4]
retn 4

How to buid a Visual C++ project targeted to a specific Visual C++ Redistributable version

however that is a highly controlled environment

Which is the problem, that machine hasn't received the latest security updates for the CRT. If that machine is also the originator of the installer then you'll certainly get the problem you describe, you are asking for a DLL version that's not available on the machine.

Deploying files to a user's machine that has known security problems is definitely a kind of policy that needs to be reviewed. Defining the _CRT_ASSEMBLY_VERSION macro is the correct approach, but do consider setting that macro in the project settings instead of your source file so you can be absolutely sure that it is set before vc/include/crtassem.h gets #included. Project + Properties, C/C++, Preprocessor, Preprocessor definitions setting.

And yes, certainly on all your projects.



Related Topics



Leave a reply



Submit