CmdLiner package is invoking multiple commands, not only the one I requesed

newbie question:

I think I followed (but most likely have made some mistake) in how to handle a CmdLiner.Term project which has 7 subcommands, each with 0, 1, or 2 arguments.

I am two issues I am seeing

The command
ocommander TemplateCreate takes two arguments -name NAME -path PATH

But when I run it with no arguments, I find it invokes two addidtional commands (oCmmand and templateList) which have no arguments, in addition to the TemplateCreate command.

(as you can see I am using BuckleScript to execute, but I don’t think that is the issue).

D:\CRIME\ocommander\src>node ocommander.bs.js TemplateCreate
* dummy - do not call * ** template list called in error ** TemplateCreate - name: *dummy* path:

The second issue is tied to this. What I am really want to say is that TemplateCreate has two REQUIRED arguments -name NAME and -path PATH

and if they are not supplied then help for TemplateCreate should be shown. I guess what I am asking for is REQUIRED options (maybe an oxymoron), but I don’t want positional arguments, since the order is not important, and folks like the -arg VALUE syntax.

The code probably has too much boilerplate, but it does make it easy to read:

(* Demo, just print the args. *)
open Cmdliner 
[%%raw "process.argv.shift()"]

let actionHelp = [
 `S "COMMAND HELP";
 `P "Use `$(mname) $(i,COMMAND) --help' for help on a single command.";
 `S Manpage.s_bugs; `P "Email bug reports to jpaasch@draper.com";]

(* Actions *) 

let oCommander = 
  Printf.printf "* dummy - do not call * "

let templateCreate name path = 
  Printf.printf "TemplateCreate - name: %s path: %s" name path

let templateDetails name = 
  Printf.printf "TemplateDetails - name: %s" name

let templateList = 
  Printf.printf "** template list called in error ** " 

let deployStack deployment template provider = 
  Printf.printf "DeployStack - deployment: %s template: %s provider: %s" deployment template provider

let deployRemove deployment template provider = 
  Printf.printf "DeployRemove - deployment: %s template: %s provider: %s" deployment template provider

(* Arguments *)

let nameArg =
  let doc = "$(docv) of the template" in
  Arg.(value & opt string "*dummy*" & info ["n"; "name"] ~docv:"NAME" ~doc)

let pathArg =
  let doc = "$(docv) to template file" in
  Arg.(value & opt string "" & info ["p"; "path"] ~docv:"PATH" ~doc)

let deployArg =
  let doc = "$(docv) - name to use for deployment" in
  Arg.(value & opt string "" & info ["d"; "deployment"] ~docv:"DEPLOYMENT" ~doc)

let templateArg =
  let doc = "$(docv) - name of template" in 
  Arg.(value & opt string "" & info ["t"; "template"] ~docv:"TEMPLATE" ~doc)

let providerArg = 
  let doc = "$(docv) - cloud Provider (e.g. AWS)" in
  Arg.(value & opt string "" & info ["p"; "provider"] ~docv:"PROVIDER" ~doc)

(* Help Terms *)

