Search code examples
compiler-errorsclangocamlocaml-core

Why is there this compilation error for OCaml code?


I am currently testing out Facebook's Infer (open source) v0.17.0 and trying to build it from source code using the bash file by the command

$> ./build-infer.sh clang

However, I am getting an error compiling it, the error specifically happens like this.

[23:35:46][ 98156] Building clang plugin...
[      0s][ 98156] SUCCESS Building clang plugin
[23:35:46][ 98165] Building clang plugin OCaml interface...
[      0s][ 98165] SUCCESS Building clang plugin OCaml interface
[23:35:47][ 98205] Generating source dependencies...
[      0s][ 98205] SUCCESS Generating source dependencies
[23:35:47][ 98298] Building native(opt) Infer...
[*ERROR**][98298] *** ERROR 'Building native(opt) Infer'
[*ERROR**][98298] *** command: ' make INTERACTIVE=1 -C /home/roksui/Dev/dbtest/infer/src infer'
[*ERROR**][98298] *** CWD: '/home/roksui/Dev/dbtest'
[*ERROR**][98298] *** stdout:
[*ERROR**][98298] make[1]: Entering directory '/home/roksui/Dev/dbtest/infer/src'
[*ERROR**][98298] Makefile:122: recipe for target '/home/roksui/Dev/dbtest/infer/bin/infer.exe' failed
[*ERROR**][98298] make[1]: Leaving directory '/home/roksui/Dev/dbtest/infer/src'
[*ERROR**][98298] *** stderr:
[*ERROR**][98298] Entering directory '/home/roksui/Dev/dbtest/infer'
[*ERROR**][98298] File "src/base/Utils.ml", line 322, characters 4-13:
[*ERROR**][98298] 322 |     Unix.dup2 ~src ~dst:Unix.stderr () ;
[*ERROR**][98298]           ^^^^^^^^^
[*ERROR**][98298] Error: This function has type
[*ERROR**][98298]          src:IStdlib.IStd.Unix.File_descr.t ->
[*ERROR**][98298]          dst:IStdlib.IStd.Unix.File_descr.t -> unit
[*ERROR**][98298]        It is applied to too many arguments; maybe you forgot a `;'.
[*ERROR**][98298] make[1]: *** [/home/roksui/Dev/dbtest/infer/bin/infer.exe] Error 1

It seems to be a problem with the function Unix.dup2 having too many arguments and so I searched the ml file and below is the code snippet of where the error is occuring.

let suppress_stderr2 f2 x1 x2 =
  let restore_stderr src =
    Unix.dup2 ~src ~dst:Unix.stderr () ;
    Unix.close src
  in
  let orig_stderr = Unix.dup Unix.stderr in
  Unix.dup2 ~src:(Lazy.force devnull) ~dst:Unix.stderr () ;
  let f () = f2 x1 x2 in
  let finally () = restore_stderr orig_stderr in
  protect ~f ~finally

From what I know, Unix.dup2 function accepts two arguments src and dst. But what is happening here with the extra unit argument ()?

Does this error happen because I am using a wrong version of ocaml compiler? Why is this error occuring? Any insight would be appreciated. Thank you.


Solution

  • Facebook Infer uses the core standard library replacement, v0.14.x, which had a terminating unit argument. The latest version no longer does. So the problem seems to be that you have the wrong version installed.

    Edit: Actually, I looked at the wrong docs, which despite being hosted at jane street and mentioning core several times in the URL, seems to actually be the documentation for the OCaml std lib Unix module. The latest version of Unix.dup2 in Core still has the optional and terminating unit argument. Which probably means that you don't have Core installed at all. But either way you need to go back and review the build and prerequisite instructions I think.

    A terminating unit argument is conventionally used when you have a function with optional arguments and otherwise only labeled arguments. As labeled arguments can be applied in any order the compiler therefore cannot know if a function application without the optional arguments should be considered partially or fully applied. It will assume partial application, and the optional argument is therefore not actually optional in that case. To remedy that, a non-labeled unit argument is often used to tell the compiler that the function should be considered fully applied.

    For some reason the optional argument was removed from dup2, along with the terminating unit argument since it was no longer needed.