atlbase.h and different versions of VC CRT - c++

I have a C++/CLI project created with Visual Studio 2010 that targets .NET Framework 3.5 and PlatformToolset v90. Initially it requests the VC CRT of version 9.0.21022.8, but if I include atlbase.h header then it requests the VC CRT of version 9.0.30729.6161.
Why does this happen? And how can I make it to target 9.0.30729.6161 without including atlbase.h?
I tried to define macroses _BIND_TO_CURRENT_CRT_VERSION=1 and _BIND_TO_CURRENT_VCLIBS_VERSION=1 but this didn't help.

The version is set by vc/include/crtassem.h, near the bottom you can see:
#ifndef _CRT_ASSEMBLY_VERSION
#if _BIND_TO_CURRENT_CRT_VERSION
#define _CRT_ASSEMBLY_VERSION "9.0.30729.6161"
#else
#define _CRT_ASSEMBLY_VERSION "9.0.21022.8"
#endif
#endif
So the rule is that you can explicitly override the version by #defining _CRT_ASSEMBLY_VERSION. Don't do that. As you noted in your question, #defining _BIND_TO_CURRENT_CRT_VERSION to 1 gets you the version string you want.
Having a problem with this in a C++/CLI project is possible. You can compile C++/CLI code without ever #including any of the CRT include files. So you'll end up with a default version which, ironically, is defaulted by the linker to its own version of the CRT. So a workaround is to explicitly put #include <crtassem.h> in one of your source code files. #including atlbase.h would do that too since it does include CRT headers but of course is the big hammer approach.
Additional troubleshooting is available from Project + Properties, C/C++, Advanced, Show Includes = Yes. You'll see a trace of all the #include files getting included in the Output window.
Beware that you'll now have the additional burden to ensure that the up-to-date version of msvcr90.dll gets deployed on the user's machine. Your program will fail to start if it is missing or old.

Related

Why is my generated precompiled file so big when using a boost based library?

I'm working on a project using libraries handled through vcpkg.
As compile time wasn't that great, I did some headers clean up and configured the project to use precompiled headers, putting STL and vcpkg headers inside.
I started to run into the infamous C1076, C3859 and C1060 errors, and a quick check to the generated pch showed me a massive 1.2GB file ...
I ran a build using the /showIncludes switch, and it appears that spirit-po, a Boost based library that I use for translations, references more than 2600 Boost headers. (My project just has 70 files, with nothing fancy)
It's the only Boost based library used in the project.
Just to be sure this was the culprit, I removed everything but the spirit-po files from the pch :
#pragma warning(push)
#pragma warning(disable : 4267)
#include <spirit_po/spirit_po.hpp>
#pragma warning(pop)
and the resulting generated file is still 1GB big ...
There's no difference in size between debug and release build.
With an empty pch file, the generated file is around 4MB.
Provided that a 250MB file is considered big, how come I end up with a file 4 times that size ?
With just that library in the pch I don't have errors compiling anymore, but I don't want the problem to arise again in the future.
I'm using Microsoft Visual Studio Community 2019 Version 16.8.4.
What are my options to improve the situation ?
Could this be a misconfiguration in Visual Studio ?
Do I have to ditch the library altogether to remove the Boost dependency ?
Is there another alternative ?
Thanks for reading me :)
Header only libraries work because there are no details left out of those headers.
Precompiled headers contain all the compiled information of the headers before start of the translation unit.
A large part (the majority) of boost libraries are header only. To add insult to injury, they're highly generic meaning there will be many templates and their instantiations.
1 + 2 + 3 are the perfect storm. If the size is a concern, your better bet is to shield boost from your headers and include them in the select translation units that actively depend on them.
While doing some more research, I came across the following libraries :
tinygettext :
+ Doesn't depend on Boost
- Needs Iconv library to work, which isn't that trivial to make it work on Windows even if it's available as a vcpkg package
spiritless_po
+ Doesn't depend on Boost
+ Self contained
- Not compatible with spirit-po
I tested both, and I must say the last one is a perfect fit for my use, which is to use directly po files as translations ...
I guess it's not a fit all solution, but it might be enough for some.

C++ Linux code breaks the Windows build because missing headers means the functions are undefined

