Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
24
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

@ousttrue

ビルドツールpremakeの紹介

ビルドツールpremakeについてご紹介。

20161014追記
201609更新

Premakeの守備範囲はだいたいCMakeに似ていて、定義ファイルからvcソリューションやMakeFileの生成をすることができます。プロジェクトで各ライブラリのオプション(/MTとか/MTDとかDEFINEなど)をまとめて変えたい場合、生成物の出力ディレクトリをDebug, Release, Win32, Win64, VS2010, VS2013で違うディレクトリに出力したい、もしくは同じディレクトリに違う名前で出力したい場合などに設定をluaコードで記述することができます。
こういった場合、VSで開発しているとプロジェクトの設定を開いてマウスでぽちぽちしたりvcxprojのXMLを直接編集するのを強いられますし、CMakeではCMake語がよくわかりません。しかしPremakeで管理していれば次のように記述してソリューションを再生成するだけでさくっと設定完了できるかもしれません。

premake5.lua抜粋

-- PlatformとConfiguration毎に出力ディレクトリを分ける
filter {"platforms:Win32", "configurations:Debug" }
    targetdir "build/Win32/Debug"
filter {"platforms:Win32", "configurations:Release" }
    targetdir "build/Win32/Release"
filter {"platforms:Win64", "configurations:Debug" }
    targetdir "build/Win64/Debug"
filter {"platforms:Win64", "configurations:Release" }
    targetdir "build/Win64/Release"

-- すべてのPlatformとConfiigurationのvcのリンクをStaticRuntime(/MT, /MTdの方)にする
filter {} -- filterをクリア。すべてが対象になる
    flags { "StaticRuntime" }

Download

https://premake.github.io/download.html
のリンクからPremake 5.0 (alpha)を取得するべし。

HelloWorldプロジェクト

HelloWorldしてみる。
新しいディレクトリを作ってファイルを配置します。

+ hello_premake
  + hello.c
  + premake5.lua
  + premake5.exe
hello.c
#include <stdio.h>

int main(void) 
{
   puts("Hello, word!");
   return 0;
}

各コマンドは呼び出しにスコープのような効果範囲が決まっていて
直近のprojectとfilterが呼び出しが範囲を決める。
エディタでインデントをかけるとフラットになっていしまうので
lua言語のブロックdo, endで人工的にインデントしてみた。

premake5.lua
-- premake5.lua
workspace "hello_premake"
configurations { "Debug", "Release" }

project "hello_premake"
do
    kind "ConsoleApp"
    language "C"

    files { "**.h", "**.c" }

    filter "configurations:Debug"
    do
        defines { "DEBUG" }
        flags { "Symbols" }
    end

    filter "configurations:Release"
    do
        defines { "NDEBUG" }
        optimize "On"
    end
end

premake5.exeを実行してプロジェクトを生成。

ソリューションを生成
> premake5.exe vs2015
Building configurations...
Running action 'vs2015'...
Generated hello_premake.sln...
Generated hello_premake.vcxproj...
Done (24ms).

が生成されます。
ビルド

コマンドラインでビルド
> set MSBUILD=C:\Program Files (x86)\MSBuild\14.0\Bin\msbuild.exe
> "%MSBUILD%" hello_premake.sln /p:Configuration=Release /p:Platform=Win32
Microsoft (R) Build Engine バージョン 14.0.25420.1
Copyright (C) Microsoft Corporation. All rights reserved.

このソリューション内のプロジェクトを 1 度に 1 つずつビルドします。並行ビルドを有効にするには、"/m"  スイッチを追加してください。
2016/09/25 0:10:16 にビルドを開始しました。
ノード 1 上のプロジェクト "D:\dev\hello_premake\hello_premake.sln" (既定のターゲット)ValidateSolutionConfiguration:
  ソリューション構成 "Release|Win32" をビルドしています。
プロジェクト "D:\dev\hello_premake\hello_premake.sln" (1) は、ノード 1 上に "D:\dev\hello_premake\hello_premake.
vcxproj" (2) をビルドしています (既定のターゲット)PrepareForBuild:
  ディレクトリ "obj\Release\" を作成しています。
  ディレクトリ "bin\Release\" を作成しています。
  ディレクトリ "obj\Release\hello_premake.tlog\" を作成しています。
InitializeBuildStatus:
  "AlwaysCreate" が指定されたため "obj\Release\hello_premake.tlog\unsuccessfulbuild" を作成していま す。
ClCompile:
  C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\CL.exe /c /Zi /nologo /W3 /WX- /Ox /Oi
   /Oy- /D NDEBUG /D _UNICODE /D UNICODE /GF /Gm- /EHsc /MD /GS /Gy /fp:precise /Zc:wchar_t /Zc:for
  Scope /Zc:inline /Fo"obj\Release\\" /Fd"obj\Release\vc140.pdb" /Gd /TC /analyze- /errorReport:que
  ue hello.c
  hello.c
