The logic of the ocaml compile process - functional-programming

I wrote a small project in OCaml.
I have two folders:
./myUnionFind. inside there is a file myUnionFind.ml.
./percolation. inside there are two files: myPercolation.ml and percolation_stats.ml.
myUnionFind.ml works as a module.
myPercolation.ml works as a module too, but it uses MyUnionFind module defined in myUnionFind.ml.
percolation_stats.ml uses myPercolation.ml.
together with above all, I also use Batteries.
I want to compile them all to work and get a executable file run.
But how?
I have tried the following:
inside folder ./percolation, I did ocamlfind ocamlc -package batteries -linkpkg ../myUnionFind/myUnionFind.ml myPercolation.ml percolation_stats.ml -o run
It failed, and said File "myPercolation.ml", line 1, characters 0-16:
Error: Unbound module MyUnionFind, but I did include that folder ../myUnionFind, right?
Also, if I just want to compile ./myUnionFind/myUnionFind.ml once, how can I do so that not every time, myUnionFind.ml gets compiled again and again?

Inside myUnionFind, you should compile myUnionfind.ml to a compiled unit:
cd myUnionFind
ocamlc -c myUnionFind.ml
This will generate myUnionFind.cmo, which stores the compiled implementation, and myUnionFind.cmi, which stores the compiled interface. Other modules using MyUnionFind will need to access the cmi at type-checking type.
Inside percolation, you can compile myPercolation.ml to a module by doing
cd percolation
ocamlc -I ../myUnionFind -c myPercolation.ml
Again, you get both a .cmo and a .cmi. Note that the compiler has looked up myUnionFind.cmi automatically in the search path, and found it because of the -I option.
You can then compile percolation_stats (relying on both previous compilation units)
ocamlc -I ../myUnionFind -c percolation_stats.ml
You finally link the three resulting .cmo together to build an executable:
ocamlc ../myUnionFind.cmo myPercolation.cmo percolation_stats.cmo -o run
(If you use batteries, wrap each command with ocamlfind ocamlc -package batteries, but only the linking command with linkpkg).
To make this process simpler:
ocamlbuild is good at finding and compiling all the files of your current project to produce an executable. In the percolation directory, ocamlbuild percolation_stats.byte can produce an executable with all the stuff present
but if you want to use myUnionFind as an external library, the best thing to do would be to install it with findlib, to make it easy to find and specify from percolation; for information on how to create a findlib package (it's very simple), please see this older answer
once myUnionFind is a findlib package, the single command ocamlbuild -use-ocamlfind -pkgs batteries,my-union-find percolation_stats.byte (or .native) should be enough to get an executable

Related

Compile With Static Library Using GNAT

To learn the processes behind compilation of Ada programs (without resorting to using gpr), I've decided to compile one of my projects manually. To compile a program, I run the following command on each .adb file therein (not manually, however):
$ gcc -c src/<file>.adb -o obj/<file>.o
That compiles all the files and puts them in the obj directory.
Or rather, it would. There is a slight problem with this. I have an archive (static library) that I've generated from another project, called libapples.a, containing package Apples. The Apples package is used by the files you see me compiling above.
Since libapples.a doesn't have source files anymore (given its archive format), it's not viable (not even possible) to provide the sources of that library to the command above using -I switches; on the other hand, if I don't have the sources included, the command above comes back to me saying:
<file>.adb:<y>:<x>: file "apples.ads" not found
gnatmake: "src/<file>.adb" compilation error
I've attempted to include the library in the compilation process by using flags -L and l (which I believe is how you'd do it in C; feel free to correct me if I'm wrong). In another attempt I placed the archive right in the source directory.
How does one go about including a library in the compilation process?
apples.ads is somewhat like a header in C and you definitely need it for your file to compile. You should use -I to point gcc to the directory where apples.ads is located in.
Be aware that compiling an Ada source not only yields an object file, but also an Ada Library Information (.ali) file. You'll need that for the next step. You should not use the -o flag because it may lead to your .o and .ali files having different names.
On the other hand, since you only want to produce an object file, you should use -c to tell gcc to only compile. In other languages like C, gcc compiles and links by default; in Ada, the process is more complex.
After compilation, you need to call gnatbind on the .ali file of your main program. This generates a package that will take care of proper initialization of everything. To do that, gnatbind needs the .ali file of the Apples package! You can specify the .ali search directory with -aO.
Finally, gnatlink called on the main .ali file will link everything together. It figures out itself which object files and libraries it needs. It will append the necessary options to the linker, including the reference to libapples.a. It also compiles the package generated by gnatlink.
I don't know exactly what gnatlink will do under the hood; you could probably compile the package generated by gnatbind manually and then call the linker if you can figure out the proper arguments.

How can be C files linked when using E-ACSL plugin?

I am trying to generate an annotated file with Frama-C E-ACSL plugin. I created the following files:
Insert.c: contains all the structures to create a linked list.
AxiomTest.c: includes the main function where the asserts it must fulfil are indicated. All functions and structures are determined in terms of Insert.c file
When compiling/instrumenting a program the manual specifies the following terminal command:
$ e-acsl-gcc.sh -c <files> -O <output>
For a successful compilation Insert.c and AxiomTest.c must be linked but I cannot find any flag for that.
Any help? Or is there any other way to do it right?
e-acsl-gcc.sh does compile and link files with option -c, despite looking like it only compiles (the -c here is unrelated to GCC's -c option, which does only compilation, without linking).
If you want to give extra flags to the linker, man e-acsl-gcc.sh (or e-acsl-gcc.sh -h) will indicate option -l:
-l pass additional options to the linker

Specifying Directories during Fortran Compilation

I am using GNU Fortran 95 on OpenSUSE Leap to compile my source code, and I am trying to figure out how to tell gfortran to change the default directory to search for my modules.
Let me explain my setup. I've written several module files that contain general subroutines I use. I've placed and compiled these files in a folder entitled ModuleRepo. My working scripts are placed in a separate folder. For example, I tried the following command:
gfortran -o script script.f95 -I/pathToFolder/ModuleRepo module1.o module2.o
However, this is not working. It is returning the following error:
gfortran: error: module1.o: No such file or directory.
The *.o files do exist in ModuleRepo, so I'm unsure what's going on. Everything works fine if I copy all my module files to the directory. But, I'd like a way to avoid copying the same files over and over.
gfortran -o script script.f95 -I/pathToFolder/ModuleRepo /pathToFolder/ModuleRepo/module1.o /pathToFolder/ModuleRepo/module2.o

How to load a module inside an OCaml file?

I wish to use module Std inside my OCaml .ml file.
I tried #load "Std", but the compiler complains.
How can I load a module inside OCaml?
You must compile the module you wish to include first, provide the location of the compiled files to compilation commands of modules depending on it, then provide it in the final compilation command line.
Let's consider for instance file foo/moduleA.ml:
let v = 1
and file bar/moduleB.ml:
open ModuleA
let w = v
The commands:
$ cd foo
$ ocamlc -c moduleA.ml
$ cd ..
will produce moduleA.cmo and moduleA.cmi. The former is the bytecode object of the module (like a .o file in for native object files, but containing bytecode data and text), the later is a bytecode compiled header, produced from an automatically generated .mli file. This bytecode header is necessary for the compiler to compile files which depend on ModuleA.
$ cd bar
$ ocamlc -I ../foo -c moduleB.ml
$ cd ..
will succeed in producing moduleB.cmo, which depends on ModuleA, because the previous command has been successful, and because we indicate the compiler where to look for dependancies with the -I command line parameter, followed by the path of the first module.
The last command below will produce a bytecode executable from both modules:
$ ocamlc -I foo -I bar moduleA.cmo moduleB.cmo -o prog.byte
The modules must be provided in that order, to let the compiler know the dependancies first. The -I parameters this time indicate where to find the .cmo files.
In your case, you must therefore use the -I <location of std.cmi> for the compilation proper phase, and -I <location of std.cmo> (or std.cma, if it is a library) for the second phase (the link phase). If you can combine both phases in one command (ie. ocamlc -I foo foo/moduleA.ml bar/moduleB.ml -o prog.byte), and if both cmo and cmi files are in the same directory, only one parameter will suffice.

How to let autotools compile a QT module with qmake

In my project I have made configure.ac and Makefile.am files correctly so my components compile and dynamically link to the appropriate libraries. One of these components links to a library that uses QT, so the appropriate Makefile must be generated out of the .pro file prior compilation on the target system.
For this I think that I need to find a way to tell my make scripts, through Makefile.am perhaps, that this library must be compiled on its own by first running qmake and the generated Makefile in that directory.
Is this even possible? If so, how do I do it?
Researching on my own I have found an apparently abandoned project called “AutoTroll” which is supposed to automatically alter files of autotools in order to add compatibility with Qt4. I have tried to make it work with no luck. It lacks a proper documentation also.
Without this tool, compiling Qt4 modules with autotools requires a lot of hacking and interventions, making it really hard and even more for a cross-platform application.
I have switched to CMake. CMake’s setup is far easier than autotools’ and it supports Qt4 modules out of the box.
We do this, its not that difficult. In configure.ac:
QT_QMAKE
[
echo $QMAKE -o Makefile.myapp $(realpath $(dirname $0))/myapp.pro
$QMAKE -o Makefile.myapp $(realpath $(dirname $0))/myapp.pro
]
Then (Assuming your macros are located in the standard m4 directory), make a file called qt_qmake.m4 there.
AC_DEFUN([OTT_QT_QMAKE],[
if test -z "$QMAKE"; then
QMAKE=$(which qmake)
$QMAKE -v > /dev/null 2>&1
if test $? -ne 0; then
AC_MSG_ERROR([qmake executable not found!])
fi
fi
AC_SUBST(QMAKE)
])
Then in Makefile.am:
ACLOCAL_AMFLAGS=-Im4
all-am:
make -f Makefile.myapp all
install-am:
make -f Makefile.myapp install
qmake_all:
make -f Makefile.myapp qmake_all
clean-am:
make -f Makefile.myapp clean
That should align with the targets that QTCreator uses, and allows you to "bootstrap" qmake using autotools to make a config.h for instance, or global qmake include file to make shadow builds easier. Theres a lot I'm leaving out if you want to have version checking,etc... but it should get you started. If you built qt yourself, or have it not in your path, ie redhat (/usr/lib{64}/qt5/bin/qmake), you can just use the QMAKE variable to point to it. QT is smart enough with that to take it from there usually. I know its not the most elegant solution, but its worked for us cross-linux for almost a decade.

Resources