let oCommanderHelp =
  let doc = "CLI for CRIME System" in
  let exits = Term.default_exits in
  let man =  [`Blocks actionHelp; ] in
  Term.(const oCommander ),
  Term.info "oCommander" ~doc ~exits ~version:"0.1.0" ~man

let templateCreateHelp = 
let doc = "Create a Template from a file" in
let exits = Term.default_exits in
  Term.(const templateCreate $ nameArg $ pathArg), 
    Term.info "TemplateCreate" ~doc ~exits

let templateDetailsHelp = 
let doc = "Show Details about a Template" in
let exits = Term.default_exits in
  Term.(const templateDetails $ nameArg ), 
    Term.info "TemplateDetails" ~doc ~exits

let templateListHelp = 
let doc = "List all Templates for this user" in
let exits = Term.default_exits in
  Term.(const templateList ), 
    Term.info "TemplateList" ~doc ~exits

let deployStackHelp = 
let doc = "Deploy a Stack to a Provider" in
let exits = Term.default_exits in
  Term.(const deployStack $ deployArg $ templateArg $ providerArg ), 
    Term.info "DeployStack" ~doc ~exits 
 
let deployRemoveHelp = 
let doc = "Remove a deployed stack from a Provider" in
let exits = Term.default_exits in
  Term.(const deployRemove $ deployArg $ templateArg $ providerArg ), 
    Term.info "DeployRemove" ~doc ~exits 

(* Run *)

let actions = [templateCreateHelp; templateDetailsHelp; templateListHelp; deployStackHelp; deployRemoveHelp]
let () = Term.(exit @@ eval_choice oCommanderHelp actions)

These are not functions but toplevel expressions which are evaluated on any program run during the initialisation of the module.

You likely wanted to write

let oCommander () = Printf.printf ...

Yes, I suspected they were being run at init. But this is why the question is in the beginners section!

When I modify the definition as you suggested:

let oCommander () = Printf.printf "* dummy - do not call * "

I get a compile issue on the last line that was not there before:

let () = Term.(exit @@ eval_choice oCommanderHelp actions)
Error: This expression has type
         (unit Cmdliner.Term.t * Cmdliner.Term.info) list
       but an expression was expected of type
         ((unit -> unit) Cmdliner.Term.t * Cmdliner.Term.info) list
       Type unit is not compatible with type unit -> unit 

I believe the issue is easier to see if I just change the signature of the templateList function

Error: This expression has type
         (unit -> unit) Cmdliner.Term.t * Cmdliner.Term.info
       but an expression was expected of type
         unit Cmdliner.Term.t * Cmdliner.Term.info
       Type unit -> unit is not compatible with type unit 

which happens on the templateListHelp element of the array:

let actions = [templateCreateHelp; templateDetailsHelp; templateListHelp; deployStackHelp; deployRemoveHelp]

I am still trying to figure out how to make these arguments required, not purely optional.

Well if you change the types and it compiled before, it’s not surprising it doesn’t compile anymore! :slight_smile:

Now that you have fixed your code to define functions rather than values, you need to make sure that they are supplied with their argument. There is an example of how to do it in the β€œbasics” section of the docs:

open Cmdliner
let revolt () = print_endline "Revolt!"
let revolt_t = Term.(const revolt $ const ())

As for making your arguments required, there is a Arg.required function with type 'a option Arg.t -> 'a Term.t.

To figure out how to use it, you need to let the types guide you. You need to produce a string option Arg.t rather than a string Arg.t. So you need a string option Arg.conv. You then find that Arg.some can produce that, so you replace string with (some string). The last missing piece is that in the type of Arg.opt, the argument for the default value now needs to be a string option, so instead of "" you put the natural default for an option type, None.

At the end of the day, for instance, this:

Arg.(value & opt string "" & info ["t"; "template"] ~docv:"TEMPLATE" ~doc)

becomes:

Arg.(required & opt (some string) None & info ["t"; "template"] ~docv:"TEMPLATE" ~doc)

Notice that thanks to the option type your program is now more robust: since you’re no longer using a dummy string value, there is no risk of mistakenly using the dummy value as if it came from the command line.

1 Like

@threepwood , really outstanding. Not only how to fix, but a great lesson in OCAML typing (I only read the OCAML from the beginning book, but it was not sufficient for these types of parameterized types).

I did now just try and do something a bit more sophisticate, to enforce not just a string but a file for the end of the path:

 let pathArg =
  let doc = "$(docv) to template file" in
  Arg.(required & opt (some Arg.non_dir_file) None & info ["p"; "path"] ~docv:"PATH" ~doc)

But when I try to reference a file in my current path, which I know exists, I get a run-time error.

D:\CRIME\ocommander>node src\ocommander.bs.js TemplateCreate --name test1 --path package.json

C:\Users\ysg4206\AppData\Roaming\npm\node_modules\bs-platform\lib\js\printexc.js:273
  if (slot.tag) {
       ^
TypeError: Cannot read property 'tag' of undefined
    at format_backtrace_slot (C:\Users\ysg4206\AppData\Roaming\npm\node_modules\bs-platform\lib\js\printexc.js:273:12)
    at Object.raw_backtrace_to_string (C:\Users\ysg4206\AppData\Roaming\npm\node_modules\bs-platform\lib\js\printexc.js:378:19)
    at Object.pp_backtrace (D:\CRIME\ocommander\node_modules\@elliottcable\bs-cmdliner\src\cmdliner_msg.bs.js:461:23)
    at do_result (D:\CRIME\ocommander\node_modules\@elliottcable\bs-cmdliner\src\cmdliner.bs.js:309:24)
    at Object.eval_choice (D:\CRIME\ocommander\node_modules\@elliottcable\bs-cmdliner\src\cmdliner.bs.js:452:12)
    at Object.<anonymous> (D:\CRIME\ocommander\src\ocommander.bs.js:363:24)
    at Module._compile (internal/modules/cjs/loader.js:689:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
    at Module.load (internal/modules/cjs/loader.js:599:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:538:12)

I assumed it might have to do with the NONE default argument, but my understanding of NONE (from haskell) is that NONE should already be something like

(None : option Arg.file ) - which does not work anyway.

So I’m afraid I can’t help you with that one, because it looks like an error related to JS / Node, and I have no experience with how the file system works when using Node + Bucklescript. One thing is that I suspect your code would run fine if you compiled it with the base compiler. (Or maybe the code would fail but you would at least get a more intelligible error – it looks like the error might have occurred while printing an earlier error?)

It might be worth asking on the Reason forums or discord if you can’t figure it out.

At any rate, I am not sure I understand what you mean by this:

but:

  1. The type of None is 'a option in general and string option in the specific context of your code. Type constructors come second in OCaml.

  2. Like in Haskell, with option types library authors can create APIs where there is no risk of any runtime errors like β€œundefined property”, null-accesses, missing attributes or whatever. So the fact there is something like that here should make you suspect this is a javascript problem. (In particular there is no such thing as β€œundefined” in OCaml.)

Gotcha. Well, before I try the BuckleScript folks, let me tell you what I tried with getting this working with the OCAML build system (which my senior team mates say is less developed than haskell, Personally, I don’t have an opinion.)

using utop: (note utop crashes and the end of loading my package, some thing about a lock file not being created).

utop # #use "topfind"
;;
- : unit = ()
Findlib has been successfully loaded. Additional directives:
  #require "package";;      to load a package
  #list;;                   to list the available packages
  #camlp4o;;                to load camlp4 (standard syntax)
  #camlp4r;;                to load camlp4 (revised syntax)
  #predicates "p,q,...";;   to set these predicates
  Topfind.reset();;         to force that packages will be reloaded
  #thread;;                 to enable threads

- : unit = ()
─( 17:26:50 )─< command 7 >──────────────────────────────────────{ counter: 0 }─

utop # #require "Cmdliner";;
─( 17:29:11 )─< command 8 >──────────────────────────────────────{ counter: 0 }─

utop # #use "ocommander.ml";;
File "ocommander.ml", line 3, characters 3-6:
Error: Uninterpreted extension 'raw'.
─( 17:29:25 )─< command 9 >──────────────────────────────────────{ counter: 0 }─

utop # #use "ocommander.ml";;
val actionHelp : [> `P of string | `S of string ] list =
  [`S "COMMAND HELP";
   `P "Use `$(mname) $(i,COMMAND) --help' for help on a single command.";
   `S "BUGS"; `P "Email bug reports to jpaasch@draper.com"]
