Skip to content

MS_MSBuildDefineConstants

nishi_74322014 edited this page Aug 21, 2026 · 1 revision

dotnetコマンドのビルドで、#if-#endifのDefineConstantsを認識しない

概要

Linux 上の .NET Core 環境で dotnet コマンドのビルドで
条件付きコンパイルシンボル(DefineConstants)に設定した値が効かず、
#if-#endif が適切に動作しない。

詳細

  • 以下の Condition が Linux 環境と異なるっぽい。
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
  • 単純に Condition を削除したら動作した。
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
  <DefineConstants>TRACE;NETCORE</DefineConstants>
</PropertyGroup>

↓ ↓ ↓

<PropertyGroup>
  <DefineConstants>TRACE;NETCORE</DefineConstants>
</PropertyGroup>

補足(原因の特定): 原文の「Linux 環境と異なるっぽい」という
見立ては正しく、$(Platform) の既定値が一致していないことが原因である。

【Visual Studio でビルド】
   Platform = "AnyCPU"      ← .sln のソリューション構成から渡される
   → Condition が成立する

【dotnet build(.csproj 単体)】
   Platform = "AnyCPU" の場合もあるが、
   SDK スタイルでは PlatformTarget と混同されやすく、
   ソリューションを介さないと空や別の値になることがある
   → Condition が成立せず、DefineConstants が設定されない

Linux 固有の問題ではなく、
「IDE 経由かどうか」「.sln 経由かどうか」の差
である
(Windows でも dotnet build Foo.csproj で再現し得る)。

確認方法: 実際に渡っているプロパティを出力させる。

dotnet build -v:diag 2>&1 | grep -E "^\s+Platform = |^\s+DefineConstants = "

# あるいは、プロパティを直接評価する
dotnet msbuild Foo.csproj -getProperty:Platform -getProperty:DefineConstants

-getProperty(.NET 8 SDK 以降)は、
ビルドせずにプロパティの評価結果だけを見られるため、
この種の調査に有用である。

補足(推奨する書き方): 原文の対処
Condition を外す)は確実だが、
「Debug の時だけ」という意図が失われる。
意図を保ったまま安全にする書き方を挙げておく。

Configuration だけで判定するPlatform に依存しない)

<PropertyGroup Condition="'$(Configuration)'=='Debug'">
  <DefineConstants>$(DefineConstants);MY_DEBUG_ONLY</DefineConstants>
</PropertyGroup>

② SDK が用意する定数を使う(自分で定義しない)

SDK スタイルでは、次の定数が自動で定義される

定数 条件
DEBUG Configuration=Debug
TRACE 既定で常に(<DefineTrace>
NET8_0, NET8_0_OR_GREATER ターゲット フレームワーク
NETCOREAPP, NETSTANDARD, NETFRAMEWORK プラットフォーム系
WINDOWS, LINUX, MACOS OS 固有 TFM 使用時
#if NET8_0_OR_GREATER
    // .NET 8 以降
#elif NETFRAMEWORK
    // .NET Framework
#endif

原文が定義している NETCORE は、
標準の NETCOREAPP で代替できる

ターゲット フレームワークのバージョン)。
自前の定数を定義しないのが、この種の事故を防ぐ最善策である。

③ 追記形式にする(既存の定数を潰さない)

<!-- 悪い:TRACE / DEBUG を上書きして消してしまう -->
<DefineConstants>NETCORE</DefineConstants>

<!-- 良い:既存に足す -->
<DefineConstants>$(DefineConstants);NETCORE</DefineConstants>

原文の例(TRACE;NETCORE)は TRACE を手で書き足しているが、
$(DefineConstants) を展開する形にしておく方が安全である。

補足(インクリメンタル ビルドの罠): 原文が参照している
MSBuild Issue #3350 は、
**「DefineConstants を変更しても再コンパイルされない」**という
別の問題である。

DefineConstants を書き換える
  → ソース ファイルは変わっていない
  → MSBuild が「最新」と判断し、CoreCompile を省略する
  → 変更が反映されない

この現象は現在は修正されているが、
疑わしい場合はクリーンしてから確認する

dotnet clean && dotnet build
# あるいは
rm -rf obj bin && dotnet build

「設定を変えたのに効かない」時に、
設定の問題なのかキャッシュの問題なのかを切り分けるため、
まずクリーン ビルドで確認するのが定石である。

参考

Microsoft Learn


Tags: 移行, テスト, デバッグ, デプロイ, .NET開発, .NET Core

NetDevInfraWiki

マイクロソフト系技術情報 Wiki
Open 棟梁 Wiki

(未着手)

開発基盤部会 Wiki

移行管理: DONETODO

Clone this wiki locally