分割コンパイル
(2018年度) 担当:笹倉・佐藤 2018.12.20分割コンパイルとは
• 一つのプログラムのソースを複数のソース ファイルに分けてコンパイルすること • ある程度大きなプログラムの場合ソースファ イルをいくつかに分割して開発するのが普通なぜ分割コンパイルするのか
1. コンパイル時間を短縮するため 2. ソースコードを見やすくするため 3. ソースコードを再利用しやすくするため 4. 複数人での開発をしやすくするため分割コンパイル演習
クイックソートのプログラムで試してみる. 1. ~sasakura/compiler/2007/src/qsort .c を自分のところにコピーする 2. このプログラムを main 関数だけのソース ファイル main.c と quicksort 関数だけの分割コンパイル演習
• コンパイルのしかた × gcc -o main main.c × gcc -o quicksort quicksort.c ○ gcc -c main.c ○ gcc -c quicksort.c○ gcc -o qsort main.o quicksort.o
それぞれのソースファイルをコンパイルして オブジェクトファイルを作っている オブジェクトファイル同士をリンクしている
分割コンパイル演習
• quicksort.c の中のコメントアウトしてある部 分のコメントを外して(アンコメント)動くように する • (この部分はクイックソートの途中経過を表示 するもの)分割コンパイル演習
• コメントを外しただけでは動かない理由 1. MAXNUM を知らないと言われる
2. data を知らないと言われる • 対処方法
1. #define MAXNUM 10 を quicksort.c にいれる 2. extern data[]; をquicksort.c にいれる
大域変数と分割コンパイル
• 大域変数のスコープは通常はそのソースファ イルの中 • 他のソースファイルで宣言されている大域変 数を参照したいときは参照したい方のソース ファイルで extern 宣言をするプロトタイプ宣言と分割コンパイル
• 他のソースファイルにある関数のプロトタイプ 宣言はなくてもコンパイルエラーにはならない • しかし,それはコンパイル時に検査していな いだけ • もし型が違えばリンク時にエラーが出る • よって,使用する関数についてはプロトタイプ 宣言をしておいた方がよいヘッダファイルの活用
• 記号定数,extern 宣言,関数のプロトタイプ 宣言は main.c にも quicksort.c にも同じもの を書かなくてはならない → 面倒 共通のものをヘッダファイルにしてそれを include するようにする • 他にも共通の typedef などはヘッダファイル にいれると便利ヘッダファイルの例
#define MAXNUM 10 extern int data[];
void quicksort(int[], int, int);
myHeader.h (main.c, quicksort.c と同じディレクトリに作る) #include “myHeader.h” を main.c と quicksort.c にいれる
make の利用
• 毎回以下の用なコマンドを手で打つのは面倒 gcc -c main.c gcc -c quicksort.cmake とは
• ファイルの更新時間をみて処理を行うための ツール • 主に分割コンパイルの支援のために使われ る • Unix で標準でついてくるツールmake の基本
• デフォルトでは Makefile (makefile でもい い)に処理の規則を書く • 処理の規則の書き方 FileB : FileA1 FileA2 …. <tab>指定するコマンドFileA1, FileA2, …のファイルのうちどれか
一つでも更新時間が FileBよりも新しけれ
Makefile の例
• 以下の内容の Makefile をソースファイルのおい てあるディレクトリで作成する • make とすると,更新されたものだけコンパイルさ れる • でも,これだとソースファイルが増えるたびにいち いち同じようなことを書かないといけない→面倒qsort : main.o quicksort.o
gcc -o qsort main.o quicksort.o main.o : main.c myHeader.h
gcc -c main.c
quicksort.o : quicksort.c myHeader.h gcc -c quicksort.c
賢い
make の使い方
• マクロの利用 – 長いものに別名をつけて何度も書かなくていい ように – 変更も容易 • 暗黙のルールの利用Makefile の例2
CC = gcc CFLAGS = -O -Wall HDRS = myHeader.h LDFLAGS = LIBS =OBJS = main.o quicksort.o PROGRAM = qsort
all: $(PROGRAM) $(PROGRAM): $(OBJS) $(HDRS)
$(CC) $(OBJS) $(LDFLAGS) $(LIBS) -o $(PROGRAM) clean:; rm -f *.o *~
###
main.o: main.c myHeader.h
quicksort.o: quicksort.c myHeader.h make についてもっと知りたい人は http://www.ecoop.net/coop/translated/GNUMake3.77/make_toc.jp.html などを参照のこと
yacc,lexを使うときのmakefileの例
CC = gcc CFLAGS = -O –Wall LEX = flex YACC = bison -d HDRS = parse.tab.h LDFLAGS = -lfl -ly LIBS =OBJS = parse.tab.o lex.yy.o ast.o PROGRAM = mycompiler
all: $(PROGRAM)
$(PROGRAM): $(OBJS) $(HDRS)
$(CC) $(OBJS) $(LDFLAGS) $(LIBS) -o $(PROGRAM) lex.yy.c: lex.l
$(LEX) lex.l parse.tab.c: parse.y
$(YACC) parse.y