--------------------------------------------------------------------------- Distribution of "ocaml_make" Copyright (C) 1999, 2000 Markus Mottl - free to copy and modify! USE AT YOUR OWN RISK! --------------------------------------------------------------------------- Prerequisites *** YOU WILL NEED GNU-MAKE! *** --------------------------------------------------------------------------- Contents of this distribution Changes - guess what? ;-) OcamlMakefile - Makefile for easy handling of compilation of not so easy OCaml-projects. It generates dependencies of Ocaml-files automatically, is able to handle "ocamllex"-, "ocamlyacc"-, IDL- and C-files and generates native- or byte-code, as executable or as library - with thread-support if you want! Profiling and debugging support can be added on the fly! There is also support for installing libraries. Ah, yes, and you can also create toplevels from any sources: this allows you immediate interactive testing! README - this file calc/ - Directory containing a fully-featured example of what "OcamlMakefile" can do for you. This example makes use of "ocamllex", "ocamlyacc", IDL + C and threads. idl/ - Contains a very small example of how to use "camlidl" together with "OcamlMakefile". Also intended to show, how easy it is to interface OCaml and C. threads/ - Two examples of how to use threads (originally posted by Xavier Leroy some time ago). Shows the use of "OcamlMakefile" in an environment of multiple compilation targets. --------------------------------------------------------------------------- Why should you use it? For several reasons: * It is well-tested (I use it in all of my projects). * In contrast to most other approaches it generates dependencies correctly by ensuring that all automatically generated OCaml-files exist before dependency calculation. This is the only way to guarantee that "ocamldep" works correctly. * It is extremely convenient (at least I think so ;-). Even quite complex compilation processes (see example "calc.ml") need very little information to work correctly - actually just about the minimum (file names of sources). --------------------------------------------------------------------------- When you shouldn't use it... In projects where every compilation unit needs other flags - but in such complicated cases you will be on your own anyway. Luckily, this doesn't happen too frequently... --------------------------------------------------------------------------- How to use "OcamlMakefile" in your own project (Take a look at the examples for a quick introduction!) Create your project-specific "Makefile" in the appropriate directory. Now there are two ways of making use of "OcamlMakefile": 1) Have a look at the default settings in "OcamlMakefile" and set them to the values that are vaild on your system - whether the path to the standard libraries is ok, what executables shall be used, etc... 2) Copy it into the directory of the project to be compiled. Add "-include OcamlMakefile" as a last line of your "Makefile". 3) Put it somewhere else on the system. In this case you will have to set a variable "OCAMLMAKEFILE" in your project-specific "Makefile". This is the way in which the examples are written: so you need only one version of "OcamlMakefile" to manage all your projects! See the examples for details. You should usually specify two further variables for your project: * SOURCES (default: foo.ml) * RESULT (default: foo) Put all the sources necessary for a target into variable "SOURCES". Then set "RESULT" to the name of the target. If you want to generate libraries, you should *not* specify the suffix (".cma", ".cmxa", ".a") - it will be added automatically if you specify that you want to build a library. ** Don't forget to add the ".mli"-files, too! ** ** Don't forget that order of the source files matters! ** The minimum of your "Makefile" looks like this (assuming that "OcamlMakefile" is in the search path of "make"): -include OcamlMakefile This will assume that you want to compile a file "foo.ml" to a binary "foo". Otherwise, your Makefile will probably contain something like this: SOURCES = foo.ml RESULT = foo -include OcamlMakefile Be careful with the names you put into these variables: if they are wrong, a "make clean" might erase the wrong files - but I know you will not do that ;-) A simple "make" will generate a byte-code executable. If you want to change this, you may add an "all"-rule that generates something else. E.g.: SOURCES = foo.ml RESULT = foo all: native-code-library -include OcamlMakefile This will build a native-code library "foo.cmxa" (+ "foo.a") from file "foo.ml". You may even build several targets at once. To produce byte- and native-code executables with one "make", add the following rule: all: byte-code native-code You will probably want to use a different suffix for each of these targets so that the result will not be overwritten (see optional variables below for details). You may also tell "make" at the command-line what kind of target to produce (e.g. "make nc"). Here all the possibilities with shortcuts between parenthesis: * byte-code (bc) * byte-code-library (bcl) * native-code (nc) * native-code-library (ncl) * debug-code (dc) * debug-code-library (dcl) * profiling-byte-code (pbc) * profiling-byte-code-library (pbcl) * profiling-native-code (pnc) * profiling-native-code-library (pncl) * toplevel interpreter (top) Here a short note concerning building and linking byte code libraries with C-files: OCaml links C-object files only when they are used in an executable. After compilation they should be placed in some directory that is in your include path if you link your library against an executable. It is sometimes more convenient to link all C-object files into a single C-library. Then you have to override the automatic link flags of your library using "-noautolink" and add another linkflag that links in your C-library explicitely. What concerns maintainance: "make clean" removes all (all!) automatically generated files - so again: make sure your variables are ok! Another way to destroy some important files is by having "OcamlMakefile" automatically generate files with the same name. Read the documentation about the tools in the OCaml-distribution to see what kind of files are generated. "OcamlMakefile" additionally generates ('%' is basename of source file): %_idl.c - "camlidl" generates a file "%.c" from "%.idl", but this is not such a good idea, because when generating native-code, both the file "%.c" and "%.ml" would generate files "%.o" which would overwrite each other. Thus, "OcamlMakefile" renames "%.c" to "%_idl.c" to work around this problem. The dependencies are stored in three different subdirectories (dot dirs): ._d - contains dependencies for .ml-files ._bcdi - contains byte code dependencies for .mli-files ._ncdi - contains native code dependencies for .mli-files The endings of the dependency files are: "%.d" for those generated from "%.ml"-files, "%.di" for ones derived from "%.mli"-files. --------------------------------------------------------------------------- Debugging This is easy: if you discover a bug, just do a "make clean; make dc" to recompile your project with debugging information. Then you can immediately apply "ocamldebug" to the executable. --------------------------------------------------------------------------- Profiling For generating code that can be profiled with "ocamlprof" (byte code) or "gprof" (native code), compile your project with one of the profiling targets (see targets above). E.g.: * "make pbc" will build byte code that can be profiled with "ocamlprof". * "make pnc" will build native code that can be profiled with "gprof". Please note that it is not currently possible to profile byte code with threads. OcamlMakefile will force an error if you try to do this. A short hint for DEC Alpha-users (under Digital Unix): you may also compile your sources to native code without any further profiling options/targets. Then call "pixie my_exec", "my_exec" being your executable. This will produce (among other files) an executable "my_exec.pixie". Call it and it will produce profiling information which can be analysed using "prof -pixie my_exec". The resulting information is extremely detailed and allows analysis up to the clock cycle level... --------------------------------------------------------------------------- Library (Un-)Installation Support OcamlMakefile contains two targets for this purpose: * libinstall * libuninstall These two targets require the existence of the variable "LIBINSTALL_FILES", which should be set to all the files that you want to install in the library directory (usually %.mli, %.cmi, %.cma, %.cmxa, %.a and possibly further C-libraries). The target "libinstall" has the dependency "all" to force compilation of the library so make sure you define target "all" in your Makefile appropriately. The targets inform the user about the configured install path and ask for confirmation to (un)install there. If you want to use them, it is often a good idea to just alias them in your Makefile to "install" and "uninstall" respectively. See also variable "OCAML_LIB_INSTALL" for details on how the installation directory is determined. --------------------------------------------------------------------------- Building toplevels There is just one target for this: * top The generated file can be used immediately for interactive sessions - even with scanners, parsers, C-files, etc.! --------------------------------------------------------------------------- Optional variables that may be passed to "OcamlMakefile" * THREADS - say "THREADS = yes" in your "Makefile" if you need thread support compiled in, otherwise leave it away. * INCDIRS - directories that should be searched for ".cmi"- and ".cmo"-files. You need not write "-I ..." - just the plain names. * LIBDIRS - directories that should be searched for libraries Also just put the plain paths into this variable * LIBS - OCaml-libraries that should be linked (just plain names). E.g. if you want to link the Str-library, just write "str" (without quotes). The new OCaml-compiler handles libraries in such a way that they "remember" whether they have to be linked against a C-library and it gets linked in automatically. * CLIBS - C-libraries that should be linked (just plain names). * LIBINSTALL_FILES - the files of a library that should be installed under the path given in "$(OCAML_LIB_INSTALL)" (see below). * OCAMLFLAGS - flags passed to the compilers * OCAMLBCFLAGS - flags passed to the byte code compiler only * OCAMLNCFLAGS - flags passed to the native code compiler only * OCAMLLDFLAGS - flags passed to the OCaml-linker * OCAMLBLDFLAGS - flags passed to the OCaml-linker when linking byte code * OCAMLNLDFLAGS - flags passed to the OCaml-linker when linking native code * OCAMLCPFLAGS - profiling flags passed to "ocamlcp" (default: "a") * YFLAGS - flags passed to "ocamlyacc" * IDLFLAGS - flags passed to "camlidl" * CC - the C-compiler to be used * CFLAGS - additional flags passed to the C-compilers. The flag "-DNATIVE_CODE" will be passed automatically if you choose to build native code. This allows you to compile your C-files conditionally. But please note: You should do a "make clean" or remove the object files manually or touch the %.c-files: otherwise, they may not be correctly recompiled between different builds. * LDFLAGS - additional flags passed to the C-linker * OCAMLLIBPATH - path to the OCaml-standard-libraries (first default: `$(OCAMLC) -where`) (second default: "/usr/local/lib/ocaml") * OCAML_DEFAULT_DIRS - additional path in which the user can supply default directories to his own collection of libraries. The idea is to pass this as an environment variable so that the Makefiles do not have to contain this path all the time. * OCAML_LIB_INSTALL - path in which libraries should be installed using the builtin installation targets. This variable defaults to "$(OCAMLLIBPATH)/contrib". * OCAMLC - byte-code compiler (default: "ocamlc") * OCAMLOPT - native-code compiler (default: "ocamlopt") * OCAMLMKTOP - top-level compiler (default: "ocamlmktop") * OCAMLCP - profiling byte-code compiler (default: "ocamlcp") * OCAMLDEP - dependency generator (default: "ocamldep") * OCAMLLEX - scanner generator (default: "ocamllex") * OCAMLYACC - parser generator (default: "ocamlyacc") * OCAMLIDL - IDL-code generator (default: "camlidl") * NOIDLHEADER - set to "yes" to prohibit "OcamlMakefile" from using the default camlidl-flag "-header". * OCAMLMAKEFILE - location of (=path to) this "OcamlMakefile". Because it calles itself recursively, it has to know where it is. (default: "OcamlMakefile" = local directory) * BCSUFFIX - Suffix for all byte-code files. E.g.: RESULT = foo BCSUFFIX = _bc This will produce byte-code executables/libraries with basename "foo_bc". * NCSUFFIX - Similar to "BCSUFFIX", but for native-code files. * TOPSUFFIX - Suffix added to toplevel interpreters (default: ".top") --------------------------------------------------------------------------- Up-to-date information (newest release of distribution) can always be found at: http://miss.wu-wien.ac.at/~mottl/ocaml_sources --------------------------------------------------------------------------- Enjoy! Vienna, 2001-01-24 Markus Mottl e-mail: mottl@miss.wu-wien.ac.at WWW: http://miss.wu.wien.ac.at/~mottl