プロフィール

けい

Author:けい
公開したWebサービス・アプリ一覧はこちら

※2014年12月、私が個人で開発したWebサービス・アプリへの
累計アクセス数は8億を超えました。
負荷対策頑張ります。日々精進していきます!!


■■■ 業務経歴 ■■■
社会人1年目:携帯電話開発。画面周りを1年間
2年目 :海外向け携帯電話ミドルウェア開発
     ブラウザとプロトコルスタック周り
2年目後半~:携帯電話の通信専用チップ開発
3年目:カーナビ。画面周りの開発
3年目後半~:BDビデオカメラ
     組み込みLinux カーネルと
     ドライバの開発。
4年目12月:プロジェクト途中で退社
~ここまではC、またはC++で開発~

~ここからJavaがメインの開発~
4年目1月:Web系の会社に転職
       ~4ヶ月間の研修
5年目5月:製造業向け生産管理システム開発
6年目9月:証券会社向けシステム開発
7年目10月~携帯電話向けコミックサイトの運用・開発
8年目12月:プロジェクト途中で退社

~ここからPHPがメインの開発~
8年目1月~仲介手数料が無料の不動産屋の社内SEに転職
交渉しほぼ完全に裁量労働が可能な立場になる。
業務内容はシステム全般ですが、
最近はSEO対策の作業が多いです。
現在14年目 まだ、しばらくはこの会社に居るつもりです。

あと、全ての記事がリンクフリーです。

最近の記事

過去ログ

全ての記事を表示する

全ての記事を表示する

カテゴリー

FC2カウンター

RSSフィード

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
--.--.--    [ Myカテゴリ:スポンサー広告 ]

今更ながらMakefileを勉強してみた。


今更ながらMakefile について勉強してみました。
まずは以下のMakefileを見てください。 















makefile



読み方


1 a.out : main.o utils.o
2   g++ main.o utils.o
3
4 main.o : main.c utils.h
5   g++ -c main.c
6
7 utils.o : utils.c
8   g++ -c utils.c
1 a.outはmain.o utils.o に依存している。
2 main.oとutils.oをg++ でビルドしたものがa.outである。
3
4 main.o はmain.c utils.hに依存している。
5 main.cをg++ -c でコンパイルしたものがmain.oである。
6
7 utils.o は utils.cに依存している。
8 utils.cをg++ -c でコンパイルしたものがutils.oである。


Makefileの基本はこんな感じである。それぞれ : で区切られた依存するモノがあれば、処理を行っている。
Cに慣れた人には記載順などでオヤ?と思うかもしれない。私も最初に1,2 の行は最後に書かなくていいのか?
と思ったがC言語と違い、結構記載する順番は適当でもうまくmakeが探してくれる。

が、しかし、実際には上記のようなMakefileの書き方をしている人はいない。
それはなぜか? オープンソースのプロジェクトのMakefileを見ると、分岐など複雑な処理がありそんなに簡単に読み解くことができません。でも大丈夫。C言語が理解できているあなたにはMakefileを読むことは簡単です。
 












ちょっと難しそうにみえるmakefile
CFLAGS = -O -Wall
CPPFLAGS = -c
OBJECTS = main.o utils.o

sample: $(OBJECTS)
$(CC) $(CFLAGS) $^ -o $@

main.o: main.c utils.h
$(CC) $(CFLAGS) $(CPPFLAGS) $< -o $@
utils.o: utils.c main.h
$(CC) $(CFLAGS) $(CPPFLAGS) $< -o $@

clean:
$(RM) $(OBJECTS)


