The OMake user guide and reference manual: 2章 OMakeのクイックスタートガイド - Chapter 2 OMake quickstart guide
http://omake.metaprl.org/manual/omake-quickstart.htmlの日本語訳。<< 1章 ガイド - 目次に戻る - 3章 さらなるビルドの例
訳文
- 概要 - Description
- すでにmakeに慣れているユーザのために - For users already familiar with make
- 小さなCのプログラムをビルドする - Building a small C program
- より大きなプロジェクト - Larger projects
- サブディレクトリ - Subdirectories
- その他に考慮すべき点 - Other things to consider
- OCamlのプログラムをビルドする - Building OCaml programs
- OMakefileとOMakerootファイル - The OMakefile and OMakeroot files
- 複数バージョンのサポート - Multiple version support
- メモ - Notes
2.1 概要 - Description
omakeは、複数ディレクトリにソースファイルがあるプロジェクトをビルドするために作られました。通常、プロジェクトを設定するために、プロジェクトの各ディレクトリ内のOMakefileとプロジェクトのルートディレクトリ内のOMakerootファイルを使用します。OMakerootファイルでは全体的なビルド規則を設定し、OMakefileでは各サブディレクトリのビルドパラメータを設定します。omakeを実行すると、設定ツリーを調べ回り、すべてのOmakefileの規則を評価します。プロジェクトのビルドは全てのビルド規則に基づいて行われます。
omake is designed for building projects that might have source files in several directories. Projects are normally specified using an OMakefile in each of the project directories, and an OMakeroot file in the root directory of the project. The OMakeroot file specifies general build rules, and the OMakefiles specify the build parameters specific to each of the subdirectories. When omake runs, it walks the configuration tree, evaluating rules from all of the OMakefiles. The project is then built from the entire collection of build rules.
2.1.1 自動的な依存関係の解析 - Automatic dependency analysis
make(1)プログラムでは依存関係の解析に常に問題がありました。omakeではこの問題を扱うために、依存関係を生成するコマンドを指定するための.SCANNERターゲットを追加しています。例えば、以下の規則は
Dependency analysis has always been problematic with the make(1) program. omake addresses this by adding the .SCANNER target, which specifies a command to produce dependencies. For example, the following rule
.SCANNER: %.o: %.c $(CC) $(INCLUDE) -MM $<
.cファイルの依存関係を生成するための標準的な方法です。ファイルの依存関係を決める必要がある場合、omakeは自動的にスキャナを実行します。
is the standard way to generate dependencies for .c files. omake will automatically run the scanner when it needs to determine dependencies for a file.
2.1.2 内容に基づく依存関係の解析 - Content-based dependency analysis
omakeの依存関係の分析では、ファイルが変更を検知するためにMD5ダイジェストを使います。実行が終わる毎に、プロジェクトのルートディレクトリ内の.omakedbというファイルに依存関係の情報を保存します。実行時に規則を検討し、直前のomakeの実行以後にターゲットや依存関係、コマンド文字列が変更されていなければコマンドを実行しません。
Dependency analysis in omake uses MD5 digests to determine whether files have changed. After each run, omake stores the dependency information in a file called .omakedb in the project root directory. When a rule is considered for execution, the command is not executed if the target, dependencies, and command sequence are unchanged since the last run of omake. As an optimization, omake does not recompute the digest for a file that has an unchanged modification time, size, and inode number.
2.2 すでにmakeに慣れているユーザ向け - For users already familiar with make
すでにmakeに慣れているユーザ向けの、omakeを使う上で覚えておくべき相違点のリストです。
For users already familiar with the make(1) command, here is a list of differences to keep in mind when using omake.
- omakeでは、独自のビルド規則を定義する必要はほとんどありません。omakeではビルドをより簡単に設定するために(静的CライブラリやCプログラムのような)標準的な関数を多く用意しています。これについては13章で説明します。
- .SUFFIXESや.suf1.suf2:を使った暗黙のルールをサポートしません。代わりにワイルドカードパターン%.suf2: %.suf1が使えます。
- スコープが重要です。変数と.PHONYターゲット(8.10節参照)は、使用する前に定義します。
- サブディレクトリは.SUBDIRSターゲット(8.8節参照)を使ってプロジェクトに組み込みます。
- In omake, you are much less likely to define build rules of your own. The system provides many standard functions (like StaticCLibrary and CProgram), described in Chapter 13, to specify these builds more simply.
- Implicit rules using .SUFFIXES and the .suf1.suf2: are not supported. You should use wildcard patterns instead %.suf2: %.suf1.
- Scoping is significant: you should define variables and .PHONY targets (see Section 8.10) before they are used.
- Subdirectories are incorporated into a project using the .SUBDIRS: target (see Section 8.8).
2.3 小さなCのプログラムをビルドする - Building a small C program
新しいプロジェクトを始めるための最も簡単な方法は、プロジェクトのルートディレクトに移動して、omake --installコマンドを使ってデフォルトのOMakefileをインストールすることです。
To start a new project, the easiest method is to change directories to the project root and use the command omake --install to install default OMakefiles.
$ cd ~/newproject $ omake --install *** omake: creating OMakeroot *** omake: creating OMakefile *** omake: project files OMakefile and OMakeroot have been installed *** omake: you should edit these files before continuing
デフォルトのOmakefileにはCとOCamlのプログラムをビルドするセクションが含まれています。今回は、簡単なCのプロジェクトをビルドしましょう。
The default OMakefile contains sections for building C and OCaml programs. For now, we'll build a simple C project.
以下のコードを含むhello_code.cというCのファイルがあるとします。
Suppose we have a C file called hello_code.c containing the following code:
#includeint main(int argc, char **argv) { printf("Hello world\n"); return 0; }
このファイルからhelloというプログラムをビルドするには、CProgram関数を使います。Omakeファイルは、hello_code.cファイル内のソースコードからhelloプログラムをビルドするための行だけを含みます。
To build the program a program hello from this file, we can use the CProgram function. The OMakefile contains just one line that specifies that the program hello is to be built from the source code in the hello_code.c file (note that file suffixes are not passed to these functions).
CProgram(hello, hello_code)
ここで、omakeを実行するとプロジェクトをビルドできます。omakeを初めて実行すると、ファイルhello_code.cの依存関係のスキャンとccコンパイラによるコンパイルが実行されます。ステータス行の最後にはスキャンされたファイルの数とビルドされたファイルの数、計算されたMD5ダイジェストの数が表示されます。
Now we can run omake to build the project. Note that the first time we run omake, it both scans the hello_code.c file for dependencies, and compiles it using the cc compiler. The status line printed at the end indicates how many files were scanned, how many were built, and how many MD5 digests were computed.
$ omake hello *** omake: reading OMakefiles *** omake: finished reading OMakefiles (0.0 sec) - scan . hello_code.o + cc -I. -MM hello_code.c - build . hello_code.o + cc -I. -c -o hello_code.o hello_code.c - build . hello + cc -o hello hello_code.o *** omake: done (0.5 sec, 1/6 scans, 2/6 rules, 5/22 digests) $ omake *** omake: reading OMakefiles *** omake: finished reading OMakefiles (0.1 sec) *** omake: done (0.1 sec, 0/4 scans, 0/4 rules, 0/9 digests)
コンパイルオプションを変更したい場合、CProgram行の前でCCとCFLAGS変数を再定義します。この例では、gccコンパイラを-gオプションを付けて使用します。さらに、デフォルトでビルドされる.DEFAULTターゲットを指定します。Win32システムの場合、EXE変数には.exeが定義されています。他のシステムの場合、空文字列が定義されています。
If we want to change the compile options, we can redefine the CC and CFLAGS variables before the CProgram line. In this example, we will use the gcc compiler with the -g option. In addition, we will specify a .DEFAULT target to be built by default. The EXE variable is defined to be .exe on Win32 systems; it is empty otherwise.
CC = gcc CFLAGS += -g CProgram(hello, hello_code) .DEFAULT: hello$(EXE)
omakeを実行すると以下のようになります。
Here is the corresponding run for omake.
$ omake *** omake: reading OMakefiles *** omake: finished reading OMakefiles (0.0 sec) - scan . hello_code.o + gcc -g -I. -MM hello_code.c - build . hello_code.o + gcc -g -I. -c -o hello_code.o hello_code.c - build . hello + gcc -g -o hello hello_code.o *** omake: done (0.4 sec, 1/7 scans, 2/7 rules, 3/22 digests)
プログラムに複数のファイルを含めることももちろん可能です。新たなファイルhello_helper.cを作るとします。このファイルをプロジェクトに含めるには以下のようにします。
We can, of course, include multiple files in the program. Suppose we write a new file hello_helper.c. We would include this in the project as follows.
CC = gcc CFLAGS += -g CProgram(hello, hello_code hello_helper) .DEFAULT: hello$(EXE)
2.4 より大きなプロジェクト - Larger projects
プロジェクトが大きくなると、コードのライブラリをビルドしたくなります。ライブラリをビルドするにはStaticCLibrary関数を使います。以下は二つのライブラリを含んだOmakefileの例です。
As the project grows it is likely that we will want to build libraries of code. Libraries can be built using the StaticCLibrary function. Here is an example of an OMakefile with two libraries.
CC = gcc CFLAGS += -g FOO_FILES = foo_a foo_b BAR_FILES = bar_a bar_b bar_c StaticCLibrary(libfoo, $(FOO_FILES)) StaticCLibrary(libbar, $(BAR_FILES)) # プログラムhelloは両方のライブラリをリンクする - The hello program is linked with both libraries LIBS = libfoo libbar CProgram(hello, hello_code hello_helper) .DEFAULT: hello$(EXE)
2.5 サブディレクトリ - Subdirectories
プロジェクトがさらに大きくなったら、複数のディレクトリに分けた方が良いです。libfooとlibbarをサブディレクトリに配置します。
As the project grows even further, it is a good idea to split it into several directories. Suppose we place the libfoo and libbar into subdirectories.
サブディレクトリ毎にOMakefileを定義します。たとえば、以下はサブディレクトリfoo用のOMakefileの例です。
In each subdirectory, we define an OMakefile for that directory. For example, here is an example OMakefile for the foo subdirectory.
INCLUDES += .. ../bar FOO_FILES = foo_a foo_b StaticCLibrary(libfoo, $(FOO_FILES))
INCLUDES変数にはプロジェクトに含まれる他のディレクトリを定義します。
Note the the INCLUDES variable is defined to include the other directories in the project.
さて、次のステップはサブディレクトリをメインプロジェクトに関連付けることです。プロジェクトのOMakefileを変更してSUBDIRS: ターゲットを含めます。
Now, the next step is to link the subdirectories into the main project. The project OMakefile should be modified to include a .SUBDIRS: target.
# プロジェクト設定 - Project configuration CC = gcc CFLAGS += -g # サブディレクトリ - Subdirectories .SUBDIRS: foo bar # 今のところライブラリはサブディレクトリ中にある - The libraries are now in subdirectories LIBS = foo/libfoo bar/libbar CProgram(hello, hello_code hello_helper) .DEFAULT: hello$(EXE)
CCとCFLAGS変数は.SUBDIRSターゲットより前で定義しています。これらの変数はサブディレクトリにも定義が引き継がれるので、libfooとlibbarもgcc -gを使います。
Note that the variables CC and CFLAGS are defined before the .SUBDIRS target. These variables remain defined in the subdirectories, so that libfoo and libbar use gcc -g.
二つのディレクトリを個別に設定するには、二つのやり方があります。それぞれのサブディレクトリのOmakefileを変更することで設定できます(通常はこのようにします)。もう一つは、ルートのOMakefileを変更することでも設定できます。
If the two directories are to be configured differently, we have two choices. The OMakefile in each subdirectory can be modified with its configuration (this is how it would normally be done). Alternatively, we can also place the change in the root OMakefile.
# プロジェクトのデフォルトの設定 - Default project configuration CC = gcc CFLAGS += -g # libfooはデフォルトの設定を使う - libfoo uses the default configuration .SUBDIRS: foo # libberはコンパイラの最適化を使う - libbar uses the optimizing compiler CFLAGS += -O3 .SUBDIRS: bar # メインプログラム - Main program LIBS = foo/libfoo bar/libbar CProgram(hello, hello_code hello_helper) .DEFAULT: hello$(EXE)
CFLAGS変数にCProgram用の-O3オプションを設定したので、hello_code.cとhello_helper.cはどちらも-O3オプション付きでコンパイルされます。もしこの設定をlibbarだけに適用したければ、section形式でにスコープ中にbarサブディレクトリを設定することができます。
Note that the way we have specified it, the CFLAGS variable also contains the -O3 option for the CProgram, and hello_code.c and hello_helper.c file will both be compiled with the -O3 option. If we want to make the change truly local to libbar, we can put the bar subdirectory in its own scope using the section form.
# プロジェクトのデフォルトの設定 - Default project configuration CC = gcc CFLAGS += -g # libfooはデフォルトの設定を使う - libfoo uses the default configuration .SUBDIRS: foo # libberはコンパイラの最適化を使う - libbar uses the optimizing compiler section CFLAGS += -O3 .SUBDIRS: bar # メインプログラムはコンパイラの最適化を使用しない - Main program does not use the optimizing compiler LIBS = foo/libfoo bar/libbar CProgram(hello, hello_code hello_helper) .DEFAULT: hello$(EXE)
後になってこのプロジェクトをWin32に移植することになったら、他のコンパイラフラグや追加のライブラリが必要です。
Later, suppose we decide to port this project to Win32, and we discover that we need different compiler flags and an additional library.
# プロジェクトのデフォルトの設定 - Default project configuration if $(equal $(OSTYPE), Win32) CC = cl /nologo CFLAGS += /DWIN32 /MT export else CC = gcc CFLAGS += -g export # libfooはデフォルトの設定を使う - libfoo uses the default configuration .SUBDIRS: foo # libberはコンパイラの最適化を使う - libbar uses the optimizing compiler section CFLAGS += $(if $(equal $(OSTYPE), Win32), $(EMPTY), -O3) .SUBDIRS: bar # デフォルトのライブラリ - Default libraries LIBS = foo/libfoo bar/libbar # Win32ではlibwin32が必要 - We need libwin32 only on Win32 if $(equal $(OSTYPE), Win32) LIBS += win32/libwin32 .SUBDIRS: win32 export # メインプログラムはコンパイラの最適化を使用しない - Main program does not use the optimizing compiler CProgram(hello, hello_code hello_helper) .DEFAULT: hello$(EXE)
exportディレクトリを使うとif文から変数定義をエクスポートできます。omakeでは、ネストされたブロック(大きくインデントされたブロック)内の変数はスコープに属する変数であり、通常ブロックの外では定義されません。exportディレクティブを使うと、ネストされたブロック内の変数定義を上位のブロックにエクスポートできます。
Note the use of the export directives to export the variable definitions from the if-statements. Variables in omake are scoped-variables in nested blocks (blocks with greater indentation), are not normally defined in outer blocks. The export directive specifies that the variable definitions in the nested blocks should be exported to their parent block.
最後の例として、すべてのライブラリをlibディレクトリにコピーすることにします。まずディレクトリ変数を定義し、文字列libがあるところを変数に置き換えます。
Finally, for this example, we decide to copy all libraries into a common lib directory. We first define a directory variable, and replace occurrences of the lib string with the variable.
# 共通のlibディレクトリ - The common lib directory LIB = $(dir lib) # ライブラリのビルドだけに使うインチキターゲット - phony target to build just the libraries .PHONY: makelibs # プロジェクトのデフォルトの設定 - Default project configuration if $(equal $(OSTYPE), Win32) CC = cl /nologo CFLAGS += /DWIN32 /MT export else CC = gcc CFLAGS += -g export # libfooはデフォルトの設定を使う - libfoo uses the default configuration .SUBDIRS: foo # libbarはコンパイラの最適化を使う - libbar uses the optimizing compiler section CFLAGS += $(if $(equal $(OSTYPE), Win32), $(EMPTY), -O3) .SUBDIRS: bar # デフォルトのライブラリ - Default libraries LIBS = $(LIB)/libfoo $(LIB)/libbar # Win32ではlibwin32が必要 - We need libwin32 only on Win32 if $(equal $(OSTYPE), Win32) LIBS += $(LIB)/libwin32 .SUBDIRS: win32 export # メインプログラムはコンパイラの最適化を使用しない - Main program does not use the optimizing compiler CProgram(hello, hello_code hello_helper) .DEFAULT: hello$(EXE)
各サブディレクトリでは、$(LIB)ディレクトリにインストールを行うようにライブラリディレクトリ中のOmakefileを変更します。以下はfoo/OMakefileの変更点です。
In each subdirectory, we modify the OMakefiles in the library directories to install them into the $(LIB) directory. Here is the relevant change to foo/OMakefile.
INCLUDES += .. ../bar FOO_FILES = foo_a foo_b StaticCLibraryInstall(makelib, $(LIB), libfoo, $(FOO_FILES))
ディレクトリ(やファイル名)は相対パスになります。fooディレクトリ中では、$(LIB)変数は../libになります。
Directory (and file names) evaluate to relative pathnames. Within the foo directory, the $(LIB) variable evaluates to ../lib.
他の例として、各サブディレクトリに個別にINCLUDES変数を定義する代わりに、最上位で以下のように定義することもできます。
As another example, instead of defining the INCLUDES variable separately in each subdirectory, we can define it in the toplevel as follows.
INCLUDES = $(ROOT) $(dir foo bar win32)
fooディレクトリでは、INCLUDES変数は文字列 .. . ../bar ../win32になります。barディレクトリでは、.. ../foo . ../win32になります。rootディレクトリでは . foo bar win32になります。
In the foo directory, the INCLUDES variable will evaluate to the string .. . ../bar ../win32. In the bar directory, it would be .. ../foo . ../win32. In the root directory it would be . foo bar win32.
2.6 その他に考慮すべき点 - Other things to consider
omakeはサブディレクトリを再帰的に処理します。たとえば、fooディレクトリ中にサブディレクトリがある場合です。foo/OMakefileは固有の.SUBDIRSターゲットを持ち、そのサブディレクトリはそれぞれ固有のOmakefileを持ちます。
omake also handles recursive subdirectories. For example, suppose the foo directory itself contains several subdirectories. The foo/OMakefile would then contain its own .SUBDIRS target, and each of its subdirectories would contain its own OMakefile.
2.7 OCamlのプログラムをビルドする - Building OCaml programs
デフォルトでは、omakeにはOcamlのプログラムをビルドするための関数も設定されています。OCamlのプログラム用の関数はOCamlプレフィックスを使います。例として、先ほどの例をOCamlで作り直します。以下のコードを含むhello_code.mlというファイルがあるとします。
By default, omake is also configured with functions for building OCaml programs. The functions for OCaml program use the OCaml prefix. For example, suppose we reconstruct the previous example in OCaml, and we have a file called hello_code.ml that contains the following code.
open Printf let () = printf "Hello world\n"
この簡単なプロジェクト用のOMakefileには以下が含まれます。
An example OMakefile for this simple project would contain the following.
# バイトコードコンパイラを使う - Use the byte-code compiler BYTE_ENABLED = true NATIVE_ENABLED = false OCAMLCFLAGS += -g # プログラムをビルドする - Build the program OCamlProgram(hello, hello_code) .DEFAULT: hello.run
次に、ライブラリを含む二つのサブディレクトリを考えます。Cで書いたfooサブディレクトリと、OCamlで書いたbarディレクトリです。OCamlの標準のUnixモジュールを使用する必要があります。
Next, suppose the we have two library subdirectories: the foo subdirectory is written in C, the bar directory is written in OCaml, and we need to use the standard OCaml Unix module.
# プロジェクトのデフォルトの設定 - Default project configuration if $(equal $(OSTYPE), Win32) CC = cl /nologo CFLAGS += /DWIN32 /MT export else CC = gcc CFLAGS += -g export # バイトコードコンパイラを使う - Use the byte-code compiler BYTE_ENABLED = true NATIVE_ENABLED = false OCAMLCFLAGS += -g # ライブラリサブディレクトリ - library subdirectories INCLUDES += $(dir foo bar) OCAMLINCLUDES += $(dir foo bar) .SUBDIRS: foo bar # Cライブラリ - C libraries LIBS = foo/libfoo # OCamlライブラリ - OCaml libraries OCAML_LIBS = bar/libbar # Unixモジュールも使用する - Also use the Unix module OCAML_OTHER_LIBS = unix # メインプログラム - The main program OCamlProgram(hello, hello_code hello_helper) .DEFAULT: hello
foo/OMakefileをCライブラリ用の設定します。
The foo/OMakefile would be configured as a C library.
FOO_FILES = foo_a foo_b StaticCLibrary(libfoo, $(FOO_FILES))
bar/OMakefileはMLライブラリのビルドを行います。
The bar/OMakefile would build an ML library.
BAR_FILES = bar_a bar_b bar_c OCamlLibrary(libbar, $(BAR_FILES))
2.8 OMakefileとOMakerootファイル - The OMakefile and OMakeroot files
OMakeはプロジェクトの設定のためにOmakefileとOmakerootというファイルを使用します。これらのファイルの文法は同じですが、役割は微妙に異なります。たとえば、OMakerootファイルは必ずプロジェクトのルートディレクトリに一つだけ必要です。このファイルによってプロジェクトのルートが識別できるようになります。またこのファイルではプロジェクトの設定をします。一方、OMakefileはディレクトリが複数あるプロジェクトではサブディレクトリ毎に置くことができます。このファイルではサブディレクトリ中のファイルのビルド方法を設定します。
OMake uses the OMakefile and OMakeroot files for configuring a project. The syntax of these files is the same, but their role is slightly different. For one thing, every project must have exactly one OMakeroot file in the project root directory. This file serves to identify the project root, and it contains code that sets up the project. In contrast, a multi-directory project will often have an OMakefile in each of the project subdirectories, specifying how to build the files in that subdirectory.
通常、OMakerootファイルは定型的です。以下は典型的な例です。
Normally, the OMakeroot file is boilerplate. The following listing is a typical example.
include $(STDLIB)/build/Common include $(STDLIB)/build/C include $(STDLIB)/build/OCaml include $(STDLIB)/build/LaTeX # コマンドライン変数を再定義する - Redefine the command-line variables DefineCommandVars(.) # カレントディレクトリがプロジェクトの一部である - The current directory is part of the project .SUBDIRS: .
include行はプロジェクトに必要な標準設定ファイルをインクルードします。$(STDLIB)はomakeのライブラリのディレクトリを表します。設定ファイルのうちCommonだけは必須です。その他は任意です。たとえば、$(STDLIB)/build/OCamlファイルはプロジェクト中にOCamlで書かれたプログラムがある場合だけ必要です。
The include lines include the standard configuration files needed for the project. The $(STDLIB) represents the omake library directory. The only required configuration file is Common. The others are optional; for example, the $(STDLIB)/build/OCaml file is needed only when the project contains programs written in OCaml.
DefineCommandVars関数は、(VAR=形式で引数として)コマンドラインで指定する変数を定義します。.SUBDIRS行ではカレントディレクトリをプロジェクトに含めるよう指定しています(そのためOMakefileは読み込まれます)。
The DefineCommandVars function defines any variables specified on the command line (as arguments of the form VAR=
). The .SUBDIRS line specifies that the current directory is part of the project (so the OMakefile should be read).
通常、OMakerootファイルは小さく、プロジェクト固有ではりません。プロジェクト固有の設定はOMakefile内に設定した方がよいです。
Normally, the OMakeroot file should be small and project-independent. Any project-specific configuration should be placed in the OMakefiles of the project.
2.9 複数バージョンのサポート - Multiple version support
OMakeバージョン0.9.6ではプロジェクトの複数のバージョンを予備的にサポートしています。バージョン付けのために、vmount(dir1, dir2)関数を使用して、ディレクトリdir2上にディレクトリdir1の「仮想マウント」を定義します。「仮想マウント」は、Unixの透過的なマウントに似ており、dir1のファイルがdir2の名前空間に現れるとともに、新たなファイルはdir2に作られます。もっと詳しく言うと、ファイル名dir2/fooは、a) 存在すれば、dir1/fooを参照し、b) 存在しなければ、dir2/fooを参照します。
OMake version 0.9.6 introduced preliminary support for multiple, simultaneous versions of a project. Versioning uses the vmount(dir1, dir2) function, which defines a “virtual mount” of directory dir1 over directory dir2. A “virtual mount” is like a transparent mount in Unix, where the files from dir1 appear in the dir2 namespace, but new files are created in dir2. More precisely, the filename dir2/foo refers to: a) the file dir1/foo if it exists, or b) dir2/foo otherwise.
vmount関数を使えばプロジェクトの複数のバージョンを簡単に作れます。ソースファイルをsrc/ディレクトリに格納するプロジェクトがあり、デバッグをサポートするバージョンと最適化したバージョンの、二つのバージョンをコンパイルしたいとします。debugとoptというディレクトリを作り、srcディレクトリをこれらのディレクトリ上にマウントします。
The vmount function makes it easy to specify multiple versions of a project. Suppose we have a project where the source files are in the directory src/, and we want to compile two versions, one with debugging support and one optimized. We create two directories, debug and opt, and mount the src directory over them.
section CFLAGS += -g vmount(-l, src, debug) .SUBDIRS: debug section CFLAGS += -O3 vmount(-l, src, opt) .SUBDIRS: opt
今、vmountのスコープを定義するためにセクション構造を使用しています。これを行う必要のないプロジェクトもあると思います。
Here, we are using section blocks to define the scope of the vmount-you may not need them in your project.
-lはオプションです。これは、ソースディレクトリ内に対象ディレクトリへのリンクを作る(ただし、システムがWin32の場合はファイルをコピーする)ことを指定します。ファイルを参照するリンクが追加されます。オプションを指定しないと、ファイルのコピーもリンクの作成も行われませんが、ファイル名はsrc/のファイルを直接参照するように変換されます。
The -l option is optional. It specifies that files form the src directory should be linked into the target directories (or copied, if the system is Win32). The links are added as files are referenced. If no options are given, then files are not copied or linked, but filenames are translated to refer directly to the src/ files.
debugディレクトリにファイルが存在する場合、そのファイルはsrcディレクトリからリンクされています。たとえば、ファイルdebug/OMakefileを読み取れる場合、src/OMalefileはdebug/ディレクトリをリンクしています。
Now, when a file is referenced in the debug directory, it is linked from the src directory if it exists. For example, when the file debug/OMakefile is read, the src/OMakefile is linked into the debug/ directory.
vmountモデルはほとんど透過的です。src/ディレクトリのファイルを参照するようにOMakefileを記述できます。つまり、マウントしていることを意識しなくてすみます。しかし、意識すべき点はいくつかあります。
The vmount model is fairly transparent. The OMakefiles can be written as if referring to files in the src/ directory-they need not be aware of mounting. However, there are a few points to keep in mind.
2.10 メモ - Notes
- バージョン付けにvmount関数を使うと、コンパイルされたバージョンとソースファイルとをうまく区別できます。たとえば、ソースディレクトリにsrc/foo.oが含まれるとします。マウントしている場合、ファイルfoo.oは全てのバージョンで同じになってしまいますが、これはやりたいこととは違うでしょう。src/ディレクトリはコンパイルされたコードを含まない方が良いです。
- vmountで-lオプションを使うと、プロジェクトを参照した場合だけファイルがバージョンディレクトリへリンクされます。($(ls ...)のような)ファイルシステムを調べる関数は予期しない結果になることがあります。
- When using the vmount function for versioning, it wise to keep the source files distinct from the compiled versions. For example, suppose the source directory contained a file src/foo.o. When mounted, the foo.o file will be the same in all versions, which is probably not what you want. It is better to keep the src/ directory pristine, containing no compiled code.
- When using the vmount -l option, files are linked into the version directory only if they are referenced in the project. Functions that examine the filesystem (like $(ls ...)) may produce unexpected results.