For solutions, projects, folders and files - properties can be defined that are used by the project system in the build process. These property values can be viewed and modified using the properties window in conjunction with the project explorer. As you select an item in the project explorer the properties window will list the set of properties that are applicable.
Some properties are only applicable to a given item type. For example linker properties are only applicable to a project that builds an executable file. However other properties can be applied either at the file, project or solution project node. For example a compiler property can be applied to the solution, project or individual file. By setting properties at the solution level you enable all files of the solution to use this property value.
A unique property has one value - either a bool or a number. When a build is done the value of a unique property is the first one defined in the project hierarchy. For example the Treat Warnings As Errors property could be set to Yes at the solution level which would then be applicable to every file in the solution that is compiled, assembled and linked. You can then selectively define property values for other project items. For a example particular source file may have warnings that you decide are allowable so you set the Treat Warnings As Errors to No for this particular file.
Note that when the properties window displays a project property it will be shown in bold if it has been defined for unique properties the inherited or default value will be shown if it hasn't been defined.
solution — Treat Warnings As Errors = Yes
project1 — Treat Warnings As Errors = Yes
file1 — Treat Warnings
As Errors
= Yes
file2 — Treat Warnings As
Errors = No
project2 — Treat Warnings As Errors = No
file1 — Treat Warnings
As Errors
= No
file2 — Treat Warnings
As
Errors = Yes
In the above example the files will be compiled with these values for Treat Warnings As Errors
project1/file1 | Yes |
project1/file2 | No |
project2/file1 | No |
project2/file2 | Yes |
An aggregating property collects all of the values that are defined for it in the project hierarchy. For example when a C file is compiled the Preprocessor Definitions property will take all of the values defined at the file, project and solution level. Note that the properties window will NOT show the inherited values of an aggregating property.
solution — Preprocessor
Definitions = SolutionDef
project1
— Preprocessor Definitions =
file1 — Preprocessor Definitions
=
file2 — Preprocessor Definitions
= File1Def
project2 — Preprocessor Definitions = ProjectDef
file1 — Preprocessor Definitions
=
file2 — Preprocessor
Definitions
= File2Def
In the above example the files will be compiled with these Preprocessor Definitions
project1/file1 | SolutionDef |
project1/file2 | SolutionDef, File1Def |
project2/file1 | SolutionDef, ProjectDef |
project2/file2 | SolutionDef, ProjectDef, File2Def |
Property values are defined for a configuration so you can have different values for a property for different builds. A given configuration can inherit the property values of other configurations. When the project system requires a property value it checks for the existence of the property value in current configuration and then in the set of inherited configurations. You can specify the set of inherited configurations using the Configurations dialog.
There is a special configuration named Common that is always inherited by a configuration. The Common configuration enables property values to be set that will apply to all configurations that you create. You can select the Common configuration using the Configurations combo box of the properties window. If you are modifying a property value of your project it's almost certain that you want each configuration to inherit these values - so ensure that the Common configuration has been selected.
If the property is unique then it will use the one defined for the particular configuration. If the property isn't defined for this configuration then it uses an arbitrary one from the set of inherited configurations. If the property still isn't defined it uses the value for the Common configuration. If it still isn't defined then it tries the to find the value in the next level of the project hierarchy.
solution [Common] — Preprocessor
Definitions = CommonSolutionDef
solution [Debug] — Preprocessor
Definitions = DebugSolutionDef
solution [Release] — Preprocessor
Definitions = ReleaseSolutionDef
project1 - Preprocessor Definitions =
file1 - Preprocessor Definitions
=
file2 [Common] — Preprocessor
Definitions = CommonFile1Def
file2 [Debug] — Preprocessor
Definitions = DebugFile1Def
project2 [Common] — Preprocessor Definitions
= ProjectDef
file1 — Preprocessor Definitions
=
file2 [Common] - Preprocessor
Definitions = File2Def
In the above example the files will be compiled with these Preprocessor Definitions when in Debug configuration
project1/file1 | CommonSolutionDef, DebugSolutionDef |
project1/file2 | CommonSolutionDef, DebugSolutionDef,CommonFile1Def, DebugFile1Def |
project2/file1 | CommonSolutionDef, DebugSolutionDef, ProjectDef |
project2/file2 | ComonSolutionDef, DebugSolutionDef, ProjectDef, File2Def |
and the files will be compiled with these Preprocessor Definitions when in Release configuration
project1/file1 | CommonSolutionDef, ReleaseSolutionDef |
project1/file2 | CommonSolutionDef, ReleaseSolutionDef, CommonFile1Def |
project2/file1 | CommonSolutionDef, ReleaseSolutionDef, ProjectDef |
project2/file2 | ComonSolutionDef, ReleaseSolutionDef, ProjectDef, File2Def |