val oCommander : unit -> unit = <fun>
val templateCreate : string -> string -> unit = <fun>
val templateDetails : string -> unit = <fun>
val templateList : unit -> unit = <fun>
val deployStack : string -> string -> string -> unit = <fun>
val deployRemove : string -> string -> string -> unit = <fun>
val nameArg : string Term.t = <abstr>
val pathArg : string Term.t = <abstr>
val deployArg : string Term.t = <abstr>
val templateArg : string Term.t = <abstr>
val providerArg : string Term.t = <abstr>
val oCommanderHelp : unit Term.t * Term.info = (<abstr>, <abstr>)
val templateCreateHelp : unit Term.t * Term.info = (<abstr>, <abstr>)
val templateDetailsHelp : unit Term.t * Term.info = (<abstr>, <abstr>)
val templateListHelp : unit Term.t * Term.info = (<abstr>, <abstr>)
val deployStackHelp : unit Term.t * Term.info = (<abstr>, <abstr>)
val deployRemoveHelp : unit Term.t * Term.info = (<abstr>, <abstr>)
val actions : (unit Term.t * Term.info) list =
  [(<abstr>, <abstr>); (<abstr>, <abstr>); (<abstr>, <abstr>);
   (<abstr>, <abstr>); (<abstr>, <abstr>)]
