I am trying to compile an OCaml file with the debugger flag -g with the following line within the file -- #use "file2.ml". Why does the file not compile as long as I have the use keyword in it? What exactly does the "#use" keyword do? Is there an alternative?
The directives starting with # are supported only in the toplevel, the OCaml interpreter, also known as a read-eval-print loop.
In the toplevel, #use causes the interpreter to read OCaml code from a text file. Afterward it continues to take commands interactively.
For compiled code, you should compile separately then link your modules together. If the code in file2.ml doesn't form a full module, you'll probably want to cut/paste it directly into the main file. OCaml doesn't have compile-time sourcefile inclusion like the C family has.
Update
Here's how to compile two OCaml files the old school way. You'll find there are those who say these ways are obsolete and that you should learn to use ocamlbuild. This may be correct, but I am old school at least for now.
$ ocamlc -o program file2.ml file1.ml
You have to list the .ml files in dependency order, i.e., a file has to be listed after any files it uses. This is already one reason to use a more powerful build tool.
Note that this does not behave the same as with #use, which loads all the top-level names of file2.ml into the global namespace. With separate compilation, names from file2.ml will be contained in a module named File2. If you want to call a function f defined in file2.ml, you should call it as File2.f.
TL;DR;
Use ocamlbuild to drive your compilation process.
ocamlbuild -clfags -g file1.native
Deeper into the woods
#use is a special directive in the OCaml toplevel, in other words in OCaml interpreter. This directives are special commands that are executed by the interpreter for some effects. They are not part of the language. Moreover, different interpreters have different directives. If you want to write an OCaml program, then you need to compile, since OCaml is a compiled language.
OCaml comes with a very descent infrastructure, here is a short guideline. First of all, there're two compilers, bytecode and native. Bytecode is slow (still much faster than Python or Ruby), but portable. Native compiles to native machine code and thus very fast. If you have an access to both compilers, then use the latter. One can say, that native compilation is slower, I would say that on a modern machines the difference is negligible.
The plethora of tools is pretty large, we have ocaml for interpreter, ocamlc for bytecode compiler, ocamlopt for native compilation, ocamldep for finding dependencies between modules, ocamldoc for compiling documentation, ocamlmktop for making your own interpreters, ocamlmklib to bundle libraries, ocamlrun to run bytecode. Also we have ocamlfind to find libraries on your system. Fortunately we also have One Tool to rule them all, One Tool to find them, One Tool to bring them all and in the darkness bind them.
Here comes ocamlbuild. This tool is a part of OCaml language distribution, and it knows everything about all 9 minor tools. So you don't really need to learn them in order to start programming in OCaml. ocamlbuild will find all dependencies, link libraries, and create for you anything you want, including shared libraries or your own interpreters. For example, to link with core library, just pass -pkg core option. Moreover, ocamlbuild has _tags file, that allows you to store your arguments and save some space on your command line. So, other way to always pass -g option (not a bad idea, btw) to compiler is to add the following to your _tags file:
debug : true
And since, you're adding this -g option, I suspect that you're interested in backtraces. If that is true, then don't forget to enable backtracing recording with either calling to Printexc.record_backtrace or by setting environment variable OCAMLRUNPARAM=b.
I came up with exactly the same problem, but the solution which I have found is to use the #include directive from the cppo preprocessor. You can include the preprocessor in the -pp switch on the OCaml compiler.
Related
I've been searching around for different custom pre-processor extensions and replacements, but all of them seem to come with 1 of 2 caveats:
Either 1), you generate the code as a separate build-system, them manually put the output into your real (CMake) build system, or 2) you end up losing the builtin preprocessor for GCC.
Is there really no tool that can, say, run each file it gets against some configured script, then through cpp, then pass the result to gcc?
I'd love to use something like Cog by just setting an environment variable for gcc, indicating a tool that runs Cog first and then the standard preprocessor.
Alternatively, is there a straightforward way to accomplish that in CMake, itself? I don't want to have to write a custom script for each file, especially if I have to then hard-code the compiler/preprocessor flags in each target.
edit: For clarity, I am aware of several partial/partially-applicable solutions. For example, how to tell GCC to use a different preprocessor. (Or really, to look in a different place for its own preprocessor, cc1. See: Custom gcc preprocessor) However, that leaves a lot of work to do, to modify files, and then correctly invoke the real cc1, with the correct original arguments.
Since that is effectively a constant/generic problem, I'm just surprised there is no drop in program.
Edit 2: After looking over several proposed solutions, I am not convinced there is an answer to this question. For example, if files are going to be generated by CMake, then they can't be included and browsed by the IDE - due to not yet existing.
As ridiculous as it sounds, I don't think there is any way to extend the preprocessor short of forking Gcc. Everything recommended so far, constitutes incomplete hacks.
The GCC (C++ compiler) is made for compiling C++ programs. As the C++ preprocessor is standardized within the C++ standard there is usually no need for anything like a "plugin" or "extension" there.
Don't listen to the comments, that suggest you using any exotic extension to CMake or change source code of GCC. Running source files through a different program (cog in your case) before compiling is a well known task and all major build systems support it right away.
In CMake you can use the add_custom_command function. If you need this for more than one file, you could use a CMake loop like e.g. suggested in this answer.
I am trying to build code using ocamlc however, I got error
Error: Unbound module Stdlib
The /usr/lib/ocaml/ directory includes the following
stdlib.a stdlib.cma stdlib.cxma stdlib.p.a stdlib.p.cxma
OCaml version : 4.05.0
The standard library was renamed from Pervasives to Stdlib fairly recently. Your compiler is from before the change; i.e., the 4.05.0 compiler has a Pervasives module and no Stdlib module. The code you're trying to compile is most likely from after the change.
There's usually no reason to mention the name of the standard library because it is "pervasive". So you could try removing "Stdlib." wherever you see it. Or you could try renaming it to "Pervasives.".
If the code is much more recent than the 4.05.0 compiler you could encounter other problems, however.
The Stdlib module was introduced in 4.07.0. Before that it was called Pervasives. It seems like you're mixing installations.
A few commands that might help untangle it:
which ocamlc will tell you where the compiler is located.
ocamlc -config will tell you where the standard library is expected to be.
It is also strongly advised to use opam, the OCaml Package Manager, to manage OCaml installations as it allows you to switch between multiple installations and gives you access to the latest compiler as soon as it's released.
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 :)
I am currently developing a C++ command line utility to be distributed as an open-source utility on Github. However, I want people who download the program to be able to easily compile and run the program on any platform (specifically Mac, Linux, and Windows) in as few steps as possible. Assuming only small changes have to be made to the code to make it compatible with the various platform-independent C++ compilers (g++ and win32), how can I do this? Are makefiles relevant?
My advice is, do not use make files, maintaining the files for big enougth projects is tedious and errors happen sometimes which you don't catch immediatly (because the *.o file is still there).
See this question here
Makefiles are indeed highly relevant. You may find that you need (at least) two different makefiles to compensate for the fact that you have different compilers.
It's hard to be specific about how you solve this, since it depends on how complex the project is. It may be easiest to write a script/batchfile, and just document "Use the command build.sh on Linux/Unix, and build.bat on Windows") - and then let the respective files deal with for example setting up the name of the compiler and flags, etc.
Or you can have an include into the makefile, which is determined by the architecture. Or different makefiles.
If the project is REALLY simple, it may be just enough to provide a basic makefile - but it's unlikely, as a compile of x.cpp on Linux/MacOS makes an object file is called x.o, on windows the object file is called x.obj. Libraries have different names, dll's have differnet names, and on Linux/MacOS, the final executable has no extension (typically) so it's called "myprog", where the executable under windows is called "myprog.exe".
These sorts of differences mean that the makefile needs to be different.
I'm building a special-purpose embedded Python interpreter and want to avoid having dependencies on dynamic libraries so I want to compile the interpreter with static libraries instead (e.g. libc.a not libc.so).
I would also like to statically link all dynamic libraries that are part of the Python standard library. I know this can be done using Freeze.py, but is there an alternative so that it can be done in one step?
I found this (mainly concerning static compilation of Python modules):
http://bytes.com/groups/python/23235-build-static-python-executable-linux
Which describes a file used for configuration located here:
<Python_Source>/Modules/Setup
If this file isn't present, it can be created by copying:
<Python_Source>/Modules/Setup.dist
The Setup file has tons of documentation in it and the README included with the source offers lots of good compilation information as well.
I haven't tried compiling yet, but I think with these resources, I should be successful when I try. I will post my results as a comment here.
Update
To get a pure-static python executable, you must also configure as follows:
./configure LDFLAGS="-static -static-libgcc" CPPFLAGS="-static"
Once you build with these flags enabled, you will likely get lots of warnings about "renaming because library isn't present". This means that you have not configured Modules/Setup correctly and need to:
a) add a single line (near the top) like this:
*static*
(that's asterisk/star the word "static" and asterisk with no spaces)
b) uncomment all modules that you want to be available statically (such as math, array, etc...)
You may also need to add specific linker flags (as mentioned in the link I posted above). My experience so far has been that the libraries are working without modification.
It may also be helpful to run make with as follows:
make 2>&1 | grep 'renaming'
This will show all modules that are failing to compile due to being statically linked.
CPython CMake Buildsystem offers an alternative way to build Python, using CMake.
It can build python lib statically, and include in that lib all the modules you want. Just set CMake's options
BUILD_SHARED OFF
BUILD_STATIC ON
and set the BUILTIN_<extension> you want to ON.
Using freeze doesn't prevent doing it all in one run (no matter what approach you use, you will need multiple build steps - e.g. many compiler invocations). First, you edit Modules/Setup to include all extension modules that you want. Next, you build Python, getting libpythonxy.a. Then, you run freeze, getting a number of C files and a config.c. You compile these as well, and integrate them into libpythonxy.a (or create a separate library).
You do all this once, for each architecture and Python version you want to integrate. When building your application, you only link with libpythonxy.a, and the library that freeze has produced.
You can try with ELF STATIFIER. I've been used it before and it works fairly well. I just had problems with it in a couple of cases and then I had to use another similar program called Ermine. Unfortunately this one is a commercial program.