Link:
  C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\link.exe /ERRORREPORT:QUEUE /OUT:"bin\
  Release\hello_premake.exe" /INCREMENTAL:NO /NOLOGO kernel32.lib user32.lib gdi32.lib winspool.lib
   comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /M
  ANIFEST /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /manifest:embed /PDB:"bin\Release\hello
  _premake.pdb" /SUBSYSTEM:CONSOLE /OPT:REF /OPT:ICF /TLBID:1 /ENTRY:"mainCRTStartup" /DYNAMICBASE
  /NXCOMPAT /IMPLIB:"bin\Release\hello_premake.lib" /MACHINE:X86 /SAFESEH obj\Release\hello.obj
  hello_premake.vcxproj -> D:\dev\hello_premake\bin\Release\hello_premake.exe
FinalizeBuildStatus:
  ファイル "obj\Release\hello_premake.tlog\unsuccessfulbuild" を削除しています。
  "obj\Release\hello_premake.tlog\hello_premake.lastbuildstate" のタッチ タスクを実行しています。
プロジェクト "D:\dev\hello_premake\hello_premake.vcxproj" (既定のターゲット) のビルドが完了しました 。

プロジェクト "D:\dev\hello_premake\hello_premake.sln" (既定のターゲット) のビルドが完了しました。


ビルドに成功しました。
    0 個の警告
    0 エラー

以下のbatファイルを作っておくとわりと便利。

premake5_vs2015.bat
premake5.exe vs2015

ファイル名の命名規則

カレントのpremake5.luaがデフォルトの設定として使われる。なければpremake4.luaも検索される。
個別にファイルを指定するには"--file="コマンドラインを使う。

luaのシンタックス上の注意

関数呼び出し時に、引数が文字列かテーブルのリテラルの場合のみ括弧を省略できる。

project "project_name"

files {
  "hello.c",
}

リテラルじゃない場合エラーになります

local name="project_name"

project name -- x
project(name) -- o

環境、種別を切り分ける概念

action

どの種類のプロジェクトを生成しているか。premake5.exeのコマンドライン引数。

vs2010, vs2013, vs2015, gmake, etc...

action別に切り分けできる。

filter { "action:vs*" }
  -- vs用の設定

filter { "action:gmake" }
  -- gmake用の設定

configuration

バリエーション。
よく使うのはこれ。

-- 定義して
configurations { "Debug", "Release" }

-- 設定する
filter "configurations:Debug"
do
    defines { "DEBUG", "_DEBUG" }
    flags { "Symbols" }
end
filter "configurations:Release"
do
    defines { "NDEBUG" }
    optimize "On"
end

以外にも

dll_debug32, static_debug32

等自由に定義できる。

platform

バリエーションその2。

Unlike build configurations, platforms are completely optional. If you don't need them, just don't call the platforms function at all and the toolset's default behavior will be used.

x86, x86_64, etc...

-- 定義して
platforms { "x86_64", "x86" }

-- 設定する
filter { "platforms:x86" }
   architecture "x86"
filter { "platforms:x86_64" }
   architecture "x86_64"

実用的な雛形

筆者がいつも使っているものです。

  • sln, vcxproj等の出力ディレクトリを_build_premakeに隔離
  • 32bit, 64bitの2種類
  • Debug, Releaseの2種類
  • 成果物(exe, dll)の出力を_build_premake/Win64_Releaseという風に指定
  • 出力ディレクトリを分けたのでライブラリ名に_dといったサフィックスは付けない

実際には、Win32をばっさり削ってます。
あと、プロジェクト定義は別々のファイルに分割してincludeかdofileで読み込みます(後述)。

premake5.lua
local build_dir="_build_premake"

-- premake5.lua
location(build_dir)

workspace "workspace"
do
    configurations { "Debug", "Release" }
    platforms { "Win32", "Win64" }
end

filter "configurations:Debug"
do
    defines { "DEBUG", "_DEBUG" }
    flags { "Symbols" }
end

filter "configurations:Release"
do
    defines { "NDEBUG" }
    optimize "On"
end

filter { "platforms:Win32" }
   architecture "x86"
filter {"platforms:Win32", "configurations:Debug" }
    targetdir(build_dir.."/Win32_Debug")
filter {"platforms:Win32", "configurations:Release" }
    targetdir(build_dir.."/Win32_Release")

filter { "platforms:Win64" }
   architecture "x64"
filter {"platforms:Win64", "configurations:Debug" }
    targetdir(build_dir.."/Win64_Debug")
filter {"platforms:Win64", "configurations:Release" }
    targetdir(build_dir.."/Win64_Release")

filter { "action:vs*" }
    buildoptions {
        "/wd4996",
    }
    defines {
        "_CRT_SECURE_NO_DEPRECATE",
        "NOMINMAX",
    }
    --characterset "Unicode"
    characterset "MBCS"

