GYP における MSBuild Settings (msbuild_settings) の使い方

前回、"ビルドツール GYP で Visual Studio プロジェクトのあれこれを設定しよう" の中で GYP における MSVS settings (msvs_settings) を使った Visual Studio のビルド設定について紹介しました。

調べてみると、GYP には他に MSBuild settings (msbuild_settings) という項目が存在しており、MSVS settings を置き換えることができるようです。今回は MSBuild settings について紹介します。

MSVS Settings と MSBuild Settings

GYP で Visual Studio のビルド設定を行う方法は2つあります。1つは MSVS settings を使って記述する方法ともう1つは MSBuild settings を使う方法です。それぞれ次のような記述になります。

'msvs_settings': {
  'VCCLCompilerTool': {
    'WarningLevel': '3', # /W3 (Level 3)
    'Optimization': '3', # /Ox
    'EnableFunctionLevelLinking': 'true', # /Gy
  },
  'VCLinkerTool': {
    'SubSystem': '1', # /SUBSYSTEM:CONSOLE
  },
  'VCLibrarianTool': {
    'LinkTimeCodeGeneration': 'true', # /LTCG
  },
},
'msbuild_settings': {
  'ClCompile': {
    'WarningLevel': 'Level3', # /W3 (Level 3)
    'Optimization': 'Full',   # /Ox
    'FunctionLevelLinking': 'true', # /Gy
  },
  'Link': {
    'SubSystem': 'Console', # /SUBSYSTEM:CONSOLE
  },
  'Lib': {
    'LinkTimeCodeGeneration': 'true', # /LTCG
  },
},

それぞれ同じ Visual Studio のビルド設定を示しています。 VCCLCompilerToolClCompile となっている他、ところどころ項目名が変わっている点に注目です。また SubSystem について見てみると、列挙型の整数値で指定していた MSVS settings に比べ、MSBuild settings では Console のように文字列で指定しています。 比べてみると、MSBuild settings は MSVS settings より記述しやすく、読みやすいのが特徴的です。

もともと GYP では MSVS settings が使われてきましたが、後から MSBuild settings が加わりました。MSBuild settings では、MSBuild のスキーマに考慮した名前が各項目に用いられるようになり、また、後述するように Visual Studio 2010 以降のプロジェクトをターゲットにしています。

使い分けよう

MSVS settings と MSBuild settings の両者の違いはターゲットとしている Visual Studio のバージョンです。 Visual Studio 2008 を含めたそれ以前の Visual Studio のビルド設定については MSVS settings を使って記述する必要があります。Visual Studio 2010 以降をターゲットにしたビルド設定では、MSBuild Settings を指定します。

また、これまで通り MSVS settings で指定した内容は、Visual Studio 2010 以降のプロジェクトファイルにおいても有効です。GYP の内部では、MSVS settings の内容を MSBuild settings に変換してから Visual Studio のプロジェクトを生成しています。(実装については gyp/pylib/gyp/MSVSSettings.py 内の ConvertToMSBuildSettings のコードを参照ください。)

特に理由がなく、すでに最新の Visual Studio を利用している場合は、MSBuild Settings を使うことをおすすめします。

Visual Studio には Visual Studio 2010 以降の新たに追加されたコンパイルオプションが存在しています。例えば /MP (Build with Multiple Processes) オプションや、/Fi (Preprocess Output File Name) オプションなどです。これらを GYP から設定する場合は、Visual Studio 2010 以降に対応した MSBuild settings を利用する必要があります。

Note: MSVS settings はいつまで使える?
Chromium プロジェクトでは、今も GYP ファイル内で MSVS settings が使用されています。GYP は元々 Chromium のビルドツールとして開発された経緯があるため、Chromium の中で参照されている間は(大きな問題がない限り) MSVS settings と MSBuild settings の両方をサポートし続けるでしょう。

Configuration Attributes

MSBuild* を冠するのは msbuild_settings だけではありません。 他に msbuild_configuration_attributes が追加されました。 これは GYP における msvs_configuration_attributes に相当します。

例えば、出力ディレクトリを Visual Studio のバージョンによって変更するような設定も可能です。

'target_defaults': {
  'msvs_configuration_attributes': {
    'OutputDirectory': '$(SolutionDir)$(ConfigurationName)VC90/',
  },
  'msbuild_configuration_attributes': {
    'OutputDirectory': '$(SolutionDir)$(ConfigurationName)VC100/',
  },
}

