Как проверить директивы компилятора с условием MSBuild в файле .csproj?

Я совершенно не знаком с функциями и условиями в файлах .csproj, поэтому любая помощь приветствуется.

Что я хочу сделать, так это проверить конкретную директиву компилятора в текущей конфигурации. Примером может быть что-то вроде следующего:

<Choose>
    <When Condition= [current configuration has CONST-1 compiler constant defined] >
        ...
    </When>
    <When Condition= [current configuration has CONST-2 compiler constant defined] >
        ...
    </When>
</Choose>

Я даже не знаю, возможно ли это или нет. Если есть лучший способ сделать то, о чем я прошу, дайте мне знать об этом. В любом случае, я хочу проверить состояние, независимое от конфигурации.

ИЗМЕНИТЬ

Что мне действительно нужно, так это значение, которое я могу легко редактировать, предпочтительно в Visual Studio, которое я также могу проверить независимо от конфигурации. Я подумал о константах компилятора, потому что вы можете легко изменить их в свойствах проекта в VS.


person Mike Webb    schedule 18.10.2012    source источник
comment
Вероятно, более распространенным было бы использование элемента Property. Ваш файл csproj уже будет иметь условные элементы PropertyGroup, в зависимости от конфигурации. Внутри них вы можете добавить новые пользовательские элементы Property, а также протестировать их обычным способом в своем атрибуте Condition=. Будет ли это работать для вас, или вам действительно нужны директивы компилятора? Они более сложны, потому что существуют различные способы их определения.   -  person    schedule 18.10.2012
comment
Это может быть. Есть ли способ легко редактировать элементы пользовательских свойств после их добавления в VS без необходимости редактировать файл .csproj каждый раз, когда я хочу их изменить?   -  person Mike Webb    schedule 18.10.2012
comment
Мне нужно определенное значение, которое я могу изменить и проверить независимо от конфигурации.   -  person Mike Webb    schedule 18.10.2012
comment
Нет, в графическом интерфейсе нет возможности редактировать пользовательские свойства, если только вы не хотите создать надстройку VS (некоторые надстройки добавляют свойства и предоставляют их в виде новой вкладки в свойствах проекта, но это, вероятно, слишком много работы)   -  person    schedule 18.10.2012


Ответы (3)


Константы компилятора устанавливаются в свойство «DefineConstants», поэтому вы должны просто оценить это свойство. Ваш оператор Choose должен идти после групп свойств, которые определяют константы, или внутри цели.

<Choose>
    <When Condition="$(DefineConstants.Contains(CONST-1))">
        ...
    </When>
    <When Condition="$(DefineConstants.Contains(CONST-2))">
        ...
    </When>
</Choose>
person Ted Elliott    schedule 18.10.2012
comment
Спасибо, это сработало отлично... Однако мне пришлось удалить кавычки вокруг CONST-1 или любого другого условного определения. - person Randeep; 11.06.2014

Если вы используете MSBuild 4 или выше, я предлагаю использовать регулярное выражение вместо String.Contains(). Причина этого в том, что хотя String.Contains() обычно работает хорошо, в некоторых случаях у вас могут возникнуть проблемы.

Например:

Рассмотрим случай, когда вы используете директивы CONST-1 и CONST-12 в своем коде. Однако вы решили определить только директиву CONST-12 для текущей сборки.
Теперь Condition="$(DefineConstants.Contains('CONST-1'))" оценивается как True, хотя CONST-1 не определена.

Решение с RegularExpressions.RegEx:

<When Condition="$([System.Text.RegularExpressions.Regex]::IsMatch($(DefineConstants), '^(.*;)*CONST-1(;.*)*$'))">
...
</When>

Подводя итог, вы можете либо быть осторожным, чтобы убедиться, что вы не используете директиву, которая является подстрокой другой, либо вы можете использовать регулярное выражение и вообще не беспокоиться.

person Manthess    schedule 02.12.2014
comment
Это единственный System.Text.RegularExpressions.Regex, который работает в целевом файле, спасибо: ‹When Condition=$([System.Text.RegularExpressions.Regex]::IsMatch($(DefineConstants), '^(.*;) *CONST-1(;.*)*$'))› - person SoLaR; 27.01.2020

Чтобы добавить к другим ответам, размещенным здесь, еще один способ, которым вы можете подойти к этому, - обернуть свойство DefineConstants точкой с запятой, чтобы гарантировать, что «;CONST-1;» будет содержаться в DefineConstants тогда и только тогда, когда определена константа "CONST-1". Без точек с запятой вы могли бы иметь CONST-100 или UNCONST-1, но не CONST-1 в качестве переменной, и она была бы оценена как истина.

<PropertyGroup>
    <DefineConstants2>;$(DefineConstants);</DefineConstants2>
    <Foo Condition="'$(DefineConstants2.Contains(`;CONST-1;`))'">It worked</Foo>
    <Bar>$(Foo)</Bar> <!--It worked-->
</PropertyGroup>
person nuzzolilo    schedule 08.10.2017