C++ 有效地为多个项目和配置使用 Visual Studio 项目属性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3502530/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using Visual Studio project properties effectively for multiple projects and configurations
提问by Fire Lancer
I have always used Visual Studios built in GUI support for configuring my projects, often using property sheets so that several projects will use a common set.
我一直使用内置 GUI 支持的 Visual Studios 来配置我的项目,经常使用属性表,以便多个项目将使用一个公共集。
One of my main gripes with this is managing multiple projects, configurations and platforms. If you just do everything with the main GUI (right click the project -> properties) it quickly becomes a mess, difficult to maintain and prone to bugs (like failing to correctly define some macro, or using the wrong runtime library, etc). Dealing with the fact that different people put there dependency libraries in different places (eg mine all live in "C:\Libs\[C,C++]\[lib-name]\") and then often manage the different versions of those libraries differently as well (release, debug, x86, x64, etc) is also a large problem since it vastly complicates the time to set it up on a new system, and then there is issues with version-control and keeping everyone's paths separate...
我对此的主要抱怨之一是管理多个项目、配置和平台。如果您只是使用主 GUI 完成所有操作(右键单击项目 -> 属性),它很快就会变得一团糟,难以维护并且容易出现错误(例如未能正确定义某些宏,或使用错误的运行时库等)。处理不同的人将依赖库放在不同位置的事实(例如我的都位于“C:\Libs\[C,C++]\[lib-name]\”),然后经常管理这些库的不同版本不同的(发布、调试、x86、x64 等)也是一个大问题,因为它使在新系统上设置它的时间大大复杂化,然后存在版本控制和保持每个人的路径分开的问题。 .
Property sheets make this a bit better, but I cant have one sheet have separate settings for different configurations and platforms (the drop down boxes a greyed out), resulting in me having many sheets which if inherited in the correct order do what I want ("x86", "x64", "debug", "release", "common", "directories" (deals with the previously mentioned dependency issue by defining user macros like BoostX86LibDir), etc) and if inherited in the wrong order (eg "common" before "x64" and "debug") lead to issues like trying to link an incorrect library version, or incorrectly naming the output...
属性表使这更好一点,但我不能让一张表对不同的配置和平台有单独的设置(下拉框变灰),导致我有很多表,如果以正确的顺序继承,可以做我想要的( “x86”、“x64”、“debug”、“release”、“common”、“directories”(通过定义像 BoostX86LibDir 这样的用户宏来处理前面提到的依赖问题),并且如果以错误的顺序继承(例如“x64”和“debug”之前的“common”)会导致诸如尝试链接不正确的库版本或错误地命名输出之类的问题...
What I want is a way of dealing with all these scattered dependencies and setting up a set of "rules" which are used by all my projects in the solution, like naming an output library as "mylib-[vc90,vc100]-[x86,x64][-d].lib", without having to do all this for each individual project, configuration and platform combination, and then keep them all correctly in sync.
我想要的是一种处理所有这些分散的依赖项并设置解决方案中所有项目使用的“规则”的方法,例如将输出库命名为“mylib-[vc90,vc100]-[x86 ,x64][-d].lib",而不必为每个单独的项目、配置和平台组合执行所有这些操作,然后使它们全部正确同步。
I am aware of moving to entirely different systems like CMake that create the needed files, however this then complicates things elsewhere by making it so even simple tasks like adding a new file to the project then requires additional changes elsewhere, which is not something I am entirely happy with either, unless there is some with VS2010 integration which can keep track of these sorts of changes.
我知道移动到完全不同的系统,如创建所需文件的 CMake,但是这会使其他地方的事情复杂化,因为它使即使是简单的任务,例如向项目添加新文件,然后需要在其他地方进行额外的更改,这不是我的事情对任何一个都非常满意,除非有一些与 VS2010 集成可以跟踪这些类型的变化。
回答by Fire Lancer
I just found out somthing I didnt think was possible (it is not exposed by the GUI) that helps make property sheet far more useful. The "Condition" attribute of many of the tags in the project property files and it can be used in the .props files as well!
我刚刚发现了一些我认为不可能的东西(它没有被 GUI 暴露),这有助于使属性表更有用。项目属性文件中许多标签的“条件”属性,它也可以在 .props 文件中使用!
I just put together the following as a test and it worked great and did the task of 5 (common,x64,x86,debug,release) separate property sheets!
我只是将以下内容放在一起作为测试,效果很好,并完成了 5 个(通用、x64、x86、调试、发布)单独属性表的任务!
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="UserMacros">
<!--debug suffix-->
<DebugSuffix Condition="'$(Configuration)'=='Debug'">-d</DebugSuffix>
<DebugSuffix Condition="'$(Configuration)'!='Debug'"></DebugSuffix>
<!--platform-->
<ShortPlatform Condition="'$(Platform)' == 'Win32'">x86</ShortPlatform>
<ShortPlatform Condition="'$(Platform)' == 'x64'">x64</ShortPlatform>
<!--toolset-->
<Toolset Condition="'$(PlatformToolset)' == 'v90'">vc90</Toolset>
<Toolset Condition="'$(PlatformToolset)' == 'v100'">vc100</Toolset>
</PropertyGroup>
<!--target-->
<PropertyGroup>
<TargetName>$(ProjectName)-$(Toolset)-$(ShortPlatform)$(DebugSuffix)</TargetName>
</PropertyGroup>
</Project>
Only issue is the properties GUI cant handle it, a project that uses the above property sheet just reports default inherited values like "$(ProjectName)" for the target.
唯一的问题是属性 GUI 无法处理它,使用上述属性表的项目只报告目标的默认继承值,如“$(ProjectName)”。
回答by lunicon
I made some improvements, may be useful for somebody
我做了一些改进,可能对某人有用
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="UserMacros">
<!--IsDebug: search for 'Debug' in Configuration-->
<IsDebug>$([System.Convert]::ToString( $([System.Text.RegularExpressions.Regex]::IsMatch($(Configuration), '[Dd]ebug'))))</IsDebug>
<!--ShortPlatform-->
<ShortPlatform Condition="'$(Platform)' == 'Win32'">x86</ShortPlatform>
<ShortPlatform Condition="'$(Platform)' == 'x64'">x64</ShortPlatform>
<!--build parameters-->
<BUILD_DIR>$(registry:HKEY_CURRENT_USER\Software\MyCompany\@BUILD_DIR)</BUILD_DIR>
</PropertyGroup>
<Choose>
<When Condition="$([System.Convert]::ToBoolean($(IsDebug)))">
<!-- debug macroses -->
<PropertyGroup Label="UserMacros">
<MyOutDirBase>Debug</MyOutDirBase>
<DebugSuffix>-d</DebugSuffix>
</PropertyGroup>
</When>
<Otherwise>
<!-- other/release macroses -->
<PropertyGroup Label="UserMacros">
<MyOutDirBase>Release</MyOutDirBase>
<DebugSuffix></DebugSuffix>
</PropertyGroup>
</Otherwise>
</Choose>
<Choose>
<When Condition="Exists($(BUILD_DIR))">
<PropertyGroup Label="UserMacros">
<MyOutDir>$(BUILD_DIR)\Bin$(MyOutDirBase)_$(ShortPlatform)\</MyOutDir>
<MyIntDir>$(BUILD_DIR)\Build$(Configuration)_$(ShortPlatform)_$(PlatformToolset)$(ProjectGuid)\</MyIntDir>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup Label="UserMacros">
<MyOutDir>$(SolutionDir)\Bin$(MyOutDirBase)_$(ShortPlatform)\</MyOutDir>
<MyIntDir>$(SolutionDir)\Build$(Configuration)_$(ShortPlatform)_$(PlatformToolset)$(ProjectGuid)\</MyIntDir>
</PropertyGroup>
</Otherwise>
</Choose>
<PropertyGroup>
<OutDir>$(MyOutDir)</OutDir>
<IntDir>$(MyIntDir)</IntDir>
<!-- some common for projects
<CharacterSet>Unicode</CharacterSet>
<LinkIncremental>false</LinkIncremental>
-->
</PropertyGroup>
</Project>
have fun!
玩得开心!
回答by Peon the Great
I had same pain for the product of my company (200+ projects) before. The way I solved it is to build a nice hierarchy of the property sheets.
我以前对我公司的产品(200多个项目)有同样的痛苦。我解决它的方法是建立一个很好的属性表层次结构。
The projects inherits the property sheet by its output type, say x64.Debug.Dynamic.Library.vsprops. This vsprops file simply inherits other property sheets using the InheritedPropertySheets attribute
项目通过其输出类型继承属性表,例如 x64.Debug.Dynamic.Library.vsprops。这个 vsprops 文件使用 InheritedPropertySheets 属性简单地继承了其他属性表
<VisualStudioPropertySheet
ProjectType="Visual C++"
Version="8.00"
Name="x64.Debug.Dynamic.Binary"
InheritedPropertySheets=".\Common.vsprops;.\x64.vsprops;.\Debug.vsprops;.\Runtime.Debug.Dynamic.vsprops;.\Output.x64.Library.vsprops"
>
You can also use variables (i.e. UserMacro, whose value can be absolute or even environment variables) in property sheets to customize a lot of things based on your need. For example, defining a BIN variable in Debug.vsprops
您还可以在属性表中使用变量(即UserMacro,其值可以是绝对变量甚至环境变量)来根据需要自定义很多东西。比如在Debug.vsprops中定义一个BIN变量
<UserMacro name="BIN" Value="Debug" />
then when you set the output name in the series of vsprops, say, Output.x64.Library.vsprops
然后当你在一系列 vsprops 中设置输出名称时,比如 Output.x64.Library.vsprops
<VisualStudioPropertySheet
ProjectType="Visual C++"
Version="8.00"
OutputDirectory="$(BIN)"
>
The $(BIN) variable will be expanded to what's been set (in this case, Debug). Use this technique you can easily construct a nice hierarchy of property sheets to meet your demand.
$(BIN) 变量将扩展为已设置的值(在本例中为 Debug)。使用此技术,您可以轻松构建良好的属性表层次结构以满足您的需求。
Now there's one more thing you might want to do: build your own project templates that uses your property sheet set. The real difficult part is to enforce proper usage of the templates and property sheets. My personal experience is that even if everything is setup, somebody will still forget to use the template to create new projects ...
现在,您可能还想做一件事:使用您的属性表集构建您自己的项目模板。真正困难的部分是强制正确使用模板和属性表。我个人的经验是,即使一切都设置好了,仍然有人会忘记使用模板来创建新项目......
回答by gogisan
It is possible to create a separate property sheet for each configuration. To do this:
可以为每个配置创建单独的属性表。去做这个:
- Create a configuration-specific property sheet
- Open the Property Manager
- Right click the configuration(not the project) that you would like to modify
- Click "Add Existing Property Sheet" and add your sheet
- 创建特定于配置的属性表
- 打开物业管理器
- 右键单击要修改的配置(不是项目)
- 单击“添加现有属性表”并添加您的表
This relieves you from inserting conditions into a single sheet for multiple configurations. If you have some common attributes that you would like to share between configurations, then create a hierarchy. The top sheet can be used in all configurations and the nested sheets will only contain the configuration-specific attribut
这使您无需为多个配置将条件插入到单个工作表中。如果您有一些想要在配置之间共享的公共属性,请创建一个层次结构。顶部工作表可用于所有配置,嵌套工作表将仅包含特定于配置的属性
回答by ngoozeff
As far as the output library goes, you can select all your projects, then bring up the property pages, select All Configurations, All Platforms and then set the Target Name to:
就输出库而言,您可以选择所有项目,然后调出属性页面,选择所有配置、所有平台,然后将目标名称设置为:
$(ProjectName)-$(PlatformToolset)-$(PlatformShortName)-$(Configuration)
$(ProjectName)-$(PlatformToolset)-$(PlatformShortName)-$(Configuration)
which would give an output like mylib-v100-x86-Debug.lib
这将提供类似 mylib-v100-x86-Debug.lib 的输出
We do something similar to this for Additional Library Directories as well, using $(PlatformName)
and #(Configuration)
to pick out the right library paths, although it does mean some messing around with initial setup of the libraries. eg we have boost install its libs to boost/lib.Win32
or boost/lib.x64
.
我们也对附加库目录执行了类似的操作,使用$(PlatformName)
并#(Configuration)
挑选出正确的库路径,尽管这确实意味着对库的初始设置进行了一些处理。例如,我们已将其库提升安装到boost/lib.Win32
或boost/lib.x64
。
With regards to libraries, and people installing them in different places, there are a couple of options. If you have a very robust source control system, you can just put everything in source control, living in a libs folder next to your source. That probably won't work if you use more than a few libraries though, or if they are particularly large.
关于库,以及在不同地方安装它们的人,有几种选择。如果您有一个非常强大的源代码控制系统,您可以将所有内容都放在源代码控制中,并保存在源代码旁边的 libs 文件夹中。如果您使用多个库,或者它们特别大,这可能不起作用。
The other option that comes to mind is to set an environment variable on each user machine that points to the root of their libraries folder, eg LIB_ROOT=c:\libraries
, and you can then access that in Visual Studio as $(LIB_ROOT)
.
想到的另一个选项是在每个用户计算机上设置一个指向其库文件夹根目录的环境变量,例如LIB_ROOT=c:\libraries
,然后您可以在 Visual Studio 中以$(LIB_ROOT)
.
回答by Rune Andersen
It sounds like it could be worth checking out a build tool - at my place we use a custom made tool that watches files and projects for changes and figures the dependencies and compile order. Adding a new file is no big deal - compilation is done with msbuild.
听起来可能值得检查一个构建工具——在我这里,我们使用一个定制的工具来监视文件和项目的更改并计算依赖项和编译顺序。添加新文件没什么大不了的 - 编译是用 msbuild 完成的。
If i had to compile more than a bunch of projects I would use something like nant: http://nant.sourceforge.net/
如果我必须编译多个项目,我会使用类似 nant 的东西:http: //nant.sourceforge.net/