The unpac monorepo manager self-hosting as a monorepo using unpac
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add runtime suffixes to bytecode stub libraries

ocamlc -dllib-suffixed appends the runtime's host triplet and bytecode
runtime ID to the supplied name when searching for the DLL, and records
the base name only in .cma / executable files.

ocamlmklib -suffixed instructs ocamlmklib to use -dllib-suffixed when
generating .cma files instead of -dllib.

The effect is that stub libraries built this way have names which will
be unique for a given configuration of OCaml and so will be ignored by
other runtimes.

+215 -51
+4 -2
Changes
··· 96 96 harmoniously on a single system. The IDs are used, along with the host 97 97 triplet, to provide mangled names for the ocamlrun executable and its variants 98 98 and the DLL versions of both the bytecode and native runtimes, with symlinks 99 - created for the original names. The behaviour is disabled by configuring with 100 - --disable-suffixing. 99 + created for the original names. They are also used to mangle the names of stub 100 + libraries so that stub libraries compiled for a given configuration of the 101 + runtime will only be sought by that runtime. The behaviour is disabled by 102 + configuring with --disable-suffixing. 101 103 (David Allsopp, review by Damien Doligez and Samuel Hym) 102 104 103 105 - #12269, #12410, #13063: Fix unsafety, deadlocks, and/or leaks should
+30 -6
bytecomp/bytelink.ml
··· 553 553 let start_code = pos_out outchan in 554 554 Symtable.init(); 555 555 clear_crc_interfaces (); 556 - let sharedobjs = List.map Dll.extract_dll_name !Clflags.dllibs in 556 + let (tocheck, sharedobjs) = 557 + let process_dllib ((~suffixed, name) as dllib) (tocheck, sharedobjs) = 558 + let resolved_name = Dll.extract_dll_name dllib in 559 + let partial_name = 560 + if suffixed then 561 + if String.starts_with ~prefix:"-l" name then 562 + (~suffixed, "dll" ^ String.sub name 2 (String.length name - 2)) 563 + else 564 + dllib 565 + else 566 + (~suffixed:false, resolved_name) 567 + in 568 + (resolved_name::tocheck, partial_name::sharedobjs) 569 + in 570 + List.fold_right process_dllib !Clflags.dllibs ([], []) 571 + in 557 572 let check_dlls = standalone && Config.target = Config.host in 558 573 if check_dlls then begin 559 574 (* Initialize the DLL machinery *) 560 575 Dll.init_compile !Clflags.no_std_include; 561 576 Dll.add_path (Load_path.get_path_list ()); 562 - try Dll.open_dlls Dll.For_checking sharedobjs 577 + try Dll.open_dlls Dll.For_checking tocheck 563 578 with Failure reason -> raise(Error(Cannot_open_dll reason)) 564 579 end; 565 580 let output_fun buf = ··· 576 591 (* DLL stuff *) 577 592 if standalone then begin 578 593 (* The extra search path for DLLs *) 579 - output_string outchan (concat_null_terminated !Clflags.dllpaths); 580 - Bytesections.record toc_writer DLPT; 594 + if !Clflags.dllpaths <> [] then begin 595 + output_string outchan (concat_null_terminated !Clflags.dllpaths); 596 + Bytesections.record toc_writer DLPT 597 + end; 581 598 (* The names of the DLLs *) 582 - output_string outchan (concat_null_terminated sharedobjs); 583 - Bytesections.record toc_writer DLLS 599 + if sharedobjs <> [] then begin 600 + let output_sharedobj (~suffixed, name) = 601 + output_char outchan (if suffixed then '-' else ':'); 602 + output_string outchan name; 603 + output_byte outchan 0 604 + in 605 + List.iter output_sharedobj sharedobjs; 606 + Bytesections.record toc_writer DLLS 607 + end 584 608 end; 585 609 (* The names of all primitives *) 586 610 Symtable.output_primitive_names outchan;
+12 -5
bytecomp/dll.ml
··· 51 51 52 52 (* Extract the name of a DLLs from its external name (xxx.so or -lxxx) *) 53 53 54 - let extract_dll_name file = 55 - if Filename.check_suffix file Config.ext_dll then 54 + let extract_dll_name (~suffixed, file) = 55 + if not suffixed && Filename.check_suffix file Config.ext_dll then 56 56 Filename.chop_suffix file Config.ext_dll 57 - else if String.length file >= 2 && String.sub file 0 2 = "-l" then 58 - "dll" ^ String.sub file 2 (String.length file - 2) 59 57 else 60 - file (* will cause error later *) 58 + let file = 59 + if String.starts_with ~prefix:"-l" file then 60 + "dll" ^ String.sub file 2 (String.length file - 2) 61 + else 62 + file 63 + in 64 + if suffixed then 65 + Misc.RuntimeID.stubslib file 66 + else 67 + file 61 68 62 69 (* Open a list of DLLs, adding them to opened_dlls. 63 70 Raise [Failure msg] in case of error. *)
+5 -2
bytecomp/dll.mli
··· 15 15 16 16 (* Handling of dynamically-linked libraries *) 17 17 18 - (* Extract the name of a DLLs from its external name (xxx.so or -lxxx) *) 19 - val extract_dll_name: string -> string 18 + (* Extract the name of a DLLs from its mangled or external name. If 19 + [~suffixed:true] then the name is just the undecorated basename of the DLL 20 + (no -l and no .so). If [~suffixed:false] then the external name may include 21 + the DLL extension or linking symbol (xxx.so or -lxxx) *) 22 + val extract_dll_name: (suffixed:bool * string) -> string 20 23 21 24 type dll_mode = 22 25 | For_checking (* will just check existence of symbols;
+4 -4
driver/compenv.ml
··· 626 626 | ProcessCFile of string 627 627 | ProcessOtherFile of string 628 628 | ProcessObjects of string list 629 - | ProcessDLLs of string list 629 + | ProcessDLLs of bool * string list 630 630 631 631 let c_object_of_filename name = 632 632 Filename.chop_suffix (Filename.basename name) ".c" ^ Config.ext_obj ··· 675 675 ccobjs := obj_name :: !ccobjs 676 676 | ProcessObjects names -> 677 677 ccobjs := names @ !ccobjs 678 - | ProcessDLLs names -> 679 - dllibs := names @ !dllibs 678 + | ProcessDLLs (suffixed, names) -> 679 + dllibs := (List.map (fun n -> (~suffixed, n)) names) @ !dllibs 680 680 | ProcessOtherFile name -> 681 681 if Filename.check_suffix name ocaml_mod_ext 682 682 || Filename.check_suffix name ocaml_lib_ext then ··· 689 689 ccobjs := name :: !ccobjs 690 690 end 691 691 else if not !native_code && Filename.check_suffix name Config.ext_dll then 692 - dllibs := name :: !dllibs 692 + dllibs := (~suffixed:false, name) :: !dllibs 693 693 else 694 694 match Compiler_pass.of_input_filename name with 695 695 | Some start_from ->
+1 -1
driver/compenv.mli
··· 53 53 | ProcessCFile of string 54 54 | ProcessOtherFile of string 55 55 | ProcessObjects of string list 56 - | ProcessDLLs of string list 56 + | ProcessDLLs of bool * string list 57 57 58 58 val c_object_of_filename : string -> string 59 59
+10 -1
driver/main_args.ml
··· 89 89 let mk_dllib f = 90 90 "-dllib", Arg.String f, "<lib> Use the dynamically-loaded library <lib>" 91 91 92 + let mk_dllib_suffixed f = 93 + "-dllib-suffixed", Arg.String f, 94 + "<lib> Use the dynamically-loaded library <lib>, with the runtime suffix \ 95 + appended to the name" 96 + 92 97 let mk_dllpath f = 93 98 "-dllpath", Arg.String f, 94 99 "<dir> Add <dir> to the run-time search path for shared libraries" ··· 957 962 val _custom : unit -> unit 958 963 val _no_check_prims : unit -> unit 959 964 val _dllib : string -> unit 965 + val _dllib_suffixed : string -> unit 960 966 val _dllpath : string -> unit 961 967 val _make_runtime : unit -> unit 962 968 val _vmthread : unit -> unit ··· 1093 1099 mk_config_var F._config_var; 1094 1100 mk_custom F._custom; 1095 1101 mk_dllib F._dllib; 1102 + mk_dllib_suffixed F._dllib_suffixed; 1096 1103 mk_dllpath F._dllpath; 1097 1104 mk_dtypes F._annot; 1098 1105 mk_for_pack_byt F._for_pack; ··· 1999 2006 let _custom = set custom_runtime 2000 2007 let _dcamlprimc = set keep_camlprimc_file 2001 2008 let _dinstr = set dump_instr 2002 - let _dllib s = Compenv.defer (ProcessDLLs (Misc.rev_split_words s)) 2009 + let _dllib s = Compenv.defer (ProcessDLLs (false, Misc.rev_split_words s)) 2010 + let _dllib_suffixed s = 2011 + Compenv.defer (ProcessDLLs (true, Misc.rev_split_words s)) 2003 2012 let _dllpath s = dllpaths := ((!dllpaths) @ [s]) 2004 2013 let _make_runtime () = 2005 2014 custom_runtime := true; make_runtime := true; link_everything := true
+1
driver/main_args.mli
··· 161 161 val _custom : unit -> unit 162 162 val _no_check_prims : unit -> unit 163 163 val _dllib : string -> unit 164 + val _dllib_suffixed : string -> unit 164 165 val _dllpath : string -> unit 165 166 val _make_runtime : unit -> unit 166 167 val _vmthread : unit -> unit
+1 -1
file_formats/cmo_format.mli
··· 67 67 how they end up being used on the command line. *) 68 68 lib_ccobjs: string list; (* C object files needed for -custom *) 69 69 lib_ccopts: string list; (* Extra opts to C compiler *) 70 - lib_dllibs: string list } (* DLLs needed *) 70 + lib_dllibs: (suffixed:bool * string) list } (* DLLs needed *) 71 71 72 72 (* Format of a .cma file: 73 73 magic number (Config.cma_magic_number)
+9
man/ocamlc.1
··· 355 355 .BR ocamlrun (1) 356 356 at program start-up time. 357 357 .TP 358 + .BI \-dllib\-suffixed\ \-l libname 359 + As for 360 + .BI \-dllib 361 + but the name recorded is mangled by 362 + .BR ocamlrun (1) 363 + at program start-up time. This is used for C stub libraries; see 364 + .B ocamlmklib\ \-suffixed 365 + for further information. 366 + .TP 358 367 .BI \-dllpath " dir" 359 368 Adds the directory 360 369 .I dir
+8
manual/src/cmds/unified-options.etex
··· 229 229 by the run-time system "ocamlrun" at program start-up time. 230 230 }%comp 231 231 232 + \comp{ 233 + \item["-dllib-suffixed" "-l"\var{libname}] 234 + As for "-dllib" but the name recorded is mangled with the Runtime ID and host of 235 + the interpreter before being loaded by the run-time system "ocamlrun" at program 236 + start-up time. Ths is used for C stub libraries, for example by DLLs produced 237 + with "ocamlmklib -suffixed". 238 + }%comp 239 + 232 240 \comp{\item["-dllpath" \var{dir}] 233 241 Adds the directory \var{dir} to the run-time search path for shared 234 242 C libraries. At link-time, shared libraries are searched in the
+3 -1
ocamltest/ocaml_actions.ml
··· 604 604 Ocaml_commands.ocamlrun_ocamlmklib; 605 605 "-ocamlc '" ^ ocamlc_command ^ "'"; 606 606 "-o " ^ program 607 - ] @ modules env in 607 + ] @ (if Ocamltest_config.suffixing then ["-suffixed"] else []) 608 + @ modules env 609 + in 608 610 let expected_exit_status = 0 in 609 611 let exit_status = 610 612 Actions_helpers.run_cmd
+2
ocamltest/ocamltest_config.ml.in
··· 104 104 let tsan = @tsan@ 105 105 106 106 let has_relative_libdir = @target_libdir_is_relative@ 107 + 108 + let suffixing = @suffixing@
+4
ocamltest/ocamltest_config.mli
··· 148 148 149 149 val has_relative_libdir : bool 150 150 (** Whether the compiler has been configured using --with-relative-libdir *) 151 + 152 + val suffixing : bool 153 + (** Whether C stub library filenames are being mangled with the Bytecode 154 + Runtime ID and {!Config.target}. *)
+21 -6
otherlibs/Makefile.otherlibs.common
··· 35 35 OPTCOMPFLAGS += -O3 36 36 endif 37 37 MKLIB=$(OCAMLRUN) $(ROOTDIR)/tools/ocamlmklib$(EXE) 38 + ifeq "$(SUFFIXING)" "true" 39 + MKLIB += -suffixed 40 + endif 38 41 39 42 # Variables that must be defined by individual libraries: 40 43 # LIBNAME ··· 52 55 CLIBNAME ?= $(LIBNAME) 53 56 54 57 ifeq "$(C_SOURCES)" "" 55 - STUBSLIB= 58 + 59 + STUBSLIB_BYTECODE= 60 + STUBSLIB_NATIVE= 61 + STUBSDLL= 62 + 56 63 else 64 + 57 65 COBJS_BYTECODE = $(C_SOURCES:.c=.b.$(O)) 58 66 COBJS_NATIVE = $(C_SOURCES:.c=.n.$(O)) 59 67 COBJS = $(COBJS_BYTECODE) $(COBJS_NATIVE) ··· 62 70 CLIBNAME_NATIVE=$(CLIBNAME)nat 63 71 STUBSLIB_BYTECODE=lib$(CLIBNAME_BYTECODE).$(A) 64 72 STUBSLIB_NATIVE=lib$(CLIBNAME_NATIVE).$(A) 73 + 74 + ifeq "$(SUFFIXING)" "true" 75 + STUBSDLL=dll$(CLIBNAME_BYTECODE)-$(TARGET)-$(BYTECODE_RUNTIME_ID)$(EXT_DLL) 76 + else 77 + STUBSDLL=dll$(CLIBNAME_BYTECODE)$(EXT_DLL) 78 + endif 65 79 endif 66 80 67 81 .PHONY: all allopt opt.opt # allopt and opt.opt are synonyms ··· 98 112 INSTALL_LIBDIR_LIBNAME = $(INSTALL_LIBDIR)/$(LIBNAME) 99 113 100 114 install:: 115 + ifneq "$(STUBSLIB_BYTECODE)" "" 101 116 ifeq "$(SUPPORTS_SHARED_LIBRARIES)" "true" 102 - $(INSTALL_PROG) dll$(CLIBNAME_BYTECODE)$(EXT_DLL) "$(INSTALL_STUBLIBDIR)" 117 + $(INSTALL_PROG) $(STUBSDLL) "$(INSTALL_STUBLIBDIR)" 103 118 endif 104 - ifneq "$(STUBSLIB_BYTECODE)" "" 105 119 $(INSTALL_DATA) $(STUBSLIB_BYTECODE) "$(INSTALL_LIBDIR)/" 106 120 endif 107 121 # If installing over a previous OCaml version, ensure the library is removed ··· 131 145 if test -f $(LIBNAME).cmxs; then \ 132 146 $(INSTALL_PROG) $(LIBNAME).cmxs "$(INSTALL_LIBDIR_LIBNAME)"; \ 133 147 fi 134 - ifeq "$(SUPPORTS_SHARED_LIBRARIES)" "true" 135 - $(INSTALL_PROG) dll$(CLIBNAME_NATIVE)$(EXT_DLL) "$(INSTALL_STUBLIBDIR)" 136 - endif 148 + if test -f dll$(CLIBNAME_NATIVE)$(EXT_DLL); then \ 149 + $(INSTALL_PROG) \ 150 + dll$(CLIBNAME_NATIVE)$(EXT_DLL) "$(INSTALL_STUBLIBDIR)"; \ 151 + fi 137 152 ifneq "$(STUBSLIB_NATIVE)" "" 138 153 $(INSTALL_DATA) $(STUBSLIB_NATIVE) "$(INSTALL_LIBDIR)/" 139 154 endif
+7 -1
otherlibs/systhreads/Makefile
··· 27 27 CAMLOPT=$(BEST_OCAMLOPT) $(LIBS) 28 28 29 29 MKLIB=$(OCAMLRUN) $(ROOTDIR)/tools/ocamlmklib$(EXE) 30 + ifeq "$(SUFFIXING)" "true" 31 + MKLIB += -suffixed 32 + DLLTHREADS = dllthreads-$(TARGET)-$(BYTECODE_RUNTIME_ID)$(EXT_DLL) 33 + else 34 + DLLTHREADS = dllthreads$(EXT_DLL) 35 + endif 30 36 COMPFLAGS=-w +33..39 -warn-error +A -g -bin-annot 31 37 ifeq "$(FLAMBDA)" "true" 32 38 OPTCOMPFLAGS += -O3 ··· 101 107 102 108 install: 103 109 ifeq "$(SUPPORTS_SHARED_LIBRARIES)" "true" 104 - $(INSTALL_PROG) dllthreads$(EXT_DLL) "$(INSTALL_STUBLIBDIR)" 110 + $(INSTALL_PROG) $(DLLTHREADS) "$(INSTALL_STUBLIBDIR)" 105 111 endif 106 112 $(INSTALL_DATA) libthreads.$(A) "$(INSTALL_LIBDIR)" 107 113 $(MKDIR) "$(INSTALL_THREADSLIBDIR)"
+16 -1
runtime/dynlink.c
··· 233 233 Abort on error. */ 234 234 static void open_shared_lib(char_os * name) 235 235 { 236 - char_os * realname; 236 + char_os * realname, * suffixed = NULL; 237 237 char * u8; 238 238 void * handle; 239 239 240 + if (*name == '\0') 241 + caml_fatal_error("corrupt DLLS section"); 242 + 243 + if (*name == '-') { 244 + char * suffix = 245 + caml_stat_strconcat(4, "-", HOST, "-", BYTECODE_RUNTIME_ID); 246 + char_os * suffix_os = caml_stat_strdup_to_os(suffix); 247 + name = suffixed = caml_stat_strconcat_os(2, name + 1, suffix_os); 248 + caml_stat_free(suffix_os); 249 + caml_stat_free(suffix); 250 + } else { 251 + name++; 252 + } 253 + 240 254 realname = caml_search_dll_in_path(&caml_shared_libs_path, name); 241 255 u8 = caml_stat_strdup_of_os(realname); 242 256 CAML_GC_MESSAGE(STARTUP, "Loading shared library %s\n", u8); ··· 253 267 caml_dlerror() 254 268 ); 255 269 caml_ext_table_add(&shared_libs, handle); 270 + caml_stat_free(suffixed); 256 271 caml_stat_free(realname); 257 272 } 258 273
+7 -1
tools/objinfo.ml
··· 74 74 let print_spaced_string s = 75 75 printf " %s" s 76 76 77 + let dllib (~suffixed, name) = 78 + if suffixed then 79 + Printf.sprintf "%s-<target>-<bytecode-runtime-id>" name 80 + else 81 + name 82 + 77 83 let print_cma_infos (lib : Cmo_format.library) = 78 84 printf "Force custom: %a\n" yesno_of_bool lib.lib_custom; 79 85 printf "Extra C object files:"; ··· 83 89 List.iter print_spaced_string (List.rev lib.lib_ccopts); 84 90 printf "\n"; 85 91 print_string "Extra dynamically-loaded libraries:"; 86 - List.iter print_spaced_string (List.rev lib.lib_dllibs); 92 + List.iter print_spaced_string (List.rev_map dllib lib.lib_dllibs); 87 93 printf "\n"; 88 94 List.iter print_cmo_infos lib.lib_units 89 95
+17 -2
tools/ocamlmklib.ml
··· 49 49 and rpath = ref [] (* rpath options *) 50 50 and debug = ref false (* -g option *) 51 51 and verbose = ref false 52 + and suffixed = ref false (* -suffixed option *) 52 53 53 54 let starts_with s pref = 54 55 String.length s >= String.length pref && ··· 162 163 c_opts := s :: !c_opts 163 164 else if s = "-framework" then 164 165 (let a = next_arg s in c_opts := a :: s :: !c_opts) 166 + else if s = "-suffixed" then 167 + suffixed := true 168 + else if s = "-no-suffixed" then 169 + suffixed := false 165 170 else if starts_with s "-" then 166 171 raise (Bad_argument("Unknown option " ^ s)) 167 172 else ··· 208 213 -oc <name> Generated C library is named dll<name>.so or lib<name>.a 209 214 -rpath <dir> Same as -dllpath <dir> 210 215 -R<dir> Same as -rpath 216 + -suffixed Append runtime ID to any generated shared libraries 217 + -no-suffixed Do not append runtime ID to any generated shared libraries 218 + (default) 211 219 -verbose Print commands before executing them 212 220 -v same as -verbose 213 221 -version Print version and exit ··· 284 292 let build_libs () = 285 293 if !c_objs <> [] then begin 286 294 if !dynlink then begin 295 + let dllname = 296 + if !suffixed then 297 + Misc.RuntimeID.stubslib !output_c 298 + else 299 + !output_c 300 + in 287 301 let retcode = command 288 302 (Printf.sprintf "%s %s -o %s %s %s %s %s %s %s" 289 303 Config.mkdll 290 304 (if !debug then "-g" else "") 291 - (prepostfix "dll" !output_c Config.ext_dll) 305 + (prepostfix "dll" dllname Config.ext_dll) 292 306 (String.concat " " !c_objs) 293 307 (String.concat " " !c_opts) 294 308 (String.concat " " !ld_opts) ··· 306 320 end; 307 321 if !bytecode_objs <> [] then 308 322 scommand 309 - (sprintf "%s -a %s %s %s -o %s.cma %s %s -dllib -l%s -cclib -l%s \ 323 + (sprintf "%s -a %s %s %s -o %s.cma %s %s -dllib%s -l%s -cclib -l%s \ 310 324 %s %s %s %s" 311 325 (transl_path !ocamlc) 312 326 (if !debug then "-g" else "") ··· 315 329 !output 316 330 (String.concat " " !caml_opts) 317 331 (String.concat " " !bytecode_objs) 332 + (if !suffixed then "-suffixed" else "") 318 333 (Filename.basename !output_c) 319 334 (Filename.basename !output_c) 320 335 (String.concat " " (prefix_list "-ccopt " !c_opts))
+5 -3
utils/clflags.ml
··· 38 38 end 39 39 end) 40 40 41 - let objfiles = ref ([] : string list) (* .cmo and .cma files *) 42 - and ccobjs = ref ([] : string list) (* .o, .a, .so and -cclib -lxxx *) 43 - and dllibs = ref ([] : string list) (* .so and -dllib -lxxx *) 41 + let objfiles = ref ([] : string list) (* .cmo and .cma files *) 42 + and ccobjs = ref ([] : string list) (* .o, .a, .so and -cclib -lxxx *) 43 + and dllibs = ref ([] : (suffixed:bool * string) list) 44 + (* .so, -dllib -lxxx and 45 + -dllib-suffixed -lxxx *) 44 46 45 47 let cmi_file = ref None 46 48
+1 -1
utils/clflags.mli
··· 70 70 71 71 val objfiles : string list ref 72 72 val ccobjs : string list ref 73 - val dllibs : string list ref 73 + val dllibs : (suffixed:bool * string) list ref 74 74 val cmi_file : string option ref 75 75 val compile_only : bool ref 76 76 val output_name : string option ref
+2 -2
utils/config.mli
··· 407 407 @since 5.5 *) 408 408 409 409 val suffixing : bool 410 - (** Whether the runtime executable and shared library filenames are being 411 - mangled with Runtime IDs and the {!target}. 410 + (** Whether the runtime executable and shared library filenames and C stub 411 + library filenames are being mangled with Runtime IDs and the {!target}. 412 412 413 413 @since 5.5 *) 414 414
+5
utils/misc.ml
··· 1558 1558 Printf.sprintf "%scamlrun-%s-%s" prefix host (to_string runtime_id) 1559 1559 | Sys.Other _ -> 1560 1560 invalid_arg "Misc.RuntimeID.shared_runtime" 1561 + 1562 + let stubslib ?(runtime_id = make_bytecode ()) 1563 + ?(host = Config.target) 1564 + name = 1565 + Printf.sprintf "%s-%s-%s" name host (to_string runtime_id) 1561 1566 end
+11
utils/misc.mli
··· 966 966 = "-lasmrun-x86_64-pc-linux-gnu-b100"] for a default OCaml 5.5 967 967 build on a 64-bit system with shared library support and compressed 968 968 marshalling. *) 969 + 970 + val stubslib: ?runtime_id:t -> ?host:string -> string -> string 971 + (** [stublibs ?runtime_id ?host dllname] returns the name for the given DLL 972 + basename. [dllname] should not include {!Config.ext_dll} (and the result 973 + does not include it either). [host] and [runtime_id] default to 974 + {!Config.target} and {!make_bytecode} respectively. 975 + 976 + e.g. [stubslib ~host:"x86_64-pc-linux-gnu" "dllunixbyt" 977 + = "dllunixbyt-x86_64-pc-linux-gnu-001b"] for a default OCaml 5.5 978 + build on a 64-bit system with shared library support and compressed 979 + marshalling. *) 969 980 end 970 981 971 982 (** {1 Miscellaneous type aliases} *)