How do I compile my OCaml code into a standalone bytecode executable? - ocaml

I want to compile my OCaml project into an executable that can be run in other computers that don't have OCaml installed. Using ocamlbuild, when I compile a ".native" file it works fine on other machines but if I compile a ".byte" file it fails with a Cannot exec ocamlrun message when I try to run the executable.
Since the bytecode version of my program is significantly smaller in terms of file size, I would prefer to distribute it instead of the native code. Is there a way to bundle ocamlrun into the executable when I compile it?

You need to compile in a custom mode, from ocamlc user manual:
-custom
Link in “custom runtime” mode. In the default linking mode, the linker produces bytecode that is intended to be executed with the
shared runtime system, ocamlrun. In the custom runtime mode, the
linker produces an output file that contains both the runtime system
and the bytecode for the program. The resulting file is larger, but it
can be executed directly, even if the ocamlrun command is not
installed. Moreover, the “custom runtime” mode enables static linking
of OCaml code with user-defined C functions, as described in chapter
Unix: Never use the strip command on executables produced by ocamlc -custom, this would remove the bytecode part of the executable.
If you're using oasis then all that you need is to add Custom : true field to your executable section, similarly, for ocamlbuild, add -tag custom or put custom in _tags .

Related

How to build an EABI shared library the same way that it's built on the o/s

Here's my problem:
Trying to debug a C++ program in gdb, but bt won't produce a complete backtrace. It's getting stuck on the Glib shared library, which has been built without any debug info and without -frecord-gcc-switches - this is how it comes as part of the o/s.
I want to build the shared library exactly the same, but with debug info. How can I do this? Building it with Meson shows several other shared libraries and packages that will influence its contents depending on their presence, and there's also of course different compile time flags I can use.
Is there an easy way to ensure the version I build from source produces the same object file as that packaged with linux (plus debug info)?
I've used apt-get source glib2.0-0 and it gives me all the meson files, ninja files and help files I appear to need, but it doesnt quite say this is how it comes as part of Raspberry Pi O/S.

Compiling modules in different directories

I'm trying to follow these instructions to compile a module that depends on another module which I've created: https://ocaml.org/learn/tutorials/modules.html
In my case, I have a module ~/courseFiles/chapter5/moduleA.ml and another module in ~/OCamlCommons/listMethods.ml. I have compiled listMethods.ml using ocamlopt -c listMethods.ml and this seemed to work, it produced a file listMethods.cmx.
The file moduleA.ml contains open ListMethods;;. Now with my terminal located at ~/courseFiles/chapter5 I ran ocamlopt -c moduleA.ml but the terminal returns
Error: Unbound module ListMethods
Now I can understand why it would do this, but the instructions at that site seem to indicate that what I've done is how you're supposed to do this. Presumably I need to pass in the location of either the script or executable files when compiling moduleA.ml, but I'm not sure what the syntax should be. I've tried a few guesses, and guessed about how I could do this with ocamlfind but I haven't succeeded. I tried looking for instructions on compiling modules located in different directories but didn't find anything (or anything I can make sense of anyway).
First of all, the toolkit that is shipped with the OCaml System Distribution (aka the compiler) is very versatile but quite low-level and should be seen as a foundation layer for building more high-level build systems. Therefore, learning it is quite hard and usually makes sense only if you're going to build such systems. It is much easier to learn how to use dune or oasis or ocamlbuild instead. Moreover, it will diverge your attention from what actually matters - learning the language.
With all that said, let me answer your question in full details. OCaml implements a separate compilation scheme, where each compilation unit could be built independently and then linked into a single binary. This scheme is common in C/C++ languages, and in fact, OCaml compiler toolchain is very similar to the C compiler toolchain.
When you run ocamlopt -c x.ml you're creating a compilation unit, and as a result a few files are produced, namely:
x.o - contains actually the compiled machine code
x.cmx - contains optimization data and other compiler-specific information
x.cmi - contains compiled interface to the module X.
In order to compile a module, the compiler doesn't need the code of any other modules used in that module. But what it needs is the typing information, i.e., it needs to know what is the type of List.find function, or a type of any other function that is provided by some module which is external to your module. This information is stored in cmi files, for which (compiled) header files from C/C++ is the closest counterpart. As in C/C++ the compiler is searching for them in the include search path, which by default includes the current directory and the location of the standard library, but could be extended using the -I option (the same as in C/C++). Therefore, if your module is using another module defined in a folder A you need to tell the compiler where to search for it, e.g.,
ocamlopt -I A -c x.ml
The produced objective file will not contain any code from external modules. Therefore, once you will reach the final stage of compilation - the linking phase, you have to provide the implementation, e.g., if your module X was using a module implemented in a file with relative path A/y.ml, and you have compiled it in that folder, then you need to specify again the location of the compiled implementation, e.g.,
ocamlopt -I A y.cmx x.cmx -o exe
The order is important, all modules used by a module should be specified before that module, otherwise, you will get the "No implementations provided" error.
As you can see, it is a pretty convoluted process, and it is really not worthwhile to invest your time in learning it. So, if you have an option, then use a higher-level tool to build your programs. If not sure, then choose Dune :)

How to generate llvm bitcode for large programs with many source code files and a huge Makefile (e.g. memcached)?

