Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[Caml-list] How to avoid compiling some code (like #ifdef in C)

8 views
Skip to first unread message

David MENTRE

unread,
Sep 10, 2003, 1:20:46 PM9/10/03
to caml...@inria.fr
Hello,

In my OCaml program, I want to make the _compilation_ (and not simply
execution) of some part of the code optional (some internal auto-tests
for example), depending on some configuration option.

In C, I would use an #ifdef for this.

I'm thinking of using the following approach:
--begin--
open Printf

let compile_code = false

let a () = printf "toto\n"

let _ = if compile_code then let t = 1 in a ()
--end--

In above code, if compile_code is true, then the auto-test is executed,
otherwise not. But if compile_code is false, is the code corresponding
to 'let t = 1 in a ()' generated?

I'm using ocamlopt for compiling my code. Judging from generated
assembly file, it seems to me that if compile_code is false, the code
corresponding to the then part is not generated. Can anybody confirm
this?

Does anybody see a better approach to do such a thing?

Thanks in advance,
Yours,
david
--
David Mentré <dme...@linux-france.org>
http://www.linux-france.org/~dmentre/david-mentre-public-key.asc
GnuPG key fingerprint: A7CD 7357 3EC4 1163 745B 7FD3 FB3E AD7C 2A18 BE9=
E

-------------------
To unsubscribe, mail caml-lis...@inria.fr Archives: http://caml.inr=
ia.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr=
/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners

Markus Mottl

unread,
Sep 10, 2003, 1:33:54 PM9/10/03
to David MENTRE, caml...@inria.fr
On Wed, 10 Sep 2003, David MENTRE wrote:
> In my OCaml program, I want to make the _compilation_ (and not simply
> execution) of some part of the code optional (some internal auto-tests
> for example), depending on some configuration option.
>
> In C, I would use an #ifdef for this.

In OCaml you can either also use the C-preprocessor or the preprocessor
camlp4, e.g. (using OCamlMakefile for specifying the preprocessor in
the topmost comment):

---------------------------------------------------------------------------
(*pp camlp4o pa_macro.cmo *)

open Printf

DEFINE Compile_code

let a () = printf "toto\n"

let _ =
IFDEF Compile_code
THEN


let t = 1 in a ()

ELSE
()
END
---------------------------------------------------------------------------

Or as usual with cpp:

---------------------------------------------------------------------------
(*pp cpp *)

open Printf

#define Compile_code

let a () = printf "toto\n"

let _ =
#ifdef Compile_code


let t = 1 in a()

#else
()
#endif
---------------------------------------------------------------------------

Regards,
Markus Mottl

--
Markus Mottl http://www.oefai.at/~markus mar...@oefai.at

-------------------
To unsubscribe, mail caml-lis...@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/

Xavier Leroy

unread,
Sep 11, 2003, 11:32:20 AM9/11/03
to David MENTRE, caml...@inria.fr
> --begin--
> open Printf
>
> let compile_code = false
>
> let a () = printf "toto\n"
>
> let _ = if compile_code then let t = 1 in a ()
> --end--
>
> In above code, if compile_code is true, then the auto-test is executed,
> otherwise not. But if compile_code is false, is the code corresponding
> to 'let t = 1 in a ()' generated?

With ocamlopt, that code is eliminated as part of constant
propagation.

With ocamlc, the code of "let t = 1 in a()" is generated.

> Does anybody see a better approach to do such a thing?

Others mentioned preprocessing with the tool of your choice. Camlp4
can do #ifdef-style conditional compilation, but in a pinch you can
even use cpp as your preprocessor.

Whether this is a "better" approach is open to debate. With a
preprocessor, you can remove not just code for expressions, but also
other kind of code, e.g. code for the toplevel binding "let a() = ...".
So, you get more flexibility, but at the expense of less static
checking. In particular, code that is #ifdef-ed out is not
type-checked, while it is type-checked in your solution above.

- Xavier Leroy

-------------------
To unsubscribe, mail caml-lis...@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/

Richard Jones

unread,
Sep 11, 2003, 12:29:26 PM9/11/03
to caml...@inria.fr
On Thu, Sep 11, 2003 at 05:30:56PM +0200, Xavier Leroy wrote:
> Whether this is a "better" approach is open to debate. With a
> preprocessor, you can remove not just code for expressions, but also
> other kind of code, e.g. code for the toplevel binding "let a() = ...".
> So, you get more flexibility, but at the expense of less static
> checking. In particular, code that is #ifdef-ed out is not
> type-checked, while it is type-checked in your solution above.

However one place where the cpp approach is very useful (and better)
is code such as this:

let simulation_menu = factory#add_submenu "Simulation" in
#ifdef DEBUG
let debug_menu = factory#add_submenu "Debug" in
#endif
let help_menu = factory#add_submenu "Help" in

(*...*)

#ifdef DEBUG
let factory = new GMenu.factory debug_menu ~accel_group in
factory#add_item "Single Step (1 Event)" ~key:GdkKeysyms._T
~callback:single_step_ev_sim;
#endif

I haven't found a satisfactory alternative to the above code which
doesn't cause possible runtime errors. eg. One alternative is:

let debug_menu = if debug then Some (...) else None in

(*...*)

match debug_menu with
None -> ()
| Some menu ->
(* code to populate the menu *)

but this is not just tedious in real life, but also could have bugs
only discovered at runtime.

I'm open to a better way to do this ...

Another important case in our program:

#if LABLGTK_RELEASE
let icon icon_type size =
let icon = GMisc.image () in
icon#set_stock icon_type ~size:size;
icon
#else (* LABLGTK from CVS: *)
let icon icon_type size =
let icon = GMisc.image () in
icon#set_stock icon_type;
icon#set_icon_size size;
icon
#endif

These sorts of API changes are *really* hard to work around without a
preprocessor, unless you have two separate modules and play tricks in
the Makefile.

Again, I'm open to suggestions as to how to do this better.

Rich.

--
Richard Jones. http://www.annexia.org/ http://freshmeat.net/users/rwmj
Merjis Ltd. http://www.merjis.com/ - all your business data are belong to you.
MAKE+ is a sane replacement for GNU autoconf/automake. One script compiles,
RPMs, pkgs etc. Linux, BSD, Solaris. http://www.annexia.org/freeware/makeplus/

David MENTRE

unread,
Sep 12, 2003, 8:18:52 AM9/12/03
to Xavier Leroy, caml...@inria.fr
Hello Xavier,

Xavier Leroy <xavier...@inria.fr> writes:

> With ocamlopt, that code is eliminated as part of constant
> propagation.

Thank you to confirm my guess.

>> Does anybody see a better approach to do such a thing?

> Whether this is a "better" approach is open to debate. With a


> preprocessor, you can remove not just code for expressions, but also

> other kind of code, e.g. code for the toplevel binding "let a() = ...=


".
> So, you get more flexibility, but at the expense of less static
> checking. In particular, code that is #ifdef-ed out is not
> type-checked, while it is type-checked in your solution above.

I'm personally find that static checking is very useful. So, for my own
issue, the approach I proposed is "better". It allows me to be sure that
all automatics tests will always at least compile. And it works on
O'Caml 3.04 available in my old debian 3.0.

But I'll keep in my mind the two other approaches.


Thank you for your answer,


Yours,
david
--
David Mentré <dme...@linux-france.org>
http://www.linux-france.org/~dmentre/david-mentre-public-key.asc
GnuPG key fingerprint: A7CD 7357 3EC4 1163 745B 7FD3 FB3E AD7C 2A18 BE9=
E

-------------------
To unsubscribe, mail caml-lis...@inria.fr Archives: http://caml.inr=
ia.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr=

0 new messages