I am developing a piece of software in C++ using Visual Studio on Windows. From the beginning, I would like to have it run on both Windows and Linux. Obviously, I won't compile the Linux binary on a Windows machine, but I still want to use Visual Studio to write the code.
When it comes to headers, I am selecting while file to use based on pre-processor definitions.
A very rudimentary and simple example:
#pragma once
#ifndef PLATFORM_TIMER_H
#define PLATFORM_TIMER_H
#ifdef _WIN32
#include "win32\win32_timer.h"
#elif __linux__
#include "linux\linux_timer.h"
#endif
#endif // PLATFORM_TIMER_H
For the header it works just fine. But the .cpp-file for the Linux implementation breaks the build on Windows. That's because the Linux .cpp-file will get compiled no matter what, even on Windows. And because the Windows machine is missing Linux-headers, the function it uses will be undefined.
Question 1: What is the "industry standard" to deal with this?
Question 2: Is it reasonable to wrap both the .h and .cpp-files in "#ifdef PLATFORM" so that the code will only be enabled on the correct OS?
But the .cpp-file for the Linux implementation breaks the build on Windows. That's because the Linux .cpp-file will get compiled no matter what, even on Windows.
Why are you compiling the Linux-specific file for a Windows build?
Question 1: What is the "industry standard" to deal with this?
If you're going to create separate source files for Windows-specific and Linux-specific code, then the whole point would be that you use only the appropriate one for the current platform when you build.
An alternative approach would be to have both implementations in the same source file, using conditional compilation to choose which parts to use. That's pretty conventional, too, especially where the parts that vary are smaller than whole functions.
Question 2: Is it reasonable to wrap both the .h and .cpp-files in "#ifdef PLATFORM" so that the code will only be enabled on the correct OS?
It would be strange to go to the trouble of creating separate, platform-specific source files and then use conditional compilation to include them all in every build. It could work, but it would not fall within my personal definition of "reasonable".
Any code specific to one operating system needs to have the proper #ifdef's set up, whether in header files or source files.

Apple LLVM 6.0 preprocessor magical #if defined()

I'm currently working on a project which has a lot of dependencies. It is written in Objective-C with C++ libraries. It uses cross platform code with conditional compilation for different platforms in the libraries.
After the latest update I have encountered a peculiar issue with preprocessor macros with this
#if defined(DEBUG)
#warning WARNING_1
#elif defined(DEBUG_gibberish)
#warning WARNING_2
#elif defined(SOMETHING)
#warning WARNING_3
#else
#warning WARNING_DEFAULT
#endif
code.
In this case DEBUG macro is defined in Xcode Apple LLVM 6.0 Preprocessing section
Please see the pic
So basically the problem is that #if defined() doesn't work as expected for this particular project. If I copy the same code to some clean test project it works as expected.
It also has another interesting effect, if I define DEBUG_gibberish then it will be evaluated instead of else case. After performing a couple of experiments it seems that it always evaluates/uses the first true condition and then the second true condition or #else if there was no second true condition.
I have already tried to clean project, clean derived data, restart Xcode, reboot my mac and even voodoo dolls.
I would appreciate any thought on why this happens and how to fix it.
EDIT1: I have a hierarchy of Xcode projects in my main project. The problematic library is a subproject in my main project. If I try to build it separately it works fine. If I compile it as dependency from main project I encounter this issue.
Ok, I have found the problem.
I use some of the headers from third party libraries in my project to make my own subclasses of libraries' classes.
I believe Xcode gives a composite representation of warnings:
In my code it shows WARNING_1 after preprocessing of the header in
library where DEBUG macro is defined.
Then it shows WARNING_DEFAULT after preprocessing the same header
in my project where DEBUG macro is not defined.
But both warnings are shown as if they are in the same file.
By doing that it led me to conclusion that something is wrong with preprocessor or my code. Because of that I didn't think about simple thing that my project and library are built separately and my project doesn't contain needed macros.
So in the end solution was simple, I had to define needed macros in my project and then it compiled fine.

How to get rid of _WIN32_WINNT not defined warning?

