ocaml top level and native library - c

I have a library that calls C code. It's compile with the -custom, -cclib, -l flags, which is working ok when I compile my code against the library with ocamlc,
but when I use the "ocaml" top level to run a script like:
ocaml -I /opt/godi/lib/ocaml/pkg-lib/xxxx xxx.cma myprog.ml
it says:
Error: The external function `caml_yyyy' is not available
Do I need additional parameters to tell the top level ?

You should build your own toplevel using "ocamlmktop":
$ ocamlmktop -custom -I /opt/godi/lib/ocaml/pkg-lib/xxxx xxx.cma -o ocaml_with_xxx
Then, you can use it :
$ ./ocaml_with_xxx -I /opt/godi/lib/ocaml/pkg-lib/xxxx
Note that you still need the -I so that the toplevel can find the interface files of the library that it contains.

IIRC you cannot use libraries compiled with -custom in toplevel. You should compile dynamically-loadable stubs so that toplevel could pick up them. This is very easy to do with e.g. oasis and somewhat more involved if invoking ocaml tools manually.

Related

Expand macros of a single file when compiling linux kernel

I'm interested in expanding the macros of a single Linux kernel file (arch/x86/kernel/nmi.c).
I know that normally one can use gcc -E to expand the macros.
However since the file is part of the Linux kernel, many options need to be passed to gcc. I'm then trying to modify the kernel Makefile to pass the -E flag.
I'm currently modifying the /arch/x86/kernel/Makefile that is the one use to compile nmi.c and call this particular sub-Makefile by
make M=arch/x86/kernel
I found out that extra gcc flags can be passed by using CFLAGS_nmi.o.
However adding
CFLAGS_nmi.o := -E
to the Makefile does not have the expected effect
This is the output after modifying the Makefile
~/git/linux$ make M=arch/x86/kernel
CC arch/x86/kernel/nmi.o
AR arch/x86/kernel/built-in.a
Building modules, stage 2.
MODPOST 3 modules
I would expect the expanded code after the "CC arch/x86/kernel/nmi.o" line.
I also tried "CFLAGS_nmi.o := -E > nmi.out" to try to redirect the output, but the generated file is empty.
Adding
CFLAGS_nmi.o := -save-temps=obj
did the trick. Thanks!

How to trace specific functions/files in C?

I have already known that the GCC's argument -finstrument-functions can hook the functions and the argument -finstrument-functions-exclude-file(functions)-list can exclude some files/functions to be traced.
But now I have a lot of files to be compiled and only some of them need to be traced. I wonder if I can include some specific functions/files to be traced, such as something like -finstrument-functions-include-file(functions)-list?
Thanks a lot!
GCC does not support this out-of-the-box (it's more a task for your build system). One common hack to achieve what you want is to write a shell wrapper which replaces GCC and adds flags where needed:
$ cat path/to/fake/gcc
#!/bin/sh
FLAGS=
if echo "$*" | grep -q 'myfile1.c'; then
FLAGS=-finstrument-functions
fi
exec /usr/bin/gcc "$#" $FLAGS
$ export PATH="path/to/fake:$PATH"
If you use cmake to build your project you may benefit from adding COMPILE_OPTIONS at a specific level. Use
add_compile_options()
for directory-wide settings
target_compile_options()
for target-specific settings and
set_source_files_properties()
for file specific settings.
In your case
set_source_files_properties(
myfile1.cc PROPERTIES COMPILE_FLAGS -finstrument-functions)
Recent GCC compilers can be extended by GCC plugins.
But now I have a lot of files to be compiled and only some of them need to be traced.
You should consider writing your own GCC plugin to do that job. See also this draft report.
You may configure your build automation tool (e.g. GNU make or ninja) to help you.
At last, some of your C code (e.g. #include-ed files) could be generated. Think of meta-programming approaches (e.g. with SWIG or ANTLR or Bison or GPP or your own C code generator), perhaps using X-macros.

Shell command to compile C in Gprbuild

Using GtkAda, I'm trying to use the resource API to include the Glade file directly inside my code.
For this, we can generate C code from a set of resources using glib-compile-resources which can then be linked to the Ada code.
The problem is that this C code requires Gtk includes which we usually get from the pkg-config command under Linux such as
gcc -c -x c `pkg-config --cflags gio-2.0` myglade.gresource.c
I'd like to know how to provide the same kind of information in a GPRBuild project file.
FYI, I already tried to use the pkg-config command inside the compiler package for C language without any success. Of course, I managed to build by hand but that's a bit long :)
This might work for you:
project Config_Demo is
Pkg_Config := external_as_list ("PKG_CONFIG", " ");
package Compiler is
-- only this file needs the extra switches
for Switches ("myglade.gresource.c") use Pkg_Config;
end Compiler;
end Config_Demo;
and then
gprbuild -P config_demo -XPKG_CONFIG="`pkg-config -cflags gio-2.0`"
Your best bet will be to do what GtkAda does: Look at its shared.gpr.in file, it uses the token #GTK_LIBS_GPR# which will be replaced by the configure script, giving a usable shared.gpr.
Thing is, you need to issue the pkg-config call and build your gpr file from the result somehow. GPRBuild is not equipped to do this for you and process the result. If you're comfortable with GNU autotools, you can look further at how GtkAda achieves it:
GTK_LIBS_GPR is set in aclocal.m4 using a macro that converts the C-style flags to a GPR array. The value comes from GTK_LIBS which is queried here via pkg-config.
If you're not comfortable with GNU autotools, you can write your configure script using basic shell commandos, a scripting language like Python or with whatever other tool you're comfortable with.

Unable to compile a c application that reads smartcard

I am trying to compile an example c application that is using pkcs#11 to finds all
the private keys on the token, and print their label and id, but getting following errors
/tmp/ccAqQ7UI.o: In function initialize':
pkcs11_example1.c:(.text+0x8e5): undefined reference to C_Initialize'
/tmp/ccAqQ7UI.o: In function `get_slot':
The example is taken from here
compilling by using following command;
`gcc pkcs11_example1.c -o slots -L /usr/lib/opensc-pkcs11.so`
I am not sure which library i should link after -L.
Can anyone guide how to compile this and are there some libraries required to link.
C_Initialize and other 60+ functions with "C_" prefix are cryptoki functions defined in PKCS#11 specification. They are usually implemented in standalone library provided by HSM vendor. Looking at your code samples I would say that you need to directly link also PKCS#11 library or you can modify the code to dynamically load PKCS#11 library in runtime with LoadLibrary or dlopen and then acquire pointers to all cryptoki functions via the C_GetFunctionList call. You can also take a look at pkcs11-logger the source code for an example on how to do that.
The link command you give, gcc pkcs11_example1.c -o slots -L /usr/lib/opensc-pkcs11.so, is wrong.
-L takes just path, which is added to paths where libs are searched from, but /usr/lib is default so you don't need this switch at all.
You are missing -l, which takes the library name without lib prefix or .so suffix, so looks like you need -lopensc-pkcs11.
So, first make sure your library file really is /usr/lib/libopensc-pkcs11.so (note lib prefix!) possibly with verion numbers following. Then change build options so link command becomes
gcc pkcs11_example1.c -o slots -lopensc-pkcs11

