モーダルを閉じる工作HardwareHub ロゴ画像

工作HardwareHubは、ロボット工作や電子工作に関する情報やモノが行き交うコミュニティサイトです。さらに詳しく

利用規約プライバシーポリシー に同意したうえでログインしてください。

工作HardwareHub ロゴ画像 (Laptop端末利用時)
工作HardwareHub ロゴ画像 (Mobile端末利用時)

Makefile コードスニペット

モーダルを閉じる

ステッカーを選択してください

モーダルを閉じる

お支払い内容をご確認ください

購入商品
」ステッカーの表示権
メッセージ
料金
(税込)
決済方法
GooglePayマーク
決済プラットフォーム
確認事項

利用規約をご確認のうえお支払いください

※カード情報はGoogleアカウント内に保存されます。本サイトやStripeには保存されません

※記事の執筆者は購入者のユーザー名を知ることができます

※購入後のキャンセルはできません

作成日作成日
2013/07/09
最終更新最終更新
2021/12/26
記事区分記事区分
一般公開

目次

    C++やMakefileを活用した開発環境整備について学びながら記事を書いています!

    0
    ステッカーを贈るとは?

    Makefileの基本的な構造

    makeコマンドを使えば、Makefileにあらかじめ記述しておいた手順にしたがって、C/C++などのソースファイルから実行ファイルを自動で生成できます。

    処理名: 依存するファイルあるいは処理名
    [タブひとつ]実行されるコマンド
    

    Makefile

    Sample: sample.cpp
    	g++ -o sample sample.cpp
    

    sample.cpp

    #include <iostream>
    using namespace std;
    
    int main() {
        cout << "This is a sample." << endl;
        return 0;
    }
    

    実行例

    $ make
    g++ -o sample sample.cpp
    $ ./sample
    This is a sample.
    

    複数の処理

    処理は複数記述できます。makeコマンドの引数を指定しなければ一番上の処理が実行されます。

    Makefile

    Sample1: sample1.cpp
    	g++ -o sample1 sample1.cpp
    
    Sample2: sample2.cpp
    	g++ -o sample2 sample2.cpp
    

    sample1.cpp

    #include <iostream>
    using namespace std;
    
    int main() {
        cout << "This is Sample1." << endl;
        return 0;
    }
    

    sample2.cpp

    #include <iostream>
    using namespace std;
    
    int main() {
        cout << "This is Sample2." << endl;
        return 0;
    }
    

    Sample2の処理を実行したければ

    $ make Sample2
    

    とします。

    変数の利用

    Makefile

    CC = g++
    CFLAGS = -g -Wall
    
    Sample1: sample1.cpp
    	$(CC) $(CFLAGS) -o sample1 sample1.cpp
    
    Sample2: sample2.cpp
    	$(CC) $(CFLAGS) -o sample2 sample2.cpp
    

    処理をネスト

    処理をネストさせることができます。一番上にALLという名称の処理を用意して、依存する処理名にSample1とSample2を半角スペースで区切って指定します。すると、ALLの処理を実行すると再帰的にSample1,Sample2の処理も実行されます。

    Makefile

    CC = g++
    CFLAGS = -g -Wall
    
    ALL: Sample1 Sample2
    
    Sample1: sample1.cpp
    	$(CC) $(CFLAGS) -o sample1 sample1.cpp
    
    Sample2: sample2.cpp
    	$(CC) $(CFLAGS) -o sample2 sample2.cpp
    

    ヘッダファイル更新を検知

    ヘッダファイルが更新された場合にも処理が実行されるようにするためには、依存ファイルを記述する箇所にヘッダファイルを追記します。

    Makefile

    CC = g++
    CFLAGS = -g -Wall
    
    ALL: Sample1 Sample2
    
    Sample1: sample1.cpp sample1.h
    	$(CC) $(CFLAGS) -o sample1 sample1.cpp
    
    Sample2: sample2.cpp sample2.h
    	$(CC) $(CFLAGS) -o sample2 sample2.cpp
    

    分割コンパイル

    処理のネスト関係を利用すると、分割コンパイル (オブジェクトファイル main.osub.o-c フラグで別々に生成してから、ALL の処理でリンク) もできます。

    Makefile

    CC = g++
    CFLAGS = -g -Wall
    
    ALL: main.o sub.o
    	$(CC) $(CFLAGS) -o main main.o sub.o
    
    main.o: main.cpp
    	$(CC) $(CFLAGS) -o main.o -c main.cpp
    
    sub.o: sub.cpp sub.h
    	$(CC) $(CFLAGS) -o sub.o -c sub.cpp
    

    main.cpp

    #include <iostream>
    #include "sub.h"
    using namespace std;
    
    int main() {
        cout << sub::str << endl;
        return 0;
    }
    

    sub.h

    namespace sub {
        extern char str[32];
    }
    

    sub.cpp

    #include "sub.h"
    namespace sub {
        char str[32] = "Externally defined string.";
    }
    

    実行例

    $ make
    g++ -g -Wall -o main.o -c main.cpp
    g++ -g -Wall -o sub.o -c sub.cpp
    g++ -g -Wall -o main main.o sub.o
    $ ./main 
    Externally defined string.
    

    特殊変数

    $@ および $< という特殊変数を用いると Makefile 内の共通部分の記述を省略できます。

    Makefile

    CC = g++
    CFLAGS = -g -Wall
    
    ALL: main.o sub.o
    	$(CC) $(CFLAGS) -o main main.o sub.o
    
    main.o: main.cpp
    	$(CC) $(CFLAGS) -o $@ -c $<
    
    sub.o: sub.cpp
    	$(CC) $(CFLAGS) -o $@ -c $<
    
    sub.o: sub.h
    

    $@ には処理名が入っており、$< には依存するファイルあるいは処理名のうち更新されたものが入っています。sub.hだけ更新される場合があやしいので、sub.oを二つに分けてみました。

    共通化 記法1

    どの処理名よりも先に.cpp.oという処理を記述すると、依存ファイルがcppで処理名がoの処理を共通化させることができます。

    Makefile

    CC = g++
    CFLAGS = -g -Wall
    
    .cpp.o:
    	$(CC) $(CFLAGS) -o $@ -c $<
    
    ALL: main.o sub.o
    	$(CC) $(CFLAGS) -o main main.o sub.o
    
    sub.o: sub.h
    

    共通化 記法2 (GNU make限定)

    .cpp.oを用いない別の記述も可能です。処理名がワイルドカード%.oで一致した場合、依存ファイル%.cppの%に%.oの.oを除いた部分が代入されます。

    CC = g++
    CFLAGS = -g -Wall
    
    %.o: %.cpp
    	$(CC) $(CFLAGS) -o $@ -c $<
    
    ALL: main.o sub.o
    	$(CC) $(CFLAGS) -o main main.o sub.o
    
    sub.o: sub.h
    

    ワイルドカード (GNU make限定)

    拡張子を置換したリストを生成するためにもワイルドカードを使用できます。

    Makefile

    CC = g++
    CFLAGS = -g -Wall
    OBJS = main.o sub.o
    DOCS = $(OBJS:%.o=%.txt)
    TARGET = main
    
    %.o: %.cpp
    	$(CC) $(CFLAGS) -o $@ -c $<
    
    ALL: $(OBJS)
    	$(CC) $(CFLAGS) -o $(TARGET) $(OBJS)
    
    sub.o: sub.h
    
    docs:
    	touch $(DOCS)
    
    clean:
    	rm -rf $(OBJS) $(TARGET) $(DOCS)
    

    実行例

    $ make
    g++ -g -Wall -o main.o -c main.cpp
    g++ -g -Wall -o sub.o -c sub.cpp
    g++ -g -Wall -o main main.o sub.o
    $ make docs
    touch main.txt sub.txt
    $ make clean
    rm -rf main.o sub.o main main.txt sub.txt
    

    その他の話題

    コマンド文字列の出力を抑制

    @ を付けるとコマンド文字列 が出力されなくなります。

    Makefile

    hello:
    	@echo ok
    	echo ok2
    

    出力例

    $ make 
    ok
    echo ok2
    ok2
    

    タスク名と同名のファイルが存在する場合を考慮

    .PHONY: hello
    hello:
            @echo ok
            echo ok2
    

    同名のファイルが存在しており .PHONY がない場合、タスクが実行できなくなります。

    $ ls
    hello  Makefile
    $ make
    make: 'hello' is up to date.
    

    既定で実行されるタスクを指定

    .DEFAULT_GOAL を指定すると、二つ目以降のタスクが既定で実行されるように設定できます。

    $ make
    help
    

    Makefile

    .DEFAULT_GOAL := help
    
    hello:
    	@echo ok
    
    help:
    	@echo help
    
    0
    詳細設定を開く/閉じる
    アカウント プロフィール画像 (本文下)

    C++やMakefileを活用した開発環境整備について学びながら記事を書いています!

    記事の執筆者にステッカーを贈る

    有益な情報に対するお礼として、またはコメント欄における質問への返答に対するお礼として、 記事の読者は、執筆者に有料のステッカーを贈ることができます。

    さらに詳しく →
    ステッカーを贈る コンセプト画像

    Feedbacks

    Feedbacks コンセプト画像

      ログインするとコメントを投稿できます。

      関連記事