_WIN32_WINNT not defined. Defaulting to _WIN32_WINNT_MAXVER (see WinSDKVer.h)
This error keeps popping up during my compilation. It doesn't seem to affect compilation, but how should I get rid of it? Am I risking anything by ignoring it?
Set it to the oldest Windows Operating System you want your program to run on.
The possible values are given in this MSDN article, Using the Windows Headers.
You can define these symbols by using the #define statement in each
source file, or by specifying the /D compiler option supported by
Visual C++.
For example, to set WINVER in your source file, use the
following statement:
#define WINVER 0x0502 // Windows Server 2003 with SP1, Windows XP with SP2
To set _WIN32_WINNT in your source file, use the following statement:
#define _WIN32_WINNT 0x0502 // Windows Server 2003 with SP1, Windows XP with SP2
To set _WIN32_WINNT using the /D compiler option, use the following command:
cl -c /D_WIN32_WINNT=0x0502 source.cpp
It is defined for you through WinSDKVer.h. So just define it explicitly on the top of your source code (e.g. in the beginning of stdafx.h) and you will get rid of the warning.
Having it defined to the same value (as compared to _WIN32_WINNT_MAXVER from WinSDKVer.h) is highly unlikely to break anything.
For example, WinSDKVer.h of Windows® Software Development Kit (SDK) for Windows 7 and .NET Framework 3.5 Service Pack 1 contains:
// This list contains the highest version constants supported by content
// in the Windows SDK.
// [...]
#define _WIN32_WINNT_MAXVER 0x0601
Solving in VS2019
Ways to solve this and a link to possible values to use can be found here in the super answer by user93353 which I used to solve the problem.
https://stackoverflow.com/a/12871547/3070485
However, after reading the solution, I set my compiler option in my IDE which is Visual Studio 2019.
For anyone wanting to set it there quickly and wanting to know the location (as these things change from IDE release to release, or maybe someone is more familiar with another IDE), here is where it went.
Configuration Properties
C/C++
Preprocessor
Preprocessor Definitions
_WIN32_WINNT=0x0502
Note: the #define _WIN32_WINNT must occur before any header file, including "stdafx.h".
If using MFC: My preferred answer is to include windows.h. But if you are using MFC, you cannot do this*. To avoid defining WINVER in your project, instead you can include sdkddkver.h before afx.h.
#include <sdkddkver.h>
#include <afx.h>
The sdkddkver system header sets WINVER and _WIN32_WINNT so you don't need to add it to your project. This does the same as windows.h for versioning windows SDK/DDK from the system headers.
*if you include windows.h before afx.h you get: #error: WINDOWS.H already included. MFC apps must not #include <Windows.h>
#define _WIN32_WINNT and #define WINVER can occur in a header, so long as they occur before including SDKDDKVer.h or any headers from the Windows SDK (in particular Windows.h). Visual Studio VC++ projects typically provide a targetver.h header, where you can include WinSDKVer.h, define _WIN32_WINNT, NTDDI_VERSION and WINVER, and then include SDKDDKVer.h. Comments within this file say:
// If you wish to build your application for a previous Windows platform, include `WinSDKVer.h`
// and set the _WIN32_WINNT macro to the platform you wish to support before including `SDKDDKVer.h`.
The Microsoft article Update WINVER and _WIN32_WINNT goes out of its way to instruct you to define _WIN32_WINNT and WINVER in targetver.h (though it mentions these can be defined using command-line parameters, too).
Note: targetver.h gets included in certain .rc resource files generated by Visual Studio, so this is another reason to fill out the contents of the targetver.h file as described, above.
Note: defining _WIN32_WINNT, NTDDI_VERSION and WINVER using command-line parameters or preprocessor directives within the project's build configurations can also work, but neither takes care of the need to include WinSDKVer.h and SDKDDKVer.h.
Note: when using the Windows 8.1 SDK (or newer), you may also need to define WINAPI_FAMILY in targetver.h depending on the specific Windows platform (server, desktop, phone, store, etc.) you need. See winapifamily.h for details.
Note: In newer Windows SDK versions, the values NTDDI_VERSION, WINVER and _WIN32_IE can be set automatically based on the value you define for _WIN32_WINNT. However, you may want to define a more specific version for NTDDI_VERSION explicitly prior to including SDKDDKVer.h.

Windows library inclusion in CMake Project

I have a growing project in CMake. It is time to link to a library, which at this time exists only in Windows, Linux functionality will have to wait. I am attempting to do this with preprocessor directives as recommended in an answer to this question:
// MyLibHeader.hpp
#ifdef WIN32
#include <windows.h>
#define ProcHandle HINSTANCE
#define LoadLib LoadLibraryA
#define LoadSym GetProcAddress
#else
// ... I'll fill these in with dlopen etc. when necessary
This is the first platform specific inclusion I have had to put in my code, and It seems there is more to it than this. This is generating this error:
C:\Program Files (x86)\Microsoft Visual Studio 8\VC\include\intrin.h(944) : error C2733: second C linkage of overloaded function '_interlockedbittestandset' not allowed
The error is repeated four times, twice in intrin.h, and twice in winnt.h. So here's my question. Are there other includes or preprocessor steps I need to take to get this to work inside windows (up to now it has been a basic console application) and is there something in CMake I can leverage to make this easier.
From what I've been able to scrape up with some help and some google, one solution is indeed to comment out the duplicate definitions of _interlockedbittestandset in initrin.h
This may have been fixed in later versions of Visual Studio.
You could look at the source code of CMake, there is a C++ class that does cross platform library loading. It is a BSD style license so you could just copy the code. Works on lots of platforms. The code is here:
http://cmake.org/gitweb?p=cmake.git;a=blob;f=Source/kwsys/DynamicLoader.cxx;h=c4ee095519fe27742a0a9a9e392be4ce095af423;hb=HEAD