How to make library installed from OPAM available to OCaml? - linux

I followed this tutorial on OCaml FFI and installed Ctypes through OPAM:
opam install ctypes
However, OCaml does not find the module:
open Ctypes
(* ... *)
I receive the error:
Unbound module Ctypes
It looks like I need to let OCaml know where my Ctypes installation is? Do I need to update some path variable to let OCaml look for my libraries installed through OPAM?
This is Ubuntu 15.04, OCaml 4.01.0, OPAM 1.2.0.

Installing something on your system doesn't make it automatically visible for the compiler, this is true not only for OCaml, but for most conventional systems, like C or C++ to name a few.
That means that you need to pass some flags to the compiler, or to write Makefiles, or to use some project management systems.
In OCaml we have quite a mature infrastructure that plays very well with opam in particular. I do not want to go very deeply in explanations, just a fast overview.
ocamlfind tool is used to find libraries on your system. It is somewhat close to pkg-config in idea, but quite different in design. It wraps compiler tools in order to pass options to them.
ocamlbuild is a fancy swiss-knife that is a must have in the arsenal of every OCamler. It is a tool that knows all other tools, and how to glue them together. I would say that it is the preferred way to compile your projects, especially small one.
oasis is close to autotools in the spirit, but not that generic and is written in the premise, that it should be very easy to use. And indeed it is very easy, but still quite flexible and powerful.
With this overview in mind, we can go directly to your problem. So you've installed ctypes. Now let's take a look on how ctypes package is visible in your system from the ocamlfind perspective. The easiest way would be to list all packages, visible to ocamlfind and find ctypes there:
$ ocamlfind list | grep ctypes
ctypes (version: 0.4.1)
ctypes.foreign (version: 0.4.1)
ctypes.stubs (version: 0.4.1)
ctypes.top (version: 0.4.1)
So, it looks like, that under the ctypes umbrella there're 4 libraries. One basic library, and some extra libraries, that provides some functionality, that is not needed by default.
No let's try to use them with ocamlbuild
ocamlbuild -package ctypes yourprogram.native
Or, without ocamlbuild directly with ocamlfind:
ocamlfind ocamlopt -package ctypes yourprogram.ml -o yourprogram.native
As you may see, there is a package option, to which you can pass a name of the package as found by ocamlfind, and it will be automagically made visible to the compiler.

Related

NixOS, Haskell LSP in Neovim, XMonad imports are not found