Is there a way to load user library's from specific location ONLY on running the binary

I have a shared library's libmyworld.so in /opt/my_prog/lib and also in /home/user1/lib
Irrespective of the order I specified in LD_LIBRARY_PATH (LD_LIBRARY_PATH=/home/user1/lib;/opt/myprog/lib); my binary SHOULD always look for libmyworld.so FIRST in /opt/my_prog/lib;
Can this be done using GCC during compilation time? without modifying my_prog binary. Thanks in advance.
The search order for dynamic libraries in Linux (from ld.so man page) is the following
Using the DT_RPATH dynamic section attribute of the binary
if present and DT_RUNPATH attribute does not exist. Use of
DT_RPATH is deprecated.
Using the environment variable LD_LIBRARY_PATH. Except if
the executable is a setuid/setgid binary, in which case it
is ignored.
Using the DT_RUNPATH dynamic section attribute of the binary
if present.
From the cache file /etc/ld.so.cache which contains a
compiled list of candidate libraries previously found in the
augmented library path. If, however, the binary was linked
with -z nodeflib linker option, libraries in the default
library paths are skipped.
In the default path /lib, and then /usr/lib. If the binary
was linked with -z nodeflib linker option, this step is
skipped.
When linking, to set
DT_RUNPATH: use -Wl,--enable-new-dtags -Wl,-R$(RUNPATH)
DT_RPATH: use -Wl,--disable-new-dtags -Wl,-R$(RPATH)
In theory, it is better to use DT_RUNPATH as the LD_LIBRARY_PATH, on which the user has a control, has precedence. But here you want to avoid the user control, so use the DT_RPATH. In you link line:
-Wl,--disable-new-dtags -Wl,-R/opt/my_prog/lib
You can always launch your binary (here called foo) with
$ LD_LIBRARY_PATH=/opt/my_prog/lib foo
or make a shell script with the line above.
While compiling your source code use the below command
gcc -o [desired_executable_file_name] -L [Your shared library path] -l [your shared library name] -I [Header file path]
for example in your case
gcc -o my_word_exe -L /opt/my_prog/lib -lmyworld -I [header path if their]
Then it"ll take libmyworld.so in /opt/my_prog/lib this path
Use LD_PRELOAD.
LD_PRELOAD=/home/lib/libmyworld.so mybinary
The advantage is that you don't fiddle with LD_LIBRARY_PATH - your binary may depend on other shared libraries and it may need proper LD_LIBRARY_PATH/ld.so.conf/whatever.
PS. This is the least invasive and flexible solution, because does not affect loading of other libraries and does not hardcode paths in the user executable.

Resources