combining camlp4 and camlp5 in -pp string for ocamlopt? - ocaml

I want to combine BOLT, SEXP and ocamlViz for a large project. The problem is, that SEXP and BOLT are using CamlP4 and ocamlviz is using camlp5. But how could I combine the calls to one chain for the -pp argument of ocamlc/ocamlopt?
Here is my call for actual project without ocamlviz:
ocamlopt.opt -c -I +dynlink -I +bolt -I +threads -I +lablgtk2 -I +extlib -I +pcre -I +netsys -I +netstring -I +json-wheel -I +num -I +nums -I +sexplib -I +zip -I +xml-light -I +xmlrpc-light -I +equeue -I +netclient -g -annot -p -thread -pp 'camlp4o /usr/lib/ocaml/bolt/bolt_pp.cmo -logger '\''foo.native'\'' -level DEBUG -- -I /usr/lib/ocaml/sexplib -I /usr/lib/ocaml/type-conv pa_type_conv.cmo pa_sexp_conv.cmo' -o foo.cmx foo.ml

It is impossible to preprocess source file by two different preprocessors simultaneously for obvious reasons, and using one after another is also impossible because the first one will not recognize the syntax intended for the second one. The solution is either to use different syntaxes in different source files or port ocamlviz to camlp4.

If you pass -printer OCaml to Camlp4, it will output the pre-processed O'Caml file in source format. You can then parse this file again with Camlp5 in another step.

Related

how to chose between two implementation code in OCaml

I have uploaded the very small exemple project on a github repository
I have a school project. The specifications say that we can enable or disable a component.
I came from the c world in which we can compile c to object and chose the object to link. I try this in OCaml.
I have two source file with the same function but their effect is different.
I have two folders called "on" with implementation and "off" folder with an empty body
For the test, I have a simple a.ml and a.mli file that only print hello world and b.mli b.ml that call the module a. (so I have on/a.ml and off/a.ml)
I compile the on version and the off with this command:
ocamlc -c -I on on/a.mli on/a.ml -o on/a.cmo
then I try to link the C-way
ocamlc on/a.cmo b.ml -o on_b.exe
but I get the error
File "b.ml", line 1, characters 9-15:
Error: Unbound module A
I have then read I should specify the folder to search in with -I.
ocamlc -I on -I off on/a.cmo b.ml -o on_b.exe
I was happy because of that work for the on version
but it will not work for the off version
ocamlc -I on -I off off/a.cmo b.ml -o off_b.exe
I get the error
Error: Files b.cmo and off/a.cmo
make inconsistent assumptions over interface A
I have inspected with ocamlobjinfo it seems to build B its searches for the first module called A
In this example, I have only A and B but in future, I will build with some version on and some off... but don't do it manually
A solution found but no really efficient is to clean all .cmo and .cmi files ...
thanks for your reading and your time
EDIT:
I have also test with -open but it seems to work only for standards modules.
As you can see, compiling your .mli files produces a .cmi file. This is the file that you indicate is there by using the -I dir option.
So, if I understand you correctly, you have a a.mli in both your on and your off directory.
Now, when you refer to the module A in your code, the compiler looks for it in the current directory, then in the linked directories in the order they are given. When you compile "on", the right .cmi is found (because -I on comes before -I off in your command line). In the case of "off", the "on" cmi is found, and the compiler sees that it doesn't correspond to the right cmo.
Your two compiling lines should be:
ocamlc -I on on/a.cmo b.ml -o on_b.exe
ocamlc -I off off/a.cmo b.ml -o off_b.exe

Installing Old Active Networking Language PLAN