utop.exe: lambda-term(history): failed to lock file 'D:\cygwin64\home\ysg4206\.u
top-history': A requested file lock operation cannot be processed due to an inva
lid byte range.
utop.exe: lambda-term(history):
* dummy - do not call *
ysg4206@YSG4206 ~

So then I tried to directly compile:

ysg4206@YSG4206 ~
$ ocamlfind ocamlopt -o ocomander -package Cmdliner ocommander.ml
File "ocommander.ml", line 1:
Error: No implementations provided for the following modules:
         Cmdliner referenced from ocommander.cmx

ysg4206@YSG4206 ~

So I’m not familiar enough with the inner workings of utop, especially on Windows, to say what exactly fails here, but I can see why it doesn’t work. utop is not a build tool, it’s meant to be used interactively, and while the #use directive lets you load a bunch of commands at once it is not meant to be able to run arbitrary programs. Your code interacts with the command line, and as an interactive program utop is going to hijack your terminal, so there’s really no reason it should work.

As for your second error, the findlib quick start guide says:

If you want to create an executable, do not forget to add the -linkpkg switch:

$ ocamlfind ocamlc -o myprogram -package netstring -linkpkg myprogram.cmo

(I’m also surprised you got this error with -package Cmdliner, I thought the correct form was -package cmdliner and you would have gotten β€œpackage not found”, but maybe it’s a windows thing.)

Note though that these days people usually use dune to build their programs rather than invoke ocaml* manually.

Thanks for the tip on dune. Looks like what I am looking for. I probably should post this as a new thread:

OPAM on Windows switch create issue:

