The hmake compilation management tool


Hmake is an intelligent compilation management tool for Haskell programs. It automatically extracts dependencies between source modules, and issues the appropriate compiler commands to rebuild only those that have changed, given just the name of the program or module that you want to build. Yes, you need never write a Makefile again!

A particular benefit is that hmake knows about interface (.hi) files. Even though a source module has changed, if its interface file has not changed, then other modules which import it do not need to be recompiled.

Hmake is compiler-independent. The installation process automatically detects which Haskell compilers you have, and sets up hmake to use any of them. You can separately add or remove compilers to the configuration at any time after installation, and change which compiler is used as the default. You can easily switch between different versions of a compiler (e.g. ghc 4.08 + 5.02). See hmake-config.

Hmake is aware of pre-processors. Not only is the C preprocessor commonly used for selective imports, but tools such as happy, hsc2hs, c2hs, greencard, are also often used to generate Haskell modules. If hmake finds a module with the appropriate filename extension (.y, .ly, .hsc, .chs, .gc), it automatically runs the preprocessor before the compiler.

Usage

The basic option summary is:

    Usage: hmake [-f cfgfile] [compiler] [hmake-opts] [compiler-opts] target ...
You can have more than one target: all of them are built. A target can be a module (with .lhs, .hs, .hi, or pre-processor extension), in which case the module and everything it depends on is compiled, but not linked.

Alternatively, a target can be a program name (no .hs extension), in which case the appropriate modules are linked as well as compiled. An object or archive filename (.o, .a extension) cannot be a target, but if you add it to the commandline, it will be added into the final link.

Most options are passed straight through to the appropriate compiler. However, hmake understands and strips the following options.

-HC=comp
-hc=comp
-nhc98
-hbc
-ghc
Specify which compiler you want to use. If no compiler is specified, the default compiler is used. (See hmake-config to set the default.)
-q Quiet - don't echo compilation commands.
-n Noexec - echo the compilation commands but don't execute them.
-g Graph - show module dependency graph (implies -n).
-M Makefile - show dependencies in Makefile format (implies -n).
-Md as for -M, but treats -d objdir specially.
-f cfgfile Use cfgfile as the hmake configuration file. This file contains information about the Haskell compilers that are available. (See hmake-config for more information.)
-clean remove all .o files relevant to the given project (does not compile anything).
-realclean remove all .o and .hi files relevant to the given project (does not compile anything).

Hmake also makes use of some compiler options if you specify them. (That is, the options are used by hmake as well as being passed on to the compiler.)

-dobjdir Search for (and compile) object files in(to) a separate objdir.
-Pdir Search dir for prelude/stdlib interface files.
-Idir
-idir
Search dir for imported modules - compile them if necessary, and link against the resulting .o files.

Some options are passed to the compiler's runtime system (using whatever underlying mechanism is appropriate for the particular compiler).

-[Hh]size Compiler's heap size.
-[KVA]size Compiler's stack size.
-[BS] Compiler's garbage collector information options.

You can force an option which would otherwise be interpreted by another part of the system to be passed to the compiler by enclosing it within +CTS ... -CTS delimiters. For example, with nhc98, to set the final executable's default heapsize rather than the compiler's heapsize, use +CTS -H4mb -CTS.

Miscellaneous Features

Some improvements over previous compilation management tools are:

  • You can store object files in a separate directory from your sources.
  • Hmake understands cpp directives: this is particularly useful for imports which differ depending on which compiler you are using. For example,
            #if defined(__HBC__) || defined(__GLASGOW_HASKELL__)
            import Native
            #elsif __NHC__
            import Binary
            #endif
    
    The compiler symbols are defined automatically - you can also define other symbols with -Dsym[=val] on the commandline.
  • It automatically inserts the -cpp compiler option, but only for those modules which actually require it.
  • Various other Haskell-specific preprocessors (e.g. happy, hsc2hs) are known and called automatically when it is appropriate.
  • If you specify .o or .a files on the commandline, it simply links against them, rather than searching for source dependencies for them.

I'd welcome any bug reports, or ideas for other options or behaviours you would find useful.


The latest updates to this software are available on the WWW from http://www.cs.york.ac.uk/fp/hmake/

Information last updated: 2002-01-23
York Functional Programming Group
Malcolm.Wallace@cs.york.ac.uk