caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* managing ocaml dependencies
@ 2006-11-16 14:20 Guillaume Rousse
  2006-11-16 16:47 ` [Caml-list] " skaller
  2006-11-16 21:21 ` Ralf Wildenhues
  0 siblings, 2 replies; 6+ messages in thread
From: Guillaume Rousse @ 2006-11-16 14:20 UTC (permalink / raw)
  To: autoconf, caml-list

I'm trying to use autoconf for ocaml project, and I have troubles with
managing dependencies.

They are generated through a specific program, ocamldep, that basically
output makefile rules, so as to be used this way:
.depend:
	$(OCAMLDEP) *.ml *.mli > .depend

include .depend

They are two different strategies here, either generate them on
maintainer host and ship them in the distribution, either generate them
on user's host.

The first seems safe, excepted when you have conditional build options:
if the user has not the same setup as the maintainer host, there might
be inconsistencies. I also saw some comments in autotools description
than this strategy was also considered insecure for other languages.

The second strategy, however, heavily relies on make implementation.
Whereas GNU make happily generate .depend file on the fly with previous
snippet, some other implementations don't, such as Digital Unix's one
(and potentially others).
Make: Cannot open ../.depend.  Stop.

I also discovered than GNU make use current directory to resolve path of
included files, even when the inclusion directive is found in an
included makefile, whereas Digital Unix's one consider the directory
containing the makefile containing the inclusion directive instead.

Given the following setup:
|-- Makefile.rules
`-- a
    `-- Makefile

If the inclusion directive is given in top level Makefile.rules, itself
included in lower level a/Makefile, GNU make resolve the .depend file in
a directory, whereas Digital Unix resolve it in top-level directory.

Finally, it seems the safest strategy would be to use configure to
produce those .depend file, or is there any other possibility ?


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Caml-list] managing ocaml dependencies
  2006-11-16 14:20 managing ocaml dependencies Guillaume Rousse
@ 2006-11-16 16:47 ` skaller
  2006-11-16 19:01   ` Jean-Christophe Filliatre
  2006-11-16 21:43   ` Nicolas Pouillard
  2006-11-16 21:21 ` Ralf Wildenhues
  1 sibling, 2 replies; 6+ messages in thread
From: skaller @ 2006-11-16 16:47 UTC (permalink / raw)
  To: Guillaume Rousse; +Cc: autoconf, caml-list

On Thu, 2006-11-16 at 15:20 +0100, Guillaume Rousse wrote:
> I'm trying to use autoconf for ocaml project, and I have troubles with

> They are two different strategies here, either generate them on
> maintainer host and ship them in the distribution, either generate them
> on user's host.

There is no choice: it has to be done by the developer
because sometimes the dependency is semantic, in particular
when order of initialisation matters.

For example:

(* file 1 *)
let a : int opt = ref None 
;;

(* file 2 *)
let _ = a := Some 99
;;

(* file 3 *)
let _ = 
  match !a with
  | None -> failwith "WRONG INIT ORDER"
  | Some x -> print_endline (string_of_int x)
;;

You must link in the given order. Ocamldep can tell
2 and 3 depend on 1, but not that 3 depends on 2.

> The second strategy, however, heavily relies on make implementation.
> Whereas GNU make happily generate .depend file on the fly with previous
> snippet, some other implementations don't, such as Digital Unix's one
> (and potentially others).
> Make: Cannot open ../.depend.  Stop.

This is easy to fix: generate a new_makefile and then use
a rule something like:

	cat new_makefile_prefix .depend > new_makefile
	make -f new_makefile

Since this is a rule, the order of evaluation is strict.


-- 
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Caml-list] managing ocaml dependencies
  2006-11-16 16:47 ` [Caml-list] " skaller
@ 2006-11-16 19:01   ` Jean-Christophe Filliatre
  2006-11-16 21:43   ` Nicolas Pouillard
  1 sibling, 0 replies; 6+ messages in thread
From: Jean-Christophe Filliatre @ 2006-11-16 19:01 UTC (permalink / raw)
  To: skaller; +Cc: Guillaume Rousse, caml-list, autoconf


skaller writes:
 > On Thu, 2006-11-16 at 15:20 +0100, Guillaume Rousse wrote:
 > 
 > > They are two different strategies here, either generate them on
 > > maintainer host and ship them in the distribution, either generate them
 > > on user's host.
 > 
 > There is no choice: it has to be done by the developer
 > because sometimes the dependency is semantic, in particular
 > when order of initialisation matters.

The link order and the modules dependencies are two different matters.
Typically, the Makefile contains the link order but dependencies can
indeed be generated automatically, even on the fly; with the possible
issues mentioned by Guillaume, though.

Regarding the latter, I use the following typical Makefile for my
projects: http://www.lri.fr/~filliatr/ftp/ocaml/misc/Makefile.in
(together with http://www.lri.fr/~filliatr/ftp/ocaml/misc/configure.in)
and I ship the .depend file within the distributions.
(I don't include Makefiles; I use a single Makefile at the top
directory) But having the dependencies built by the ./configure seems
to be a good solution...

-- 
Jean-Christophe


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: managing ocaml dependencies
  2006-11-16 14:20 managing ocaml dependencies Guillaume Rousse
  2006-11-16 16:47 ` [Caml-list] " skaller
