OCaml Forge

Detail: [#1377] conditional dependencies and oasis

Bugs: Browse | Download .csv | Monitor

[#1377] conditional dependencies and oasis

2014-03-13 17:49
Submitted by:
Gabriel Radanne (drup)
Assigned to:
Sylvain Le Gall (gildor-admin)
Due in version:
Operating System:
conditional dependencies and oasis

Detailed description
I'm trying to achieve this setup with _oasis, without success for now :

I have some various data structure implementation, all in a file datastruct.ml. I would like to have conditional compilation over the dependencies of this various data structures.
Let's say I have the data structures ds_foo and ds_bar. I can use cppo [1] to add
#ifdef FOO
... code for ds_foo

and then I can invoke cppo with the option -D FOO if the oasis flag "FOO" is set. something like :
if flag(FOO)
PreBuildCommand: cppo -D FOO

I would need to list all the combination, which may be growing fast, so I hope there is a nicer solution.

The issue I have currently is that, I need to also have :
if flag(FOO)
BuildDepends+: foo

And oasis refuses that.

Do you have an idea how to implement this idea in practice ?

[1] : https://github.com/mjambon/cppo


Date: 2016-08-22 19:31
Sender: Sylvain Le Gall

Related (problem with command line orders):

Date: 2016-04-12 21:43
Sender: Sylvain Le Gall


Date: 2014-04-05 20:22
Sender: Gabriel Radanne

Since the forge's editor mess up formating and is terrible to post code, here is the file : https://github.com/Drup/LILiS/blob/cppo/_oasis#L99
Date: 2014-04-05 20:16
Sender: Gabriel Radanne

So, I solved the library side of the issue by reorganizing my library from Foo.A, Foo.B, Foo.C into FooA FooB and FooC. I'm quite happy with the result.

However, I have an issue to build two version of my executable. Here is an extract from my _oasis :

Executable glilis
Build$: flag(cairo) && flag(executable) && flag(sequence) && flag(tyxml)
BuildDepends: cmdliner, cairo2.lablgtk2, glilis, glilis.cairo, glilis.tyxml, lilis.sequence
ByteOpt: -pp 'cppo -D Tyxml Tyxml'
NativeOpt: -pp 'cppo -D Tyxml Tyxml'
Install: false
Path: glilis
MainIs: glilis_ex.ml
CompiledObject: best

Executable glilis_no_tyxml
Build$: flag(cairo) && flag(executable) && flag(sequence) && ! flag(tyxml)
BuildDepends: cmdliner, cairo2.lablgtk2, glilis, glilis.cairo, lilis.sequence
ByteOpt: -pp 'cppo -U Tyxml'
NativeOpt: -pp 'cppo -U Tyxml'
Install: false
Path: glilis
MainIs: glilis_ex.ml
CompiledObject: best

And here is the command line invoked by oasis to build the executable :

/home/gabriel/.opam/4.01.0/bin/ocamlfind ocamlopt -g -pp 'cppo -D Tyxml Tyxml' -pp 'cppo -U Tyxml' -linkpkg -package batteries -package cairo2 -package cairo2.lablgtk2 -package cmdliner -package sequence -package tyxml glilis/glilis.cmxa glilis/cairo.cmxa glilis/tyxml.cmxa mini_calc/minicalc.cmxa lilis/lilis.cmxa lilis/streams/sequence.cmxa glilis/glilis_ex.cmx -o glilis/glilis_ex.native

as you can see, *both* Opt fields are used, which is obviously wrong.
Date: 2014-03-14 10:23
Sender: Gabriel Radanne

Ok, thanks !

In my case, I'm not sure this approach is doable, as I have 3 or 4 optional dependencies like that, and I would like to add some more.

As a temporary workaround for the executable, maybe I can use the same technique than the library : multiple declarations. (I would only need 2 for the executable, so it's doable).
Date: 2014-03-14 07:34
Sender: Sylvain Le Gall

I think you understood the big idea of my proposal ;-) because this is "summarizing" module ... dependent of everything which in the proposal case will be "simple_with_foo" (and bar in fact).

To answer you:
- nice module MyLib.DataStruct.Foo and MyLib.DataStruct.Bar: you are right there is no clean way of providing that. What I have seen so far is to generate identical .ml files in different directories:
- src/mylib_with_foo/DataStruct.ml with Foo module uncommented
- src/mylib_with_bar/DataStruct.ml with Bar module uncommented
- src/mylib_with_foo_bar/DataStruct.ml with all modules uncommented
In this case, you have to install 3 different findlib package (toplevel package, not sub packages) to avoid DataStruct name clash.
But this is not really related to OASIS, this problem may have been solved if OCaml supports namespace...

- Conditional BuildDepends for executable: OK that is a good use case that make sense. It requires a fair amount of work, because I will need to manage conditional tagging for OCamlbuild -- which is not built into OCamlbuild...
Date: 2014-03-14 03:53
Sender: Gabriel Radanne

Ok, I get the point about a library which content is not always the same, depending of configure option. It's indeed not a good idea at all. Two issues remains :
- I can't provide anymore a nice module hierarchy MyLib.DataStruct.Foo and MyLib.DataStruct.Bar if I have to put Foo and Bar in different findlib packages, except by making the "summarizing" module MyLib.DataStruct dependent of everything. It's not nice.
- I'm also building an executable with some options like -use-foo and -use-bar. Of course the option -use-foo is available only if foo was available when building. Afaik, I need conditional dependencies for that.

I don't understand your proposal, so I'm not sure how it would help.
Date: 2014-03-13 19:46
Sender: Sylvain Le Gall

What do you mean by export ?

findlib export ?

If build = false, we don't install the library and the library will not show in findlib at all.

From a full workflow point of view (and this is the reason of this build dependency restriction), this is pretty hard for any other libraries/programs to say "i want to to depend on library ds that contains ds_foo". This is the kind of situation where you end up with functions like in autoconf where you have to compile some piece of code to check presence/absence of ds_foo... I want to avoid this as much as possible.

My proposal will end up by giving you a way to say in the other library "I want to depend on ds" or "I want to depend on ds.foo" (both ds and ds.foo are valid findlib package). And if someone has not built ds.foo because of a flag, it will be easy to say : not possible ds.foo is missing...
Date: 2014-03-13 18:22
Sender: Gabriel Radanne

What if I want to export only one library containing (or not) ds_foo ? In your example, you would export two libraries.

It also means that if I have foo bar and baz independent, I need to write a library for every combination .... I don't like exponential number of library definition.

I would still need cppo anyway since I build an executable which options depends on the presence of those data structures.
Date: 2014-03-13 18:16
Sender: Sylvain Le Gall

Most of the time I achieve conditional dependencies by having two different library and
Build$: flag(foo)

Library simple
BuildDepends: X

Library simple_with_foo
Build$: flag(foo)
BuildDepends: simple, foo

But this simply assume that you'll also split the code for ds_foo and ds_bar in 2 different files and actually that you won't need cppo at all....
Date: 2014-03-13 18:09
Sender: Gabriel Radanne

Actually, I can do something slightly nicer for the combination problem :

ByteOpt+: -pp cppo
NativeOpt+: -pp cppo
if flag(FOO)
ByteOpt+: -ppopt "-D FOO"

But the whole issue stays.

Attached Files:


Field Old Value Date By
assigned_tonone2014-03-13 18:16gildor-admin