I'm using the boost library in several projects in my Visual C++ 2010 solution. What I'm currently doing is modifying each project's properties by setting:
Properties->Configuration Properties->C/C++->General->Additional Include Directories to include the boost directory C:\boost\boost_1_47
Properties->Configuration Properties->Linker->General->Additional Library Directories to include the boost lib directory C:\boost\boost_1_47\lib
Now that I'm upgrading my boost version to 1.51 I realize I'm violating DRY by specifying this information more than once (i.e., once for each project). I want to define the boost info in a single place.
After researching it seems like Property Sheets are a good solution. I've read about property sheet inheritance but I don't see how that's useful because it seems that if you want to add a project-specific include directory then you will have to set the Additional Include Directories in the properties for that specific project which will then override the inherited property sheet which defines the boost include directory. If I am wrong about this please correct me.
So my next thought is to create a single property sheet called GlobalMacros.prop and define a user macro something like $(BoostDir) and then add this property sheet to each project. Then I can use the macro in each project's properties when I'm defining include directories and library directories. However, when creating a macro there is an option "set this macro as an environment variable in the build environment" and I am not sure what that does or if I should set it.
Overall I want to know what is the best way to reduce repeated configuration definitions for common settings?
I'm actually the developer that originally implemented property sheets in Visual C++ back in VS 2005 (although I'm not responsible for the mess that is the VC++ project properties dialog). Caveat: I stopped working on VC++ after 2005, so below may not be entirely accurate for your version.
In the Property Manager, you should be able to multiselect all of your project configurations in all projects and add a new property sheet. This will automatically inherit those project configurations from the same property sheet. In that property sheet, set the boost include and library directories directly or use a macro for BoostVersion and BoostDir and use those macros in the property sheet's properties.
Provided that the project configurations have "inherit from parent or project defaults" checked (this controls inserting $(Inherit) vs $(NoInherit) in 2005/2008 and %(<propertyname>) in 2010/2012) for those properties, you should see any project-specific properties set in the project configurations prepended, by default, to the values in the property sheet.
You can confirm this by going to a project and checking the compiler's "Command Line" tab to see if the switches are what you expect.
Edit: note that there are two types of properties in VC++: "single-value" and "multi-value". An example of a single-value property is the compiler's warning level. The value on the command line for a single-value property comes from the first place in the property inheritance chain that specifies it, starting with the project configuration, then the property sheets, then the built-in default in the project system. An example of a multi-value property is the compiler's include directories. Multi-value properties get concatenated with their parent property sheets unless $(NoInherit) is specified (2005/2008) or %(<propertyname>) is not specified (2010/2012). Thus, by default, you should see the boost paths showing up in your project settings provided they have intentionally not inherited the property from the property sheet.
Related
I need to link library from one project into another, and it looks there are 2 ways, can you tell what is the difference and what is the consequence of having "true" in one setting and "false" in another (the same) setting?:
and another one:
What is the difference, and do I need both setting set to "yes" or just one and if so which one?
A one-line explanation would probably be that the second option specifies something about how the first one works.
Link Library Dependencies set to Yes: if the solution is set up so that the current project has a dependency on another project that produces a .lib file, then that file will be linked in automatically.
Use Library Dependency Inputs set to Yes: useful mostly in Debug builds, when Incremental Linking is enabled. Normally, if a .lib generated by another project changes, and the current project depends on it, the linker can no longer link the current project incrementally (it's difficult for it to know how exactly the .lib changed). If you set this option to Yes, then the linker doesn't use the .lib file generated for the other project, but rather the individual .obj files that were used by the librarian to generate that .lib (as if the .lib didn't exist, and every object file from the other project were given to the linker individually, alongside the .obj files from the current project). This enables it to continue linking incrementally.
As far as I can tell, Use Library Dependency Inputs only makes sense if Link Library Dependencies and Enable Incremental Linking are both also set to Yes, and the current project depends on another project that generates a .lib file that changes often during development.
Additional information here and reference docs here.
UPDATE based on the comment from the OP:
As far as I can tell, the property entry under Project Reference Properties specifies the setting individually for each referenced project (whether to use the .lib from that specific project or not), while the one under Linker - General is the default setting for referenced projects.
For example, if you set the one under Linker - General to No and add a new referenced project, then, for that project, the setting under Project Reference Properties will default to False. However, the settings for referenced projects that were added before keep their individual setting.
I expect the individual setting under Project Reference Properties to override the default from Linker - General, but I haven't actually tested this bit.
With Makefiles I'm used to being able to write things like:
includedir=$(shell pg_config --includedir)/server
to run an external program, pg_config, with argument(s) --includedir, and include the result in a variable or as part of a variable. So if pg_config --includedir output /usr/include to stdout, the value of includedir would become:
includedir=/usr/include/server
Is there any way to do the equivalent with a Visual Studio project? Run a command, get the result, and substitute it into a property?
I find myself having to edit properties pages all over the place - changing the include directories and library directories for both the x86 and x64 configurations of a project whenever I want to build an extension against a different PostgreSQL version. It is intensely frustrating.
I want to be able to put something like this into Configuration Properties -> C/C++ -> General -> Additional Include Directories:
%(shell pg_config --includedir)
or even better:
%(shell %(PG_CONFIG) --includedir)
where %(PG_CONFIG)'s location is defined in a single place for each platform in the project.
So I'm looking for at least user-defined macros, and preferably the ability to invoke a command line tool and replace the macro with the resulting standard output.
(Preferably in a way that doesn't involve delving into semi-documented UI elements that move and get renamed in every VS version, and that appear and disappear from the various Express editions).
This has been possible in Makefiles for 20 years, there must be a way to do it in VS, right? Or do "Real Windows Developers" generate their VS projects with scripts and build them using MSBuild?
I've looked at some similar questions without finding much of use, e.g.:
Visual Studio - Where to define custom path macros?
In particular, I'm aware of property sheets (View -> Other Windows -> Property Manager), but they don't seem to provide a way to set a value in just one place, they're still per-configuration and per-architecture, so if you have four configurations and two architectures it gets awkward. Unlike with the normal project property editor you can't even apply a change across a group of architectures/configurations, either.
I could use a VS extension, but they require installation into the user's VS, can be version-specific, and seem like a very big hammer for a small problem.
I find myself having to edit properties pages all over the place
That bugged me to no end as well. Property sheets to the rescue! When setting up a major solution in VS10, for example, I had every project pull in a settings.props that contained the common settings, made in only one place. Then go through all the generated or imported projects and kill any explicit value (even if blank) for everything possible. That way things will inherit from property sheets. Select "all configurations" and on each properly use the drop-down to "inherit from...".
I have property sheets for each special library too, just defining the proper #define, include paths, lib paths, etc. Projects that use that particular external lib simply use that property sheet. Users are told, in the worst case, to “edit the XML to change the path to where you have Boost”.
As for setting such a properly to a dynamic determined value, you can do that too. There are property functions you can use.
It sounds like you're going down the same path as I did.
More notes: “prop sheets are per configuration/platform”: If you include a prop sheet at the top-level node for the project itself (not the Debug|Win32, etc. child nodes) it will include it into all current configurations at once. If you edit the properly page, you can choose Multiple or All configurations on the Property dialog box, just as with the usual project use of the Property dialog.
“Custom user macros are well hidden” A property page shows up for that when in a property sheet you created, but not when opening property dialog on a proj file as in the normal File View. The macro will be set in one place (the prop page) and usable as a $(name) in all projects that include it, and even in other property pages that come later in the evaluation sequence.
Let me know how it goes. You should be able to do everything you asked.
—John
In addition to #jdlugosz's answer:
It looks like the traditional way to do this with Visual Studio, before the advent of property functions, was to write a new MSBuild Task. The task can potentially do things like modify a property sheet.
MSBuild supports "inline tasks" where the task code is in the MSBuild project file, rather than a separate assembly, so it might not be neccessary to create a new subproject just for the task.
There are a bunch of built-in tasks, like Exec and CreateProperty that may be useful.
The docs say that:
[The Exec task] is useful when a specific MSBuild task for the job that you want to perform is not available. However, the Exec task, unlike a more specific task, cannot gather output from the tool or command that it runs.
... but that seems to be outdated/wrong so you don't need horrible workarounds.
So, prior to .NET 4.5 I'd probably have to write a custom task for this simple job, because there's no way to feed the command stdout/stderr into the CreateProperty task or have Exec create a property directly. But in 4.5 it looks like I can do it directly. At least in VS Express support for tasks etc is very limited so you'll probably land up editing the XML.
There a lots of environment variables in my project properties that I do not understand. Clicking on macros (Is there a list of Visual Studio environment variables?) gives me a list of their values, but I am unable to figure out where some of these are set.
For example, I am trying to figure out where the variable $(IntDir) is being set.
What file is responsible for setting these variables? How can I modify them?
These are not environment variables.
They're just macros defined by the build system that you can use for setting build properties for your project. They automatically expand to things like the target platform ($(Platform)), the path to store intermediate files for your project ($(IntDir)), and the name of your project ($(ProjectName)).
You can't change them directly, but you can change them by modifying your project's properties. The project file (created automatically by Visual Studio when you create a new project) is responsible for setting them.
You already found a link to the big list of 'em, which is helpful in explaining what they are and what they do. As the documentation says, you can use them anywhere in your project's property pages that string values are accepted. They keep you from having to hard-code paths and other information, which is exceptionally useful.
Unlike environment variables, they do not persist or have any meaning independent of your build system. Once your project has been built, they go away. They're not used during debugging or deployment.
.If you want to see actual values for a specific VS instance for both 'standard' and 'custom', see if this answer helps. (Basically, you can use Process Explorer to find that out.)
I am moving now from VS 2005 to VS 2010 with products consisting of few solutions with numerous projects each. I wanted to make use of the property sheets system so our numerous configurations would be easier to maintain.
One of the issues is that we want to use Windows SDK 7.1 (as we need BaseClasses sample - and if we have to use that sample that why not the entire SDK)? But this requires me to change PlatformToolset on each and every single project in all the solutions. Also we will have to remember to change that value for newly added projects. Rather bad idea.
So I wanted to set this (among other things) from a custom property sheet. There is no such option directly from dialog shown when setting properties on property sheet. Adding entries manually to the XML file didn't help as well (but I haven't also seen any error or warning message).
Then how am I supposed to set default PlatformToolset value? At best in a configuration file which can be committed to repository. But if it could be done in some computer local settings then it would be acceptable too.
(Note that I know that I can use BaseClasses differently and avoid that problem at all but I think it is interesting issue in itself.)
I also asked this question at MSDN Formus.
PlatformToolset must be set in project properties at the begin of the file before inclusion of other files so that it can be later used to set up some defaults. If non is set then those inclusions will set it up to some default value.
Resetting it later even if works is pointless as everything was already included/set up. So to change the default value to a different SDK it seems VS configuration files (those which are included) should be changed appropriately.
But this does not have to be a good thing because it is local for the machine.
There is also an option of manual inclusion of property file which sets the PlatformToolset before default inclusions. However MS warns that if project file does not keep proper order (and this would spoil the order) VS GUI tools for project set up might not work properly.
In the end I just manually changed all projects. New projects also have to be changed to the new PlatformToolset.
We have a VS solution with 99 projects. I'd like to extract XML documentation for them.
So far, the only procedure I've found involves several hundred mouse clicks; e.g. open each project properties page, one by one, find the "Generate documentation" check box, and click it. The default filename is fine.
Worse: I have to do that twice per project, once for "Release" and once for "Debug".
Is there a magic button that says "enable documentation for all projects in this solution"?
This is a general problem with project-level configuration. For example, I'd like to also set the output build directory for all projects to the same place: $SolutionRoot/bin rather than each going into 99 different $ProjectRoot/bin directories.
What is the recommended strategy for dealing with this? In makefile-land, I'd have a master makefile that defined a bunch variables that each sub-makefile would use. What's the equivalent for Visual Studio? (I'm using VS 2008)
Project files are XML, I wrote a program to open each project file as an XDocument, add the required Elements and save it again. Next time I opened visual studio, the properties were set.
For something like this, you'll want to use Visual Studio's property sheets.
Though it will be a PITA to assign the same property sheet to all 99 projects, making changes that apply to all projects in the future will be much easier - 1 change versus the original 99.
You may also want to consider creating a hierarchy of property sheets that apply to different types of projects (executables, libraries) or configurations (debug, release) to allow even more fine-grained control without requiring massive duplication.
EDIT: I guess property sheets are not available for languages other than C++. For other languages (like C#) you could refer to this answer.