Is there a convenient way to develop OCaml code, and be sure that this code will be configurable, compilable, installable and executable without changes, on any environment where OCaml is available?
I imagine a higher level "make", with most of its nicer properties, plus many enhancements. The following points seem important to me:
- target dependency system - ease of use, nice syntax (for average humans with a simple text editor) - loadable modules - built-in programming language - built-in fileutils (cp, mv, cd, rm, ...) and functions (filters, ...) - universal paths for filenames inside the project tree - natural highlighting of environment-dependent elements - possibility of harmonious integration in a graphical development environment
and also a very flexible license that allows its free redistribution and modification under any form.
Until right now I didn't find anything like this. And I was really scared when I discovered Apache Ant.
On Thu, Nov 20, 2003 at 07:47:25PM +0100, Martin Jambon wrote: > Hi,
> Is there a convenient way to develop OCaml code, and be sure that > this code will be configurable, compilable, installable and > executable without changes, on any environment where OCaml is available?
The only way is to use only pure ocaml code ( not C binding ). With this you are pretty sure not to have any problem. (Exclude for example Unix, Dbm modules ).
> I imagine a higher level "make", with most of its nicer properties, plus > many enhancements. > The following points seem important to me:
> - target dependency system > - ease of use, nice syntax (for average humans with a simple text editor) > - loadable modules > - built-in programming language > - built-in fileutils (cp, mv, cd, rm, ...) and functions (filters, ...)
... Try ocaml-fileutils ...
> - universal paths for filenames inside the project tree
... Try ocaml-fileutils ...
> - natural highlighting of environment-dependent elements > - possibility of harmonious integration in a graphical development > environment
> and also a very flexible license that allows its free redistribution and > modification under any form.
> Until right now I didn't find anything like this. And I was really scared > when I discovered Apache Ant.
Well let me give you some hints : Ocaml fileutils is a lib of mine ( not yet published, but if you want to test it, i can give you the tar ball ).
In fact, my aim is to construct approximativelly what you are looking for but for now, i have not yet the time to go over the whole things.
Ocaml-fileutils is the base path abstraction for files and fileutils. Ocaml-preprocessor is a replacement for *.in -> * ( already developped, very simple, it is something were you bind variable and function and you pass it on files where there is for example @funct "abcd"@ and it replace it with the result of the binding of funct "abcd"... ). It is also not yet published, but it seems stable to me.
I want to develop the makefile in ML. Each module will register variable, target, dependency and a big program will run to compute all this and compile file, lib, exec...
For now, it is only at an early stage ( i have some lexer/parser to autosort ocamldep generated file and try to figure how to compile only one thing ).
If you are intersted, just drop me an email, to have more information, or if you want to test ocaml-fileutils or ocaml-preprocessor.
> I want to develop the makefile in ML. Each module will register > variable, target, dependency and a big program will run to compute all > this and compile file, lib, exec...
> For now, it is only at an early stage ( i have some lexer/parser to > autosort ocamldep generated file and try to figure how to compile only > one thing ).
On Fri, Nov 21, 2003 at 10:45:47AM +0900, Nicolas Cannasse wrote: > What is the difference with OCamake ? > http://tech.motion-twin.com/ocamake/
There are a lot of things that OCamake can't do. What would be very nice would be a tool that makes it easy to build simple Ocaml programs, but also lets me, reasonably easily, manage directory trees, C bindings, C libraries, programs build with special, strange programs, etc...
There are several packages in the scons approach that seem like good ideas, but they all make very heavy use of the scripting languages they are written in.
I still haven't found anything nicer than gnatmake, the builder for Gnu Ada. A common compilation line:
gnatmake mainmodule
Builds mainmodule.adb, as well as everything it depends on. You can set a path to search for parts. This would work for ocaml, if a program had a single module that brought in everything necessary via dependencies.
> There are a lot of things that OCamake can't do. What would be very > nice would be a tool that makes it easy to build simple Ocaml programs, > but also lets me, reasonably easily, manage directory trees, C bindings, > C libraries, programs build with special, strange programs, etc...
> There are several packages in the scons approach that seem like good > ideas, but they all make very heavy use of the scripting languages they > are written in.
> I still haven't found anything nicer than gnatmake, the builder for Gnu > Ada. A common compilation line:
> gnatmake mainmodule
> Builds mainmodule.adb, as well as everything it depends on. You can set > a path to search for parts. This would work for ocaml, if a program had > a single module that brought in everything necessary via dependencies.
I agree such a thing would be very useful.
The first problem I see is that right now ocamldep is only giving you the dependencies between files that are listed in the ocamldep command. That means that you already need to know all the files before generating the dependencies between them.
The other problem is that to much of the "special programs build" are relying on OS tools that are sometimes not stricly compatible. The solution to this is to rewrite all the tools in pure ocaml ( or with a small portable C binding ) to give the "makefile" writter an API of portable commands. It looks like this is the goal of Sylvain, and that would be really something nice.
About OCamake : yes right know it only supports compilation of ml/mli/mll/mly files in a standard way, but it is now mature and is actually handling a lot of cases such as projects with multiple files paths and a best effort dependency resolver (although based on ocamldep output). Adding the auto building of C stubs could be done but this kind of tool need a lot of time in order to fix correctly all the small issues.
On Fri, Nov 21, 2003 at 02:48:17PM +0900, Nicolas Cannasse wrote: > The first problem I see is that right now ocamldep is only giving you the > dependencies between files that are listed in the ocamldep command. That > means that you already need to know all the files before generating the > dependencies between them.
Start with the module you know. As long as the path is right, ocamldep will give you the dependencies for the files it referrs to (they don't have to be named, as long as their source is in the path). You can keep doing this to get a full name. Ocamake seems to be able to do it.
On Fri, Nov 21, 2003 at 02:48:17PM +0900, Nicolas Cannasse wrote: > > > What is the difference with OCamake ? > > > http://tech.motion-twin.com/ocamake/
> > There are a lot of things that OCamake can't do. What would be very > > nice would be a tool that makes it easy to build simple Ocaml programs, > > but also lets me, reasonably easily, manage directory trees, C bindings, > > C libraries, programs build with special, strange programs, etc...
> > There are several packages in the scons approach that seem like good > > ideas, but they all make very heavy use of the scripting languages they > > are written in.
> > I still haven't found anything nicer than gnatmake, the builder for Gnu > > Ada. A common compilation line:
> > gnatmake mainmodule
> > Builds mainmodule.adb, as well as everything it depends on. You can set > > a path to search for parts. This would work for ocaml, if a program had > > a single module that brought in everything necessary via dependencies.
> I agree such a thing would be very useful.
> The first problem I see is that right now ocamldep is only giving you the > dependencies between files that are listed in the ocamldep command. That > means that you already need to know all the files before generating the > dependencies between them.
> The other problem is that to much of the "special programs build" are > relying on OS tools that are sometimes not stricly compatible. The solution > to this is to rewrite all the tools in pure ocaml ( or with a small portable > C binding ) to give the "makefile" writter an API of portable commands. It > looks like this is the goal of Sylvain, and that would be really something > nice.
> About OCamake : yes right know it only supports compilation of > ml/mli/mll/mly files in a standard way, but it is now mature and is actually > handling a lot of cases such as projects with multiple files paths and a > best effort dependency resolver (although based on ocamldep output). Adding > the auto building of C stubs could be done but this kind of tool need a lot > of time in order to fix correctly all the small issues.
> Nicolas Cannasse
Hello,
Well, i will maybe stole your code ;->
My aims is to make something more Makefile like ( ie you will have the ability to add rules ). Off course, my first goal is to compile ml file. So there will be less features than Makefile.
On the other hand the aim will be to have a self contained tools ( ie when you write a makefile you use rm, cp, touch... here the aims will be to have it in ocaml ). So you could build on every platform which support ocaml.
On Thu, Nov 20, 2003 at 07:47:25PM +0100, Martin Jambon wrote: > Until right now I didn't find anything like this. And I was really scared > when I discovered Apache Ant.
One hopes such a tool won't be as slow or as hard to use or as stupidly architected as Apache Ant ...
On Fri, 21 Nov 2003 sylvain.le-g...@polytechnique.org wrote:
> My aims is to make something more Makefile like ( ie you will have the > ability to add rules ). Off course, my first goal is to compile ml file. > So there will be less features than Makefile.
Are you sure? If this compiles only Caml code, nobody will use it for serious projects. But I was thinking of loadable modules like in emacs instead of a rigid and limited set of predefined rules. If we think of make as a preprocessor for shell-scripts, then we can create a preprocessor for OCaml that will do the same but will benefit from many built-in properties that sh doesn't have and that (GNU) make hardly provides.
On Fri, 2003-11-21 at 05:47, Martin Jambon wrote: > . And I was really scared > when I discovered Apache Ant.
Excuse my ignorance but what is that? A bug generator?? <g> -- John Max Skaller, mailto:skal...@ozemail.com.au snail:25/85c Wigram Rd, Glebe, NSW 2037, Australia. voice:61-2-9660-0850. Checkout Felix: http://felix.sf.net
Martin Jambon wrote: > Is there a convenient way to develop OCaml code, and be sure that > this code will be configurable, compilable, installable and > executable without changes, on any environment where OCaml is available?
We have been using omake to build several large projects, primarily on Linux and Windows. omake is written in OCaml, and provides a build system with syntax similar to make, but project-wide dependency analysis. Here are some features:
- omake runs on Unix, Windows, MacOS, and presumably other architectures where OCaml is available. - dependency analysis is project-wide (like cons), based on MD5 digests - automated dependency analysis - there is builtin support for OCaml and C code, and it is easy to add support for other kinds of files (just like make). - the OMakefile syntax is similar to GNU make, but - omake has user-defined functions - OMakefile programs are functional - the .SUBDIRS target is used to define the project hierarchy - different parts of the project can have different configuration.
omake is available by anonynous CVS from cvs.metaprl.org. % cvs -d :pserver:anon...@cvs.metaprl.org:/cvsroot login The password is anoncvs. % cvs -d :pserver:anon...@cvs.metaprl.org:/cvsroot checkout omake
Alternatively, RPMs are available at rpm.nogin.org.
Here is a short description. Every project must have an OMakeroot file in the project root. It is usually boilerplate; this is typical:
# Include the standard configuration include $(STDROOT)
# Include the OMakefile .SUBDIRS: .
The project commands are then placed in an OMakefile. To build a standalone OCaml program from files a.ml b.ml and c.ml, you just need one line. The OCamlProgram function is defined in the system OMakeroot.
OCamlProgram(foo, a b c)
You can choose the byte-compiler, native-code compiler, or both.
BYTE_ENABLED = true NATIVE_ENABLED = true OCamlProgram(foo, a b c)
Maybe you have some C files you need to include in your compile as well. Perhaps f.c is a generated file.
f.c: f1.c f2.c cat $+ > $@ StaticCLibrary(bar, d e f) LIBS = bar OCamlProgram(foo, a b c)
Perhaps you use the C-preprocessor on some .mlp files:
%.ml: %.mlp $(CPP) $*.mlp > $@
The system sources contain more examples, and the MetaPRL system, also available at cvs.metaprl.org, provides a very large, complex, example.
SYNOPSIS omake is a replacement for the make(1) build program. The omake system provides the following additional features.
Recursive builds
Omake(1) is designed for building projects that might have source files in several directories. In Omake, projects are normally specified using an OMakefile in each of the project directories, and an OMakeroot file in the root directory. 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, merging rules from all of the OMakefiles. The project is then built from the entire collection of build rules.
Automatic dependency analysis.
Dependency analysis has always been problematic with the make(1) pro- gram. Omake addresses this by adding the .SCANNER target, which speci- fies a command to produce dependencies. For example, the rule
.SCANNER: %.c $(CC) $(INCLUDE) -MM $+
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.
Content-based dependency analysis.
Dependency analysis in omake uses MD5 digests to determine whether files have changed. After each run, omake stores the dependency infor- mation 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.
OMakefile The OMakefile has a formal similar to Makefile. An OMakefile has three kinds of syntac objects: variable definitions, function definitions, and rule definitions.
Variables
Variables are defined with the following syntax. The name is any sequence of alphanumeric characters, underscore ’_’, and hyphen ’-’.
<name> = <value>
Values are represented as a sequence of literal characters and variable expansions. A variable expansion has the form "$(<name>)," which rep- resents the value of the "<name>" variable in the current environment. Some examples are shown below.
In this example, the value of the COMMAND variable is the string "gcc -Wall -g -O2".
Unlike make, variable expansion is eager, and functional. That is, variable values are expanded immediately and new variable definitions to not affect old ones. For example, consider the following variable definitions.
X = $(COMMAND) COMMAND = $(COMMAND) -O3 Y = $(COMMAND)
In this example, the value of the X variable is the string "gcc -Wall -g -O2" as before, and the value of the Y variable is "gcc -Wall -g -O2 -O3".
Functions
Functions are defined using the following syntax.
<name>(<params>) = <indented-body>
The parameters are a comma-separated list of identifiers, and the body must be placed on a separate set of lines that are indented from the function definition itself. For example, the following text defines a function that concatenates its arguments.
CONCAT(a, b) = $(a)$(b)
Functions are called using the GNU-make syntax, "$(<name> <args))", where "<args>" is a comma-separated list of values.
Built-in functions
addsuffix The addsuffix function adds a suffix to each component of a white-space separated list of strings. Double-quotes may be used to delimit components that contain spaces.
$(addsuffix <suffix>, <names)) For example, $(addsuffix .c, a b "c d") expands to a.c b.c "c d".c.
addprefix The addprefix function adds a prefix to each component of a white-space separated list of strings. Double-quotes may be used to delimit components that contain spaces.
$(addprefix <prefix>, <names)) For example, $(addprefix foo/, a b "c d") expands to foo/a foo/b foo/"c d".
replacesuffixes The replacesuffixes function modifies the suffix in each component of a white-space separated list of strings.
$(replacesuffixes <old-suffixes>, <new-suffixes>, <names)) For example, $(replacesuffixes, .h .c, .o .o, a.c b.h c.z) expands to a.o b.o c.z.
set The set function sorts a set of string components, eliminating duplicates. Note that the quote symbol in a string component is significant.
$(set <names>) For example, $(set z y z "m n" w a) expands to "m n" a w y z.
not Boolean values in omake are represented by case-insensitive strings. The false value can be represented by the strings false, no, nil, undefined or 0, and everything else is true. The not func- tion negates a Boolean value.
$(not <value>) For example, $(not false) expands to the string true, and $(not hello world) expands to false.
equal The equal function tests for equality of two values.
$(equal <value1>, <value2>) For example $(equal a, b) expands to false, and $(equal hello world, hello world) expands to true.
if The if function represents a conditional based on a Boolean value.
$(if <test>, <value1> <value2>) For example $(if $(equal a, b), c, d) expands to d.
filter-out The filter-out function removes a component from a white- space separated list of strings.
$(filter-out <value>, <names>)$ For example $(filter-out a, c d a "hello world") expands to c d "hello world".
file The file and dir functions define location-independent references to files and directories. In omake, the commands to build a target are executed in the target’s directory. Since there may be many directories in an omake project, the build system provdes a way to construct a reference to a file in one directory, and use it in another without explicitly modifying the file name. The functions have the following syntax, where the name should refer to a file or directory.
$(file <name>) , $(dir <name>) For example, we can construct a reference to a file "foo" in the cur- rent directory.
FOO = $(file foo) .SUBDIRS: bar
If the FOO variable is expanded in the bar subdirectory, it will expand to ../foo.
These commands are often used in the top-level OMakefile to provide location-independent references to top-level directories, so that build commands may refer to these directories as if they were absolute.
ROOT = $(dir .) LIB = $(dir lib) BIN = $(dir bin)
Once these variables are defined, they can be used in build commands in subdirectories as follows, where $(BIN) will expand to the location of the bin directory relative to the command being executed.
install: hello cp hello $(BIN)
in The in function is closely related to the dir and file functions. It takes a directory and a file, and gives the filename expanded relative to that directory. For example, one common way to install a file is to define a symbol link, where the value of the link is relative to the directory where the link is created.
$(in <dir>, <file>) The following commands create links in the $(LIB) directory.
This rule states that the hello.o file depends on the hello.c file. If the hello.c file is newer, the command "$(CC) $(CFLAGS) -c -o hello.o hello.c" is to be executed to update the target file hello.o.
A rule can have an arbitrary number of commands. The individual com- mand lines are executed independently by the shell sh(1). The commands do not have to begin with a tab, but they must be indented from the dependency line.
Rules can also be implicit. That is, the files may be specified by wildcard patterns. The wildcard character is %. For example, the fol- lowing rule specifies a generic way to build .o files.
%.o: %.c $(CC) $(CFLAGS) -c -o $@ $*.c
This rule is a general rule to build an arbitrry .o file from a .c file. The variables $@ and $* are special. The following variables may be used in rules.
$*: the target name, without a suffix. $@: the target name. $^: a list of the sources, with duplicates removed. $+: a list of the sources, dpulicates are not removed. $<: the first source
On Fri, 2003-11-21 at 17:49, sylvain.le-g...@polytechnique.org wrote: > On Fri, Nov 21, 2003 at 02:48:17PM +0900, Nicolas Cannasse wrote: > On the other hand the aim will be to have a self contained tools ( ie > when you write a makefile you use rm, cp, touch > .. here the aims will be > to have it in ocaml ). So you could build on every platform which > support ocaml.
The goal is impossible. For example, all my Ocaml source is literate programmed. You surely aren't going to rewrite Interscript in Ocaml are you?
At best, you can cheat with system() function but then all the dependency checking is lost.
Make systems are all conceptually wrong. There a huge number of projects to replace Make (and autoconf et al) and not a single one I've seen recognizes that the fundamental design is flawed .. instead they all try to copy the make idea.
First observe that building a system is a process where it is not always possible to determine the full sequence of commands in advance. Sometimes, you have to perform some action before you can decide what to do next.
Example: you cannot build interscript packaged sources or a tarball directly, you have to extract the contents first.
Example: the rules for building a package may have to be generated or extracted from the package.
Next observe that the linear dependency checking is naive. First, what some target depends on can be conditional: obviously true for C :-)
But it is much worse. A target can depend on itself. Interscript assumes that. An example is a Latex build, which depends on auxilliary files generated by the build [Ocamldoc output can take 4 passes to fixate for example].
This leads to the first novel idea. Fixpoints. Interscript is based on that idea.
With fixpoints, you dont CARE about dependencies. What you do is repeatedly execute some process until the defined outputs are stable. The inputs do not need to be known.
Now we backstep. We try to *predict* whether the outputs will be the same this run as last. If we can -- and we have to be *sure* -- we can terminate one cycle earlier.
This is dependency checking with a new twist: its optional. :-)
Well, I will jump ahead now. A build system does NOT have targets. That's a bad idea too.
A build systems has processes and files. Lets call the processes ARROWS and the files OBJECTS.
Oh. That's a category. We allow of course, products of files (multiple outputs and inputs) and sums of files (choose one of several). [And of course we'd better make it cartesian closed and allow processes to be files .. called scripts .. :]
The control system allows you to 'click' on an arrow to execute the process. This is manual running. It also allows to to click on a object to run all the processes required to produce the object. By using a caching concept, some process can be elided as an optimisation.
For example .c -cc--> .o -link--> exe, we can use the cached .o instead of running cc on the .c provided the .c is older.
BTW: I have *built* this system, including a graphic interface which allowed construction of the build category.
I needed this much power. Make is a total joke. What I was doing was writing a book, literate programmed of course, and needed to generate a LOT of different documents -- I had to build code, test it, capture the output, typeset the book, build indices, contents ...
In a *real* build system, you do NOT want to make everything from scratch everytime. Sometime you're happy using old data, at least for a while.
Anyhow .. a lot of new ideas for a build system are here. Just copying the make concept is not going to solve any problems .. its going to make things much WORSE by having yet another inadequate tool -- which of course the poor client will have to build, making the tool chain even longer. [Trying to replace Make destroyed Boost IMHO]
skaller wrote: > But it is much worse. A target can > depend on itself. Interscript assumes that. > An example is a Latex build, which depends > on auxilliary files generated by the build > [Ocamldoc output can take 4 passes to fixate > for example].
> This leads to the first novel idea. Fixpoints. > Interscript is based on that idea.
Just to be pedantic ;-) A Tex or Latex build is not guaranteed to converge so you may not have a fixed point in the computation. They can oscillate and it may be necessary to slightly alter the source document to get things to settle down.
On Fri, Nov 21, 2003 at 09:05:22AM -0800, Jason Hickey wrote: > Martin Jambon wrote: > >Is there a convenient way to develop OCaml code, and be sure that > >this code will be configurable, compilable, installable and > >executable without changes, on any environment where OCaml is available?
> We have been using omake to build several large projects, primarily on > Linux and Windows. omake is written in OCaml, and provides a build > system with syntax similar to make, but project-wide dependency > analysis. Here are some features:
> - omake runs on Unix, Windows, MacOS, and presumably > other architectures where OCaml is available. > - dependency analysis is project-wide (like cons), > based on MD5 digests > - automated dependency analysis > - there is builtin support for OCaml and C code, > and it is easy to add support for other kinds > of files (just like make). > - the OMakefile syntax is similar to GNU make, but > - omake has user-defined functions > - OMakefile programs are functional > - the .SUBDIRS target is used to define > the project hierarchy > - different parts of the project can have > different configuration.
> omake is available by anonynous CVS from cvs.metaprl.org. > % cvs -d :pserver:anon...@cvs.metaprl.org:/cvsroot login > The password is anoncvs. > % cvs -d :pserver:anon...@cvs.metaprl.org:/cvsroot checkout omake
> Alternatively, RPMs are available at rpm.nogin.org.
> Here is a short description. Every project must have an OMakeroot file > in the project root. It is usually boilerplate; this is typical:
> # Include the standard configuration > include $(STDROOT)
> # Include the OMakefile > .SUBDIRS: .
> The project commands are then placed in an OMakefile. To build a > standalone OCaml program from files a.ml b.ml and c.ml, you just need > one line. The OCamlProgram function is defined in the system OMakeroot.
> OCamlProgram(foo, a b c)
> You can choose the byte-compiler, native-code compiler, or both.
> BYTE_ENABLED = true > NATIVE_ENABLED = true > OCamlProgram(foo, a b c)
> Maybe you have some C files you need to include in your compile as well. > Perhaps f.c is a generated file.
> f.c: f1.c f2.c > cat $+ > $@ > StaticCLibrary(bar, d e f) > LIBS = bar > OCamlProgram(foo, a b c)
> Perhaps you use the C-preprocessor on some .mlp files:
> %.ml: %.mlp > $(CPP) $*.mlp > $@
> The system sources contain more examples, and the MetaPRL system, also > available at cvs.metaprl.org, provides a very large, complex, example.
> Jason
Hello,
It seems great to me...
Is there way to define camlp4 syntax ? ( for example XXX.ml needs camlp4 with cmo zoggy.cmo or something like that )
Is there a kind of configure in it ?
Can you use META files.
(... a lot of other question but i will take a look at it before asking ).
On Fri, Nov 21, 2003 at 05:32:50PM +0100, Martin Jambon wrote: > On Fri, 21 Nov 2003 sylvain.le-g...@polytechnique.org wrote:
> > My aims is to make something more Makefile like ( ie you will have the > > ability to add rules ). Off course, my first goal is to compile ml file. > > So there will be less features than Makefile.
> Are you sure? If this compiles only Caml code, nobody will use it for > serious projects. But I was thinking of loadable modules like in emacs > instead of a rigid and limited set of predefined rules. > If we think of make as a preprocessor for shell-scripts, then we can > create a preprocessor for OCaml that will do the same but will benefit > from many built-in properties that sh doesn't have and that (GNU) make > hardly provides.
Hello,
I was thinking of dynlink for loadable module...
But i need to investigate on other tools ( omake ).
On Sat, Nov 22, 2003 at 03:12:48AM +1100, skaller wrote: > On Fri, 2003-11-21 at 17:49, sylvain.le-g...@polytechnique.org wrote: > > On Fri, Nov 21, 2003 at 02:48:17PM +0900, Nicolas Cannasse wrote:
> > On the other hand the aim will be to have a self contained tools ( ie > > when you write a makefile you use rm, cp, touch > > .. here the aims will be > > to have it in ocaml ). So you could build on every platform which > > support ocaml.
> The goal is impossible. For example, all my Ocaml > source is literate programmed. You surely aren't > going to rewrite Interscript in Ocaml are you?
Ok i have read your mail but i need time to understand all what is lying in it.
I don't want to reproduce make bugs... I just want to do something simple where you can type :
let my_prog = { name : "my_prog"; compile_target : [Opt;Byte]; toplevel_files : [ "my_prog.ml" ; "something_ocamldep_dont_recognize_as_toplevel.ml" ]; package : "all_my_life" ; target_tag : Binary; ( or Documentation or Custom of string ) }
let _ = add_target my_prog
Ie, it is not makefile syntax.
But, i don't really have begin my project... So i can't already said that i will use this or that...
Kind regard Sylvain LE GALL
ps : if you are interested, i will contact you when i will consider enough mature to begin with this huge task ( in fact, i have made a kind of start with the findlib branch of cameleon, but i am not finished ).
On 21.11.2003 10:55, sylvain.le-g...@polytechnique.org wrote:
> Is there way to define camlp4 syntax ? ( for example XXX.ml needs camlp4 > with cmo zoggy.cmo or something like that )
Yes, the syntax would be something like
if true OCAMLFLAGS += -pp "camlp4 zoggy.cmo" XXX.cmx XXX.o: XXX.cmo:
The idea is the following: - variables inside the "if" statements are locally scope (unless you explicitly export the variable environment back to the parent scope), so we use the "if true" as a synonym for "local". So, the above tells omake to add a preprocessor flag to ocamlc/ocamlopt when compiling XXX.cmx, XXX.o and XXX.cmo.
There are a number of mechanisms for hooking to an external one. For example, you could specify dependencies and commands when including file as:
.INCLUDE: foo bla bla > foo
.INCLUDE: foo: foo.in bla bla bla bla < foo.in > foo
The above tell omake that - it should include foo and if the file does not exist, it should use "bla bla" to generate it. Next, it should check whether foo is newer than foo.in and generate foo again (using "bla bla blah blah" this time) and then include it again.
You can also specify dependencies for the OMakefile itself:
if $(not $(equal $(OSTYPE), Win32)) OMakefile: OMakefile.in config.status @echo "*** Build system is out-of-date, rebuilding ***" $(DOT)config.status @echo "*** OMakefile was rebuilt, session should restart ***"
> Can you use META files.
Not sure what those are.
On 21.11.2003 08:12, skaller wrote:
> But it is much worse. A target can > depend on itself. Interscript assumes that. > An example is a Latex build, which depends > on auxilliary files generated by the build > [Ocamldoc output can take 4 passes to fixate > for example].
> The idea is the following: > - variables inside the "if" statements are locally scope (unless you > explicitly export the variable environment back to the parent scope), so > we use the "if true" as a synonym for "local". So, the above tells omake > to add a preprocessor flag to ocamlc/ocamlopt when compiling XXX.cmx, > XXX.o and XXX.cmo.
> There are a number of mechanisms for hooking to an external one. For > example, you could specify dependencies and commands when including file as:
> .INCLUDE: foo > bla bla > foo
> .INCLUDE: foo: foo.in > bla bla bla bla < foo.in > foo
Ok. But i am looking for something included in it ( think that in your very large project, you have a library that builds against an external one, i want that the makefile system detect it and output that it needs this library... ).
> if $(not $(equal $(OSTYPE), Win32)) > OMakefile: OMakefile.in config.status > @echo "*** Build system is out-of-date, rebuilding ***" > $(DOT)config.status > @echo "*** OMakefile was rebuilt, session should restart ***"
In fact i want to get rid of it ( no $(DOT)config.status ). Autools et al are very well made but i think that it is too much complicated ( having try to understand how it is build but most of the time i really can t get into it ).
> >Can you use META files.
> Not sure what those are.
META file comes with findlib. Findlib is an helper to configure ocaml compilation : ocamlfind ocamlc -package "fileutils" xxx.ml will run ocamlc -I /usr/lib/ocaml/fileutils ...
Gerd Stolpmann write it ( www.ocaml-programming.de ). Sorry to the author if i mistyped his name...
I take a quick glance to you OMakefile...
Well i think it is very powerfull and very interesting... But ( there is always a but ), i am looking for something between your very complete suite and ocamake which is light and permits to do fast job for ocaml stuff.
I know, i will run into problem if not targeting all people... But, i cannot choose all options. I want something enough powerfull to build little to medium ocaml project -- with some C binding. I don't want to rebuild make. The ideal project ( in size ) will be cameleon ( fully written in ocaml ) or mldonkey ( mostly ocaml with some C ). I don't really want to be able to compile C, python, Ada...
I want to use some kind of ocaml script ( let say makefile.ml which will contain the instruction to build, explains the dependency etc ) to enable user to be fully consistent with their project ( they learn ocaml and not makefile syntax ). I think it should be necessary to have a plugin system ( through dynlink or topfind, don't know yet ) to enable them to develop their own set of rules ( if they want to compile specific things ).
What i have read in you omakefile is a kind of full rewrite of make ( ie you have construct of function, dependency etc ). I precisely don't want to develop my own langage for this purpose, i want to have it written in ocaml.
Just to give you an example, all the student i know have problem using makefile because they don't want to spend two hours understanding this big script... So they simply don't use it... How many times i have seen one-file-project without makefile, or people using "ocamlc X.ml && ocamlc Y.ml && ocamlc Z.ml..."
I want ( just as i have posted before ) :
let my_prog = { name = "my_prog";...;toplevels = [ "X.ml" ] } in add_target my_prog
and that's all. And i want to be able to do it on linux or win without being needed to do if Win32 then ... else ... ( every time you write if ... else ..., it is a possible infinite source of error ).
I will have a deeper look to your omakefile ( understanding how it is working, if i can learn from the rules to target process ... ).
thanks for having helped me to find more project similar to mine.
Kind regard Sylvain LE GALL
ps : i cannot find your project omakefile on humps pps : if you have time you could take a look at cameleon CVS, branch findlib : http://savannah.nongnu.org/projects/cameleon, there is a bunc of ten lines makefile which are sufficient to define what to compile for each directory... That is the mininum sums of information i want user to give to have a fully working makefile system
> Well i think it is very powerfull and very interesting... But ( there is > always a but ), i am looking for something between your very complete > suite and ocamake which is light and permits to do fast job for ocaml > stuff.
> I know, i will run into problem if not targeting all people... But, i > cannot choose all options. I want something enough powerfull to build > little to medium ocaml project -- with some C binding. I don't want to > rebuild make. The ideal project ( in size ) will be cameleon ( fully > written in ocaml ) or mldonkey ( mostly ocaml with some C ). I don't > really want to be able to compile C, python, Ada...
> I want to use some kind of ocaml script ( let say makefile.ml which will > contain the instruction to build, explains the dependency etc ) to > enable user to be fully consistent with their project ( they learn ocaml > and not makefile syntax ). I think it should be necessary to have a > plugin system ( through dynlink or topfind, don't know yet ) to enable them > to develop their own set of rules ( if they want to compile specific > things ).
I definitly thinks that such a thing could use OCamake. As I told before, adding C bindings compilation might be easy but require some fixes. For other operations (file rename, copy, auto install, etc... ) we can provide them in another module. I agree to work on that with you if you want (french language will help ^^).
[...]
> Just to give you an example, all the student i know have problem using > makefile because they don't want to spend two hours understanding this > big script... So they simply don't use it... How many times i have seen > one-file-project without makefile, or people using "ocamlc X.ml && > ocamlc Y.ml && ocamlc Z.ml..."
That's precisely why I wrote OCamake...
> I want ( just as i have posted before ) :
> let my_prog = { name = "my_prog";...;toplevels = [ "X.ml" ] } > in > add_target my_prog
> and that's all. And i want to be able to do it on linux or win without > being needed to do if Win32 then ... else ... ( every time you write if > ... else ..., it is a possible infinite source of error ).
> I looked quickly at it, and tried to use for a project I am currently > working on,
> however my project uses "-pack" in order to pack some branches > (sub-directories) and avoid A_B_.._M module names.
> looking at Omakeroot, it seems to me there is no support for things like > that :-( > Has someone already managed to do it ?
Didn't have time to write more about this earlier today, but it should be very simple. The following macro will probably work (haven't tested it myself)
On 21.11.2003 15:48, sylvain.le-g...@polytechnique.org wrote:
> Ok. But i am looking for something included in it ( think that in your > very large project, you have a library that builds against an external > one, i want that the makefile system detect it and output that it needs > this library... ).
Well, included is a macro language that should (ideally) allow you to define things you want. If needed, you can relatively easily extend the language of built-in functions as well (which means you have to change omake source code, but it gives you access to full OCaml).
> META file comes with findlib. Findlib is an helper to configure ocaml > compilation : > ocamlfind ocamlc -package "fileutils" xxx.ml > will run ocamlc -I /usr/lib/ocaml/fileutils ...
[...]
> I want ( just as i have posted before ) :
> let my_prog = { name = "my_prog";...;toplevels = [ "X.ml" ] } > in > add_target my_prog
Well, does it really have to be written in OCaml?
Note that if one would want to use omake for simple projects, all that [s]he would have to learn is couple of macros (which completely hide the notions of "target", "dependency", etc) and couple of standard variables. E.g, you'd need couple of line for the project:
OCAMLC = ocamlfind ocamlc -package "fileutils" OCamlProgram(my_prog, X Y Z ...)
Note that the standard macros are not in any way built-in (the way make has a big number of built-in rule), they just come from an include file (that can be studied and even modified if a small simple project ends up growing into a large and complicated one).
Note - if in the example above you do not want to rely on external ocamlfind, you could add ocamlfind code to omake, changing the above to
OCAMLINCLUDES += $(ocamlfind fileutils) OCamlProgram(my_prog, X Y Z ...)
> This leads to the first novel idea. Fixpoints. > Interscript is based on that idea. > A build system does NOT have targets. > A build systems has processes and files. > Lets call the processes ARROWS and the files OBJECTS. > Oh. That's a category. We allow of course, > products of files (multiple outputs and inputs) > and sums of files (choose one of several). > [And of course we'd better make it cartesian > closed and allow processes to be files .. > called scripts .. :]
this is a fascinating proposal. i have two immediate questions:
* as someone else pointed out, relying on convergence towards fixpoints may be too strong. some build processes may never converge, rather they evenually stabilise in some "open ball", so you might need some (user supplied) notion of "close enough". how do you do that?
* according to [1], a cartesian closed category with fixpoints and finite sums is equivalent to the category with one object and one arrow. how do you deal with this?
martin
[1] Hagen Huwig and Axel Poigne, A note on inconsistencies caused by fixpoints in a cartesian dosed category, Theoretical Computer Science 73 (1990), p. 101-112.
On Sat, 2003-11-22 at 06:04, sylvain.le-g...@polytechnique.org wrote: > I don't want to reproduce make bugs... I just want to do something > simple where you can type :
> let my_prog = { > name : "my_prog"; > compile_target : [Opt;Byte]; > toplevel_files : [ "my_prog.ml" ; > "something_ocamldep_dont_recognize_as_toplevel.ml" ]; > package : "all_my_life" ; > target_tag : Binary; ( or Documentation or Custom of string ) > }
> let _ = > add_target my_prog
> Ie, it is not makefile syntax.
My guess is that the 'object oriented design paradigm' has something to say here -- do it bottom up. The first step is to define things like
compare_time_stamp(f1, f2)
a module for 'dependency graph', and other tools that may be useful.
Then just write plain Ocaml code using these tools.
This may be a bit long winded, so check out camlp4 to sweeten it up.
The advantage of this approach is that a make script is an arbitrary caml script.
Which means: it can do anything easily (since caml is so expressive), it is also type checked (hey, why shouldn't build scripts be type checked?)
etc etc etc ...
Finally after all that if you still think a language translator is needed to express the build conditions above and beyond caml with camlp4 ... then one can be written, plugged into the front, invoked by the caml build script, compiled and executed .. all without requiring ME or anyone else to use your language (you can just embed the translator in your package).
This is basically what interscript does only its hooks Python and it's aimed at packaging software components (meaning source codes and documentation) in a more general fashion than merely building them would require. It actually has a language translator, but it's a pretty brain dead one that basically allows code, doco, and executable script to be mixed together in a single source file.
On Sat, 2003-11-22 at 04:53, Eric Dahlman wrote: > skaller wrote:
> > But it is much worse. A target can > > depend on itself. Interscript assumes that. > > An example is a Latex build, which depends > > on auxilliary files generated by the build > > [Ocamldoc output can take 4 passes to fixate > > for example].
> > This leads to the first novel idea. Fixpoints. > > Interscript is based on that idea.
> Just to be pedantic ;-) A Tex or Latex build is not guaranteed to > converge so you may not have a fixed point in the computation. They can > oscillate and it may be necessary to slightly alter the source document > to get things to settle down.
If I may also be pedantic: this is not a matter of pedantry :-)
The idea of fixpoints is still novel and useful here. As you comment, oscillations are possible. Divergence is also possible. Interscript has a command line like
iscr --passes=4 other options ...
which limits the number of passes. The default is one pass, but it has a persistence mechanism (Python marshal), so that executing the command 4 times is roughly equivalent to a single invocation with --passes=4, except that with the --passes=4 option 1 to 4 passes are executed.
Interscript is also Make friendly -- if it writes the same as a files contents the timestamps are not changed. [Which is how it detects convergence :-]
It *also* has dependency checking which can detect that a pass would be the same as the last pass and so it is possible that 0 passes are executed.
The design is not particularly efficient, however it handles things like: you can read a file that doesn't exist, and later write it. No problem. The error on the first pass is ignored. The file is there on the second pass .. although it might not fix.
BTW: there is a fun caveat. The one thing that you must be careful NOT to ever do in Interscript is put the code generation time directly into the generated code -- that guarrantees divergence :-)
On Sun, 2003-11-23 at 01:32, Martin Berger wrote: > > Make systems are all conceptually wrong. > * as someone else pointed out, relying on convergence towards > fixpoints may be too strong. some build processes may > never converge, rather they evenually stabilise in some > "open ball", so you might need some (user supplied) notion > of "close enough". how do you do that?
In interscript I have an iteration limit. In a GUI system, one pass per mouse click I guess.
> * according to [1], a cartesian closed category with fixpoints > and finite sums is equivalent to the category with one object > and one arrow. how do you deal with this?
> martin
> [1] Hagen Huwig and Axel Poigne, A note on inconsistencies caused > by fixpoints in a cartesian dosed category, Theoretical Computer > Science 73 (1990), p. 101-112.
Ouch. First, the concept above is to use categories as an inspirational model, but we do have to layer the abstraction on real storage/execution systems, so that theoretical constraint is unlikely to the most difficult problem :-)
Second .. well, Ocaml uses this model 'as inspiration' as well, and it's authors know a good deal more theory than me so they're more likely to be able to answer :-)
Yeah, both answers are a cop-out (meaning I don't know :-)