📖

Premake5の拡張

2021/02/23に公開

📌 はじめに

Premakeは定義ファイルからVisualStudioやXcodeなどのプロジェクトファイルを生成するコマンドラインツールです.最新版は premake5 です.開発規模が大きくなってくると取り扱うファイルも増え,追加忘れやソリューション上のフォルダ構成がエクスプローラ上と違うとか,カスタムビルドを設定するものが多いと非常に面倒です.また,ソリューション構成やターゲットが増えるほど管理が大変になり,定義ファイル上で手軽に変更できるのはPremakeの良いところだと思います.とはいえ,実際に実務で使う場合には拡張が必須だと思います.ここでは,Premake自体のビルドと拡張,あとは定義ファイルについて少し書いておこうと思います.備忘録的な内容となっています.また環境はWindowsです.

📌 Premake

公式は以下です.

📌 ドキュメント

📌 はじめてのpremake

まずは以下を参照することをオススメします.

📌 拡張について

以下が参考になります.

📌 Premake のビルド

以下からフォークやクローンします.

ビルドの方法については BUILD.txt に書いてあります.Windowsの場合はVisualStudioのコマンドプロンプト上で次のコマンドを実行します.

nmake -f Bootstrap.mak windows

Visual Studio のコマンドプロンプトはスタートメニューから開くか,次のようなバッチファイルを用意すると比較的楽です.

@echo off
set VSPROMPT_2015="%VS140COMNTOOLS%vsvars32.bat"
set VSPROMPT_2017="C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Auxiliary\Build\vcvars64.bat"
set VSPROMPT_2017C="C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat"
set VSPROMPT_2019="C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Auxiliary\Build\vcvars64.bat"
set VSPROMPT_2019C="C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat"
set VSPROMPT=
if exist %VSPROMPT_2015% ( 
    echo found %VSPROMPT_2015%
    set VSPROMPT=%VSPROMPT_2015% 
)
if exist %VSPROMPT_2017C% (
    echo found %VSPROMPT_2017C%
    set VSPROMPT=%VSPROMPT_2017C%
)
if exist %VSPROMPT_2017% (
    echo found %VSPROMPT_2017%
    set VSPROMPT=%VSPROMPT_2017%
)
if exist %VSPROMPT_2019C% (
    echo found %VSPROMPT_2019C%
    set VSPROMPT=%VSPROMPT_2019C%
)
if exist %VSPROMPT_2019% (
    echo found %VSPROMPT_2019%
    set VSPROMPT=%VSPROMPT_2019%
)
call %VSPROMPT%

Visual Studio 2017 から VS14XCOMNTOOLS といった環境変数がなくなっています.
このバッチファイルは以下のVisual Studio に対応しています.

  • Visual Studio 2015 (v140)
  • Visual Studio 2017 Community (v141)
  • Visual Studio 2017 Professional (v141)
  • Visual Studio 2019 Community (v142)
  • Visual Studio 2019 Professional (v142)

例えば,vscmd.bat という名前でバッチファイルを作成したとすれば通常のコマンドプロンプトで

vscmd.bat
nmake -f Bootstrap.mak windows

とします.これで bin/release/premake5.exe が出来上がります.premake の定義ファイルは Lua ファイルで,premake内でも Lua スクリプトを使って処理しています.以下のコマンドを実行すると Lua スクリプトを premake5.exe に埋め込みます.

.\bin\release\premake5 embed
devenv .\build\bootstrap\premake5.sln /Build Release

これは premake を使ってプロジェクトファイルを作成して,そのプロジェクトファイルを使ってビルドすると Lua スクリプトが埋め込まれた premake が出来上がるという面白い仕組みになっています.

📌 拡張

ここでは新しくプロパティシートを追加する importprops 関数を追加します.premake は Lua スクリプトで処理しているので,Luaファイルを変更します.基本的に新しい関数の定義は src/_premake_init.luaapi.register で登録します.

api.register {
    name = "importprops",
    scope = "config",
    kind = "list:path",
    tokens = true
}

次に,実装です.Visual Studio の処理は主に modules/vstudio/vs2010_vcxproj.lua にあります.プロパティシート関連は m.propertySheets() の部分です.

function m.propertySheets(cfg)
    p.push('<ImportGroup Label="PropertySheets" %s>', m.condition(cfg))
    p.w('<Import Project="$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props" Condition="exists(\'$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\')" Label="LocalAppDataPlatform" />')
    p.pop('</ImportGroup>')
end

ここに,今回 importprops の処理を追加します.

function m.propertySheets(cfg)
    p.push('<ImportGroup Label="PropertySheets" %s>', m.condition(cfg))
    p.w('<Import Project="$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props" Condition="exists(\'$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\')" Label="LocalAppDataPlatform" />')

    if cfg.importprops and #cfg.importprops > 0 then
        for i = 1, #cfg.importprops do
            local prop = project.getrelative(cfg.project, cfg.importprops[i])
	    p.w('<Import Project="%s" />', prop);
        end
    end

    p.pop('</ImportGroup>')
end

これで実装は完了です.Luaスクリプトを更新したので,以下のコマンドで再ビルドします.

.\bin\release\premake5 embed
devenv .\build\bootstrap\premake5.sln /Build Release

これで importprops が使えます.

使用例

filter { "platforms:x64", "configurations:Debug" }
    importprops "props/Debug_x64.props"

リポジトリ

importprops を追加した premake のリポジトリは以下です.

vscmd.batbuild.bat, make.bat を追加しています.

make.bat

@echo off
call vscmd.bat
nmake -f Bootstrap.mak windows
pause

build.bat

@echo off
call vscmd.bat
.\bin\release\premake5 embed
devenv .\build\bootstrap\premake5.sln /Build Release
pause

📌 Tips

OR

filter { "platforms:x64", "configurations:Debug or Release" }
   ...

外部プロジェクト

externalproject "Hoge"
    location <Hoge.vcxprojがある場所>
    kind "StaticLib"
    language "C++"

グループ

フォルダを追加します.

group "libs"
    externalproject "Hoge"
        location "hoge.vcxproj"
        kind "StaticLib"
        language "C++"

依存関係

プロジェクト Foo がライブラリ Hoge に依存している場合

project "Foo"
  links { "Hoge" }
  group "libs"
    externalproject "Hoge"
      location <Hoge.vcxprojがある場所>
      kind "StaticLib"
      language "C++"

共有DLLを使わない

project "Foo"
    flags { staticruntime "On" }

プリコンパイル済みヘッダー

project "Foo"
    pchheader "stdafx.h"
    pchsource "stdafx.cpp"

Discussion