MSVS Settings と MSBuild Settings の対応表

MSVS settings で記述したビルド設定を MSBuild settings に置換する場合は、次の対応表のように置き換えていきます。

VS 2008 and earlier VS 2010+
msvs_settings msbuild_settings
msvs_configuration_attributes msbuild_configuration_attributes
VCCLCompilerTool ClCompile
VCLinkerTool Link
VCLibrarianTool Lib

設定するビルドオプションによっては MSVS settings と MSBuild settings では名前が異なっていることがあります。 例えば、MSVS settings の WarnAsError は MSBuild settings において TreatWarningAsError に変更されています。 これは MSBuild settings の各項目は MSBuild のスキーマに沿った名前となっているためです。

msvs_settings msbuild_settings Option
EnableFunctionLevelLinking FunctionLevelLinking /Gy
EnableIntrinsicFunctions IntrinsicFunctions /Oi
KeepComments PreprocessKeepComments /C
ObjectFile ObjectFileName /Fo
OpenMP OpenMPSupport /openmp
PrecompiledHeaderThrough PrecompiledHeaderFile filename used /Yc, /Yu
PrecompiledHeaderFile PrecompiledHeaderOutputFile /Fp
UsePrecompiledHeader PrecompiledHeader /Yc, /Yu
WarnAsError TreatWarningAsError /WX

MSBuild のスキーマに沿った命名のため、ClCompile, Link, Lib の各ビルドオプションについては それぞれ次の MSDN のページが参考になります:

せっかくなので MSBuild settings の具体的な記述例を紹介します。

ClCompile (MSBuild Settings)

'msbuild_settings': {
  'ClCompile': {

    'BufferSecurityCheck': 'false', # /GS-
    #'BufferSecurityCheck': 'true', # /GS

    'CompileAs': 'Default',
    #'CompileAs': 'CompileAsC',   # /TC
    #'CompileAs': 'CompileAsCpp', # /TP

    'CompileAsManaged': 'false',
    #'CompileAsManaged': 'true',      # /clr
    #'CompileAsManaged': 'Pure',      # /clr:pure
    #'CompileAsManaged': 'Safe',      # /clr:safe
    #'CompileAsManaged': 'OldSyntax', # /clr:oldSyntax

    'CreateHotpatchableImage': 'true', # /hotpatch

    'FloatingPointExceptions': 'false', # /fp:except-
    #'FloatingPointExceptions': 'true', # /fp:except

    'FunctionLevelLinking': 'true', # /Gy

    'InlineFunctionExpansion': 'Default',             # Default
    #'InlineFunctionExpansion': 'OnlyExplicitInline', # /Ob1
    #'InlineFunctionExpansion': 'AnySuitable',        # /Ob2
    #'InlineFunctionExpansion': 'Disabled',           # /Ob0

    'IntrinsicFunctions': 'true', # /Oi

    'MinimalRebuild': 'false', # /Gm-
    #'MinimalRebuild': 'true', # /Gm

    'MultiProcessorCompilation': 'true', # /MP

    'Optimization': 'Disabled',  # /Od
    #'Optimization': 'MinSpace', # /O1
    #'Optimization': 'MaxSpeed', # /O2
    #'Optimization': 'Full',     # /Ox

    'PreprocessorDefinitions': '_WIN32_WINNT=0x0601;WIN32_LEAN_AND_MEAN;NOMINMAX';
    #'PreprocessorDefinitions': [
    #  '_WIN32_WINNT=0x0601', # Windows 7 or later
    #  'WIN32_LEAN_AND_MEAN',
    #  'NOMINMAX',
    #],

    'RuntimeLibrary': 'MultiThreaded',          # /MT
    #'RuntimeLibrary': 'MultiThreadedDebug',    # /MTd
    #'RuntimeLibrary': 'MultiThreadedDLL',      # /MD
    #'RuntimeLibrary': 'MultiThreadedDebugDLL', # /MDd

    'StringPooling': 'true', # /GF

    'SuppressStartupBanner': 'true', # /nologo

    'TreatWarningAsError': 'true', # /WX

    'WarningLevel': 'TurnOffAllWarnings', # /W0
    #'WarningLevel': 'Level1', # /W1
    #'WarningLevel': 'Level2', # /W2
    #'WarningLevel': 'Level3', # /W3
    #'WarningLevel': 'Level4', # /W4

    'WholeProgramOptimization': 'true', # /GL
  },
},

