Я прочитал этот вопрос и другие, но моя проблема с компиляцией не решена.

Тестирую раздельную компиляцию с этими файлами:

Testmoda.ml

module Testmoda = struct
  let greeter () = print_endline "greetings from module a"
end

Testmodb.ml

module Testmodb = struct
  let dogreet () = print_endline "Modul B:"; Testmoda.greeter ()
end

Testmod.ml

let main () =
  print_endline "Calling modules now...";
  Testmoda.greeter ();
  Testmodb.dogreet (); 
  print_endline "End."
;;
let _ = main ()

Теперь я создаю файл .mli

ocamlc -c -i testmoda.ml >testmoda.mli

И там есть testmoda.cmi.

Далее создаю файл .cmo без ошибок:

ocamlc -c testmoda.ml

Хорошо, сделайте то же самое с testmodb.ml:

strobel@s131-amd:~/Ocaml/ml/testmod> ocamlc -c -i testmodb.ml >testmodb.mli
File "testmodb.ml", line 3, characters 45-61:
Error: Unbound value Testmoda.greeter

Еще одна попытка:

strobel@s131-amd:~/Ocaml/ml/testmod> ocamlc -c testmoda.cmo testmodb.ml
File "testmodb.ml", line 3, characters 45-61:
Error: Unbound value Testmoda.greeter

Другие комбинации тоже не удались.

Как скомпилировать testmodb.ml и testmod.ml? Это должно быть легко - я думаю, без ocamlbuild / omake / oasis.

Синтаксические ошибки в файлах исключены, если я объединю их в один файл (с требуемым пространством между ними), он компилируется и отлично выполняется.

3
Str. 26 Фев 2014 в 03:04

1 ответ

Лучший ответ

OCaml бесплатно предоставляет модуль на верхнем уровне каждого исходного файла. Итак, ваш первый модуль на самом деле называется Testmoda.Testmoda, функция - Testmoda.Testmoda.greeter и так далее. Все будет работать лучше, если ваши файлы будут содержать только определения функций.

В качестве дополнительного комментария, если вы собираетесь использовать интерфейс, сгенерированный ocamlc -i, вам действительно не нужны файлы mli. Интерфейс при отсутствии файла mli такой же, как и интерфейс, созданный ocamlc -i. Если вам не нужен интерфейс по умолчанию, использование ocamlc -i станет хорошей отправной точкой для вашего mli-файла. Но для такого простого примера, как этот, все выглядит намного сложнее, чем есть на самом деле (ИМХО).

Если вы измените свои файлы, как я описываю (удалите лишние объявления модулей), вы можете скомпилировать и запустить с нуля следующим образом:

$ ls
testmod.ml  testmoda.ml testmodb.ml
$ cat testmoda.ml
let greeter () = print_endline "greetings from module a"
$ cat testmodb.ml
let dogreet () = print_endline "Modul B:"; Testmoda.greeter ()
$ ocamlc -o testmod testmoda.ml testmodb.ml testmod.ml
$ ./testmod
Calling modules now...
greetings from module a
Modul B:
greetings from module a
End.

Если вы уже скомпилировали файл (с ocamlc -c file.ml), вы можете заменить .ml на .cmo в приведенной выше команде. Это работает, даже если все имена файлов являются файлами .cmo; в этом случае ocamlc просто связывает их за вас.

5
Jeffrey Scofield 26 Фев 2014 в 19:59
О чудо, без явного определения модуля он работает так, как ожидалось, ocamlc -c testmoda.ml создает .cmi и .cmo, последний может использоваться для компиляции testmod.ml - отдельной компиляции.
 – 
Str.
26 Фев 2014 в 16:22
1
(не удалось отредактировать комментарий) Итак, вот отдельная компиляция: ocamlc -c testmoda.ml;ocamlc -c testmodb.ml; ocamlc -o testmod testmoda.cmo testmodb.cmo testmod.ml
 – 
Str.
26 Фев 2014 в 16:29
Обратите внимание, что одна команда, которую я дал, также выполняет отдельную компиляцию :-) Она полностью эквивалентна этим трем командам. Но, конечно, иногда вы хотите скомпилировать только один из исходных файлов, как вы показываете. Это также работает для testmod.ml.
 – 
Jeffrey Scofield
26 Фев 2014 в 19:08