How to fix the Unbound module Graphics in an ocaml project

Image
From ~/pr/gitl/ocaml-gol In a constant effort to learn new programming languages, I'm currently trying to use ocaml , a free and open-source general-purpose, multi-paradigm programming language maintained at the Inria . It's basically an extension of Caml with object-oriented features. I'm mostly interested by its functionnal and pattern matching features but the module part of the language can be a bit difficult to understand for someone with little to none ML (Meta Language) background.   The error When trying to use the graphics module to create a graphical window and go just a little further than the simplest helloworld program, here is the result : If the project uses dune : (executable (name ocaml_project) (libraries lwt.unix graphics) ) with this code : let () = Printf.printf "Hello, world!\n";; Lwt_io.printf "Hello, world!\n";; Graphics.open_graph " 800x600";; The first times I built this project running the du...

How to generate a file from a template using cmake

If you use cmake to configure a project, whatever the programming language the project is written in, you can and certainly already use the configure_file() cmake function to copy a file and modify its content using variables substitution.

A screenshot showing two calls to cmake's configure_file function.

The configure_file function

While this trick is generally used to generate, often plateform-dependant config.h from a config.h.in template, it can be used to generate arbitrary file using variable substitution. For example, Doxyfile, the file used to generate doxygen API documentation

Destination directory

You can also change the destination directory of the file. For example, often, we use a build/ subdirectory to call cmake from to avoid project source tree pollution :

configure_file(
  "${PROJECT_SOURCE_DIR}/config.h.in"
  "${PROJECT_BINARY_DIR}/config.h"
  )

The variables are PROJECT_SOURCE_DIR and PROJECT_BINARY_DIR to change the source and destination directory of the generated file. If you called cmake .. while inside the build directory, you could see that in a tree-like view :

.
├── config.h.in
└── build
    └── config.h

Including generated header

However, to be able to be able to correctly include config.h header, you must add the cmake binary dir and since, even if building from a build/ subdirectory seems to be a convention, you can't pretend to know this name, you obviously don't want to include build/config.h :

include_directories(${PROJECT_BINARY_DIR})

Variable substitution

One very usefull feature of this is the substitutions of variables. cmake generates a lot of variables and you can use their values in generated files. You can obviously define you own variable in CMakeLists.txt :

set(PROJECT  "prjname")
set(VERSION  0.0.10)
set(REVISION 30)
Then, in the template .in file :
#define PACKAGE        "${PROJECT}"
#define VERSION        "${VERSION}-${REVISION}"
#define VERSION_STRING "${PROJECT} v${VERSION}-${REVISION}"

After variable substitution, result will be, in another file, located in the build/ directory :

#define PACKAGE        "prjname"
#define VERSION        "0.0.10-30"
#define VERSION_STRING "prjname v0.0.10-30"

Conclusion

You can now generate files in the cmake/pre-compilation process so you can build your code using cmake-script defined variables using string substitution. Enjoy!

Comments

Popular posts from this blog

How to make a map of variant in C++