Can someone please help me interpret this? I am trying to install PLAN (a Packet Language for Active Networks). From my terminal on Mac OS X 10.8.4:
hntvlan569:~ Scott_Andrew_Collins$ cd OCamlPLAN
hntvlan569:OCamlPLAN Scott_Andrew_Collins$ cd plan-3.22/
hntvlan569:plan-3.22 Scott_Andrew_Collins$ make
ocamlc.opt -pp "camlp4o pa_ifdef.cmo -DPLAN_UNSAFE -DPLANPORT_TCP -DC_CRYPTO" -w s
-thread -I basis -I interpreter -I planet -I port -I util -I RIP -I resident -I
arp -I csum -I frag -I net -I reliable -I dns -I exp -I flow -I security -I
crypto -I builder -I snap -I apps -I common -c common/critical.ml -o
common/critical.cmo Camlp4: Uncaught exception: DynLoader.Error ("pa_ifdef.cmo",
"file not found in path")
Error while running external preprocessor
Command line: camlp4o pa_ifdef.cmo -DPLAN_UNSAFE -DPLANPORT_TCP -DC_CRYPTO
'common/critical.ml' >
/var/folders/pm/m53jrwbd10x0q701d7sw2zrw0000gp/T/ocamlpp9101d0
make: *** [common/critical.cmo] Error 2
You don't say the version of OCaml you're using.
The missing file pa_ifdef.cmo is (perhaps obviously) a preprocessing plugin for camlp4. Looking through the OCaml releases on my system, I see that it was present (maybe in an unsupported form) under OCaml 3.12 but is not there for OCaml 4 (unless I missed it somehow). I suspect support for this plugin has been dropped.
I've used this plugin myself; its purpose is roughly the same as cpp, the C preprocessor. I.e., it does conditional compilation based on tests of flags supplied at compile time.
In recent years I've been lucky enough to do without conditional compilation, so I don't know the latest status of this facility. But it wouldn't surprise me at all if there were a similar plugin that works with the most recent OCaml compiler. So, one solution would be to look into the recent camlp4 and find the replacement.
If the compile-time conditions aren't used widely in your sources you could also go through and remove them.
Another choice would be to compile with an older version of OCaml.

ocaml batteries compiling : Unbound module Toploop

**Build mode: shared
ocamlbuild -no-links syntax.otarget byte.otarget src/batteries_help.cmo META shared.otarget
Finished, 0 targets (0 cached) in 00:00:00.
+ ocamlfind ocamlc -c -g -annot -warn-error A -package camomile,num,str -package camlp4.lib -pp camlp4of -pp camlp4of -I libs/estring -I benchsuite -I src -I testsuite -I build -I qtest -I libs -I src/syntax/pa_comprehension -I src/syntax/pa_strings -o libs/estring/pa_estring_top.cmo
libs/estring/pa_estring_top.ml
File "libs/estring/pa_estring_top.ml", line 18, characters 15-44:
Error: Unbound module Toploop
Command exited with code 2.**
Compilation unsuccessful after building 6 targets (5 cached) in 00:00:00.**
I have found toploop.cmi in path:
cd OCaml/lib/ocaml/compiler-libs/
ls topl*
toploop.cmi
and as you see,
export PATH=/home/xxx/OCaml/lib/ocaml/compiler-libs/:$PATH
I have made /home/xxx/... as my system path. But it still did not work. What I should do to include the module toploop?
You appear to be compiling Batteries (which version?) with OCaml 4.00, which introduced the new compiler-libs directory (but some distributions had one before so that may be off). toploop used to be at the root of the OCaml stdlib's directory, but you should now add a -I +compiler-libs option somewhere, or use the corresponding ocamlfind packaging (-package compiler-libs.toplevel).

What are the GCC default include directories?

