学生実験1-3 : Make, CVS の使い方








実験の進め方

内容と達成目標

今回のテーマ「make と cvs の使い方」では,システム開発の際に必須のツールと言える make, cvs の基本的な使い方を習得する.make に関してはプログラミング1 or 2 で触れているが,その復習も兼ねて実習を行う.

  • 達成目標1:make が必要とされる理由を理解し,自ら開発するシステムに関する Makefile を書けるようになる.
  • 達成目標2:オープンソースとして公開されているソフトウェアをインストールできるようになる.
  • 達成目標3:バージョン管理ソフト cvs が必要とされる理由を理解し,今後の開発において cvs を導入することが出来る.
  • 達成目標4:複数人による共同作業(プログラミング)で利用されているリポジトリに対し,競合時の問題を解決できる.
進め方
  • テキスト・補助教材:本ページや参考文献参照(サンプルソースあり)
  • 作業スタイル:個人作業(1人1レポート)
評価基準

(先週と同じ)レポートでは指定した課題をこなしている(提出している)事を前提に基準点を設け,適宜加点・減点を行う.

課題と提出方法
  • 1人1レポート提出.
  • 全ての Level にトライし,レポートとしてまとめよ.ただし,Level 4 は 4.3 のグラフ作成(1つ)までを必須とする.
  • 本文とは分けて表紙を作成する事.表紙には以下の項目を記述すること.
    • 課題番号,タイトル,担当教員名
    • 氏名,学籍番号
    • 実験日,提出期限日,提出した日
  • レポートは LaTeX で作成し,印刷物を提出すること.
  • 提出期限:4/28(金) のクラスの期限は 5/8(月),5/2(火) のクラスは 5/12(金) 中に 705室へ提出すること.



1. make の使い方

1.1 make とは何か

オンラインマニュアルを読む癖をつけるということで,man から抜粋.
NAME
       make - GNU make utility to maintain groups of programs

DESCRIPTION
       The purpose of the make utility is  to  determine  automatically  which
       pieces of a large program need to be recompiled, and issue the commands
       to recompile them.

ワンポイント


とりあえず使ってみる


サンプルプログラム:make-sample.tar.gz

Level 1.1
上記サンプルプログラムをダウンロードし,make を実行せよ.make 実行時,端末上にその動作が表示されるはずである.表示された内容を記録し,その内容が何を意味するのか説明せよ.
# gzip -cd make-sample.tar.gz | tar xvf -
# cd make-sample
# make
(何が実行されているのか,観察し考察せよ.)
Level 1.2
どれか1つ以上のソースファイルを編集・保存し,make を実行せよ(コンパイルが通るのであれば編集内容は問わない).編集対象毎に make の動作は異なるはずである.どのファイルを編集するとどう動作するのかを確認せよ.
Level 1.3
touch コマンドにより1つ以上のソースファイルのタイムスタンプを更新し,make を実行せよ.この時の make の動作は Level 1.2 と比較して同じはずである.何故このような動作になっているのか考察せよ.



1.2 make の挙動

SYNOPSIS
       make [ -f makefile ] [ option ] ...  target ...