Here is a screenshot of the problem:
OS: NixOS, unstable channel.
Neovim: 0.7.2.
Haskell LSP: haskell-language-server.
Running xmonad --recompile in the terminal works.
Please help :-)
EDIT 1:
As asked by #ArtemPelenitsyn in the comments below, here is my init.lua: https://pastebin.com/70jMHm02.
The parts that I think relevant:
require'lspconfig'.hls.setup{}
I think it's something more related to NixOS and not to Neovim.
EDIT 2:
As asked by #Ben in the comments below, here is the needed info:
λ ghci
GHCi, version 9.0.2: https://www.haskell.org/ghc/ :? for help
ghci> import XMonad
<no location info>: error:
Could not find module ‘XMonad’
It is not a module in the current program, or in any known package.
ghci>
Here is everything related to Haskell and XMonad in my configuration.nix:
# snip
services.xserver.windowManager.xmonad.enable = true;
services.xserver.displayManager.defaultSession = "none+xmonad";
services.xserver.windowManager.xmonad.enableConfiguredRecompile = true;
services.xserver.windowManager.xmonad.enableContribAndExtras = true;
# snip
environment.systemPackages = with pkgs; [
ghc
haskell-language-server
haskellPackages.xmobar
haskellPackages.xmonad
haskellPackages.xmonad-contrib
];
# snip
In your configuration.nix, you have the following:
environment.systemPackages = with pkgs; [
ghc
haskell-language-server
haskellPackages.xmobar
haskellPackages.xmonad
haskellPackages.xmonad-contrib
];
Here you actually haven't installed a GHC that can access the xmobar, xmonad, and xmonad-contrib packages. Installed you've installed a GHC that doesn't know about any packages, and separately installed those Haskell packages. Any executables in those packages will be added to the PATH environment variable (which is how you can actually run xmonad), but PATH isn't know GHC finds installed packages. You need another step to connect the installation of GHC with the packages, so that you (and haskell-language-server) can import them.
The reason is that the way GHC is expecting to work is that installing packages is a mutating operation on the file system. On a "normal" system you install GHC and it knows about the packages that were bundled with it, then you install another package like xmonad into a folder that GHc will look in for packages1 and now the effect of running that same ghc program has changed.
Nix doesn't like that. Packages are supposed to be immutable in Nix. You can't change a GHC-without-xmonad into a GHC-with-xmonad after the fact.
So just installing pkgs.ghc isn't actually what you want. That package is already completely determined by the nix code that evaluates to, and the package it determines is a baseline ghc with no additional packages. Instead you need to create an entirely new package that consists of GHC installed with xmonad.
Fortunately, this is an extremely common need so there is already a wrapper function to generate this package for you. haskellPackages.ghcWithPackages2. This function takes a single argument, which must be a function you provide. That function will itself be called on a single argument which is the collection of Haskell packages available, and should return a list of which ones you want included in the GHC installation package you're building.
So that means what you actually want is something like this:
environment.systemPackages = with pkgs; [
haskell-language-server
# If you want you can use `with hpkgs; [` to avoid explicitly
# selecting into the hpkgs set on every line
(haskellPackages.ghcWithPackages (hpkgs: [
hpkgs.xmobar
hpkgs.xmonad
hpkgs.xmonad-contrib
]))
];
Under the hood what ghcWithPackages actually does is install ghc and those packages, just as you did, but then it also creates a very small "wrapper package" around ghc that sets environment variables telling it where to find the specific set of packages you installed. The thing that gets added to PATH to provide commands like ghc, ghci, etc is not the underlying GHC, but the wrapped one.3
You don't really need to know any of this "under the hood" stuff, just that every time you need GHC to have a specific set of packages you need to create a new nix package with ghcWithPackages. Knowing that it's based on wrapper scripts can help you not stress about space being wasted though; if you have 100 Haskell projects they can all share any GHC versions and Haskell package versions that are common; it's only the tiny wrappers that you have 100 copies of.
This is also the basic model used by most programming languages that have direct support in nixpkgs (and even some other things that aren't strictly programming languages but can be extended by installing plugins after the fact). It doesn't work precisely the same way for every language, as it depends on what code had to be written around the packaging tools each language has. But the basic conceptual model is frequently something like this.
This is all documented in the nixpkgs manual; as opposed to the manual for Nix itself, or for NixOS. It has a section on Languages and Frameworks where you can find the documentation for how a number of programming language ecosystems are supported in nixpkgs. Although the Haskell section under that has been turned into a small paragraph telling you to go to a separate site for the nixpkgs Haskell docs.
One final note: I'm not 100% sure whether haskell-language-server will just automatically pick up the ghc in your PATH and run with those packages, or if you need any further configuration. Since I am a Haskell developer I have a number of projects that each need different sets of available packages (or even GHC version in some cases), so I don't have any GHC (or HLS) installed at the environment.system-packages level; each of my projects has its own shell environment, ultimately generated from the projects .cabal file. This means I've never actually used haskell-language-server on "loose" Haskell files living outside of a project, and I'm not sure whether you need to do anything more to get it to work. But this is definitely what you need to get ghci> import XMonad to work (without dramatically changing how you do things).
1 And I believe also update some registry files, but I'm not 100% across all of the details. They're not important for this level of explanation.
2 And if you don't like the version of GHC (and everything else) contained in haskellPackages, all the other Haskell package sets also contain this ghcWithPackages function, such as haskell.packages.ghc924, haskell.packages.ghc8102, etc (the top level haskellPackages is one of these sets; whichever is determined to be a good default in the revision of nixpkgs you happen to be using).
3 The environment variables I can see in the wrapper script all have NIX_ in the name, so I suspect the base GHC packages in nixpkgs are patched to support this behaviour.

Haskell Platform Installation

I tried to install Haskell Platform from the official website and they asked me to configure Chocolatey on my computer and then to run choco install haskell-dev refreshenv, so I did it and installed:
ghc v8.10.1
chocolatey-core.extension v1.3.5.1
haskell-dev v0.0.1
msys2 v20190524.0.0.20191030
cabal v3.2.0.0
and now i have no idea how to get started with the Haskell and whether I've installed everything I needed, could somebody help me?
This looks like pretty much everything you need. It looks like you’re struggling a bit to understand what everything is for, so I’ll explain the purpose of each component:
ghc is the Glasgow Haskell Compiler a.k.a. GHC, which compiles your code to an executable. Also included in this package is ghci, the GHC interpreter a.k.a. GHCi, which you can use to interactively enter and execute code.
haskell-dev appears to be an auxiliary package to get msys2 properly set up.
msys2 is MSYS2, which provides an environment allowing access to Unix-like tools. You won’t need it for simple stuff, but it can be invaluable when trying to build some Haskell packages.
cabal is the Haskell package manager. (Well, one Haskell package manager: the alternative is Stack, which is compatible with Cabal.) You’ll be using this to develop, build and install Haskell packages.
As for ‘how to get started with Haskell’, this isn’t really the place to ask (maybe try Reddit /r/haskell), but off the top of my head I can think of http://learnyouahaskell.com/ and https://haskellbook.com/ as well-known resources for learning the basics. If you already know the basics and want to start learning more advanced features, try What I Wish I Knew When Learning Haskell.

OCaml graphics package

I have installed OCaml on my xfce and now I want to do some graphics program.
The problem is that I don't know how I can install graphics.cma ( I think it's this file that I need but i'm not sure ).
I have research on Google and in This forum but I can't find it..
After little search, I see that i have graphics.cma and graphics.cmxa .
I found this with ls $(ocamlc -where) | egrep cmx?a
I don't know why but yet, my graphics function work at all.
Sorry for inconvenience.
Thanks for helping me guys.
Have a nice day
I would suggest installing and using ocamlfind in order to not have to worry about library location:
ocamlfind ocamlc -package graphics -linkpkg test.ml
will compile your file with the right files loaded.
You can also load the package in the toplevel using
#use "topfind";;
#require "graphics";;
You have already installed the graphics module.
On Debian based systems the ocaml package is split into ocaml-base-nox and ocaml-base. The later contains the graphics module while the former is trimmed down.
The ocaml package is a meta package that depends on both of those and the description says (at the end):
This package contains everything needed to develop OCaml applications,
including the graphics libraries.
So you are all set to play with graphics. Juliens answere of installing ocamlfind is a good idea though as it makes using graphics and other modules easier.

How to compile ocaml program with using Graphics module by ocamlopt?

As I understand, graphics.cmax isn't exist.
But how to compile ocaml program with using Graphics module by ocamlopt?
Is it possible? Maybe some alternative graphics libraries?
Well, graphics.cmax indeed doesn't exist, why it should? But graphics.cmxa does. So of course it is possible compile programs that use graphics library to a machine code. You can use ocamlfind to find a proper library depending on your compilation mode. For example on mine machine:
$ ocamlfind query -predicates native -a-format graphics
/home/ivg/.opam/fresh/lib/ocaml/graphics.cmxa
In a simple case, like this, with the graphics library that is distributed with the OCaml system itself, you can just add graphics.cmxa to the compilation string. On more complex cases, just use ocamlfind ocamlopt instead of ocamlopt, and specify -package option to refer to a library name, in your case it would be:
$ ocamlfind ocamlopt -package graphics ...
Or you can use ocamlbuld:
$ ocamlbuild -package graphics my_cool_application.native
where your cool application has an entry point in the my_cool_application.ml file.

How to upgrade Haskell Platform

I have the Haskell Platform 2012.4 installed on Windows. I would like to try the new extensions in GHC 7.6.2. It looks like the GHC 7.6.2 x86_64 download does not include an installer and is just the binaries. What is the proper way to get the latest version installed and set as the default for building Haskell projects? Thanks.
If you download GHC itself, you just get GHC and a tiny handful of libraries. If you download the Haskell Platform, you get GHC plus a much bigger collection of libraries. However, the Haskell Platform is updated infrequently, so you'll get an older version of GHC.
If you're asking "how do I install the Haskell Platform and then make it work with a newer GHC?", then the answer is "you don't". Haskell libraries have to be compiled for the specific version of GHC you're using.
You basically have two options:
Use the Haskell Platform, together with the version of GHC that it supplies.
Use the latest GHC, and compile whatever libraries you want manually.
On Linux it's not too bad, but Haskell libraries that bind to external C code tend to be fiddly to build on Windows. (Stuff like OpenGL, zlib, etc.) Packages that are 100% vanilla Haskell code are drop-dead easy to compile on any system.
I haven't done this and I'm at work so I can't test it out, but looking at the GHC docs I would think you can use the --with-compiler=path flag to select which version of GHC to use?
See also this question, related to using cabal with multiple versions of ghc installed. I would guess that you probably want to use cabal-dev or something to sandbox this, otherwise your package database may become a mess.
EDIT: As far as a default, I think you can set that in a cabal configuration file. See the comments to the accepted answer in that question I linked.
The other answers here are great, and I wanted to add that the current best way to get the latest version of GHC installed is to look at haskell.org's installation instructions. I bounced between lots of different options before I landed there, and I think it's the best source of truth from what I can tell.
To summarize the current instructions: if you already have chocolately set up, "at an elevated command prompt, run choco install haskell-dev, followed by refreshenv."

Resources