(* TEST include dynlink; libraries = ""; readonly_files = "sheep.mli sheep.ml pig.mli"; subdirectories = "plugin1 plugin2 plugin2b plugin2c plugin3 plugin4 plugin5 plugin6"; shared-libraries; { setup-ocamlc.byte-build-env; module = "sheep.mli"; ocamlc.byte; module = "sheep.ml"; ocamlc.byte; module = "pig.mli"; ocamlc.byte; module = "test.ml"; ocamlc.byte; module = "plugin1/sheep.mli"; ocamlc.byte; flags = "-I plugin1"; module = "plugin1/sheep.ml"; ocamlc.byte; flags = ""; module = "plugin2/cow.mli"; ocamlc.byte; flags = "-I plugin2"; module = "plugin2/cow.ml"; ocamlc.byte; flags = ""; module = "plugin2b/cow.mli"; ocamlc.byte; flags = "-I plugin2b"; module = "plugin2b/cow.ml"; ocamlc.byte; flags = ""; module = "plugin2c/cow.mli"; ocamlc.byte; flags = "-I plugin2c"; module = "plugin2c/cow.ml"; ocamlc.byte; flags = ""; module = "plugin3/pig.mli"; ocamlc.byte; flags = "-I plugin3"; module = "plugin3/pig.ml"; ocamlc.byte; flags = ""; module = "plugin4/chicken.mli"; ocamlc.byte; flags = "-I plugin4"; module = "plugin4/chicken.ml"; ocamlc.byte; flags = ""; module = "plugin5/chicken.mli"; ocamlc.byte; flags = "-I plugin5"; module = "plugin5/chicken.ml"; ocamlc.byte; flags = ""; module = "plugin6/pheasant.mli"; ocamlc.byte; flags = "-I plugin6"; module = "plugin6/pheasant.ml"; ocamlc.byte; flags = ""; module = "plugin6/partridge.mli"; ocamlc.byte; flags = "-I plugin6"; module = "plugin6/partridge.ml"; ocamlc.byte; flags = ""; program = "./test.byte.exe"; libraries = "dynlink"; all_modules = "sheep.cmo test.cmo"; module = ""; ocamlc.byte; run; }{ native-dynlink; setup-ocamlopt.byte-build-env; module = "sheep.mli"; ocamlopt.byte; module = "sheep.ml"; ocamlopt.byte; module = "pig.mli"; ocamlopt.byte; module = "test.ml"; ocamlopt.byte; flags = ""; module = "plugin1/sheep.mli"; ocamlopt.byte; program = "plugin1/sheep.cmxs"; flags = "-I plugin1 -shared"; module = ""; all_modules = "plugin1/sheep.ml"; ocamlopt.byte; flags = ""; module = "plugin2/cow.mli"; ocamlopt.byte; program = "plugin2/cow.cmxs"; flags = "-I plugin2 -shared"; module = ""; all_modules = "plugin2/cow.ml"; ocamlopt.byte; flags = ""; module = "plugin2b/cow.mli"; ocamlopt.byte; program = "plugin2b/cow.cmxs"; flags = "-I plugin2b -shared"; module = ""; all_modules = "plugin2b/cow.ml"; ocamlopt.byte; flags = ""; module = "plugin2c/cow.mli"; ocamlopt.byte; program = "plugin2c/cow.cmxs"; flags = "-I plugin2c -shared"; module = ""; all_modules = "plugin2c/cow.ml"; ocamlopt.byte; flags = ""; module = "plugin3/pig.mli"; ocamlopt.byte; program = "plugin3/pig.cmxs"; flags = "-I plugin3 -shared"; module = ""; all_modules = "plugin3/pig.ml"; ocamlopt.byte; flags = ""; module = "plugin4/chicken.mli"; ocamlopt.byte; program = "plugin4/chicken.cmxs"; flags = "-I plugin4 -shared"; module = ""; all_modules = "plugin4/chicken.ml"; ocamlopt.byte; flags = ""; module = "plugin5/chicken.mli"; ocamlopt.byte; program = "plugin5/chicken.cmxs"; flags = "-I plugin5 -shared"; module = ""; all_modules = "plugin5/chicken.ml"; ocamlopt.byte; flags = ""; module = "plugin6/pheasant.mli"; ocamlopt.byte; program = "plugin6/pheasant.cmxs"; flags = "-I plugin6 -shared"; module = ""; all_modules = "plugin6/pheasant.ml"; ocamlopt.byte; flags = ""; module = "plugin6/partridge.mli"; ocamlopt.byte; program = "plugin6/partridge.cmxs"; flags = "-I plugin6 -shared"; module = ""; all_modules = "plugin6/partridge.ml"; ocamlopt.byte; flags = ""; program = "./test.opt.exe"; libraries = "dynlink"; all_modules = "sheep.cmx test.cmx"; ocamlopt.byte; run; } *) let () = Sheep.baa Sheep.s (* Use Sheep module *) let _ = fun (x : Pig.t) -> x (* Reference Pig module *) (* Test that a privately loaded module cannot have the same name as a module in the program. *) let test_sheep () = match if Dynlink.is_native then Dynlink.loadfile_private "plugin1/sheep.cmxs" else Dynlink.loadfile_private "plugin1/sheep.cmo" with | () -> assert false | exception Dynlink.Error ( Dynlink.Module_already_loaded "Sheep") -> () (* Test repeated loading of a privately-loaded module. *) let test_cow_repeated () = if Dynlink.is_native then Dynlink.loadfile_private "plugin2/cow.cmxs" else Dynlink.loadfile_private "plugin2/cow.cmo" (* Test that a privately loaded module can have the same name as a previous privately loaded module, in the case where the interfaces are the same, but the implementations differ. *) let test_cow_same_name_same_mli () = if Dynlink.is_native then Dynlink.loadfile_private "plugin2b/cow.cmxs" else Dynlink.loadfile_private "plugin2b/cow.cmo" (* Test that a privately loaded module can have the same name as a previous privately loaded module, in the case where neither the interfaces nor the implementations are the same. *) let test_cow_same_name_different_mli () = if Dynlink.is_native then Dynlink.loadfile_private "plugin2c/cow.cmxs" else Dynlink.loadfile_private "plugin2c/cow.cmo" (* Test that a privately loaded module cannot have the same name as an interface depended on by modules the program. *) let test_pig () = match if Dynlink.is_native then Dynlink.loadfile_private "plugin3/pig.cmxs" else Dynlink.loadfile_private "plugin3/pig.cmo" with | () -> assert false | exception Dynlink.Error ( Dynlink.Private_library_cannot_implement_interface "Pig") -> () (* Test that a privately loaded module can recursively load a module of the same name. *) let test_chicken () = if Dynlink.is_native then Dynlink.loadfile_private "plugin4/chicken.cmxs" else Dynlink.loadfile_private "plugin4/chicken.cmo" (* Test that a public load of a module M inside a privately-loaded module, followed by a public load of M, causes an error. *) let test_pheasant () = begin if Dynlink.is_native then Dynlink.loadfile_private "plugin6/pheasant.cmxs" else Dynlink.loadfile_private "plugin6/pheasant.cmo" end; match if Dynlink.is_native then Dynlink.loadfile "plugin6/partridge.cmxs" else Dynlink.loadfile "plugin6/partridge.cmo" with | () -> assert false | exception Dynlink.Error ( Dynlink.Module_already_loaded "Partridge") -> () let debug_runtime = String.equal (Sys.runtime_variant ()) "d" (* test_cow_repeated is disabled when running with the debug runtime. Reloading multiple times a module can cause an already initialized block to be overwritten. See https://github.com/ocaml/ocaml/issues/11016 *) let () = test_sheep (); if (not debug_runtime) then ( test_cow_repeated (); test_cow_repeated () ); test_cow_same_name_same_mli (); test_cow_same_name_different_mli (); test_pig (); test_chicken (); test_pheasant ()