(DESCRIPTION)
       To prepare to use make, you must write a file called the makefile  that
       describes the relationships among files in your program, and the states
       the commands for updating each file.  In a program, typically the  exe-
       cutable  file  is  updated from object files, which are in turn made by
       compiling source files.

       Once a suitable makefile exists,  each  time  you  change  some  source
       files, this simple shell command:

              make

       suffices  to  perform  all  necessary recompilations.  The make program
       uses the makefile data base and  the  last-modification  times  of  the
       files  to  decide  which  of the files need to be updated.  For each of
       those files, it issues the commands recorded in the data base.

       make executes commands in the makefile to update  one  or  more  target
       names,  where name is typically a program.  If no -f option is present,
       make will look for the makefiles GNUmakefile, makefile,  and  Makefile,
       in that order.

       Normally  you  should  call  your makefile either makefile or Makefile.
       (We recommend Makefile because it appears prominently near  the  begin-
       ning  of  a directory listing, right near other important files such as
       README.)  The first name checked, GNUmakefile, is not  recommended  for
       most  makefiles.   You should use this name if you have a makefile that
       is specific to GNU make, and will not be understood by  other  versions
       of make.  If makefile is `-', the standard input is read.

       make  updates  a  target  if it depends on prerequisite files that have
       been modified since the target was last modified, or if the target does
       not exist.

ワンポイント




1.3 makefileを書く

基本形

target:	[source]
	[command]
Level 2.1

サンプルには幾つかの Makefile 例があり,makefile2 は詳細動作まで記述した例である.makefile2 の source や command を削除し,make を実行せよ.この例では全く同一の動作になっているはずである.これは make に推論機能が実装されているためである.各自削除した source / command について,具体的に何が推論により補われているのかを示せ.

→(考えてみよう!)ソースとして「hoge.o」を指定した場合,「hoge.c」があれば make はそのソースが cc によりコンパイルします.これは make がそのような関係を知っているからですが,知らないものに対してはどのように教えれば良いのか?

マクロ

CC = gcc
CFLAGS = -Wall -O2
LOADLIBS = -lm
USER_DEFILED_MACRO = hoge1 hoge2 hoge3

コマンドの応用例

clean:
	rm -f a.out *.o *~
演習1
上記の clean は大抵の makefile に定義されている内容である(コマンドやその引数は必要に応じてマクロを使うことが多い).これは何をしているのか.Level 1 でダウンロードした Makefile に類似の機能を記述し,実行せよ.その際,clean 実行前後で何がどう変わるのかを確認しなさい.

1.4 make の利用例

makefileを書く」で見て来たように,command 部では gcc のようなコンパイラだけでなく,コマンドライン上で実行出来るソフトウェアならば何でも利用することが可能である.いくつか例を見てみよう.


1.5 ネット上に公開されているソフトウェアをコンパイルしてみる

Makefile は自分が楽するためだけではなく,他の人が利用しやすくするために用意する物でもあります.最近は rpm/fink/epkg などでコンパイル済みのバイナリファイルを直接インストール(コピーするだけ)する方式が増えてきました. make により自分でコンパイルするのと比較した場合の rpm 等の利点・欠点は下記に示したものがあります.

rpm 等の利点
  • 自分でコンパイルする必要が無い.
  • パッケージの管理が便利(なことが多い).
rpm 等の欠点
  • 誰かがパッケージを作成(&公開)するまで待つ必要がある.(epkg は誰が用意しているのか?)
  • オプションの指定により機能追加したい等,カスタマイズしたパッケージが欲しい場合には,そのパッケージを探し出す必要がある.(自分でコンパイルした方が早い?)

今回は,例題としてApacheをインストールしてみよう.

  1. ダウンロード: Apache→ダウンロード→適当なサーバを選択→httpd-2.2.0.tar.gzをダウンロード
  2. 作業用ディレクトリに移動し,解凍.
    % mkdir  ~/temp
    % cd  ~/temp
    % tar  xvfz  httpd-2.2.0.tar.gz
    % cd  httpd-2.2.0
    
  3. コンパイル/インストール方法を確認: README, INSTALLを読んだり,「./configure --help」でインストール時のオプションを設定した上で make を実行する.
    (一般的な手順 [今回の手順は別にあります])
    % ./configure
    % make
    % make  test
    % sudo  make  install
    
    (今回は ~/apache2 にインストールしてみる)
    % ./configure  --prefix=$HOME/apache2
    % make
    % make  install
    
  4. 設定ファイルを編集する
    % cd  ~/apache2/conf
    % emacs -nw httpd.conf
    (User, Group, ServerAdmin, ServerName を編集.)
     User www
     Group www
     ServerAdmin j050xx@ie.u-ryukyu.ac.jp
     ServerName localhost:80
    
  5. httpd を起動する
    % sudo  ~/apache2/bin/apachectl  -k  start
    (この apachectl もシェルスクリプトで記述されています!)
    
  6. 動作確認する
    (1)ブラウザを開き,
     http://localhost:80/
    へアクセスする.
    
    (2)アクセスログを確認する
    % cat ~/apache2/logs/access_log
    
  7. httpd を停止する
    % sudo ~/apache2/bin/apachectl  -k  stop
    
(オプション課題)configure について
  • 「configure」は何のために実行する必要があるのか.
  • どのようにすれば自分で作成したシステムに configure を導入することが出来るのか.
  • 参考キーワード:autoconf, automake
  • Easy Package で配布されているパッケージは何故 make する必要がないのか?







2. CVS の使い方

2.1 CVS とは何か

Concurrent Versions System(バージョン管理システム)の略で,プログラムソースだけではなく,テキストベースのファイル一般についてバージョンを管理するためのシステム. 関連するソースファイル一式をプロジェクトとして管理する. ソースファイルの変遷を記録し,日付・リビジョン番号・リソース番号を参照し,任意の時点のソースファイル一式のコピーを取ってくることが可能.


2.2 クイックスタート

iBook で個人用 CVS を使ってみよう!

  1. 環境変数を設定(メインとなるリポジトリの設定)
    # tcsh の人は ~/.tcshrc に以下の設定を記述
    setenv  CVSROOT  $HOME/CVS_DB
    setenv  CVSEDITOR  "emacs -nw"
    # bash の人は ~/.bashrc に以下の設定を記述
    export  CVSROOT=$HOME/CVS_DB
    export  CVSEDITOR="emacs -nw"
    (vi 等,emacs 以外を使用したい場合には使用したいエディタを指定)
    
  2. シェルに環境変数を読み込む(ターミナルを再起動でもOK)
    # tcsh の人
    % source  ~/.tcshrc
    # bash の人
    % .  ~/.bashrc
    
  3. リポジトリの作成,確認.
    % mkdir  ~/CVS_DB
    % cvs  init  (一度だけ実行)
    % ls  ~/CVS_DB
    (~/CVS_DB/CVSROOT/ が作成されていればOK!)
    
  4. 例として,ダウンロードした「make-sample」を登録する.
    % cd  hogehoge/make-sample
    % make  -f  makefile2  clean
    % cvs  import  make-sample  j050xx  start
    (エディタが起動するので,
     中身が分かるようにコメントを記入して終了する)
    (登録が済めば以下のように出力されるはず・・)
    
    N make-sample/0readme.txt
    N make-sample/add.c
    N make-sample/Makefile
    N make-sample/makefile1
    N make-sample/makefile2
    N make-sample/makefile3
    N make-sample/multi.c
    N make-sample/sample.c
    
    No conflicts created by this import
    
    (この import では競合が発生しなかった)
    (ls ~/CVS_DB/ や ls ~/CVS_DB/make-sample
     として確認してみると吉)
    
  5. import(新規登録)で登録されていることを確認したら,make-sample を削除し,リポジトリからコピーを取得してみる.
    % cd  ..
    % rm -rf make-sample
    % cvs  checkout  make-sample
    (成功すれば以下のような出力が得られます)
    
    cvs checkout: Updating make-sample
    U make-sample/0readme.txt
    U make-sample/Makefile
    U make-sample/add.c
    U make-sample/makefile1
    U make-sample/makefile2
    U make-sample/makefile3
    U make-sample/multi.c
    U make-sample/sample.c
    
    (ls make-sample として,中身を確認してみよう.
     一点登録時には無かったモノがあるはずです)
    
  6. ソースを更新して,動作確認をした上で,オリジナルと何処が異なるのかを確認する.
    % cd  make-sample
    % emacs  -nw  multi.c
    ==== multi.c に以下を追加(4行) ====
    /* divide: x/y を計算 */
    int divide(int x, int y){
      return (x/y);
    }
    ==== multi.c 追加ここまで ====
    ==== sample.c に以下を追加(2行) ====
    // 関数宣言部に・・・
    int divide(int x, int y);
    // main 関数内に・・・
      fprintf(stdout,"divide(%d,%d)=%d\n",x,y,divide(x,y));
    ==== sample.c 追加ここまで ====
    (動作確認)
    % make
    % ./sample
    (ちゃんと動いた後で,
     オリジナル(リポジトリ情報)と比較して
     どこが変更されているのかを確認する)
    % cvs  status
     更新されていないファイルについては
    
    File: 0readme.txt       Status: Up-to-date
    
     更新されたファイルについては
    
    File: multi.c           Status: Locally Modified
    
     のように,
      最新を保っているか,
      ローカルで更新がなされているのか,
      別の誰かが更新されているのか(Status: Needs Patch),
     を確認できる.
     特に,変更箇所を確認したい場合は
    % cvs  diff
     とすると,変更のあったファイル名,変更点を確認できる.
    
  7. 動作確認後,変更したファイルを新バージョンとして登録する.
    (ちゃんと動いていれば,
     新バージョンとして登録する)
    % cvs  commit
    (変更されたファイル multi.c と sample.c
     が自動的に抽出されているのを確認し,
     変更内容を記入して保存)
    (正しくアップデートできれば,
     以下のような出力が得られます)
    
    cvs commit: Examining .
    Checking in multi.c;
    /Users/tnal/CVS_DB/make-sample/multi.c,v  <--  multi.c
    new revision: 1.2; previous revision: 1.1
    done
    Checking in sample.c;
    /Users/tnal/CVS_DB/make-sample/sample.c,v  <--  sample.c
    new revision: 1.2; previous revision: 1.1
    done
    
    
  8. ログ(コメント)を確認してみる.
    % cvs  log  multi.c  |  nkf  -e
    (コメントは読めますか?)
    

2.3 CVS での一日の作業

クイックスタートでは具体例を示しながら動作を確認することがメインであったため,全体像が把握しづらかったと思われるが,一般的な作業の流れは以下のようになる.

  1. import: 新規プロジェクトの登録(プロジェクト開始時の一度のみ).
  2. checkout: 作業用コピーをチェックアウトする.
  3. 変更を加える.
  4. diff, log, update: 自分や共同作業者の作業内容を調べる.
  5. commit: 最新版としてリポジトリへ変更を通知する.
Level 3.1

余り(%計算)を求める関数 mod(x,y) を mod.c として作成し,main 関数内でその関数を実行するように修正せよ. 動作確認をした後で,新規に追加すべきファイル(mod.c)を追加しつつ,修正した sample.c の修正バージョンの2点を,新バージョンとしてCVSに登録せよ. なお,レポートには cvs commit 時に出力されたログを示すこと.

Hint: cvs add

Level 3.2

現在,make-sample プロジェクトには以下に示すバージョンが含まれているはずである.

  1. 初期バージョン(ダウンロードしたままのもの.多少の修正はされてても良い)
  2. 割り算を追加したバージョン
  3. 余剰計算を追加したバージョン

上記の3バージョン時のソースファイル一式を取り出せ. レポートには取り出した際のコマンドと,その出力結果を引用すること.

Level 3.3(オプション)

make や cvs は共同作業時により有効に機能する. しかし,cvs では checkout 時にロック制御を行わないため,「複数人が現バージョンのコピーを取得し,同じファイルに修正を加える状況(競合)」が起こり得る. この場合,cvs は誰の修正が正しいのかを判断することが出来ないため,ユーザ同士で修正箇所を確認し合い,人手により競合を解決する(正しい修正を通知する)必要がある. 実際にそのような状況を作り出し,実験してみよ.


課題と提出方法

課題
  • 全員必須:全ての Level にトライし,レポートとしてまとめよ.
  • オプション:gcc以外にどのような使い道があるか?検討/調査/実験し,その結果を報告せよ.
提出方法
  • 1人1レポート提出.
  • レポートは LaTeX で作成し,印刷物を提出すること.

用語説明

make
自動コンパイラ.
makefile
make にコンパイル対象・方法を指定するための設定ファイル.
target, ターゲット
make で生成したい対象名のこと(例:a.out).指定したターゲットが存在しない場合や,生成元ファイル(ソースと呼びます)の日付が新しい場合に,そのターゲットを生成しようとします.
source, ソース
ソースファイル名(例:hello.c).
command, コマンド
ソースからターゲットを生成するためのコマンドのこと(例:gcc).


参考文献・サイト

make 関連
cvs 関連