[CMake] Visual Studio 2010 default property sheets

David Hunter davidhunter22 at gmail.com
Mon Dec 12 09:44:00 EST 2011


Sorry if this a re-post had mail issue.

I'm not sure if this has been discussed much within the CMake
developer community but I wanted to give some thoughts on the use of
Visual Sudio property sheets and some suggestion for CMake. As far as
I know this is only relevant to Visual Studio 10 and hence MSBuild. I
am not familiar with older versions of VS. Sorry if this a bit long
winded or it falls into the "bleeding obvious" category. I did look
around and couldn't find any discussion like this online.

So first an overview of property sheets in VS10/MSBuild skip this if
you are in the know.

For those not to familiar with property sheets you can consider them
to be collections of compiler/linker flags and other build related
information. Physically property sheets are just MSBuild XML files
which get included into the main Visaul Studio project file, the
.vcxproj file, which is also an MSBuild XML file. To a certain degree
you can consider one of Visual Studio functions to be a glorified
editor of MSBuild XML files.

When you create a project in Visual Studio you have to select what
type of project it is, for instance a standard DLL, aka shared
library, project. When you do this the project file that VS produces
will automatically includes certain property sheets that Microsoft
supplies with MSBuild. These files can be found in something like
"C:\Program Files (x86)\MSBuild\Microsoft.Cpp/v4.0" and have names
like "Microsoft.Cl.Common.props". The is also a sub directory called
"Platforms" which contains directories like "Win32" and "x64". These
correspond directly to the "Platform" you see in VS. These directories
contain further MSBuild predefined platform specific property sheets
like "Microsoft.Cpp.Win32.props"
>
>
Property sheets can be inherited what this means is that a property
sheet can inherit a set of compiler flags from a parent sheet and can
override or extend them if it wants to. This is the key to the
usefulness of property sheets. If you look in the "Property Manager"
screen in VS of a standard DLL project you should see something like
the following property sheets being inherited for a 32 bit windows
build

Microsoft.Cpp.Win32.user
Windows Dynamic Link Library
Multi-byte Character Support
Core Windows Libraries

Sheets higher up inherit and can override sheets lower down the list.
The bottom three correspond to MSBuild supplied property sheets in the
MSBuild install directories mentioned earlier. Sadly I haven't found a
way in the VS GUI of finding out the actual file name and path of the
property sheet but you can normally guess it. The
"Microsoft.Cpp.Win32.user" property sheet which is normally somewhere
like "AppData\Local\Microsoft\MSBuild\v4.0" in your user id allows you
to store user specific build overrides which is generally a bad idea.

When you right click on a project in VS solution explorer ( or other
equivalent method ) you can look at the properties of that project,
including all the compiler/linker flags. Items that are in bold font
are defined directly in the property sheet you are looking at while
non bold indicates a value that has been inherited. For some compiler
flags like the include path it makes sense to inherit the value from
your parent property sheet and extend it. In this case you'll see
something like "%(AdditionIncludeDirectories)" in the value which is a
macro value representing the value of this field inherited from the
parent sheet.

A very key portion of the property sheet you can see in VS GUI is the
"General" page under "Configuration Properties". At the bottom of this
screen is a section called "Project Defaults" which looks something
like

Configuration Type                            Dynamic Library (.dll)
Use of MFC                                     Use Standard Windows Libraries
Use of ATL                                       Not using ATL
Character Set                                   Use Multi Byte Character Set
Common Language Runtime Support  No Common Language Runtime Support
Whole Program Optimization              No Whole Program Optimization

The above are not really compiler flags directly but define which
MSBuild supplied property sheets to inherit. In other words they
effect compiler flags used in your build by changing what property
sheets you inherit from. So if you change the "Character set" from
multi byte to Unicode you will see in the property manager that you
now inherit from a sheet called "Unicode Support" rather than
"Multi-byte Character set". This may change many compiler/linker
flags/defines etc...

Note the situation is a little more complicated as you can define
certain MSBuild XML elements before you inherit the MSBuild supplied
property sheets which influence what flags they set. A good exmple of
this is the <UseDebugLibraries>true<UseDebugLibraries> which amongst
many other things makes the build process link to the debug versions
"MDd" of the MS runtime libraries rather than the optimized/release
ones.

End of overview

So what was the point of this ramble through property sheets. My
assertion is that at present, probably for historic reasons, CMake
does not allow you to completely control what MSBuild supplied
property sheets you inherit and often ends up setting specific
compiler flags that the MSBuild supplied property sheets would have
set anyway if the correct ones had been inherited. In general I
believe the ethos is to use the, presumably consistent and correct,
set of flags the MSBuild supplied property sheets give you and only
specifically override these flags if you really have a reason.

In CMake you can control this, at least in 2.8.6, to a certain degree.
Most of the action happens in
cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues. In
this memeber function you can see XML being written out like
"<CharacterSet>Unicode</CharacterSet>" which makes MSBuild inherit the
"Unicode" property sheet rather than the default "Multi-Byte" one. In
this case you can trigger this by adding the define "-D_UNICODE" to
your Cmake input file. This is probably a side effect that many are
not aware of and the result might be a lot more than just adding
"-D_UNICODE" to you compile line as the property sheet may do many
things. Note this
http://www.cmake.org/pipermail/cmake/2011-June/045002.html concerning
an extension to this particular element.
In the case of MFC a magic "CMAKE_MFC_FLAG" variable is used, there is
no equivalent magic flag for ATL or CLR. Note CLR was the origional
reason I looked at all this. Locally I added the following code for
another magic flag
    const char* clrFlag =
this->Target->GetMakefile()->GetDefinition("CMAKE_CLR_FLAG");
    if(clrFlag)
      {
      this->WriteString("<CLRSupport>true</CLRSupport>\n", 2);
      }
This causes the "CLR" property sheet to be inherited which would fix
the relatively often asked question how do I get CMake to build
C++/CLI code.

So my question about all of this is should CMake have a consistent way
to influence what property sheets you inherit from and if so how? If
this was done one related, and possibly harder, issue would be to
remove the explicit setting of the many flags the inherited property
sheets now set for you, for instance the "/MDd" flag mentioned
earlier. How could you tell if the inherited flags are the same as the
ones the CMake explicitly set in all configurations?

So, I am happy to volunteer to do some of this work but wanted to
know, being a CMake internals newbie, what the experts thought. Is is
worth doing or if not why not, or is someone already doing this? What
would be the best approach? How much do people care about consistency
of flags between CMake releases? All thoughts welcomed.

David


--
M +1 917 545-0240
Skype davidhunter22


More information about the CMake mailing list