I have my pass that I tested on toy programs and now I want to run it on large programs, many of which are open source programs like memcached. Such programs have their own Makefile and a complicated compilation procedure. I want to generate a bitcode file for such programs to let my pass work on them. Help and suggestions will be appreciated!
Depending on what you're pass is doing you can:
Build with LTO: adding -flto to the CFLAGS and building your application with your own built linker plugin is quite seamless from a build system point of view. However it requires some understand about how to setup LTO.
Build with your own built clang: adding statically your pass to the LLVM pipeline and use your own built clang. Depending on the build system, exporting CC/CXX environment variable pointing to your installed clang should be enough.
Build by loading your pass dynamically into clang, for example this is what Polly is (optionally) doing.
If you add -emit-llvm to your clang flags, it will emit BC files instead of object files or LL files instead of assembly.
You'll likely have to modify the makefile some more bit that should get you started in the right direction.

Haxe - Create a C++ Stand-alone executable

I have written a haxe program that tries to communicate with a remote server. I was able to compile to the C++ target successfully. The executable runs just fine on my system. However, when I try to run the same on another windows box, it fails with the following error
Error: Could not load module std#socket_init__0
I then installed haxe and hxcpp which worked like a charm. I was able to run the exe. I understand now that there is dependency on hxcpp.
That still did not solve my problem as I want to create a stand-alone application. After some research I found a file (ExampleMain.CPP) with the following instructions that I think might solve my problem. However, I am a novice and do not quite follow. Can some one walk me through with this? Thanks
ExampleMain.CPP
This is an example mainline that can be used to link a static version.
First you need to build the static version of the standard libs, with:
cd $HXCPP/runtime
haxelib run hxcpp BuildLibs.xml -Dstatic_link
Then the static verion of your application with (note: extra space before 'static_link'):
haxe -main YourMain -cpp cpp -D static_link
You then need to link the above libraries with this (or a modified version) main.
You may choose to create a VisualStudio project, and add the libraries from
$HXCPP/bin/Windows/(std,regexp,zlib).lib and your application library.
Note also, that if you compile with the -debug flag, your library will have a different name.
Linking from the command line for windows (user32.lib only required for debug version):
cl ExampleMain.cpp cpp/YourMain.lib $HXCPP/bin/Windows/std.lib $HXCPP/bin/Windows/zlib.lib $HXCPP/bin/Windows/regexp.lib user32.lib
From other OSs, the compile+link command will be different. Here is one for mac:
g++ ExampleMain.cpp cpp/Test-debug.a $HXCPP/bin/Mac/regexp.a $HXCPP/bin/Mac/std.a $HXCPP/bin/Mac/zlib.a
If you wish to add other static libraries besides these 3 (eg, nme) you will
need to compile these with the "-Dstatic_link" flag too, and call their "register_prims"
init call. The inclusion of the extra static library will require the library
in the link line, and may requires additional dependencies to be linked.
Also note, that there may be licensing implications with static linking
thirdparty libraries.
I'm not sure, but it seems that you are taking the same extra steps hxcpp does for you already. When you compile your standalone application it is actually standalone and doesn't have a dependency on hxcpp per se - but it has a dependency on the standard libraries within hxcpp you may have used. For instance, if you use regular expressions, you will need the regexp.dll that hxcpp has for it, as you noted. The haxe standard library is in the std.dll and the zlib is if you used compression from the zip packages.
If I am not mistaken, the default is to reference these components dynamically. In order for your application to be standalone as you suggest, you simply have to copy these dll's alongside your binary.
If you want to link to these library components statically, automatically from your haxe code, just import the types from the cpp.link package. This instructs hxcpp to automatically bring its libraries as part of the compilation, linking it statically into your binary instead of dynamically. No extra steps are necessary!
Short answer: add import cpp.link.StaticStd; and any other library components in the link package somewhere to your code. It can be anywhere as long as it's imported, it will be linked in.

How to make a library in c++ in linux

I am writing a small application in c++ and I have some questions regarding that. I am basically a Java developer now moving into c++.
If I use some library like boost, curl etc. can I make it run without installing that on the client machine (I mean something like including all library jar files inside the project in Java)
I have installed some library or software in linux. After that if I type in the terminal it pings the software. For example php, after you install it you can use php from terminal. How does this work? Can I use my simple c++ project to do so?
Yes. You use a process called static linking, which links all the libraries into one big executable. In ./configure scripts (from autotools), you use the --enable-static flag. When building your program, you use the -static flag. The static libraries are the ones with the .a suffixes; shared libraries use .so, sometimes with a version number suffix).
PHP is not a library, it is a language (i.e. executable) which provides its own command-line interface. Your C++ executable can work similarly, you just have to get the input from cin (in <iostream>) and write results to cout, using cerr for error messages.
Your title question, "How to make a library in c++ in linux" (as opposed to using a library): You use the ar program to link several .o files into a single .a library file. You can also use ranlib to clean up the .a file. Read the man pages for those commands to see how they are used.
1)Answer to your Q1 is compilation with libraries statically linked. For example with gcc Compiler:
# gcc -static myfile.c -o myfile
2)Answer to you Q2 is appending the absolute path of executable to $PATH Environment Variable. For example in Bash shell:
# export PATH=${PATH}:/home/user/pathofexecutable
The above setup will be temporary only for that terminal you do. To make it available to all terminal in you machine add the above export command to /home/user/.bashrc file.
For question 1, you want to compile the program as a static executable. (Just pass -static to g++.) It will make the program much larger since it needs to include a copy of stuff normally kept as libraries.
For question 2 I'm pretty sure what you mean is having a program in the PATH. Type echo $PATH to see the path on your current machine. If you install your program in one of those directories it will run from anywhere. (Most likely /usr/local/bin/)