[ocaml-platform] An alternative proposal for namespaces

Alain Frisch alain.frisch at lexifi.com
Thu Mar 21 06:42:11 GMT 2013


On 3/20/2013 10:07 PM, Leo White wrote:
> This is the strategy I have referred to as "regular ocamldep with
> generated search path files", it works just as well with simple
> namespaces. The only difference is that the build system generates the
> search path file to give to ocamldep, rather than making the user write
> it by hand.

So the "good" mode for using ocamldep would be to have the build system 
generate a big search path file for each call to ocamldep?

   - How does the build system generate this search path file?  I guess 
it has to know about the "simple namespaces" convention.  Does it?  And 
does it know about the "-name" arguments scattered around in many 
subdirectories.  Concretely, I don't see how this would work under 
omake, for instance.

   - How this would work for non-namespaced modules?  Can you represent 
them with searh path files as in your proposal.  I thought that search 
path files only defined namespaced names.

   - If you assume that the build system can generate a search path file 
to avoid calling ocamldep (and thus the compiler as well) with any -I 
directory, what's the point of supporting -I directories any more in the 
compiler and tools?

> As a side note, I think that "ocamldep -modules" should continue to be a
> purely syntactic version that ignores the search path. It is regular
> ocamldep that should be used for this purpose.

I propose that "ocamldep -modules" ignores the search path directories, 
but knows about the definition of namespaces.  Otherwise, you need to 
invent a new convention to report possible namespaces together with each 
module dependency.

>>> I'm not particularly worried about hypothetical build systems. If you
>>> want to implement such a build system then you should really add hooks
>>> into the OCaml compiler. This argument also assumes that catching
>>> "Sys.file_exists" is fine but catching "Sys.readdir" is impossible.
>>
>> No, this argument does not assume that.  But catching Sys.readdir is useless, since you don't know which files the
>> compiler is interested in. The tool would have to assume that the dependency is on the entire directory, which is of
>> course way too weak.
>
> The tool would only have to know what files it could produce, but it
> should already know that to answer Sys.file_exists queries.

That's not the way it works, Sys.file_exists returns not only files that 
the build system can produce but also files which are already here.

The build system I was referring to worked like that:

  - The project is specified by a list of build commands, each of which 
annotated with a list of target files (assumed to be created by the 
command).

  - The build is triggered by asking to build one target.

  - To build one target X, the system picks a command which lists X as a 
target.

  - If the exact same command has already been run previously (this 
information is kept in a persistent cache), the system checks that pre- 
and post-conditions attached to that run are still valid in the current 
state of the file system.  If yes, the command does not need to be run 
again.

  - The recorded conditions are:  the content (before execution) of any 
file opened for reading and the content (after execution) of any file 
opened for writing; the presence or absence (before execution) of any 
file checked for existence (stat) during the command.

  - When running a command, the tool records those conditions and if the 
command checks a file for existence or open a file for reading, the tool 
tries to build this file as a target, recursively.

The result of system calls are not modified, they are just intercepted 
to allow recording and intermediate compilation of other files.  The 
tool make the assumption that the behavior of the build commands only 
depend on the file existence/absence and content, not on extra meta-data 
(such as mtimes, environment variables, or the system date).

A simpler variant of the system was specified with an ordered set of 
commands to be executed in sequence, with the same cache behavior.  The 
benefit is that you don't need to tell the system about which files can 
be generated by each command.

And as said, even if you don't believe that is a viable approach for a 
robust build system, the same approach can be used to add extra checks 
to existing build system that they don't miss dependencies.

> This assumes that a C compiler won't read a directory (say to cache its
> contents) in order to check for the existence of a file. It is not
> exactly the most robust basis for a build system, which is probably why
> it is only a hypothetical build system.

Well, it worked very well for ocaml + gcc.  I could build non trivial 
code bases (CDuce + all its library dependencies), with extremely 
precise dynamic dependency analysis and without having to use ocamldep.

> This kind of behaviour already exists in OCaml. Consider this piece of code:
>
>      type t = Bar.t (* Bar only contains type definitions *)
>
> If you rename bar.mli to baz.mli but don't remove bar.cmi then it will
> continue to compile until you run "make clean".

Yes, and I see it as a problem.  I would actually prefer a system where 
one must pass explicitly to the compiler the list of files it can use, 
but this is not possible because of backward compatibility.  Since 
namespaces change the way OCaml interact with the file system anyway and 
we have this nice notion of explicitly listing available units in 
well-defined files (which can be used by other tools), I think it's a 
good opportunity to fix the existing problems (partially).

Moreover, since the relation between the name of compiled units and of 
source files will be less tightly coupled for namespaces files (because 
of "-name" or "-namespace"), the chances for facing difficult to track 
error messages will become higher.

> I really don't think that preventing a very unlikely scenario, which can
> already happen anyway, is a good reason to make namespaces significantly
> less convenient for the average user.

I don't think it will.  The average user who creates a library to be 
used by others will need to pick a good namespace name and list which 
files constitute the library.  At this point, writing an explicit 
.mlpath file does not add any burden (the same source of information can 
be used to define the content of the library).


-- Alain


More information about the Platform mailing list