When I compile a very simple source file with gcc I don't have to specify the path to standard include files such as stdio or stdlib.
How does GCC know how to find these files?
Does it have the /usr/include path hardwired inside, or it will get the paths from other OS components?
In order to figure out the default paths used by gcc/g++, as well as their priorities, you need to examine the output of the following commands:
For C:
gcc -xc -E -v -
For C++:
gcc -xc++ -E -v -
The credit goes to Qt Creator team.
There is a command with a shorter output, which allows to automatically cut the include pathes from lines, starting with a single space:
$ echo | gcc -Wp,-v -x c++ - -fsyntax-only
ignoring nonexistent directory "/usr/lib/gcc/x86_64-redhat-linux/4.8.2/include-fixed"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-redhat-linux/4.8.2/../../../../x86_64-redhat-linux/include"
#include "..." search starts here:
#include <...> search starts here:
/usr/lib/gcc/x86_64-redhat-linux/4.8.2/../../../../include/c++/4.8.2
/usr/lib/gcc/x86_64-redhat-linux/4.8.2/../../../../include/c++/4.8.2/x86_64-redhat-linux
/usr/lib/gcc/x86_64-redhat-linux/4.8.2/../../../../include/c++/4.8.2/backward
/usr/lib/gcc/x86_64-redhat-linux/4.8.2/include
/usr/local/include
/usr/include
End of search list.
The credit goes to the libc++ front-page.
To summarise the other answers:
For C++:
c++ -xc++ /dev/null -E -Wp,-v 2>&1 | sed -n 's,^ ,,p'
For C:
cc -xc /dev/null -E -Wp,-v 2>&1 | sed -n 's,^ ,,p'
Though I agree with Ihor Kaharlichenko’s answer for considering C++ and with abyss.7’s answer for the compactness of its output, they are still incomplete for the multi-arch versions of gcc because input processing depends on the command line parameters and macros.
Example:
echo | /opt/gcc-arm-none-eabi-9-2019-q4-major/bin/arm-none-eabi-g++ -specs=nano.specs -mcpu=cortex-m4 -march=armv7e-m -mthumb -mfloat-abi=soft -x c++ -E -Wp,-v\
- -fsyntax-only yields
⋮
/opt/gcc-arm-none-eabi-9-2019-q4-major/bin/../arm-none-eabi/include/newlib-nano
/opt/gcc-arm-none-eabi-9-2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/include/c++/9.2.1
/opt/gcc-arm-none-eabi-9-2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/include/c++/9.2.1/arm-none-eabi/thumb/v7e-m/nofp
/opt/gcc-arm-none-eabi-9-2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/include/c++/9.2.1/backward
/opt/gcc-arm-none-eabi-9-2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/include
/opt/gcc-arm-none-eabi-9-2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/include-fixed
/opt/gcc-arm-none-eabi-9-2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/include
⋮
whereas echo | /opt/gcc-arm-none-eabi-9-2019-q4-major/bin/arm-none-eabi-g++ -x c++ -E -Wp,-v - -fsyntax-only yields
⋮
/opt/gcc-arm-none-eabi-9-2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/include/c++/9.2.1
/opt/gcc-arm-none-eabi-9-2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/include/c++/9.2.1/arm-none-eabi
/opt/gcc-arm-none-eabi-9-2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/include/c++/9.2.1/backward
/opt/gcc-arm-none-eabi-9-2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/include
/opt/gcc-arm-none-eabi-9-2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/include-fixed
/opt/gcc-arm-none-eabi-9-2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/include
⋮
The former invocation utilizes newlib (see lines 1 and 3 of the output), the latter goes with the standard includes. The common files at the end of the list are an example for the usage of include_next.
Bottom line: Always consider all macros and compiler options when printing the include directories.
Just run the following to list the default search paths:
$(gcc -print-prog-name=cc1) -v

xgettext - extract translatable strings and update .pot

I have inherited a sample.pot file. Now, I have added new messages in a1.c and a2.cpp. Is it possible for me to use xgettext and output the contents to same sample.pot instead of creating a new one? Eg:-
xgettext -d sample -s -o sample.pot a1.c
xgettext -d sample -s -o sample.pot a2.cpp
Is this preferred way to go in order to update the template such that old messages are also preserved? The other question is how do we distinguish translatable strings from normal strings in source code. I assume xgettext will pull all strings from mentioned source code file.
It would be great if anybody can share the correct approach..Thanks
Does the -j, --join-existing option ("join messages with existing file") not do what you need?
Note that you can specify more than one input file on the command line.
xgettext -d sample -s -j -o sample.pot a1.c a2.cpp
The simplest way to achieve this is:
xgettext -o sample.pot -s a1.c a2.cpp sample.pot
You don't need -j, --join-existing because xgettext accepts .po and .pot files as regular input files.
The option -j, --join-existing is rarely useful. In conjunction with -D, --directory it has the effect that the output file sample.pot used as an input file is not searched in the list of directories. If you use -l c, --language=c you need -j, --join-existing because sample.pot would otherwise be parsed as a C/C++ source file.
Besides, -o sample.pot, --output=sample.pot has exactly the same effect as -d sample, --default-domain=sample. You can safely omit one of them.