🙆

CMakeが怖いので、Premake始めました

2023/04/10に公開

環境

  • Windows
  • Visual Studio
  • C++

Premakeとは?

Premake はプロジェクトファイルを生成するためのコマンドラインツールです。ここでいうプロジェクトファイルというのはVisualStudioでいうところの.sln.vcxprojファイルのことです。ターゲットプラットフォームが複数の場合も、MacユーザーはXCode、WindowsユーザーはVisual Studioのような各々の環境にあったプロジェクトファイルを生成して作業が行えるようになります。また、他の有名ツールにCMakeがあります。Githubでよく見かけるアレCMakeLists.txtです

https://premake.github.io/

Blizzard 社も利用

blizzardの社員であり、box2dで有名な ErinCattoさんと、imguiで有名な Omarさん のツイートの一部です。

https://twitter.com/erin_catto/status/861354488623316992?s=46&t=SV0jCAVYEyz4Tu4z0w9LdQ

Blizzard は premake に移行しているみたいです。

使い方

Premakeは.lua形式のスクリプトに生成したいプロジェクトのプロパティを記述し、premake5.exeを実行することでプロジェクトが生成されます。コマンドライン引数で生成するプロジェクト形式を指定します。指定するプロジェクト形式一覧

premake5.exe vs2022

デフォルトでは、premake5.luaという命名のファイルを検索して実行されますが--fileでスクリプト名も指定可能です。

premake5.exe vs2022 --file=hoge.lua

手間を省くために、バッチファイル化しておくと良いと思います

@echo off
call premake5.exe vs2022
PAUSE

プロジェクトの構成

Visual Studioの場合、ソリューションファイル.slnがプロジェクトファイル.vcxprojのリストを保持する形で構成され、プロジェクトファイル.vcxproj単位でビルドが行われています。Gameというソリューションで、FrameworkApplication というプロジェクトがある場合このような構成になります。

Game.sln
 |- Framework.vcxproj
 |- Application.vcxproj

lua スクリプト

最小構成で書くとこうなります 「--」行はコメントです

-- ソリューション: Game
workspace "Game"
configurations
{
    "Debug",
    "Release",
}

-- プロジェクト: Framework
project "Framework"
    location      "Framework"
    kind          "StaticLib" -- スタティックライブラリ
    
-- プロジェクト: Application
project "Application"
    location      "Application"
    kind          "ConsoleApp" -- コンソールアプリ

実行すると、この様に生成されます

その他のプロパティ

使いそうなプロパティをまとめてみました。
詳しくは Premakeのリファレンス を参考にしてください

include "../xxx.lua"
include "xxx.lua"

project "Framework"
    location  "Framework"
    targetdir ("bin/%{prj.name}/%{cfg.buildcfg}")              -- 出力ディレクトリ
    objdir    ("bin/%{prj.name}/%{cfg.buildcfg}/intermediate") -- 中間ディレクトリ
    
    language      "C++"
    cppdialect    "C++17"
    kind          "StaticLib" -- .lib
    staticruntime "on"        -- 'on': マルチスレッド 'off': マルチスレッドDLL

    -- ビルド順序
    dependson
    { 
        "Framework",
        "Application",
    }

    -- プリプロセッサ
    defines
    {
        "FRAMEWORK_API"
    }

    -- プロジェクトに含むソース
    files 
    { 
        "%{prj.name}/Source/**.h",
        "%{prj.name}/Source/**.c",
        "%{prj.name}/Source/**.hpp",
        "%{prj.name}/Source/**.cpp",
    }

    -- ビルド後イベント
    postbuildcommands
    {
        -- xcopy
        "{COPYFILE} bin/Framework.lib Application/Lib/Framework.lib"
    }

    -- 追加のインクルードディレクトリ
    includedirs 
    {
        "%{prj.name}/Include",
    }

    -- 追加のライブラリディレクトリ
    libdirs
    {
        "%{prj.name}/Lib",
    }

    -- 追加の依存ファイル
    links
    {
        "xxx.lib",
    }

    -- 最新のSDKを使用する
    filter "system:windows"
        systemversion "latest"

    -- デバックビルド時: シンボル
    filter "configurations:Debug"
        symbols "On"

    -- リリースビルド時: 最適化
    filter "configurations:Release"
        optimize "On"

最後に

個人的な意見になりますが、ターゲットプラットフォームが1つであったり、ソリューション内にプロジェクトが1つしかない場合であっても、GUIでページを切り替えながらポチポチとプロパティを設定するよりシンプルにプロパティを管理することができると思いました。私と同じようにCMakeに恐怖を感じた人はPremakeをオススメします。

Discussion