Unbound modules in OCaml - module

My problem is that ocamlc and ocamlopt apear to be refusing to find third party libraries installed through apt-get. I first started having this problem when I tried to incorporate third-party modules into my own OCaml programs, and quickly wrote it off as a personal failing in understanding OCaml compilation. Soon-- however-- I found myself running into the same problem when trying to compile other peoples projects under their own instructions.
Here is the most straight-forward example. The others all use ocamlbuild, which obfuscates things a little bit.
The program: http://groups.google.com/group/fa.caml/msg/5aee553df34548e2
The compilation:
$ocamlc -g -dtypes -pp camlp4oof -I +camlp4 dynlink.cma camlp4lib.cma -cc g++ llvm.cma llvm_bitwriter.cma minml.ml -o minml
File "minml.ml", line 43, characters 0-9:
Error:Unbound module Llvm
Even when I provide ocamlc with the obsolute paths to the llvm files, like so...
$ ocamlc -g -dtypes -pp camlp4oof -I +camlp4 dynlink.cma camlp4lib.cma -cc g++ /usr/lib/ocaml/llvm-2.7/llvm.cma /usr/lib/ocaml/llvm-2.7/llvm_bitwriter.cma minml.ml -o minml
... to no avail.
What am I doing wrong?

Your command is doing two things: it's compiling minml.ml (into minml.cmo), then linking the resulting object into minml.
Compiling a module requires the interfaces of the dependencies. The interfaces contain typing information that is necessary to both the type checker and the code generator; this information is not repeated in the implementation (.cma here). So for the compilation stage, llvm.cmi must be available. The compiler looks for it in the include path, so you need an additional -I +llvm-2.7 (which is short for -I /usr/lib/ocaml/llvm-2.7).
The linking stage requires llvm.cma, which contains the bytecode implementation of the module. Here, you can either use -I or give a full path to let ocamlc know where to find the file.
ocamlc -g -dtypes -I +camlp4 -I +llvm-2.7 -pp camlp4oof -c minml.ml
ocamlc -g -cc g++ -I +camlp4 -I +llvm-2.7 dynlink.cma camlp4lib.cma llvm.cma llvm_bitwriter.cma minml.cmo -o minml
or if you want to do both stages in a single command:
ocamlc -g -dtypes -cc g++ -I +camlp4 -I +llvm-2.7 dynlink.cma camlp4lib.cma llvm.cma llvm_bitwriter.cma -pp camlp4oof minml.ml -o minml

Related

MSYS2+MinGW64: why do ldd and objdump find different DLL dependencies?

I get different DLLs dependencies reported by different tools and like to deeply understand why. So answers like "tool xxx is crap, use cool yyy" are opinions and not welcome. Answers like "you have wrong path order" or "you missed to export XXX=yyyy" are not what I focus for, but if they are applicable, those are welcome too. What I exactly want to understand is for instance, which PE/ELF tables which of the tools use and which they can't see. All under the aspect of mingw / msys2 environment.
For completeness: I compiled my program inside Codelite IDE following exactly this Setup Instructions for Codelite and inserted /mingw64/bin:/clang64/bin: in front of PATH. The expectation is that this has nothing to do with my observation. Just for the case I couldn't see the wood because of all the trees. Inserted my code into the helloworld example.
For completeness II: the ucrt variant is installed for different projects. I did not use it here.
For completeness III: I give all my instructions here. Expecting, 80% have nothing to do with the question, but just in case you see things I missed.
Given: MSYS2 (Sept.2022, msys2-x86_64-20220904.exe) with:
pacman -Suy \
mingw-w64-x86_64-gcc \
base-devel development \
sys-utils \
mingw-w64-ucrt-x86_64-toolchain mingw-w64-i686-toolchain mingw-w64-x86_64-toolchain \
libmodbus \
mingw-w64-x86_64-codelite
Opened a MSYS terminal:
$ which gcc && which g++ && which clang
/mingw64/bin/gcc
/mingw64/bin/g++
/mingw64/bin/clang
codelite &
Inside Codelite I only changed Settings | Build Settings | Compilers to "MinGW 32bit (MSYS2 64bit)" and therein the two cfg lines:
make C:/c/msys64/mingw32/bin/mingw32-make.exe -j8 SHELL=sh.exe
makedir mkdir -p
Program was then built via codelite generated makefile:
C:\WINDOWS\system32\cmd.exe /C C:/c/msys64/mingw32/bin/mingw32-make.exe -j8 SHELL=sh.exe -e -f Makefile
...[cut]...
C:/c/msys64/mingw32/bin/g++.exe -c protocol_writer.cpp" -g -O0 -Wall -o Debug/protocol_writer.cpp.o -I. -I.
C:/c/msys64/mingw32/bin/g++.exe -c scan_dtsu666_main.cpp" -g -O0 -Wall -o Debug/scan_dtsu666_main.cpp.o -I. -I.
C:/c/msys64/mingw32/bin/g++.exe -o Debug/modbus-dtu-dump #"modbus-dtu-dump.txt" -L. -lmodbus
====0 errors, 0 warnings====
Program was not starting because of missing DLLs (no pop-up or error msg). Now we come to the core issue. I invoked:
$ which ldd
/usr/bin/ldd
$ ldd modbus-dtu-dump.exe
ntdll.dll => /c/WINDOWS/SYSTEM32/ntdll.dll (0x7ffdf2c70000)
ntdll.dll => /c/Windows/SysWOW64/ntdll.dll (0x77310000)
wow64.dll => /c/WINDOWS/System32/wow64.dll (0x7ffdf2510000)
wow64win.dll => /c/WINDOWS/System32/wow64win.dll (0x7ffdf1be0000)
$ which objdump
/mingw64/bin/objdump
$ objdump --private-headers modbus-dtu-dump.exe | grep 'DLL'
DLL Name: libgcc_s_dw2-1.dll
DLL Name: KERNEL32.dll
DLL Name: libmodbus-5.dll
DLL Name: msvcrt.dll
DLL Name: libwinpthread-1.dll
DLL Name: libstdc++-6.dll
... and wonder, why ldd doesn't tell anything about the mingw runtimes, while objdump doesn't tell about the windows os core dependencies.
Edit:
As I wrote in a side note "Program was not starting because of missing DLLs (no pop-up or error msg).", there seems to be another miss-configuration. Once I changed the IDE settings to use the 64bit target, it was able to start and all-aspect debugging. I'll keep this up to date, for the case Google leads some people to here, searching for similar codelite or mingw problems. Goal is to have both architectures compile-able and debug-able.