filter {} -- filter clear


project "project"
do
    --kind "ConsoleApp"
    --kind "WindowedApp"
    --kind "StaticLib"
    kind "SharedLib"
    --language "C"
    language "C++"

    objdir "%{prj.name}"

    flags{
        --"WinMain" -- with WindowedApp kind
        --"StaticRuntime",
    }
    files {
        "*.cpp",
        "*.h",
    }
    includedirs { 
    }
    defines { 
    }
    buildoptions { 
    }
    libdirs { 
    }
    links { 
    }

    postbuildcommands{
        "copy $(TargetDir)$(TargetName).dll ..",
    }
    filter { "configurations:Debug" }
    do
        postbuildcommands{
            "copy $(TargetDir)$(TargetName).pdb ..",
        }
    end
end

premakeでプロジェクト設定を管理してgitignoireに_build_premakeを設定し、slnやvcxprojを生成物と見なして
リビジョン管理から外してます。

howto/tips

プロジェクト定義を外部ファイルに分ける

dofileを使う。

dofile "subproject/premake5.lua"

省略形として

include "subproject"

変数展開

configurations { "debug", "release" }
platforms { "x86_64", "x86" }

    libdirs {
        "$(FBXSDK_DIR)/lib/%{cfg.action}/%{cfg.platform}/$(Configuration)",
    }
    -- $(FBXSDK_DIR)\lib\vs2015\x86_64\$(Configuration)と展開される

実例

libpng

+ libpng
    + premake5.lua
    + libpng-1.6.16
        + premake5.lua
    + zlib-1.2.8
        + premake5.lua
premake5.lua
-- premake5.lua
location "build"

solution "libpng"
do
    configurations { "Debug", "Release" }
    platforms { "Win32", "Win64" }
end

defines {
    "WIN32",
    "_WINDOWS",
    "_USRDLL",
}
buildoptions { "/wd4996" }

filter "configurations:Debug"
do
    defines { "DEBUG", "_DEBUG" }
    flags { "Symbols" }
end

filter "configurations:Release"
do
    defines { "NDEBUG" }
    optimize "On"
end

filter { "platforms:Win32" }
   architecture "x32"
filter { "platforms:Win64" }
   architecture "x64"

filter {"platforms:Win32", "configurations:Debug" }
    targetdir "build/Win32/Debug"
filter {"platforms:Win32", "configurations:Release" }
    targetdir "build/Win32/Release"
filter {"platforms:Win64", "configurations:Debug" }
    targetdir "build/Win64/Debug"
filter {"platforms:Win64", "configurations:Release" }
    targetdir "build/Win64/Release"

include "libpng-1.6.16"
include "zlib-1.2.8"
zlib-1.2.8/premake5.lua
project "zlib"
do
    kind "StaticLib"
    language "C"
    --language "C++"

    files { "*.h", "*.c" }
end
libpng-1.6.16/premake5.lua
project "libpng"
do
    kind "SharedLib"
    language "C"
    --language "C++"

    files { "*.h", "*.c" }
    -- 依存関係を記述できる(libファイル名か他のproject名を書ける)
    links { "zlib" }
end

とりあえずソースをダウンロードしてlibpng.dllを生成するべく定義してみた。zlibはあっさりとビルドできてしまったが、libpngの方はさすがに通らない。修正する。
libpng-1.6.16/projects/vstudio/libpng/libpng.vcxprojを参考にlibpng-1.6.16/premake5.luaを改造する。

libpng-1.6.16/premake5.lua
project "libpng"
do
    kind "SharedLib"
    language "C"
    --language "C++"

    files { 
        "png.c",
        "pngerror.c",
        "pngget.c",
        "pngmem.c",
        "pngpread.c",
        "pngread.c",
        "pngrio.c",
        "pngrtran.c",
        "pngrutil.c",
        "pngset.c",
        "pngtrans.c",
        "pngwio.c",
        "pngwrite.c",
        "pngwtran.c",
        "pngwutil.c",
    }
    includedirs {
        "../zlib-1.2.8",
    }
    -- 基準ディレクトリはvcxprojのあるところ
    prebuildcommands {
        "copy ..\\libpng-1.6.16\\scripts\\pnglibconf.h.prebuilt ..\\libpng-1.6.16\\pnglibconf.h",
    }
    links { "zlib" }
end

ビルド成功。
ss.png

/MT(/MTD)の件

premake5.luaに追記
-- buildoptions { "/wd4996" }の次の行あたり
flags { "StaticRuntime" }

static.png

MSVCR12D.DLLへの参照を消し去った。
こんな感じでプロジェクトを見通しのいい状態で管理できる。

SDL2

ドキュメント

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
24
Help us understand the problem. What are the problem?