<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> <HTML> <HEAD> <META http-equiv="Content-Type" content="text/html; charset=US-ASCII"> <META name="GENERATOR" content="hevea 1.09"> <LINK rel="stylesheet" type="text/css" href="omake-doc.css"> <TITLE>OMake quickstart guide</TITLE> </HEAD> <BODY > <img src="images/omake-manual.gif" border="0" align="top" alt=""><br> <TABLE CELLSPACING=6 CELLPADDING=0><TR><TD ALIGN=left NOWRAP>Jump to:</TD><TD VALIGN=top ALIGN=center NOWRAP>  </TD><TD ALIGN=left NOWRAP><A HREF="http://omake.metaprl.org/">OMake Home</A> • <A HREF="omake.html">Guide Home</A> • <A HREF="omake-doc.html">Guide (single-page)</A> • <A HREF="omake-toc.html">Contents (short)</A> • <A HREF="omake-contents.html">Contents (long)</A></TD></TR> <TR><TD ALIGN=left NOWRAP>Index:</TD><TD VALIGN=top ALIGN=center NOWRAP>  </TD><TD ALIGN=left NOWRAP><A HREF="omake-all-index.html">All</A> • <A HREF="omake-var-index.html">Variables</A> • <A HREF="omake-fun-index.html">Functions</A> • <A HREF="omake-obj-index.html">Objects</A> • <A HREF="omake-target-index.html">Targets</A> • <A HREF="omake-option-index.html">Options</A></TD></TR> </TABLE> <H1 CLASS="chapter"><A NAME="htoc2">Chapter 2</A>  OMake quickstart guide</H1><UL> <LI><A HREF="omake-quickstart.html#toc1">Description</A></LI> <LI><A HREF="omake-quickstart.html#toc2">For users already familiar with make</A></LI> <LI><A HREF="omake-quickstart.html#toc3">Building a small C program</A></LI> <LI><A HREF="omake-quickstart.html#toc4">Larger projects</A></LI> <LI><A HREF="omake-quickstart.html#toc5">Subdirectories</A></LI> <LI><A HREF="omake-quickstart.html#toc6">Other things to consider</A></LI> <LI><A HREF="omake-quickstart.html#toc7">Building OCaml programs</A></LI> <LI><A HREF="omake-quickstart.html#toc8">The OMakefile and OMakeroot files</A></LI> <LI><A HREF="omake-quickstart.html#toc9">Multiple version support</A></LI> <LI><A HREF="omake-quickstart.html#toc10">Notes</A></LI> </UL> <P> <A NAME="chapter:quickstart"></A> </P><H2 CLASS="section"><A NAME="toc1"></A><A NAME="htoc3">2.1</A>  Description</H2><P><TT>omake</TT> is designed for building projects that might have source files in several directories. Projects are normally specified using an <TT>OMakefile</TT> in each of the project directories, and an <TT>OMakeroot</TT> file in the root directory of the project. The <TT>OMakeroot</TT> file specifies general build rules, and the <TT>OMakefile</TT>s specify the build parameters specific to each of the subdirectories. When <TT>omake</TT> runs, it walks the configuration tree, evaluating rules from all of the <TT>OMakefile</TT>s. The project is then built from the entire collection of build rules.</P><H3 CLASS="subsection"><A NAME="htoc4">2.1.1</A>  Automatic dependency analysis</H3><P>Dependency analysis has always been problematic with the <TT>make</TT>(1) program. <TT>omake</TT> addresses this by adding the <CODE>.SCANNER</CODE> target, which specifies a command to produce dependencies. For example, the following rule</P><PRE CLASS="verbatim"> .SCANNER: %.o: %.c $(CC) $(INCLUDE) -MM $< </PRE><P>is the standard way to generate dependencies for <CODE>.c</CODE> files. <TT>omake</TT> will automatically run the scanner when it needs to determine dependencies for a file.</P><H3 CLASS="subsection"><A NAME="htoc5">2.1.2</A>  Content-based dependency analysis</H3><P>Dependency analysis in omake uses MD5 digests to determine whether files have changed. After each run, <TT>omake</TT> stores the dependency information in a file called <TT>.omakedb</TT> 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 <TT>omake</TT>. As an optimization, <TT>omake</TT> does not recompute the digest for a file that has an unchanged modification time, size, and inode number.</P><H2 CLASS="section"><A NAME="toc2"></A><A NAME="htoc6">2.2</A>  For users already familiar with make</H2><P>For users already familiar with the <TT>make</TT>(1) command, here is a list of differences to keep in mind when using <TT>omake</TT>.</P><UL CLASS="itemize"><LI CLASS="li-itemize"> In <TT>omake</TT>, you are much less likely to define build rules of your own. The system provides many standard functions (like <CODE><A HREF="omake-build.html#fun:StaticCLibrary">StaticCLibrary</A></CODE> and <CODE><A HREF="omake-build.html#fun:CProgram">CProgram</A></CODE>), described in Chapter <A HREF="omake-build.html#chapter:build">13</A>, to specify these builds more simply. </LI><LI CLASS="li-itemize">Implicit rules using <CODE>.SUFFIXES</CODE> and the <CODE>.suf1.suf2:</CODE> are not supported. You should use wildcard patterns instead <CODE>%.suf2: %.suf1</CODE>. </LI><LI CLASS="li-itemize">Scoping is significant: you should define variables and <CODE>.PHONY</CODE> targets (see Section <A HREF="omake-rules.html#target:.PHONY">8.10</A>) before they are used. </LI><LI CLASS="li-itemize">Subdirectories are incorporated into a project using the <CODE>.SUBDIRS:</CODE> target (see Section <A HREF="omake-rules.html#target:.SUBDIRS">8.8</A>). </LI></UL><H2 CLASS="section"><A NAME="toc3"></A><A NAME="htoc7">2.3</A>  Building a small C program</H2><P>To start a new project, the easiest method is to change directories to the project root and use the command <CODE>omake --install</CODE> to install default <TT>OMakefile</TT>s.</P><PRE CLASS="verbatim"> $ 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 </PRE><P>The default <TT>OMakefile</TT> contains sections for building C and OCaml programs. For now, we'll build a simple C project.</P><P>Suppose we have a C file called <CODE>hello_code.c</CODE> containing the following code:</P><PRE CLASS="verbatim"> #include <stdio.h> int main(int argc, char **argv) { printf("Hello world\n"); return 0; } </PRE><P>To build the program a program <CODE>hello</CODE> from this file, we can use the <A HREF="omake-build.html#fun:CProgram"><CODE>CProgram</CODE> function</A>. The <TT>OMakefile</TT> contains just one line that specifies that the program <CODE>hello</CODE> is to be built from the source code in the <CODE>hello_code.c</CODE> file (note that file suffixes are not passed to these functions).</P><PRE CLASS="verbatim"> CProgram(hello, hello_code) </PRE><P>Now we can run <TT>omake</TT> to build the project. Note that the first time we run <TT>omake</TT>, it both scans the <CODE>hello_code.c</CODE> file for dependencies, and compiles it using the <CODE>cc</CODE> 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.</P><PRE CLASS="verbatim"> $ 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) </PRE><P>If we want to change the compile options, we can redefine the <CODE>CC</CODE> and <CODE>CFLAGS</CODE> variables <EM>before</EM> the <CODE>CProgram</CODE> line. In this example, we will use the <CODE>gcc</CODE> compiler with the <CODE>-g</CODE> option. In addition, we will specify a <CODE>.DEFAULT</CODE> target to be built by default. The <CODE>EXE</CODE> variable is defined to be <CODE>.exe</CODE> on <CODE>Win32</CODE> systems; it is empty otherwise.</P><PRE CLASS="verbatim"> CC = gcc CFLAGS += -g CProgram(hello, hello_code) .DEFAULT: hello$(EXE) </PRE><P>Here is the corresponding run for <TT>omake</TT>.</P><PRE CLASS="verbatim"> $ 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) </PRE><P>We can, of course, include multiple files in the program. Suppose we write a new file <CODE>hello_helper.c</CODE>. We would include this in the project as follows.</P><PRE CLASS="verbatim"> CC = gcc CFLAGS += -g CProgram(hello, hello_code hello_helper) .DEFAULT: hello$(EXE) </PRE><H2 CLASS="section"><A NAME="toc4"></A><A NAME="htoc8">2.4</A>  Larger projects</H2><P>As the project grows it is likely that we will want to build libraries of code. Libraries can be built using the <CODE>StaticCLibrary</CODE> function. Here is an example of an <TT>OMakefile</TT> with two libraries.</P><PRE CLASS="verbatim"> 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)) # The hello program is linked with both libraries LIBS = libfoo libbar CProgram(hello, hello_code hello_helper) .DEFAULT: hello$(EXE) </PRE><H2 CLASS="section"><A NAME="toc5"></A><A NAME="htoc9">2.5</A>  Subdirectories</H2><P>As the project grows even further, it is a good idea to split it into several directories. Suppose we place the <CODE>libfoo</CODE> and <CODE>libbar</CODE> into subdirectories.</P><P>In each subdirectory, we define an <TT>OMakefile</TT> for that directory. For example, here is an example <TT>OMakefile</TT> for the <CODE>foo</CODE> subdirectory.</P><PRE CLASS="verbatim"> INCLUDES += .. ../bar FOO_FILES = foo_a foo_b StaticCLibrary(libfoo, $(FOO_FILES)) </PRE><P>Note the the <CODE>INCLUDES</CODE> variable is defined to include the other directories in the project.</P><P>Now, the next step is to link the subdirectories into the main project. The project <TT>OMakefile</TT> should be modified to include a <CODE>.SUBDIRS:</CODE> target.</P><PRE CLASS="verbatim"> # 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) </PRE><P>Note that the variables <CODE>CC</CODE> and <CODE>CFLAGS</CODE> are defined <EM>before</EM> the <CODE>.SUBDIRS</CODE> target. These variables remain defined in the subdirectories, so that <CODE>libfoo</CODE> and <CODE>libbar</CODE> use <CODE>gcc -g</CODE>.</P><P>If the two directories are to be configured differently, we have two choices. The <TT>OMakefile</TT> 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 <TT>OMakefile</TT>.</P><PRE CLASS="verbatim"> # Default project configuration CC = gcc CFLAGS += -g # libfoo uses the default configuration .SUBDIRS: foo # 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) </PRE><P>Note that the way we have specified it, the <CODE>CFLAGS</CODE> variable also contains the <CODE>-O3</CODE> option for the <CODE>CProgram</CODE>, and <CODE>hello_code.c</CODE> and <CODE>hello_helper.c</CODE> file will both be compiled with the <CODE>-O3</CODE> option. If we want to make the change truly local to <CODE>libbar</CODE>, we can put the <CODE>bar</CODE> subdirectory in its own scope using the <CODE>section</CODE> form.</P><PRE CLASS="verbatim"> # Default project configuration CC = gcc CFLAGS += -g # libfoo uses the default configuration .SUBDIRS: foo # 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) </PRE><P>Later, suppose we decide to port this project to <CODE>Win32</CODE>, and we discover that we need different compiler flags and an additional library.</P><PRE CLASS="verbatim"> # Default project configuration if $(equal $(OSTYPE), Win32) CC = cl /nologo CFLAGS += /DWIN32 /MT export else CC = gcc CFLAGS += -g export # libfoo uses the default configuration .SUBDIRS: foo # libbar uses the optimizing compiler section CFLAGS += $(if $(equal $(OSTYPE), Win32), $(EMPTY), -O3) .SUBDIRS: bar # Default libraries LIBS = foo/libfoo bar/libbar # 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) </PRE><P>Note the use of the <CODE>export</CODE> directives to export the variable definitions from the if-statements. Variables in <TT>omake</TT> are <EM>scoped</EM>—variables in nested blocks (blocks with greater indentation), are not normally defined in outer blocks. The <CODE>export</CODE> directive specifies that the variable definitions in the nested blocks should be exported to their parent block.</P><P>Finally, for this example, we decide to copy all libraries into a common <CODE>lib</CODE> directory. We first define a directory variable, and replace occurrences of the <CODE>lib</CODE> string with the variable.</P><PRE CLASS="verbatim"> # 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 uses the default configuration .SUBDIRS: foo # libbar uses the optimizing compiler section CFLAGS += $(if $(equal $(OSTYPE), Win32), $(EMPTY), -O3) .SUBDIRS: bar # Default libraries LIBS = $(LIB)/libfoo $(LIB)/libbar # 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) </PRE><P>In each subdirectory, we modify the <TT>OMakefile</TT>s in the library directories to install them into the <CODE>$(LIB)</CODE> directory. Here is the relevant change to <TT>foo/OMakefile</TT>.</P><PRE CLASS="verbatim"> INCLUDES += .. ../bar FOO_FILES = foo_a foo_b StaticCLibraryInstall(makelib, $(LIB), libfoo, $(FOO_FILES)) </PRE><P>Directory (and file names) evaluate to relative pathnames. Within the <CODE>foo</CODE> directory, the <CODE>$(LIB)</CODE> variable evaluates to <CODE>../lib</CODE>.</P><P>As another example, instead of defining the <CODE>INCLUDES</CODE> variable separately in each subdirectory, we can define it in the toplevel as follows.</P><PRE CLASS="verbatim"> INCLUDES = $(ROOT) $(dir foo bar win32) </PRE><P>In the <CODE>foo</CODE> directory, the <CODE>INCLUDES</CODE> variable will evaluate to the string <CODE>.. . ../bar ../win32</CODE>. In the <CODE>bar</CODE> directory, it would be <CODE>.. ../foo . ../win32</CODE>. In the root directory it would be <CODE>. foo bar win32</CODE>.</P><H2 CLASS="section"><A NAME="toc6"></A><A NAME="htoc10">2.6</A>  Other things to consider</H2><P><TT>omake</TT> also handles recursive subdirectories. For example, suppose the <CODE>foo</CODE> directory itself contains several subdirectories. The <TT>foo/OMakefile</TT> would then contain its own <CODE>.SUBDIRS</CODE> target, and each of its subdirectories would contain its own <CODE>OMakefile</CODE>.</P><H2 CLASS="section"><A NAME="toc7"></A><A NAME="htoc11">2.7</A>  Building OCaml programs</H2><P>By default, <TT>omake</TT> is also configured with functions for building OCaml programs. The functions for OCaml program use the <CODE>OCaml</CODE> prefix. For example, suppose we reconstruct the previous example in OCaml, and we have a file called <CODE>hello_code.ml</CODE> that contains the following code.</P><PRE CLASS="verbatim"> open Printf let () = printf "Hello world\n" </PRE><P>An example <TT>OMakefile</TT> for this simple project would contain the following.</P><PRE CLASS="verbatim"> # Use the byte-code compiler BYTE_ENABLED = true NATIVE_ENABLED = false OCAMLCFLAGS += -g # Build the program OCamlProgram(hello, hello_code) .DEFAULT: hello.run </PRE><P>Next, suppose the we have two library subdirectories: the <CODE>foo</CODE> subdirectory is written in C, the <CODE>bar</CODE> directory is written in OCaml, and we need to use the standard OCaml <CODE>Unix</CODE> module.</P><PRE CLASS="verbatim"> # 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 libraries LIBS = foo/libfoo # OCaml libraries OCAML_LIBS = bar/libbar # Also use the Unix module OCAML_OTHER_LIBS = unix # The main program OCamlProgram(hello, hello_code hello_helper) .DEFAULT: hello </PRE><P>The <TT>foo/OMakefile</TT> would be configured as a C library.</P><PRE CLASS="verbatim"> FOO_FILES = foo_a foo_b StaticCLibrary(libfoo, $(FOO_FILES)) </PRE><P>The <TT>bar/OMakefile</TT> would build an ML library.</P><PRE CLASS="verbatim"> BAR_FILES = bar_a bar_b bar_c OCamlLibrary(libbar, $(BAR_FILES)) </PRE><H2 CLASS="section"><A NAME="toc8"></A><A NAME="htoc12">2.8</A>  The OMakefile and OMakeroot files</H2><P> <A NAME="section:omakeroot"></A> <A NAME="@default0"></A> <A NAME="@default1"></A></P><P><TT>OMake</TT> uses the <TT>OMakefile</TT> and <TT>OMakeroot</TT> 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 <TT>OMakeroot</TT> 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 <TT>OMakefile</TT> in each of the project subdirectories, specifying how to build the files in that subdirectory.</P><P>Normally, the <TT>OMakeroot</TT> file is boilerplate. The following listing is a typical example.</P><PRE CLASS="verbatim"> 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: . </PRE><P>The <CODE>include</CODE> lines include the standard configuration files needed for the project. The <CODE>$(STDLIB)</CODE> represents the <TT>omake</TT> library directory. The only required configuration file is <CODE>Common</CODE>. The others are optional; for example, the <CODE>$(STDLIB)/build/OCaml</CODE> file is needed only when the project contains programs written in OCaml.</P><P>The <CODE>DefineCommandVars</CODE> function defines any variables specified on the command line (as arguments of the form <CODE>VAR=<value></CODE>). The <CODE>.SUBDIRS</CODE> line specifies that the current directory is part of the project (so the <CODE>OMakefile</CODE> should be read).</P><P>Normally, the <CODE>OMakeroot</CODE> file should be small and project-independent. Any project-specific configuration should be placed in the <CODE>OMakefiles</CODE> of the project.</P><H2 CLASS="section"><A NAME="toc9"></A><A NAME="htoc13">2.9</A>  Multiple version support</H2><P> <A NAME="@default2"></A></P><P>OMake version <CODE>0.9.6</CODE> introduced preliminary support for multiple, simultaneous versions of a project. Versioning uses the <CODE>vmount(dir1, dir2)</CODE> function, which defines a “virtual mount” of directory <CODE>dir1</CODE> over directory <CODE>dir2</CODE>. A “virtual mount” is like a transparent mount in Unix, where the files from <CODE>dir1</CODE> appear in the <CODE>dir2</CODE> namespace, but new files are created in <CODE>dir2</CODE>. More precisely, the filename <CODE>dir2/foo</CODE> refers to: a) the file <CODE>dir1/foo</CODE> if it exists, or b) <CODE>dir2/foo</CODE> otherwise.</P><P>The <CODE>vmount</CODE> function makes it easy to specify multiple versions of a project. Suppose we have a project where the source files are in the directory <CODE>src/</CODE>, and we want to compile two versions, one with debugging support and one optimized. We create two directories, <TT>debug</TT> and <TT>opt</TT>, and mount the <TT>src</TT> directory over them.</P><PRE CLASS="verbatim"> section CFLAGS += -g vmount(-l, src, debug) .SUBDIRS: debug section CFLAGS += -O3 vmount(-l, src, opt) .SUBDIRS: opt </PRE><P>Here, we are using <CODE>section</CODE> blocks to define the scope of the <CODE>vmount</CODE>—you may not need them in your project.</P><P>The <CODE>-l</CODE> option is optional. It specifies that files form the <CODE>src</CODE> 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 <CODE>src/</CODE> files.</P><P>Now, when a file is referenced in the <CODE>debug</CODE> directory, it is linked from the <CODE>src</CODE> directory if it exists. For example, when the file <CODE>debug/OMakefile</CODE> is read, the <CODE>src/OMakefile</CODE> is linked into the <CODE>debug/</CODE> directory.</P><P>The <CODE>vmount</CODE> model is fairly transparent. The <CODE>OMakefile</CODE>s can be written <EM>as if</EM> referring to files in the <CODE>src/</CODE> directory—they need not be aware of mounting. However, there are a few points to keep in mind.</P><H2 CLASS="section"><A NAME="toc10"></A><A NAME="htoc14">2.10</A>  Notes</H2><UL CLASS="itemize"><LI CLASS="li-itemize"> When using the <CODE>vmount</CODE> function for versioning, it wise to keep the source files distinct from the compiled versions. For example, suppose the source directory contained a file <CODE>src/foo.o</CODE>. When mounted, the <CODE>foo.o</CODE> file will be the same in all versions, which is probably not what you want. It is better to keep the <CODE>src/</CODE> directory pristine, containing no compiled code.</LI><LI CLASS="li-itemize">When using the <CODE>vmount -l</CODE> option, files are linked into the version directory only if they are referenced in the project. Functions that examine the filesystem (like <CODE>$(ls ...)</CODE>) may produce unexpected results. </LI></UL> <TABLE CELLSPACING=6 CELLPADDING=0><TR><TD ALIGN=left NOWRAP>Jump to:</TD><TD VALIGN=top ALIGN=center NOWRAP>  </TD><TD ALIGN=left NOWRAP><A HREF="http://omake.metaprl.org/">OMake Home</A> • <A HREF="omake.html">Guide Home</A> • <A HREF="omake-doc.html">Guide (single-page)</A> • <A HREF="omake-toc.html">Contents (short)</A> • <A HREF="omake-contents.html">Contents (long)</A></TD></TR> <TR><TD ALIGN=left NOWRAP>Index:</TD><TD VALIGN=top ALIGN=center NOWRAP>  </TD><TD ALIGN=left NOWRAP><A HREF="omake-all-index.html">All</A> • <A HREF="omake-var-index.html">Variables</A> • <A HREF="omake-fun-index.html">Functions</A> • <A HREF="omake-obj-index.html">Objects</A> • <A HREF="omake-target-index.html">Targets</A> • <A HREF="omake-option-index.html">Options</A></TD></TR> </TABLE> </BODY> </HTML>