Link (MSBuild Settings)

'msbuild_settings': {
  'Link': {

    'AdditionalDependencies': 'winmm.lib;ws2_32.lib;kernel32.lib',
    #'AdditionalDependencies': [
    #  'winmm.lib',
    #  'ws2_32.lib',
    #  'kernel32.lib',
    #],

    'GenerateDebugInformation': 'true', # /DEBUG

    'LinkIncremental': 'false', # /INCREMENTAL:NO
    #'LinkIncremental': 'true', # /INCREMENTAL

    'LinkTimeCodeGeneration': 'Default',
    #'LinkTimeCodeGeneration': 'UseLinkTimeCodeGeneration', # /LTCG
    #'LinkTimeCodeGeneration': 'PGInstrument',              # /LTCG:PGInstrument
    #'LinkTimeCodeGeneration': 'PGOptimization',            # /LTCG:PGOptimize
    #'LinkTimeCodeGeneration': 'PGUpdate',                  # /LTCG:PGUpdate

    'OptimizeReferences': 'false', # /OPT:NOREF
    #'OptimizeReferences': 'true', # /OPT:REF

    'SubSystem': 'Console',                  # /SUBSYSTEM:CONSOLE
    #'SubSystem': 'Windows',                 # /SUBSYSTEM:WINDOWS
    #'SubSystem': 'Native',                  # /SUBSYSTEM:NATIVE
    #'SubSystem': 'EFI Application',         # /SUBSYSTEM:EFI_APPLICATION
    #'SubSystem': 'EFI Boot Service Driver', # /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER
    #'SubSystem': 'EFI ROM',                 # /SUBSYSTEM:EFI_ROM
    #'SubSystem': 'EFI Runtime',             # /SUBSYSTEM:EFI_RUNTIME_DRIVER
    #'SubSystem': 'WindowsCE',               # /SUBSYSTEM:WINDOWSCE

    'TargetMachine': 'MachineX86',        # /MACHINE:X86
    #'TargetMachine': 'MachineARM',       # /MACHINE:ARM
    #'TargetMachine': 'MachineEBC',       # /MACHINE:EBC
    #'TargetMachine': 'MachineIA64',      # /MACHINE:IA64
    #'TargetMachine': 'MachineMIPS',      # /MACHINE:MIPS
    #'TargetMachine': 'MachineMIPS16',    # /MACHINE:MIPS16
    #'TargetMachine': 'MachineMIPSFPU',   # /MACHINE:MIPSFPU
    #'TargetMachine': 'MachineMIPSFPU16', # /MACHINE:MIPSFPU16
    #'TargetMachine': 'MachineSH4',       # /MACHINE:SH4
    #'TargetMachine': 'MachineTHUMB',     # /MACHINE:THUMB
    #'TargetMachine': 'MachineX64'        # /MACHINE:X64
  },
},

Lib (MSBuild Settings)

'msbuild_settings': {
  'Lib': {
    'LinkTimeCodeGeneration': 'true', # /LTCG
  },
},

MSBuild Configuration Attributes

'msbuild_configuration_attributes': {
  'CharacterSet': 'Unicode',    # Unicode Character Set
  #'CharacterSet': 'MultiByte', # Multibyte Character Set

  'IntermediateDirectory': '$(SolutionDir)..\\out\\obj\\$(ConfigurationName)\\$(ProjectName)',

  'OutputDirectory': '$(SolutionDir)$(ConfigurationName)',
},

最後に

要点をまとめると:

  • GYP では MSVS settings (msvs_settings) と MSBuild settings (msbuild_settings) の2つが存在している
    • MSVS settings は GYP によって内部で MSBuild settings に変換される
    • msvs_configuration_attributesmsbuild_configuration_attributes の2つについても同様
    • Visual Studio 2008 以前については MSVS settings を指定
    • Visual Studio 2010 以降については MSBuild settings を指定
  • 最新の Visual Studio をターゲットにするなら MSBuild settings を使おう

GYP には、まだまだ知らない機能やビルドオプションがありそうです。
最後に、この記事を書くきっかけを与えてくださった @mitei さん、ありがとうございました。

Leave a Reply