2017-02-07 11 views
0

У меня есть три файла:Использование ocamlc для компиляции библиотек независимо

$ ls 
lib.ml desk.ml test.ml 

$ cat lib.ml 
let myfunction() = print_endline "Hello world" 

$ cat desk.ml 
module Liberty = Lib 

$ cat test.ml 
Desk.Liberty.myfunction() 

Я хочу, чтобы скомпилировать desk.cma что делает не подвергать модуль Lib, но в состоянии использовать его. Например, я пробовал:

$ ocamlc -a lib.ml -o lib.cma 
$ ocamlc -a lib.cma desk.ml -o desk.cma 
$ ocamlc desk.cma test.ml -o test.byte 

К сожалению, если вы измените test.ml быть Lib.myfunction(), одни и те же этапы компиляции работают нормально. Я хочу, чтобы Lib не подвергался воздействию test.ml и был открыт только для desk.ml. Кто-нибудь знает как это сделать? Огромное спасибо!

ответ

1

Похоже, что вы ищете механизм OCaml -pack. Это позволяет вам создать pack.cmo (или pack.cmx для встроенной компиляции) из нескольких единиц компиляции, таких как библиотека pack.cma, но с дополнительным преимуществом, что вы можете иметь соответствующий интерфейс pack.mli, с помощью которого вы можете скрыть части, которые должны быть внутренними для вашего pack. В вашем примере, вы могли бы, например, иметь:

- lib.ml -

let myfunction() = print_endline "Hello world" 

- liberty.ml -

include Lib 

- desk.mli -

(* No module Lib: Lib will not be seen outside of the pack. *) 

module Liberty: sig 
    val myfunction: unit -> unit 
end 

Затем вы можете скомпилировать, что с

ocamlc -for-pack Desk -c lib.ml 
ocamlc -for-pack Desk -c liberty.ml 
ocamlc desk.mli 
ocamlc -pack -o desk.cmo lib.cmo liberty.cmo 

Это даст вам модуль Desk, который содержит только Liberty подмодуль. Конечно, desk.mli можно использовать для получения более мелкозернистого ограничения, например. с

module Lib: sig end 

module Liberty: sig val myfunction: unit -> unit end 

экспорта Lib с пустой подписью, тем самым скрывая один (хотя и единственный в примере ;-P) функции от Lib.

+0

Круто спасибо большое! – Kites

0

Вы хотите, чтобы Lib был модулем desk.cma, который может использовать Desk, но нет других модулей. Я уверен, что структура файла cma не предлагает такого управления.

Если вы определяете Lib внутри Desk, вы можете сделать это скрытой деталью.

$ ls 
desk.ml desk.mli test1.ml test2.ml test3.ml 

$ cat desk.ml 
module Lib = struct 
    let myfunction() = print_endline "Hello world" 
end 
module Liberty = Lib 

$ cat desk.mli 
module Liberty : sig 
val myfunction : unit -> unit 
end 

$ cat test1.ml 
Desk.Liberty.myfunction() 

$ cat test2.ml 
Lib.myfunction() 

$ cat test3.ml 
Desk.Lib.myfunction() 

Свободы модуль виден на тестовых программ, но модуль Lib не является:

$ ocamlc -c desk.mli 
$ ocamlc -a desk.ml -o desk.cma 
$ ocamlc desk.cma test1.ml -o test1.byte 
$ ./test1.byte 
Hello world 
$ ocamlc desk.cma test2.ml -o test2.byte 
File "test2.ml", line 1, characters 0-14: 
Error: Unbound module Lib 
$ ocamlc desk.cma test3.ml -o test3.byte 
File "test3.ml", line 1, characters 0-19: 
Error: Unbound module Desk.Lib 

Вы можете реализовать Lib в отдельном файле, а затем include его в определении Desk.Lib модуль.

Я подозреваю, что это не вполне удовлетворительный ответ, но я надеюсь, что это будет полезно.