@ 2006-11-16 21:21 ` Ralf Wildenhues
  1 sibling, 0 replies; 6+ messages in thread
From: Ralf Wildenhues @ 2006-11-16 21:21 UTC (permalink / raw)
  To: Guillaume Rousse; +Cc: autoconf, caml-list

Hello Guillaume,

Do you use Automake?  If yes, or if you want to add support for ocaml to
Automake, then probably its list would be more appropriate.  If not, all
of the following has relevance without Automake, it's just colored that
way a bit.

* Guillaume Rousse wrote on Thu, Nov 16, 2006 at 03:20:42PM CET:
> I'm trying to use autoconf for ocaml project, and I have troubles with
> managing dependencies.
> 
> They are generated through a specific program, ocamldep, that basically
> output makefile rules, so as to be used this way:
> .depend:
> 	$(OCAMLDEP) *.ml *.mli > .depend
> 
> include .depend
> 
> They are two different strategies here, either generate them on
> maintainer host and ship them in the distribution, either generate them
> on user's host.

FWIW, Automake's strategy is building them on the user's system.  There
is a chapter in its manual that contains rationale:
http://sources.redhat.com/automake/automake.html#Dependency-Tracking-Evolution

Further, the macro AM_MAKE_INCLUDE in automake/m4/make.m4 detects the
'include' style used by 'make'.  The automake way to handle
bootstrapping is to create (almost empty) per-target files at
config.status execution time (see m4/depout.m4), and update them as a
side effect of compilation (see m4/depend.m4 and lib/depcomp).  The side
effect method is more efficient once you have a compiler that can output
dependency information on the fly (such as GCC for some languages).

> The second strategy, however, heavily relies on make implementation.
> Whereas GNU make happily generate .depend file on the fly with previous
> snippet, some other implementations don't, such as Digital Unix's one
> (and potentially others).
> Make: Cannot open ../.depend.  Stop.

Does that mean it fails if it updates a file that is included, or that
it merely fails the first time when the file does not yet exist?

> I also discovered than GNU make use current directory to resolve path of
> included files, even when the inclusion directive is found in an
> included makefile, whereas Digital Unix's one consider the directory
> containing the makefile containing the inclusion directive instead.
> 
> Given the following setup:
> |-- Makefile.rules
> `-- a
>     `-- Makefile
> 
> If the inclusion directive is given in top level Makefile.rules, itself
> included in lower level a/Makefile, GNU make resolve the .depend file in
> a directory, whereas Digital Unix resolve it in top-level directory.

Ah, thanks, I did not know that.  (Automake does not use recursive
inclusion at 'make' run time; not to be mistaken with the automake
'include' which is resolved at 'automake' run time.)

> Finally, it seems the safest strategy would be to use configure to
> produce those .depend file, or is there any other possibility ?

Yes, that's the idea.  I think adapting Automake for ocaml should be
possible.  If you go and add support for it in Autoconf first, then it
can be made quite seamless, too.  For examples how to do this, you could
peek at how Erlang support was recently added to Autoconf, and UPC to
Automake.

Cheers,
Ralf


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Caml-list] managing ocaml dependencies
  2006-11-16 16:47 ` [Caml-list] " skaller
  2006-11-16 19:01   ` Jean-Christophe Filliatre
@ 2006-11-16 21:43   ` Nicolas Pouillard
  2006-11-17  0:36     ` skaller
  1 sibling, 1 reply; 6+ messages in thread
From: Nicolas Pouillard @ 2006-11-16 21:43 UTC (permalink / raw)
  To: skaller; +Cc: Guillaume Rousse, caml-list, autoconf

On 11/16/06, skaller <skaller@users.sourceforge.net> wrote:
> On Thu, 2006-11-16 at 15:20 +0100, Guillaume Rousse wrote:
> > I'm trying to use autoconf for ocaml project, and I have troubles with
>
> > They are two different strategies here, either generate them on
> > maintainer host and ship them in the distribution, either generate them
> > on user's host.
>
> There is no choice: it has to be done by the developer
> because sometimes the dependency is semantic, in particular
> when order of initialisation matters.

When order of initialization matters, just enforce it.

>
> For example:
>
> (* file 1 *)
> let a : int opt = ref None
> ;;
>
> (* file 2 *)
> let _ = a := Some 99
> ;;
>
> (* file 3 *)

Just add something like:

open File2;; (* because initialization order matters *)

Or if really don't want use open:

module File2 = File2;; (* because initialization order matters *)

Or if really don't want re-export that module (if you don't have a .mli):

let module File2 = File2 in ();; (* because initialization order matters *)

> let _ =
>   match !a with
>   | None -> failwith "WRONG INIT ORDER"
>   | Some x -> print_endline (string_of_int x)
> ;;
>
> You must link in the given order. Ocamldep can tell
> 2 and 3 depend on 1, but not that 3 depends on 2.
>
> > The second strategy, however, heavily relies on make implementation.
> > Whereas GNU make happily generate .depend file on the fly with previous
> > snippet, some other implementations don't, such as Digital Unix's one
> > (and potentially others).
> > Make: Cannot open ../.depend.  Stop.
>
> This is easy to fix: generate a new_makefile and then use
> a rule something like:
>
>         cat new_makefile_prefix .depend > new_makefile
>         make -f new_makefile
>
> Since this is a rule, the order of evaluation is strict.
>

-- 
Nicolas Pouillard


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Caml-list] managing ocaml dependencies
  2006-11-16 21:43   ` Nicolas Pouillard
