6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

LLVM/clangとWSLのmake使ってWindowsの実行ファイルをビルドするためのMakefile

Last updated at Posted at 2018-04-24

 clangでPDBファイルが出力できるようになったりしたので、WSLのmake使ってWindowsの実行ファイルをビルドするMakefileを書いてみました。

方針としては、clang++.exeで依存関係ファイルの生成、clang-cl.exeでコンパイル、lld-link.exeでリンクを行います。

準備

次のものをインストールしておきます。

  • Visual Studio
  • LLVM/clang
  • Windows Subsystem for Linux (WSL) 1

LLVM/clangのパスを通して、WSLのLinuxのclangではなくWindowsのclangを使用します。WSLならclang++.exe等を利用できるようにします。

今回の環境は以下のようにしています。

  • ArchWSL
  • GNU Make 4.2.1
  • Visual Studio 2017 Community(14.13.26128)
  • LLVM/clang 6.0.0

コード

ここでは、特にsrcフォルダなどを作らず、cppファイルと同じ場所にexeファイルが生成されるようにします。

Makefile
CXXFLAGS := \
	-EHsc -W4 -utf-8 -std:c++17 \
	-fcolor-diagnostics -fansi-escape-codes \
	-DUNICODE -D_UNICODE

INCLUDE :=

LDFLAGS := \
	-libpath:"c:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.13.26128/lib/x64"

LIBS := \
	kernel32.lib user32.lib gdi32.lib

TARGET := example.exe

SRCS := $(shell ls | grep '.cpp')
OBJS := $(patsubst %.cpp, %.o, $(SRCS))
PDB := $(patsubst %.exe, %.pdb, $(TARGET))
DEPENDS := $(patsubst %.cpp, %.d, $(SRCS))

.PHONY: all clean debug release

debug: CXXFLAGS += -MTd -Zi -D_DEBUG -DDEBUG
debug: LDFLAGS += -debug
debug: $(TARGET)

release: CXXFLAGS += -MT -O2 -DNDEBUG
release: $(TARGET)

%.o: %.cpp
	clang++.exe -E -std=c++17 $(INCLUDE) -MMD $< > /dev/null
	sed -i 's/\\\([^\f\n\r\t]\)/\/\1/g' $(patsubst %.cpp, %.d, $<)
	clang-cl.exe -c $(CXXFLAGS) $(INCLUDE) $< -o $@

$(TARGET): $(OBJS)
	lld-link.exe $(LDFLAGS) $^ $(LIBS) -out:$@

all: debug

clean:
	-rm $(OBJS)
	-rm $(DEPENDS)
	-rm $(PDB)
	-rm $(TARGET)

-include $(DEPENDS)

コードはここに置いておきます。
https://github.com/LNSEAB/clang_cl_makefile

解説

CXXFLAGS

clang-cl.exeのオプションを設定しています。
以下にCXXFLAGSを抜粋します。

CXXFLAGS := \
	-EHsc -W4 -utf-8 -std:c++17 \
	-fcolor-diagnostics -fansi-escape-codes \
	-DUNICODE -D_UNICODE

オプションを/の代わりに-にしています。ただし、clと同じオプションで値や文字列を指定する時は-std:c++17のように=ではなく:を使います。
-fcolor-diagnostics -fansi-escape-codesはWSLでclangのメッセージに色をつけるためのオプションです。
-DUNICODE等の-Dはマクロを定義するオプションですが、ここで値を指定する時は-DWINNT=0x0A00のように=で指定します。

LDFLAGS

lld-link.exeのオプションを設定しています。
以下にLDFLAGSを抜粋します。

LDFLAGS := \
	-libpath:"c:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.13.26128/lib/x64"

lld-linkはVisual C++のlinkと同じオプションを使えます。

ライブラリのパスを通すのに-libpathを使っており、CXXFLAGSと同様に=の代わりに:を使っています。
また、上記のようにVisual Studioにあるlibcmt.libなどのCライブラリまでのパスを通す必要があります。

SRCSからDEPENDSまで

以下にSRCSからDEPENDSまでを抜粋します。

SRCS := $(shell ls | grep '.cpp')
OBJS := $(patsubst %.cpp, %.o, $(SRCS))
PDB := $(patsubst %.exe, %.pdb, $(TARGET))
DEPENDS := $(patsubst %.cpp, %.d, $(SRCS))

.cppファイルを自分で列挙したくないのでlsgrepを使って列挙しています。さらに、それを元にmakeの組み込み関数patsubstを使ってcppファイルの拡張子をそれぞれoとdに変えて列挙しています。

debugとrelease

debugとreleaseをルールを分けて別々にオプションを指定したい時、以下のような書き方ができます。

debug: CXXFLAGS += -MTd -Zi -D_DEBUG -DDEBUG
debug: LDFLAGS += -debug
debug: $(TARGET)

release: CXXFLAGS += -MT -O2 -DNDEBUG
release: $(TARGET)

%.o: %.cpp

%.oのルールを以下に抜粋します。

%.o: %.cpp
    clang++.exe -E -std=c++17 $(INCLUDE) -MMD $< > /dev/null
    sed -i 's/\\\([^\f\n\r\t]\)/\/\1/g' $(patsubst %.cpp, %.d, $<)
    clang-cl.exe -c $(CXXFLAGS) $(INCLUDE) $< -o $@

clang++.exeの行について、-MMDでdファイルの生成し、コンパイルはしないように-E> /dev/nullで標準出力されたプリプロセス済のソースを読み捨てることで、dファイルだけを出力します。しかし、dファイル内の依存関係のパスに何故か\が混じるので、次の行でsed/に置き換えてます。
あとは、clang-cl.exeでコンパイルを行います。

おわりに

ターミナルにWSLを使っているVSCodeでのデバッグもやりやすくなりました。

参考

サンプルコード
https://github.com/LNSEAB/clang_cl_makefile

  1. MSYS2とかのmakeのある他の環境で出来るかどうかは試してない。

6
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?