I don’t think the help page on OPAM gives me enough info to figure out this myself. (https://opam.ocaml.org/doc/Usage.html )

Here is when I try to do a - (probably need to specify a more specific compiler, but which one?)

$opam --version 
2.0.5
$ opam switch create . ocaml-variants

 checking for x86_64-pc-windows-link... no
# checking for ld... ld
# checking how to print strings... printf
# checking for x86_64-pc-windows-gcc... cl
# checking whether the C compiler works... no
# configure: error: in `/cygdrive/d/crime/dune/_opam/.opam-switch/build/ocaml-variants.4.10.0+beta1+msvc64':
# configure: error: C compiler cannot create executables
# See `config.log' for more details



<><> Error report <><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>β”Œβ”€ The following actions failed
β”‚ Ξ» build ocaml-variants 4.10.0+beta1+msvc64
└─
β”Œβ”€ The following changes have been performed (the rest was aborted)
β”‚ βˆ— install base-bigarray base
β”‚ βˆ— install base-threads  base
β”‚ βˆ— install base-unix     base

here is what opam says is available for compilers:

(latest 64 bit non-beta would probably what I would guess).

 opam switch list-available
# Listing available compilers from repositories: default
# Name         # Version                            # Synopsis
ocaml-variants 3.12.1+mingw32                       3.12.1 release (mingw32)
ocaml-variants 4.00.1+mingw32                       4.00.1 release (mingw32)
ocaml-variants 4.00.1+mingw64                       4.00.1 release (mingw64)
ocaml-variants 4.01.0+mingw32                       4.01.0 release (mingw32)
ocaml-variants 4.01.0+mingw32c
          pre-compiled 4.01.0 build (mingw32)
ocaml-variants 4.01.0+mingw64                       4.01.0 release (mingw64)
ocaml-variants 4.01.0+mingw64c
          pre-compiled 4.01.0 build (mingw64)
ocaml-variants 4.02.3+mingw32                       4.02.3 release (mingw32)
ocaml-variants 4.02.3+mingw32c
          pre-compiled 4.02.3 build (mingw32)
ocaml-variants 4.02.3+mingw64                       4.02.3 release (mingw64)
ocaml-variants 4.02.3+mingw64c
          pre-compiled 4.02.3 build (mingw64)
ocaml-variants 4.03.0+flambda+mingw32
          4.03.0 release for mingw32 with flambda activated
ocaml-variants 4.03.0+flambda+mingw32c
          pre-compiled 4.03.0-flambda build (mingw32)
ocaml-variants 4.03.0+flambda+mingw64
          4.03.0 release for mingw64 with flambda activated
ocaml-variants 4.03.0+flambda+mingw64c
          pre-compiled 4.03.0-flambda build (mingw64)
ocaml-variants 4.03.0+mingw32                       4.03.0 release for mingw32
ocaml-variants 4.03.0+mingw32c
          pre-compiled 4.03.0 build (mingw32)
ocaml-variants 4.03.0+mingw64                       4.03.0 release for mingw64
ocaml-variants 4.03.0+mingw64c
          pre-compiled 4.03.0 build (mingw64)
ocaml-variants 4.03.0+msvc32
          4.03.0 release for msvc32 (please configure your environment
          manually)
ocaml-variants 4.03.0+msvc64
          4.03.0 release for msvc64 (please configure your environment
          manually)
ocaml-variants 4.04.0+flambda+mingw32
          4.04.0 release with flambda activated (mingw32)
ocaml-variants 4.04.0+flambda+mingw32c
          pre-compiled 4.04.0 release with flambda activated (mingw32)
ocaml-variants 4.04.0+flambda+mingw64
          4.04.0 release with flambda activated (mingw64)
ocaml-variants 4.04.0+flambda+mingw64c
          pre-compiled 4.04.0 release with flambda activated (mingw64)
ocaml-variants 4.04.0+mingw32                       4.04.0 release (mingw32)
ocaml-variants 4.04.0+mingw32c
          pre-compiled 4.04.0 release (mingw32)
ocaml-variants 4.04.0+mingw64                       4.04.0 release (mingw64)
ocaml-variants 4.04.0+mingw64c
          pre-compiled 4.04.0 release (mingw64)
ocaml-variants 4.04.0+msvc32                        4.04.0 release (msvc32)
ocaml-variants 4.04.0+msvc64                        4.04.0 release (msvc64)
ocaml-variants 4.04.0+msvc64c
          pre-compiled 4.04.0 release for AppVeyor (msvc64)
ocaml-variants 4.04.1+flambda+mingw32
          4.04.1 release with flambda activated (mingw32)
ocaml-variants 4.04.1+flambda+mingw32c
          pre-compiled 4.04.1 release with flambda activated (mingw32)
ocaml-variants 4.04.1+flambda+mingw64
          4.04.1 release with flambda activated (mingw64)
ocaml-variants 4.04.1+flambda+mingw64c
          pre-compiled 4.04.1 release with flambda activated (mingw64)
ocaml-variants 4.04.1+mingw32                       4.04.1 release (mingw32)
ocaml-variants 4.04.1+mingw32c
          pre-compiled 4.04.1 release (mingw32)
ocaml-variants 4.04.1+mingw64                       4.04.1 release (mingw64)
ocaml-variants 4.04.1+mingw64c
          pre-compiled 4.04.1 release (mingw64)
ocaml-variants 4.04.1+msvc32                        4.04.1 release (msvc32)
ocaml-variants 4.04.1+msvc64                        4.04.1 release (msvc64)
ocaml-variants 4.04.1+msvc64c
          pre-compiled 4.04.1 release for AppVeyor (msvc64)
ocaml-variants 4.04.2+flambda+mingw32
          4.04.2 release with flambda activated (mingw32)
ocaml-variants 4.04.2+flambda+mingw32c
          pre-compiled 4.04.2 release with flambda activated (mingw32)
ocaml-variants 4.04.2+flambda+mingw64
          4.04.2 release with flambda activated (mingw64)
ocaml-variants 4.04.2+flambda+mingw64c
          pre-compiled 4.04.2 release with flambda activated (mingw64)
ocaml-variants 4.04.2+mingw32                       4.04.2 release (mingw32)
ocaml-variants 4.04.2+mingw32c
          pre-compiled 4.04.2 release (mingw32)
ocaml-variants 4.04.2+mingw64                       4.04.2 release (mingw64)
ocaml-variants 4.04.2+mingw64c
          pre-compiled 4.04.2 release (mingw64)
ocaml-variants 4.04.2+msvc32                        4.04.2 release (msvc32)
ocaml-variants 4.04.2+msvc32c
          pre-compiled 4.04.2 release for AppVeyor (msvc32)
ocaml-variants 4.04.2+msvc64                        4.04.2 release (msvc64)
ocaml-variants 4.04.2+msvc64c
          pre-compiled 4.04.2 release for AppVeyor (msvc64)
ocaml-variants 4.05.0+flambda+mingw32
          4.05.0 release (mingw32) with flambda activated
ocaml-variants 4.05.0+flambda+mingw32c
          pre-compiled 4.05.0 release with flambda activated (mingw32)
ocaml-variants 4.05.0+flambda+mingw64
          4.05.0 release (mingw64) with flambda activated
ocaml-variants 4.05.0+flambda+mingw64c
          pre-compiled 4.05.0 release with flambda activated (mingw64)
ocaml-variants 4.05.0+mingw32                       4.05.0 release (mingw32)
ocaml-variants 4.05.0+mingw32c
          pre-compiled 4.05.0 release (mingw32)
ocaml-variants 4.05.0+mingw64                       4.05.0 release (mingw64)
ocaml-variants 4.05.0+mingw64c
          pre-compiled 4.05.0 release (mingw64)
ocaml-variants 4.05.0+msvc32                        4.05.0 release (msvc32)
ocaml-variants 4.05.0+msvc32c
          pre-compiled 4.05.0 release for AppVeyor (msvc32)
ocaml-variants 4.05.0+msvc64                        4.05.0 release (msvc64)
ocaml-variants 4.05.0+msvc64c
          pre-compiled 4.05.0 release for AppVeyor (msvc64)
ocaml-variants 4.06.0+default-unsafe-string+mingw32
          4.06.0 (mingw32), without safe strings by default
ocaml-variants 4.06.0+default-unsafe-string+mingw64
          4.06.0 (mingw64), without safe strings by default
ocaml-variants 4.06.0+flambda+mingw32
          4.06.0 with flambda activated (mingw32)
ocaml-variants 4.06.0+flambda+mingw32c
          pre-compiled 4.06.0 release with flambda activated (mingw32)
ocaml-variants 4.06.0+flambda+mingw64
          4.06.0 with flambda activated (mingw64)
ocaml-variants 4.06.0+flambda+mingw64c
          pre-compiled 4.06.0 release with flambda activated (mingw64)
ocaml-variants 4.06.0+mingw32                       4.06.0 (mingw32)
ocaml-variants 4.06.0+mingw32c
          pre-compiled 4.06.0 release (mingw32)
ocaml-variants 4.06.0+mingw64                       4.06.0 (mingw64)
ocaml-variants 4.06.0+mingw64c
          pre-compiled 4.06.0 release (mingw64)
ocaml-variants 4.06.0+msvc32                        4.06.0 (msvc32)
ocaml-variants 4.06.0+msvc32c
          pre-compiled 4.06.0 release for AppVeyor (msvc32)
ocaml-variants 4.06.0+msvc64                        4.06.0 (msvc64)
ocaml-variants 4.06.0+msvc64c
          pre-compiled 4.06.0 release for AppVeyor (msvc64)
ocaml-variants 4.06.1+default-unsafe-string+mingw32
          OCaml 4.06.1 (mingw32), without safe strings by default
ocaml-variants 4.06.1+default-unsafe-string+mingw64
          OCaml 4.06.1 (mingw64), without safe strings by default
ocaml-variants 4.06.1+flambda+mingw32
          OCaml 4.06.1 with flambda activated (mingw32)
ocaml-variants 4.06.1+flambda+mingw32c
          pre-compiled 4.06.1 release with flambda activated (mingw32)
ocaml-variants 4.06.1+flambda+mingw64
          OCaml 4.06.1 with flambda activated (mingw64)
ocaml-variants 4.06.1+flambda+mingw64c
          pre-compiled 4.06.1 release with flambda activated (mingw64)
ocaml-variants 4.06.1+mingw32                       OCaml 4.06.1 (mingw32)
ocaml-variants 4.06.1+mingw32c
          pre-compiled 4.06.1 release (mingw32)
ocaml-variants 4.06.1+mingw64                       OCaml 4.06.1 (mingw64)
ocaml-variants 4.06.1+mingw64c
          pre-compiled 4.06.1 release (mingw64)
ocaml-variants 4.06.1+msvc32                        OCaml 4.06.1 (msvc32)
ocaml-variants 4.06.1+msvc32c
          pre-compiled 4.06.1 release for AppVeyor (msvc32)
ocaml-variants 4.06.1+msvc64                        OCaml 4.06.1 (msvc64)
ocaml-variants 4.06.1+msvc64c
          pre-compiled 4.06.1 release for AppVeyor (msvc64)
ocaml-variants 4.07.0+default-unsafe-string+mingw32
          OCaml 4.07.0 (mingw32), without safe strings by default
ocaml-variants 4.07.0+default-unsafe-string+mingw64
          OCaml 4.07.0 (mingw64), without safe strings by default
ocaml-variants 4.07.0+flambda+mingw32
          OCaml 4.07.0 with flambda activated (mingw32)
ocaml-variants 4.07.0+flambda+mingw32c
          pre-compiled 4.07.0 release with flambda activated (mingw32)
ocaml-variants 4.07.0+flambda+mingw64
          OCaml 4.07.0 with flambda activated (mingw64)
ocaml-variants 4.07.0+flambda+mingw64c
          pre-compiled 4.07.0 release with flambda activated (mingw64)
ocaml-variants 4.07.0+flambda+msvc32
          OCaml 4.07.0 with flambda activated (msvc32)
ocaml-variants 4.07.0+flambda+msvc64
          OCaml 4.07.0 with flambda activated (msvc64)
ocaml-variants 4.07.0+mingw32                       OCaml 4.07.0 (mingw32)
ocaml-variants 4.07.0+mingw32c
          pre-compiled 4.07.0 release (mingw32)
ocaml-variants 4.07.0+mingw64                       OCaml 4.07.0 (mingw64)
ocaml-variants 4.07.0+mingw64c
          pre-compiled 4.07.0 release (mingw64)
ocaml-variants 4.07.0+msvc32                        OCaml 4.07.0 (msvc32)
ocaml-variants 4.07.0+msvc32c
          pre-compiled 4.07.0 release for AppVeyor (msvc32)
ocaml-variants 4.07.0+msvc64                        OCaml 4.07.0 (msvc64)
ocaml-variants 4.07.0+msvc64c
          pre-compiled 4.07.0 release for AppVeyor (msvc64)
ocaml-variants 4.07.1+flambda+mingw32
          OCaml 4.07.1 with flambda activated (mingw32)
ocaml-variants 4.07.1+flambda+mingw32c
          pre-compiled 4.07.1 release with flambda activated (mingw32)
ocaml-variants 4.07.1+flambda+mingw64
          OCaml 4.07.1 with flambda activated (mingw64)
ocaml-variants 4.07.1+flambda+mingw64c
          pre-compiled 4.07.1 release with flambda activated (mingw64)
ocaml-variants 4.07.1+flambda+msvc32
          OCaml 4.07.1 with flambda activated (msvc32)
ocaml-variants 4.07.1+flambda+msvc64
          OCaml 4.07.1 with flambda activated (msvc64)
ocaml-variants 4.07.1+mingw32                       OCaml 4.07.1 (mingw32)
ocaml-variants 4.07.1+mingw32c
          pre-compiled 4.07.1 release (mingw32)
ocaml-variants 4.07.1+mingw64                       OCaml 4.07.1 (mingw64)
ocaml-variants 4.07.1+mingw64c
          pre-compiled 4.07.1 release (mingw64)
ocaml-variants 4.07.1+msvc32                        OCaml 4.07.1 (msvc32)
ocaml-variants 4.07.1+msvc32c
          pre-compiled 4.07.1 release for AppVeyor (msvc32)
ocaml-variants 4.07.1+msvc64                        OCaml 4.07.1 (msvc64)
ocaml-variants 4.07.1+msvc64c
          pre-compiled 4.07.1 release for AppVeyor (msvc64)
ocaml-variants 4.08.0+flambda+mingw32
          OCaml 4.08.0 with flambda activated (mingw32)
ocaml-variants 4.08.0+flambda+mingw32c
          pre-compiled 4.08.0 release with flambda activated (mingw32)
ocaml-variants 4.08.0+flambda+mingw64
          OCaml 4.08.0 with flambda activated (mingw64)
ocaml-variants 4.08.0+flambda+mingw64c
          pre-compiled 4.08.0 release with flambda activated (mingw64)
ocaml-variants 4.08.0+mingw32                       OCaml 4.08.0 (mingw32)
ocaml-variants 4.08.0+mingw32c
          pre-compiled 4.08.0 release (mingw32)
ocaml-variants 4.08.0+mingw64                       OCaml 4.08.0 (mingw64)
ocaml-variants 4.08.0+mingw64c
          pre-compiled 4.08.0 release (mingw64)
ocaml-variants 4.08.0+msvc32                        OCaml 4.08.0 (msvc32)
ocaml-variants 4.08.0+msvc32c
          pre-compiled 4.08.0 release for AppVeyor (msvc32)
ocaml-variants 4.08.0+msvc64                        OCaml 4.08.0 (msvc64)
ocaml-variants 4.08.0+msvc64c
          pre-compiled 4.08.0 release for AppVeyor (msvc64)
ocaml-variants 4.08.1+flambda+mingw32
          OCaml 4.08.1 with flambda activated (mingw32)
ocaml-variants 4.08.1+flambda+mingw32c
          pre-compiled 4.08.1 release with flambda activated (mingw32)
ocaml-variants 4.08.1+flambda+mingw64
          OCaml 4.08.1 with flambda activated (mingw64)
ocaml-variants 4.08.1+flambda+mingw64c
          pre-compiled 4.08.1 release with flambda activated (mingw64)
ocaml-variants 4.08.1+mingw32                       OCaml 4.08.1 (mingw32)
ocaml-variants 4.08.1+mingw32c
          pre-compiled 4.08.1 release (mingw32)
ocaml-variants 4.08.1+mingw64                       OCaml 4.08.1 (mingw64)
ocaml-variants 4.08.1+mingw64c
          pre-compiled 4.08.1 release (mingw64)
ocaml-variants 4.08.1+msvc32                        OCaml 4.08.1 (msvc32)
ocaml-variants 4.08.1+msvc32c
          pre-compiled 4.08.1 release for AppVeyor (msvc32)
ocaml-variants 4.08.1+msvc64                        OCaml 4.08.1 (msvc64)
ocaml-variants 4.08.1+msvc64c
          pre-compiled 4.08.1 release for AppVeyor (msvc64)
ocaml-variants 4.09.0+flambda+mingw32
          OCaml 4.09.0 with flambda activated (mingw32)
ocaml-variants 4.09.0+flambda+mingw32c
          pre-compiled 4.09.0 release with flambda activated (mingw32)
ocaml-variants 4.09.0+flambda+mingw64
          OCaml 4.09.0 with flambda activated (mingw64)
ocaml-variants 4.09.0+flambda+mingw64c
          pre-compiled 4.09.0 release with flambda activated (mingw64)
ocaml-variants 4.09.0+mingw32                       OCaml 4.09.0 (mingw32)
ocaml-variants 4.09.0+mingw32c
          pre-compiled 4.09.0 release (mingw32)
ocaml-variants 4.09.0+mingw64                       OCaml 4.09.0 (mingw64)
ocaml-variants 4.09.0+mingw64c
          pre-compiled 4.09.0 release (mingw64)
ocaml-variants 4.09.0+msvc32                        OCaml 4.09.0 (msvc32)
ocaml-variants 4.09.0+msvc32c
          pre-compiled 4.09.0 release for AppVeyor (msvc32)
ocaml-variants 4.09.0+msvc64                        OCaml 4.09.0 (msvc64)
ocaml-variants 4.09.0+msvc64c
          pre-compiled 4.09.0 release for AppVeyor (msvc64)
ocaml-variants 4.10.0+beta1+flambda+mingw32
          first beta of OCaml 4.10.0 with flambda activated (mingw32)
ocaml-variants 4.10.0+beta1+flambda+mingw64
          first beta of OCaml 4.10.0 with flambda activated (mingw64)
ocaml-variants 4.10.0+beta1+mingw32
          first beta of OCaml 4.10.0 (mingw32)
ocaml-variants 4.10.0+beta1+mingw64
          first beta of OCaml 4.10.0 (mingw64)

Well this worked.:

$ opam switch create . ocaml-variants.4.09.0+msvc64c

Hopefully, the rest of the dune install and integrate with vscode will work as well.

Which variant you use depends on which C compiler you have on your system. So β€œmsvc64” means you need to have visual studio installed and β€œmingw64” means you need to have mingw64-gcc from cygwin installed.

See this page for further info, in particular about the β€œOCaml for Windows” distribution.

1 Like

Just built with DUNE, it works fine and finds the file. It is a Bucklescript issue.