@ 2006-11-17  0:36     ` skaller
  0 siblings, 0 replies; 6+ messages in thread
From: skaller @ 2006-11-17  0:36 UTC (permalink / raw)
  To: Nicolas Pouillard; +Cc: autoconf, caml-list

On Thu, 2006-11-16 at 22:43 +0100, Nicolas Pouillard wrote:
> On 11/16/06, skaller <skaller@users.sourceforge.net> wrote:

> When order of initialization matters, just enforce it.

> > For example:
> >
> > (* file 1 *)
> > let a : int opt = ref None
> > ;;
> >
> > (* file 2 *)
> > let _ = a := Some 99
> > ;;
> >
> > (* file 3 *)
> 
> Just add something like:
> 
> open File2;; (* because initialization order matters *)

Really there should be a directive such as:

require File2;;

or something, implied by 'open', and *mandatory* so that

List.fold_left

without a 

require/open List;;

was an error. In any case, using make for this kind of
job is a real negative for Ocaml. Felix compiles
dependencies recursively and conditionally. It makes
using it -- and upgrading it -- a breeze, and eliminates
the need for external tool support.

Hmm. It would be interesting to write a driver harness
that did this. The biggest impediment is the lack of
an enforced 'require' directive, and the existence
of Ocamlp4, both of which make it hard to use simple
analysis tools to calculate dependencies.

BTW: in the Felix compiler itself the initialisation
order problem arises with the 'version' record:
whenever any code changes, the time stamp in the
version record is updated. The version record
is first in the link order, so any part of the code
can refer to it .. but the actual time stamp is
last in link order to avoid gratuitous recompilations.
Its module uses the above trick -- the time stamp
is stored into the version record by executable 
initialisation code dynamically before any
functions are called in the mainline. This implies
that no modules refer to the version record dynamically in 
initialisations (except the mainline).

This is nasty because this version record is
Marshalled out into pre-compiled Felix code,
and is actually then used for the dependency
checking in Felix -- if the compiler version
changes the Felix sources need to be recompiled.

So there is a 'exponential' dependency situation, where
getting the order right is critical,
hard to enforce, and hard to detect when there
is an error.

Skallers Law: if a programmer can make a mistake ..
skaller will make it.

-- 
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2006-11-17  0:36 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-11-16 14:20 managing ocaml dependencies Guillaume Rousse
2006-11-16 16:47 ` [Caml-list] " skaller
2006-11-16 19:01   ` Jean-Christophe Filliatre
2006-11-16 21:43   ` Nicolas Pouillard
2006-11-17  0:36     ` skaller
2006-11-16 21:21 ` Ralf Wildenhues

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).