上記makefileを読んでみてください。熟読すると大文字で書かれている部分が実はC言語で言う マクロ(#define )と大差ないことに気がつくと思います。そう、つまり展開すると以下のようになります。 














ちょっと難しそうにみえるmakefile ちょっと難しそうにみえるmakefileの展開後
CFLAGS = -O -Wall
CPPFLAGS = -c
OBJECTS = main.o utils.o

sample: $(OBJECTS)
$(CC) $(CFLAGS) $^ -o $@

main.o: main.c utils.h
$(CC) $(CFLAGS) $(CPPFLAGS) $< -o $@
utils.o: utils.c main.h
$(CC) $(CFLAGS) $(CPPFLAGS) $< -o $@

clean:
$(RM) $(OBJECTS)
CFLAGS = -O -Wall
CPPFLAGS = -c
OBJECTS = main.o utils.o

sample: main.o utils.o
$(CC) -O -Wall  $^ -o $@

main.o: main.c utils.h
$(CC) -O -Wall  -c $< -o $@
utils.o: utils.c main.h
$(CC) -O -Wall -c $< -o $@

clean:
$(RM) main.o utils.o


展開するとこんな感じになり、わからない箇所は$(CC) と$^ ,  $@ , $< , $(RM) でしょうか。
それでは $(CC) と$(RM)のマクロ(#define )はどこにあるのでしょうか?
その答えは実は単なるデフォルト設定値です。
デフォルト設定値は make -p とすることで出力することができます。












デフォルト設定値
$ make -p
# GNU Make 3.80
# Copyright (C) 2002 Free Software Foundation, Inc.
# This is free software; see the source for copying conditions.
# There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
make: *** ターゲットが指定されておらず、makefile も見つかりません。中止。

# Make データベース出力 Fri Apr 28 21:35:02 2006

# 変数
# makefile 変数
SHELL = /bin/sh
# デフォルト
RM = rm -f
# デフォルト
CO = co
# デフォルト
COMPILE.mod = $(M2C) $(M2FLAGS) $(MODFLAGS) $(TARGET_ARCH)
# 環境変数
_ = /usr/bin/make
# デフォルト
PREPROCESS.F = $(FC) $(FFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -F
# デフォルト
LINK.o = $(CC) $(LDFLAGS) $(TARGET_ARCH)
# デフォルト
OUTPUT_OPTION = -o $@
# デフォルト
COMPILE.cpp = $(COMPILE.cc)
# makefile 変数
MAKEFILE_LIST :=
# デフォルト
LINK.p = $(PC) $(PFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)
# デフォルト
CC = cc
# デフォルト
CPP = $(CC) -E
# デフォルト
LINK.cc = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)
# 環境変数
PATH = /home/lfll/.dist/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/usr/lo
cal/sbin:/usr/local/bin:/usr/games:.
# デフォルト
LD = ld
# デフォルト
MAKE = $(MAKE_COMMAND)
# デフォルト
MAKE_VERSION := 3.80
# 環境変数
USER = lfll
# デフォルト
FC = f77
# 自動変数
%D = $(patsubst %/,%,$(dir $%))
# makefile 変数
MAKEFLAGS = p


そう。つまり、$(CC) はcc, $(RM)は rm -f となるわけです。
残りの$^ ,  $@ , $< は何になるかといいますと、
$@ は : の手前に記載されている部分になります。
$^  は : の後ろに記載されている部分です。
$<  は ターゲットが依存しているファイルに置き換えられる。 














ちょっと難しそうにみえるmakefileの展開後 さらに展開
 

sample: main.o utils.o
$(CC) -O -Wall  $^ -o $@


 



main.o: main.c utils.h
$(CC) -O -Wall  -c $< -o $@


clean:
$(RM) main.o utils.o


つまりこういうことです。

sample: main.o utils.o
gcc -O -Wall  main.o utils.o -o sample


#main.o utils.o をビルドし、実行ファイルsampleを作成


 


main.o: main.c utils.h
gcc -O -Wall  -c main.c -o main.o


 


 




 その他、$マークで始まるものには以下があります。
$* ターゲット名から拡張子を除いたものに展開される。










例:

sample.exe: main.o utils.o
$(CC) -O -Wall  $^ -o $*


 

sample.exe: main.o utils.o
$(CC) -O -Wall  $^ -o sample




 $? 依存ファイルの中から更新されたものに展開される。










例:

sample.exe: main.o utils.o
$(CC) -O -Wall  $^ -o $?


utils.o がsample.exeよりも新しかった場合には

sample.exe: main.o utils.o
$(CC) -O -Wall  $^ -o utils.o




Makefileの説明はこんなところです。
Makefileとはちょっと話がそれますが、C言語の#ifdefに関しては通常 gcc -D NANIKA main.c と記述するので
-D NANIKA を何かマクロで記載してしまうと楽ですね。
まだまだ色々なテクニックがありますが、それは使いながら覚えて言ってください。
最後に一つ注意点を。 













注意点


CFLAGS = -O -Wall
CPPFLAGS = -c
OBJECTS = main.o utils.o

test : test1.c test2.c



sample: $(OBJECTS)
$(CC) $(CFLAGS) $^ -o $@

main.o: main.c utils.h
$(CC) $(CFLAGS) $(CPPFLAGS) $< -o $@
utils.o: utils.c main.h
$(CC) $(CFLAGS) $(CPPFLAGS) $< -o $@

clean:
$(RM) $(OBJECTS)




 


さて上記をmakeした場合には一体何がビルドされるのでしょうか?
正解は一番上のtest のみがビルドされます。
sampleをmakeしたい場合には $make sampleとしなければいけません。
引数なしでmakeした場合には一番上のものしかmakeされないことに注意してください。

以下参考:


AutoMakeが面白そうなので、今度やってみようと思う。


スポンサーサイト
トラックバック(0)   コメント(0)   2006.06.18    [ Myカテゴリ:技術の話 ]

コメントの投稿













管理者にだけ表示を許可する

Template Designed By
ぐらいんだぁ
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。