I have an OCaml program(with a main method - it generates an executable) and I want to use it as a library.
I was compiling my program like this: ocamlc -I someDir -g -unsafe lotsOfCmoFiles -o outputFile and the program works fine.
Now I'm removing the line that makes it an executable(something like let _ = ...) and adding -a parameter to compile command: ocamlc -a -I someDir -g -unsafe lotsOfCmoFiles -o outputFile.cma
But somehow I can't load generated .cma file with ocamltop and ocamlbrowser shows an empty list. When I try to load from ocamltop:
# #load "outputFile.cma";;
Error: Reference to undefined global `Xyz'
And I'm 100% sure that xyz.cmo is included in lotsOfCmoFiles.
Am I giving some parameter wrong while compiling? Or else, what should I do to load my program in ocamltop ? (I'll use this library in another program, I'm giving ocamltop outputs as an example)
Any helps will be appreciated.
EDIT: So I can finally managed to compile and load it thanks to #cago, now I can load my library, and when I don't remove the main let _ = ... line it's automatically run when I load the .cma.
But I still can't open any modules. Strangely, this doesn't raise an exception
open Main
but then when I call a function from module Main:
# someFun;;
Error: Reference to undefined global `Main'
and ocamlbrowse still shows an empty list. now why is that?
EDIT2: I realized open Main doesn't fail because I have a Main module in the same folder(even though I didn't explicitly load it). If I move my .cma file somewhere else and load it, it works(ie. main function runs automatically), but now I can't open any modules even though ocamlobjinfo shows the modules.
EDIT3: -I doesn't help:
$ ocaml
OCaml version 4.00.1
# #load "lib.cma";;
ok
# open Lib;;
Error: Unbound module Lib
#
$ ocaml -I libFolder
OCaml version 4.00.1
# #load "toylib.cma";;
ok
# open Lib;;
# fun;;
Error: Reference to undefined global `Lib'
Some of the cmo in your lotsOfCmoFiles need to know the module Xyz. You need to take care of the dependency between your cmo files.
For example:
toto.ml:
let x = "toto"
titi.ml:
let y = Toto.x ^ " titi"
ocamlc -c toto.ml
ocamlc -c titi.ml
ocamlc -a titi.cmo toto.cmo -o lib.cma (* here is the probleme *)
# #load "lib.cma"
Error: Reference to undefined global `Toto'
Because titi depends on toto so you need to change the order of cmos:
ocamlc -a toto.cmo titi.cmo -o lib.cma
# #load "lib.cma"
# Titi.y;;
- : string = "toto titi"
EDIT:
If your cma is in a subdirectory for example, when you call ocaml you need to specify the path:
ocaml -I subdir/ (* subdir which contains lib.cma *)
# #load "lib.cma"
# Toto.x;;
- : string = "toto"
TL;DR: Make sure you don't have any top-level side-effects in the
I was running into this same kind of trouble. My project would build fine, most modules were available, but there was one module that kept triggering Reference to undefined global. But it was clear that the module was visible to the system: it was showing up in utop's autocomplete list, along with all of it's values, and I could reference it and import it into other modules.
The problem turned out to be an uncaught exception that was being thrown when that module was loaded. The exception was due to an attempt to load a non-existing file. It wouldn't cause problems during complication, but when the module was actually loaded it was breaking and the exception was being swallowed somewhere before I ever saw it.
Related
I've configured and built gpreftools. however, I can't seem to find the generated profile file of my program to display it.
I took the following actions:
Adding the -lprofiler linker flag to my .pro, building the program and the flag is added correctly at the linking stage.
QMAKE_LFLAGS += -lprofiler
Running with:
$ CPUPROFILE=/tmp/prof.out /path/to/executable
Executing:
$ pprof --gv /path/to/MyExe /tmp/prof.out
Then I get the following:
Failed to get profile: curl -s --max-time 90 'http:///pprof/profile?seconds=30' > /home/eslam/pprof/.tmp.MyExe.1509005857.: No such file or directory.
Anyone has a resolve on this?
Check that your program actually links to libprofiler.so. Some OSes (e.g. AFAIK some versions of ubuntu) do not actually add .so if none of it's symbols are actually used. E.g. ldd ./yourprogram should list libprofiler.so. If this does not happen, then you should prepend something like -Wl,--no-as-needed to your linker flags.
LD_PRELOAD method without rebuild
Besides passing -Wl,--no-as-needed,-lprofiler,--as-needed at build time mentioned by Eslam, you can also get it to work without modifying the build by passing the LD_PRELOAD option at runtime as:
LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libprofiler.so CPUPROFILE=prof.out ./main.out
You can find libprofiler.so easily with locate libprofiler.so.
See also: How can I profile C++ code running on Linux?
Tested in Ubuntu 18.04.
I upgraded my ocaml to 4.03.0.
Then, some wrapper libraries failed to build raising "No implemntations provided" Error.
I prepare a small example to explain my situation.
I write a C code in hello_stubs.c
#include<stdio.h>
#include<caml/mlvalues.h>
CAMLprim value caml_print_hello(value unit)
{
printf("Hello\n");
return Val_unit;
}
Next, I prepare the interface file for ocaml, in hello.mli.
external print_hello : unit -> unit = "caml_print_hello"
Then, I code a main program in main.ml
Hello.print_hello();;
To compile these programs, I executed the following commands.
ocamlc -c hello.mli
ocamlc -c hello_stubs.c
ocamlopt -o main main.ml hello_stubs.o
Then, unfortunately, the last command failed with the following error message.
File "_none_", line 1:
Warning 58: no cmx file was found in path for module Hello, and its interface was not compiled with -opaque
File "main.ml", line 1:
Error: No implementations provided for the following modules:
Hello referenced from main.cmx
According to the message,
I've tried ocamlc -opaque hello.mli, but it didn't solve the problem.
I also confirmed that the commands above work fine for ocaml 4.02.3.
Do you know how to compile this example with ocaml 4.03.0?
The fix is easy: create hello.ml of the same contents of hello.mli and compile it and link for main.
I guess this is due to the following change of 4.03.0:
PR#4166, PR#6956: force linking when calling external C primitives
(Jacques Garrigue, reports by Markus Mottl and Christophe Troestler)
The related section of the reference manual should be updated. See http://caml.inria.fr/mantis/view.php?id=7371
My program uses all of available memory, so I wanted to check which functions and abstracts are spoiling my project. I decided to use Memprof, so I installed their compiler and compiled my code with command
ocamlfind ocamlopt -package xml-light unix.cmxa str.cmxa -c -g NKJPxmlbasics.ml NKJP.mli NKJP.ml test.ml
and then run as suggested in tutorial
ocp-memprof --exec ./test
But there is error instead of result:
Error: no memory profiling information found. Possible causes:
- the application was not compiled with memory profiling support;
- the application exited before any major garbage collection was performed.
I even managed once to make it work but I have no idea how it happened
http://memprof.typerex.org/users/97beffbaec332eb7b2a048b94f7a38cf/2015-12-15_17-33-50_ab17218e800fe0a68fc2cfa54c13bfa6_16194/index.html
Is there any way to use this tool properly in this situation? What am I missing?
ocamlfind ... -c ... does not generate any executable. So, the ./test that you are running was probably generated by a previous command, probably without the memprof switch.
So I have been doing the following:
$ pprof /bin/ls ls.prof
Using local file /bin/ls.
Gathering CPU profile from http://ls.prof/pprof/profile?seconds=30 for 30 seconds to
/home/user/csteifel/pprof/ls.1414597606.ls.prof
Be patient...
curl: (7) couldn't connect to host
Failed to get profile: curl 'http://ls.prof/pprof/profile?seconds=30' > /home/user/csteifel/pprof/.tmp.ls.1414597606.ls.prof: No such file or directory
I'm not sure what is goign on here because this is one of the examples they show here: http://google-perftools.googlecode.com/svn/trunk/doc/cpuprofile.html
Now I understand ls isn't going to actually have information to it but I also know that it shouldn't be giving me an error about curl in this case it should be something else. What am I doing wrong here?
I have also tried doing this to a sample program that I created (eg: pprof --callgrind /home/user/csteifel/testing2/X86_64_DEBUG/el6/wtf ~/testing2/prof.out > callgrind.out and I get a similar error:
Using local file /home/user/csteifel/testing2/X86_64_DEBUG/el6/wtf.
Use of uninitialized value $host in substitution (s///) at /home/user/csteifel/usr/local/lib/bin/pprof line 3195.
Use of uninitialized value $hostport in concatenation (.) or string at /home/user/csteifel/usr/local/lib/bin/pprof line 3197.
Use of uninitialized value $prefix in concatenation (.) or string at /home/user/csteifel/usr/local/lib/bin/pprof line 3197.
Use of uninitialized value $host in substitution (s///) at /home/user/csteifel/usr/local/lib/bin/pprof line 3195.
Use of uninitialized value $hostport in concatenation (.) or string at /home/user/csteifel/usr/local/lib/bin/pprof line 3197.
Use of uninitialized value $prefix in concatenation (.) or string at /home/user/csteifel/usr/local/lib/bin/pprof line 3197.
Use of uninitialized value $host in sprintf at /home/user/csteifel/usr/local/lib/bin/pprof line 3364.
Gathering CPU profile from http:///pprof/profile?seconds=30 for 30 seconds to
/home/user/csteifel/pprof/wtf.1414597016.
Be patient...
curl: (6) Couldn't resolve host 'http:'
Failed to get profile: curl 'http:///pprof/profile?seconds=30' > /home/user/csteifel/pprof/.tmp.wtf.1414597016.: No such file or directory
Quick answer (and the fix to my problem):
If you choose method 1 of running the profiler, with an environment variable, gcc by default just ignores your link, because you're not using any symbols from that library. You need to include it with the -Wl,--no-as-needed flag like so:
-Wl,--no-as-needed -lprofiler -Wl,--as-needed
You can read more about it here.
A more thorough answer with hints for other potential problem:
pprof looks for a local file called ls.prof, which contains info about the runtime of various components of /bin/ls (this is why you compile the program in question with the -g flag, so that it can see the symbols).
Now, why is the file not there? Because it hasn't been generated! Your /bin/ls hasn't been compiled with the -lprofiler flag. If it had been, and you activated the library by one of the two ways listed in the documentation:
Define the environment variable CPUPROFILE to the filename to dump the profile to. For instance, to profile /usr/local/bin/my_binary_compiled_with_libprofiler_so
% env CPUPROFILE=/tmp/mybin.prof /usr/local/bin/my_binary_compiled_with_libprofiler_so
In your code, bracket the code you want profiled in calls to ProfilerStart() and ProfilerStop(). (These functions are declared in .) ProfilerStart() will take the profile-filename as an argument.
If you did either of those, compiled ls with the libraries, every time you run it you'll see something like
% ls -la ~
% <output>
% PROFILE: interrupts/evictions/bytes = 204/0/256
That means the profile file has been generated, and you can now look at it with
% pprof binary_compiled_with_lprofiler profile_file
I'm trying to compile an XML-RPC server written using the xmlrpc-light library in OCaml with ocamlbuild but I get:
$ ocamlbuild server.native
Finished, 0 targets (0 cached) in 00:00:00.
+ ocamlfind ocamlopt -linkpkg -package xmlrpc-light -package unix -package threads -package netsys -thread server.cmx -o server.native
File "_none_", line 1, characters 0-1:
Error: No implementations provided for the following modules:
Netsys referenced from /usr/lib/ocaml/equeue/equeue.cmxa(Uq_engines)
Command exited with code 2.
Compilation unsuccessful after building 4 targets (3 cached) in 00:00:00.
Note that I have a myocamlbuild.ml file like this one and a _tags file containing a single line:
<server.ml> or <server.native>: pkg_unix,pkg_netsys,pkg_xmlrpc-light,pkg_threads
This plugin has worked fine for me in other cases (for client.native of the same client/server application, for example) but not for server.native. The complaint suggests that the library Netsys is not available to the compiler. But we get
$ ocamlfind query netsys
/usr/lib/ocaml/netsys
meaning that netsys is installed in /usr/lib/ocaml/netsys. Inspecting that directory gives me:
$ ls /usr/lib/ocaml/netsys
META libnetsys.a netsys.a netsys.cma netsys.cmi netsys.cmxa netsys.mli
Also,
$ ocamlfind list | grep netsys
netsys (version: 2.2.9)
So, there is indeed a library called netsys installed, it does have a cmxa file ready to be used, but for some strange reason, ocamlbuild complaints that there is no implementation provided for the module Netsys. The fact that ocamlbuild could read /usr/lib/ocaml/equeue/equeue.cmxa should be enough to conclude that everything should be fine regarding environment ($PATH, etc.) in terms of finding libraries.
This is all in Debian 6.0 and my OCaml's version is 3.11.2.
After some browsing, I found an svn commit message (repository diff) which suggests that it may have to do with the number of threads used. And, in fact, I'm using a Mutex somewhere in my code (check the code of server.ml and client.ml in this other question). If I remove the Mutex stuff from my server.ml the error still happens. But if I additionally remove the pkg_threads from the _tags file then everything compiles. So, my conclusion is that I can't directly use the threads library with xmlrpc-light, which is weird.
IMHO equeue META is wrong. Adding netsys to dependencies fixes your issue :
sed -i 's/threads/netsys,threads/' /usr/lib/ocaml/equeue/META