Objective-C for Windows with Gitbash and GCC

When I compile things with gitbash and gcc, is there someway to shorten what I need to type?
In order to compile my helloworld program, I have to type the following in:
gcc -o helloworld.exe helloworld.m -I C:/GNUstep/GNUstep/System/Library/Headers -L C:/GNUstep/GNUstep/System/Library/Libraries -std=c99 -lobjc -lgnustep-base -fconstant-string-class=NSConstantString
Most people use Makefiles (or something related, e.g. CMake) in order to ease development. Makefiles are similar to bash scripts (the syntax is similar as well). After you created a Makefile you can run make and it does exactly what you specified.
If you want to know how to run Automake on Windows, read this: How to run a makefile in Windows?

Using hiredis (redis client library)

I have the redis server installed, and can use it from the command line. Now, I am wanting to write a client program using hiredis. To begin with, I tried to compile example.c which is present in the hiredis directory:
vishal#expmach:~/redis-2.6.14/deps/hiredis$ ls
adapters async.h COPYING dict.h *example.c* example-libevent.c
hiredis.c Makefile net.h sds.c test.c async.c CHANGELOG.md dict.c example-
ae.c example-libev.c fmacros.h hiredis.h net.c README.md sds.h
Here are the commands:
vishal#expmach:~/redis-2.6.14/deps/hiredis$ gcc -c -I hiredis example.c
vishal#expmach:~/redis-2.6.14/deps/hiredis$ gcc -o example -I hiredis -L hiredis -lhiredis -lm
/usr/bin/ld: cannot find -lhiredis
collect2: ld returned 1 exit status
I am not sure how to go about fixing this. Please help.
gcc -o example example.c -lhiredis $(pkg-config --cflags --libs glib-2.0)
why don't you juste juste the provided Makefile?
make
./hiredis-example

MinGW linking dynamic library with bad name

I am using MinGW64 (Windows 7) without MSYS and I have the following problem:
I have one dll, written in C99, which has to have the .mexw64 suffix so it can be used by Matlab. I would like to be able to link this dll form another dll (mexw64) dynamically but gcc won't allow me to link directly. I cannot do static linking, because both dlls have many functions of the same name which can be hidden by not exporting their symbols when creating the shared library.
So far, I have tried:
To create a symbolic link (with correct suffix and preffix) using mklink. This works, but I was not able to run mklink from the makefile. Maybe it is due to the fact I am not using MSYS which could have ln -s (I havent checked).
To do the copy of the first dll and correcting the suffix and prefix. This worked better than I expected, because on runtime the second dll actually uses the original .mexw64 and not the dll copy. I guess it is just because the .mexw64 is found first, but why is that .mexw64 searched in the first place? How the system know it is actually a dll?
My question is, is this correct/safe enough? Are there any other options?
Thanks for comments.
You should build a proper implib, either as a linker output or from a .def.
Linker:
$ gcc -shared -o testimpl.mexw64 testimpl.c -Wl,--out-implib,libtestimpl.a
$ dlltool -I libtestimpl.a
testimpl.mexw64
Or create a .def file, specifying an explicit LIBRARY:
$ cat testimpl.def
LIBRARY testimpl.mexw64
EXPORTS
test #1
$ dlltool -d testimpl.def -l libtestimpl.a
$ dlltool -I libtestimpl.a
testimpl.mexw64
And finally, link stuff:
$ gcc -o test.exe test.c libtestimpl.a
# or
$ gcc -o test.exe test.c -L. -ltestimpl
$ grep testimpl.mexw64 test.exe
Binary file test.exe matches

What does the -I option do in a g++ call?

I'm having a hard time finding good documentation on the most common g++ options. I have the following g++ command and I'm trying to understand it well:
g++ q1.cpp -o q1 -I/usr/local/include/opencv -L/usr/local/lib -lm -lopencv_core -lopencv_highgui -lopencv_calib3d -lopencv_imgproc
What does the -I option do?
-I adds to the path for searching for include files.
-l links to a particular library. (e.g. -lm links libm which is math)
It's not for a library I think it's only for include files. (It's a i not a l, l it's for libraries)