not-ocamlfind-0.14/0002755000175000017500000000000014770304423013226 5ustar stephstephnot-ocamlfind-0.14/.github/0002755000175000017500000000000014770304423014566 5ustar stephstephnot-ocamlfind-0.14/.github/workflows/0002755000175000017500000000000014770304423016623 5ustar stephstephnot-ocamlfind-0.14/.github/workflows/ci.yml0000644000175000017500000000211714770304423017740 0ustar stephstephname: CI # on: [push, pull_request] on: [workflow_dispatch] jobs: build: strategy: fail-fast: false # Test Linux, macOS and Windows with the oldest and newest supported OCaml # and trunk. matrix: os: - macos-latest - ubuntu-latest - windows-latest ocaml-version: - "4.14" - "5.3" include: - os: ubuntu-latest ocaml-version: "4.10" - os: macos-13 ocaml-version: "4.10" - os: macos-latest ocaml-version: "4.10" runs-on: ${{ matrix.os }} steps: - name: Checkout code uses: actions/checkout@v4 - name: Set-up OCaml ${{ matrix.ocaml-version }} uses: ocaml/setup-ocaml@v3 with: ocaml-compiler: ${{ matrix.ocaml-version }} - name: Setup Dependencies run: | opam install . --deps-only --with-doc --with-test opam pin add not-ocamlfind . --no-action - name: Install it with opam run: | opam install --strict not-ocamlfind not-ocamlfind-0.14/.gitignore0000644000175000017500000000003214770304423015207 0ustar stephsteph*.cm* not-ocamlfind *.exe not-ocamlfind-0.14/CHANGES0000644000175000017500000000246614770304423014227 0ustar stephstephnot-ocamlfind 0.14 ------------------ * [19 Mar 2025] update cached copy of ocamlfind to 1.9.8; update toplevel Makefile to hopefully work well on Windows. not-ocamlfind 0.13 ------------------ * [3 May 2024] add "-impl", "-intf" to the "preprocess" command (pass thru to camlp5). Also fix Freebsd build process. not-ocamlfind 0.12 ------------------ * [22 Sep 2023] change bootstrap in Makefile to avoid freebsd build bug not-ocamlfind 0.11 ------------------ * [30 Aug 2023] swap "bash" to "sh" not-ocamlfind 0.10 ------------------ * [30 Mar 2023] in "preprocess", ignore "-for-pack", "-linkall" arguments so we can just replace "ocamlc" with "preprocess" not-ocamlfind 0.08 ------------------ * [04 Aug 2021] add better support for syntax predicates. formerly, a syntax predicate gets added to "syntax_preds". with this patch, "syntax_" prepended to that predicate also gets added to "predicates". not-ocamlfind 0.07.02 --------------------- * [26 Oct 2020] remove dependencies on sexp (too many deps) since they were for debug only not-ocamlfind 0.07.01 --------------------- * [13 Oct 2020] added a changelog minor fix for ocamlgraph 2.0.0 compatibility. Since ocamlgraph 1.8.8->2.0.0 is a breaking change, this version of not-ocamlfind will only work with the newer version of ocamlgraph. not-ocamlfind-0.14/LICENSE0000644000175000017500000000241314770304423014231 0ustar stephstephThis package is a slight modification of sources originally authored by Gerd Stolpmann, and hence governed by the license on his code. ================================================================ Copyright 1999 by Gerd Stolpmann The package "findlib" is copyright by Gerd Stolpmann. Permission is hereby granted, free of charge, to any person obtaining a copy of this document and the "findlib" software (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. The Software is provided ``as is'', without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall Gerd Stolpmann be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the Software or the use or other dealings in the software. not-ocamlfind-0.14/META0000644000175000017500000000021214770304423013670 0ustar stephsteph# stub META file for "not-ocamlfind" frontend to "ocamlfind" requires = "" version = "0.14" description = "add-on commands for ocamlfind" not-ocamlfind-0.14/Makefile0000644000175000017500000000222114770304423014661 0ustar stephsteph include local-packages/ocamlfind/Makefile.config DEBUG= PACKAGES = str,unix,fmt,rresult,ocamlgraph,camlp-streams INC= -I local-packages/ocamlfind/src/findlib findlib.cma all: not-ocamlfind$(EXEC_SUFFIX) papr_official.exe not-ocamlfind$(EXEC_SUFFIX): fsmod.ml frontend.ml main.ml (cd local-packages/ocamlfind/ && make) ocamlfind ocamlc $(DEBUG) $(INC) -package $(PACKAGES) -linkall -linkpkg fsmod.ml frontend.ml main.ml -o not-ocamlfind$(EXEC_SUFFIX) bootstrap: fsmod.ORIG.ml not-ocamlfind preprocess -package camlp5,pa_ppx.deriving_plugins.show,camlp5.pr_o \ -syntax camlp5o $< > fsmod.ml.NEW mv fsmod.ml.NEW fsmod.ml papr_official.exe: papr_official.ml ocamlfind ocamlc $(DEBUG) $(INC) -package str,unix,compiler-libs.common \ -linkall -linkpkg $< -o $@ install: not-ocamlfind$(EXEC_SUFFIX) $(INSTALLFILE) not-ocamlfind$(EXEC_SUFFIX) $(OCAMLFIND_BIN) ocamlfind remove not-ocamlfind || true ocamlfind install not-ocamlfind META papr_official.exe uninstall: rm -f $(OCAMLFIND_BIN)/not-ocamlfind$(EXEC_SUFFIX) ocamlfind remove not-ocamlfind || true clean: rm -f *.cm* not-ocamlfind$(EXEC_SUFFIX) *.exe (cd local-packages/ocamlfind && make clean) not-ocamlfind-0.14/README.md0000644000175000017500000000662714770304423014516 0ustar stephsteph# not-ocamlfind Front-end to ocamlfind to add a few new commands # Features The command `not-ocamlfind` is a pass-thru to `ocamlfind`, but adds three new commands: `preprocess`, `reinstall-if-diff` and `package-graph`. ### `reinstall-if-diff` 1. `reinstall-if-diff` does what it says on the label: only reinstalls (remove then install) if the file-content of the package has changed. A regular `ocamlfind install` command like ``` ocamlfind install pa_ppx_base -destdir $(DESTDIR)/lib META $(TARGET) pa_ppx_base.cmx pa_ppx_base.cmi ``` installs a package `pa_ppx_base`, failing if the package is already installed. Rewrite that to ``` ocamlfind reinstall-if-diff pa_ppx_base -destdir $(DESTDIR)/lib META $(TARGET) pa_ppx_base.cmx pa_ppx_base.cmi ``` and it checks (a) that the package is already-installed, (b) that the files-to-be-installed are identical in names and checksums to the files already-installed, (c) if not does ``` ocamlfind remove pa_ppx_base ocamlfind install pa_ppx_base -destdir $(DESTDIR)/lib META $(TARGET) pa_ppx_base.cmx pa_ppx_base.cmi ``` and (d) if they are identical in names and checksums, does *nothing*. In projects will multiple directories, if each directory locally installs a `findlib` package, then other directories can use those packages; they can also put those packages into their `make depend` dependencies, viz. ``` EXTERNAL := $(shell $(OCAMLFIND) query -predicates byte $(PACKAGES)) $(CMO) $(CMI) $(CMX): $(EXTERNAL) ``` hence causing rebuilds to occur when other directories have changed. ### `preprocess` A compile command using PPX rewriters ``` ocamlfind ocamlc -package ounit2,ppx_deriving.show -c test_deriving_show.ml ``` can be coaxed to produce its preprocessed output by adding "-dsource". But this is messy and ugly, esp. when we might want to use that source for further compilation. It also isn't very helpful when dealing with a multi-stage PPX rewriter sequence. `preprocess` produces the source and does not attempt to compile it; as an added benefit, it prints (to stderr) the commands it executed to produce that source. So you can use this for debugging multi-stage PPX rewriter sequences: ``` ocamlfind preprocess -package ounit2,ppx_deriving.show test_deriving_show.ml ``` Note well that all the options destined only for the compiler, linker, etc, are removed (and henced rejected) for `preprocess`. Only options required for preprocessing are accepted (`-package`, `-syntax`, `-predicates`, `-ppopt`, `-ppxopt`, `-intf`, `-impl`). This can work for camlp5 also, but that little bit of documentation is TBD. ### `package-graph` This command outputs a graph in the format accepted by the ``dot`` command of graphviz. By default you get the package-dependency graph, with sizes of the archives for each packages as part of the node-label. If you add ``-dominator-from ``, it will compute the dominator-tree from that node. and if you add ``-xdot``, it will automatically invoke ``xdot`` on the graph. Example: ``` not-ocamlfind package-graph -xdot -package camlp5,ounit2,pa_ppx.here.link -dominator-from pa_ppx.here.link -xdot ``` # Installation To install `not-ocamlfind` you need a slightly-patched version of ocamlfind (branch `export-more-cmis`). Until (and unless) this patch gets integrated into the ocamlfind distribution, we build a local copy with that patch. So you merely need to: ``` ./configure make make install ``` not-ocamlfind-0.14/configure0000755000175000017500000000010214770304423015124 0ustar stephsteph#!/bin/sh (cd local-packages/ocamlfind \ && ./configure "$@" ) not-ocamlfind-0.14/frontend.ml0000644000175000017500000014050314770304423015400 0ustar stephsteph(* $Id$ * ---------------------------------------------------------------------- * *) open Findlib;; exception Usage;; exception Silent_error;; type mode = M_reinstall_if_diff | M_preprocess | M_package_graph | M_passthru ;; type psubst = Const of string | Percent of string * modifier | Lookup of string * modifier and modifier = | Plain | Plus ;; let except e = let rec except_e = function [] -> [] | elem::l -> if e = elem then except_e l else elem::except_e l in except_e ;; let sys_error code arg = if arg = "" then Sys_error (Unix.error_message code) else Sys_error (arg ^ ": " ^ Unix.error_message code) let slashify s = match Findlib_config.system with | "mingw" | "mingw64" | "cygwin" -> let b = Buffer.create 80 in String.iter (function | '\\' -> Buffer.add_char b '/' | c -> Buffer.add_char b c ) s; Buffer.contents b | _ -> s let out_path ?(prefix="") s = match Findlib_config.system with | "mingw" | "mingw64" | "cygwin" -> let u = slashify s in prefix ^ (if String.contains u ' ' then (* Desperate attempt to fix the space problem in paths. Note that we invoke commands via Unix.open_process, and this function already quotes the arguments on win32. However, for -ccopt arguments, one quoting level seems to be lost, and we have to add another level to compensate. E.g. for the list of args [ -ccopt; -L/my programs/include -L/somewhere ] we get after out_path [ -ccopt; "-I/my programs/include -L/somewhere" ] which actually translates to -ccopt "\"-I/my programs/include\" \"-L/somewhere\"" on the command line, i.e. a double-quoted argument. *) "\"" ^ u ^ "\"" else u ) | _ -> prefix ^ slashify s let percent_subst ?base spec lookup s = (* spec = [ "%c", [ "ctext1"; "ctext2"; ... ]; * "%d", [ "dtext1"; "dtext2"; ... ] ] * All occurrences of %c in the string s are replaced as specified in spec. * spec is an association list with the %-notation as keys * and lists of strings as values. The result is a list of strings containing * every combination of substituted values. * * Support for the %(name) syntax: In this case, the name is taken as * key for the [lookup] function, which either returns the string value * or raises Not_found. * * "+" modifier: A "+" after "%" causes that Findlib.resolve_path is * called for the substitution string (e.g. %+c, %+(name)). * * Example: * spec = [ "%a", [ "file1" ] ] * lookup = function "archive" -> "file2" | _ -> raise Not_found * Here, %a is substituted by file1, and %(archive) is substituted by * file2. * * ?base: The base parameter for Findlib.resolve_path. *) let l = String.length s in let fail() = failwith "bad format string" in let parenthesized_name j = try if j+1>=l then raise Not_found; let k = String.index_from s (j+1) ')' in let name = String.sub s (j+1) (k-j-1) in (name, k+1) with Not_found -> fail() in let rec preprocess i j = if j if j+1 prev :: Const "%" :: preprocess (j+2) (j+2) | '(' -> let name, j_next = parenthesized_name (j+1) in prev :: Lookup(name,Plain) :: preprocess j_next j_next | '+' -> if j+2 fail() | '(' -> let name, j_next = parenthesized_name (j+2) in prev :: Lookup(name,Plus) :: preprocess j_next j_next | _ -> let name = "%" ^ String.make 1 c in prev :: Percent(name,Plus) :: preprocess (j+3) (j+3) end else fail() | _ -> let name = "%" ^ String.make 1 c in prev :: Percent(name,Plain) :: preprocess (j+2) (j+2) end else fail() | _ -> preprocess i (j+1) end else if i u | Plus -> plus_subst u in let rec subst prefix l = match l with [] -> [prefix] | Const s :: l' -> subst (prefix ^ s) l' | Percent(name,modi) :: l' -> let replacements0 = try List.assoc name spec with Not_found -> failwith "bad format string" in let replacements = List.map (any_subst modi) replacements0 in List.flatten (List.map (fun replacement -> subst (prefix ^ replacement) l') replacements) | Lookup(name,modi) :: l' -> let replacement0 = try lookup name with Not_found -> "" in let replacement = any_subst modi replacement0 in subst (prefix ^ replacement) l' in subst "" (preprocess 0 0) ;; let rec remove_dups l = match l with x :: l' -> if List.mem x l' then remove_dups l' else x::remove_dups l' | [] -> [] ;; let current = ref 0 let argv = ref [||] let arg n = if n < Array.length !argv then (!argv).(n) else raise Not_found ;; let rec nth0 = function (0,l) -> l | (n, h::t) -> nth0 (n-1,t) | _ -> assert false ;; let remaining_args () = nth0 (!current, Array.to_list !argv) ;; let escape_if_needed s = if String.contains s ' ' then "\"" ^ String.escaped s ^ "\"" else s ;; let use_package prefix pkgnames = (* may raise No_such_package *) let pdirs = List.map (fun pname -> "-I " ^ out_path(package_directory pname) ) pkgnames in print_endline (prefix ^ String.concat " " pdirs) ;; let file_contents filename = let ic = open_in filename in let inlen = in_channel_length ic in let s = really_input_string ic inlen in close_in ic ; s ;; let parse_ldconf contents = Str.(split (regexp "\n+") contents) ;; let read_ldconf filename = let contents = file_contents filename in let lines = parse_ldconf contents in lines ;; let format_ldconf lines new_lines = let b = Buffer.create 23 in List.iter (fun line -> Buffer.add_string b (line ^ "\n")) (lines @ new_lines) ; Buffer.contents b ;; let is_dll p = let sfx = Findlib_config.dll_suffix in sfx <> "" && Filename.check_suffix p sfx ;; let identify_dir d = match Sys.os_type with | "Win32" -> failwith "identify_dir" (* not available *) | _ -> let s = Unix.stat d in (s.Unix.st_dev, s.Unix.st_ino) ;; let conflict_report incpath pkglist = (* Check whether there are several definitions for packages * in the current path. We remove duplicate directories first. * Note that all other checks are not sensitive to duplicate directories. *) Fl_package_base.package_conflict_report ~identify_dir (); (* Second check whether there are module conflicts *) let pkgpath = List.map Findlib.package_directory pkglist in Fl_package_base.module_conflict_report ~identify_dir (pkgpath @ incpath); (* Finally check whether there are multiple DLLs: *) (* Note: Only the directories mentioned in ld.conf are checked, but not the * directories in [incpath], and not the directories in CAML_LD_LIBRARY_PATH. * The idea of this check is to ensure a proper installation, and not to * complain about the user's special configuration. *) let ldconf = ocaml_ldconf() in if ldconf <> "ignore" then begin let dll_dirs = remove_dups (read_ldconf ldconf) in let dll_pairs = List.flatten (List.map (fun dll_dir -> let files = try Array.to_list (Sys.readdir dll_dir) with _ -> prerr_endline ("ocamlfind: [WARNING] Cannot read directory " ^ dll_dir ^ " which is mentioned in ld.conf"); [] in List.map (fun file -> (file, dll_dir)) (List.filter is_dll files) ) dll_dirs ) in let dll_hash = Hashtbl.create 50 in List.iter (fun (file, dll_dir) -> Hashtbl.add dll_hash file dll_dir) dll_pairs; Hashtbl.iter (fun file dll_dir -> let locations = Hashtbl.find_all dll_hash file in if List.length locations > 1 then begin prerr_endline ("ocamlfind: [WARNING] The DLL " ^ file ^ " occurs in multiple directories: " ^ dll_dir) end ) dll_hash end ;; let check_package_list l = (* may raise No_such_package *) List.iter (fun pkg -> let _ = package_directory pkg in () ) l ;; type verbosity = | Normal | Verbose | Only_show let run_command ?filter verbose cmd args = let printable_cmd = cmd ^ " " ^ String.concat " " (List.map escape_if_needed args) in ( match verbose with | Normal -> () | Verbose -> print_endline ("+ " ^ printable_cmd); if filter <> None then print_string (" (output of this command is filtered by ocamlfind)\n") | Only_show -> print_endline printable_cmd ); flush stdout; if verbose <> Only_show then ( let filter_input, cmd_output = match filter with None -> Unix.stdin (* dummy *), Unix.stdout | Some f -> Unix.pipe() in (* Signals: On SIGINT, we wait until the subprocess finishes, and * die then. This allows us to call interactive commands as subprocesses. *) let old_sigint = Sys.signal Sys.sigint Sys.Signal_ignore in let need_exe = List.mem Findlib_config.system [ "win32"; "win64"; "mingw"; "mingw64" ] in let fixed_cmd = if need_exe then ( if Filename.check_suffix cmd ".exe" then cmd else cmd ^ ".exe" ) else cmd in let pid = Unix.create_process fixed_cmd (Array.of_list (cmd :: args)) Unix.stdin cmd_output Unix.stderr in begin match filter with Some filter_fun -> begin Unix.close cmd_output; let ch = Unix.in_channel_of_descr filter_input in try while true do let line = input_line ch in match filter_fun line with None -> () (* Suppress line *) | Some line' -> print_endline line' done; assert false with End_of_file -> close_in ch; flush stdout end | None -> () end; let (_,status) = Unix.waitpid [] pid in Sys.set_signal Sys.sigint old_sigint; begin match status with Unix.WEXITED 0 -> () | Unix.WEXITED n -> if verbose = Verbose then print_string (cmd ^ " returned with exit code " ^ string_of_int n ^ "\n"); exit n | Unix.WSIGNALED _ -> print_string (cmd ^ " got signal and exited\n"); exit 2 | Unix.WSTOPPED _ -> failwith "Your operating system does not work correctly" end ) ;; (**************** preprocessor ******************************************) let select_pp_packages syntax_preds packages = if syntax_preds = [] then (* No syntax predicates, no preprocessor! *) [] else List.filter (fun pkg -> let al = try package_property syntax_preds pkg "archive" with Not_found -> "" in let w = Fl_split.in_words al in w <> [] ) packages let process_pp_spec syntax_preds packages pp_opts = (* Returns: pp_command *) (* may raise No_such_package *) (* [packages]: all packages given on the command line. May include * packages for compilation and for preprocessing. * * The difficulty is now that the preprocessor packages may have * requirements that are non-preprocessor packages. To get exactly * the preprocessor packages and its requirements, we do: * * 1. Determine the subset of [packages] that are preprocessor * packages by checking whether they have an "archive" for * [syntax_preds], i.e. the preprocessor packages mentioned * on the command line = [cl_pp_packages]. * * 2. Add their requirements = [pp_packages] * * Because the packages are now mixed, we must evaluate for * [syntax_preds] + "byte". *) (* One packages must now have the variable "preprocessor", usually camlp4 *) let cl_pp_packages = select_pp_packages syntax_preds packages in let pp_packages = package_deep_ancestors syntax_preds cl_pp_packages in let preprocessor_cmds = List.flatten (List.map (fun pname -> try [ pname, package_property syntax_preds pname "preprocessor" ] with Not_found -> [] ) pp_packages ) in let preprocessor_cmd = if syntax_preds <> [] then match preprocessor_cmds with [] -> failwith("Using -syntax, but no package is selected specifying \ a preprocessor as required for -syntax") | [_, cmd] -> Some cmd | _ -> failwith("Several packages are selected that specify \ preprocessors: " ^ String.concat ", " (List.map (fun (n,v) -> "package " ^ n ^ " defines `" ^ v ^ "'") preprocessor_cmds ) ) else None in let pp_i_options = List.flatten (List.map (fun pkg -> let pkgdir = package_directory pkg in [ "-I"; slashify pkgdir ] ) pp_packages) in let pp_archives = if preprocessor_cmd = None then [] else List.flatten (List.map (fun pkg -> let al = try package_property ("byte" :: syntax_preds) pkg "archive" with Not_found -> "" in Fl_split.in_words al ) pp_packages) in match preprocessor_cmd with None -> [] | Some cmd -> let cmd = Str.(split (regexp "[ \t]+") cmd) in cmd@ pp_i_options@ pp_archives@ pp_opts ;; (**************** ppx extensions ****************************************) let process_ppx_spec predicates packages ppx_opts = (* Returns: ppx_commands *) (* may raise No_such_package *) let ppx_packages = package_deep_ancestors predicates packages in let ppx_opts = List.map (fun opt -> match Fl_split.in_words opt with | pkg :: ((_ :: _) as opts) -> let exists = try ignore(package_directory pkg); true with No_such_package _ -> false in if not exists then failwith ("The package named in -ppxopt does not exist: " ^ pkg); pkg, opts | _ -> failwith "-ppxopt must include package name, e.g. -ppxopt \"foo,-name bar\"" ) ppx_opts in let meta_ppx_opts = List.concat (List.map (fun pname -> try let opts = package_property predicates pname "ppxopt" in (* Split by whitespace to get (package,options) combinations. Then, split by commas to get individual options. *) List.map (fun opts -> match Fl_split.in_words opts with | pkg :: ((_ :: _) as opts) -> let exists = try ignore(package_directory pkg); true with No_such_package _ -> false in if not exists then failwith ("The package named in ppxopt variable does not exist: " ^ pkg ^ " (from " ^ pname ^ ")"); let base = package_directory pname in pkg, List.map (resolve_path ~base ~explicit:true) opts | _ -> failwith ("ppxopt variable must include package name, e.g. " ^ "ppxopt=\"foo,-name bar\" (from " ^ pname ^ ")") ) (Fl_split.in_words_ws opts) with Not_found -> [] ) ppx_packages ) in List.flatten (List.map (fun pname -> let base = package_directory pname in let options = try List.concat (List.map (fun (_, opts) -> opts) (List.filter (fun (pname', _) -> pname' = pname) (meta_ppx_opts @ ppx_opts))) with Not_found -> [] in try let preprocessor = resolve_path ~base ~explicit:true (package_property predicates pname "ppx") in ["-ppx"; String.concat " " (preprocessor :: options)] with Not_found -> [] ) ppx_packages) let parse_args ?(current = current) ?(args = !argv) ?(align = true) spec anon usage = try Arg.parse_argv ~current args (if align then Arg.align spec else spec) anon usage with | Arg.Help text -> print_string text; exit 0 | Arg.Bad text -> prerr_string text; exit 2 (**************** OCAMLC/OCAMLMKTOP/OCAMLOPT subcommands ****************) let ppx_invoke1 cmd ~root f = let open Filename in let outf = temp_file root "" in (Printf.sprintf "%s %s %s" cmd f outf, outf) ;; let ppx_invoke cmds f = let open Filename in let base = basename f in if not (check_suffix base ".mli" || check_suffix base ".ml") then failwith "File must end with either .ml or .mli" ; let (root, suff) = if check_suffix base ".mli" then (chop_suffix base ".mli", ".mli") else (chop_suffix base ".ml", ".ml") in let extra_arg = if suff = ".mli" then "-intf" else "-impl" in let outf0 = temp_file root "" in let cmd0 = Printf.sprintf "ocamlfind not-ocamlfind/papr_official.exe -binary-output %s %s %s" extra_arg f outf0 in let (outf, cmdsacc, tmpfiles) = List.fold_left (fun (inf, cmdsacc, tmpfiles) cmd -> let (cmd, outf) = ppx_invoke1 ~root cmd inf in (outf, ((cmd,outf)::cmdsacc), outf::tmpfiles)) (outf0, [(cmd0, outf0)], [outf0]) cmds in let cmds = List.rev cmdsacc in (suff, cmds, outf, tmpfiles) ;; let check_rc msg cmd = Printf.fprintf stderr "%s: %s\n%!" msg cmd ; match Unix.system cmd with Unix.WEXITED 0 -> () | Unix.WEXITED n -> Printf.fprintf stderr "%s: process exited with status %d\n%!" msg n ; failwith (Printf.sprintf "%s: failed" msg) | _ -> failwith (Printf.sprintf "%s: failed with unexpected status" msg) ;; let ppx_execute (suff, cmds, outf, tmpfiles) = cmds |> List.iter (fun (cmd, outf) -> check_rc "ppx_execute" cmd ; ) ; let extra_arg = if suff = ".mli" then "-intf" else "-impl" in check_rc "format output file" (Printf.sprintf "ocamlfind not-ocamlfind/papr_official.exe -binary-input %s %s" extra_arg outf) (* check_rc "unlink tmpfiles" (Printf.sprintf "rm -f %s" (String.concat " " tmpfiles)) *) ;; type pass_file_t = Pass of string | Impl of string (* Forces module implementation: -impl *) | Intf of string (* Forces module interface: -intf *) | Cclib of string (* Option for the C linker: -cclib *) ;; let contracted_ocamlmklib_options = [ "-l"; "-L"; "-R"; "-F"; "-Wl,-rpath,"; "-Wl,-R" ] (* The ocamlmklib options where the argument is directly attached to the switch (e.g. -L instead of -L ) *) (************************************************************************) let preprocess () = (* let destdir = ref (default_location()) in *) let pass_files = ref [] in let packages = ref [] in let predicates = ref [] in let syntax_preds = ref [] in let pp_opts = ref [] in let ppx_opts = ref [] in let verbose = ref Normal in let add_pkg = Arg.String (fun s -> packages := !packages @ (Fl_split.in_words s)) in let ignore_for_pack = Arg.String (fun s -> Fmt.(pf stderr "not-ocamlfind preprocess: ignore -for-pack %s\n%!" s)) in let ignore_linkall = Arg.Unit (fun _ -> Fmt.(pf stderr "not-ocamlfind preprocess: ignore -linkall\n%!")) in let add_pred = Arg.String (fun s -> predicates := !predicates @ (Fl_split.in_words s)) in let add_syntax_pred = Arg.String (fun s -> begin syntax_preds := !syntax_preds @ (Fl_split.in_words s) ; predicates := !predicates @ (List.map (Printf.sprintf "syntax_%s") (Fl_split.in_words s)) ; end) in let do_add_pp_opt s = pp_opts := !pp_opts @ [s] in let add_pp_opt = Arg.String do_add_pp_opt in let do_add_pass_file s = pass_files := !pass_files @ [s] in let ignore_error = ref false in let arg_spec = [ "-package", add_pkg, " Refer to package when compiling"; "-for-pack", ignore_for_pack, " Ignored -for-pack option from ocamlc"; "-linkall", ignore_linkall, " Ignored -linkall option from ocamlc"; "-predicates", add_pred, "

Add predicate

when resolving package properties"; "-syntax", add_syntax_pred, "

Use preprocessor with predicate

"; "-ppopt", add_pp_opt, " Append option to preprocessor invocation"; "-ppxopt", Arg.String (fun s -> ppx_opts := !ppx_opts @ [s]), ", Append options to ppx invocation for package "; "-impl", Arg.String (fun s -> do_add_pass_file (Impl s)), " Append \"impl \" to preprocessor invocation"; "-intf", Arg.String (fun s -> do_add_pass_file (Intf s)), " Append \"intf \" to preprocessor invocation"; "-ignore-error", Arg.Set ignore_error, " Ignore the 'error' directive in META files"; "-only-show", Arg.Unit (fun () -> verbose := Only_show), " Only show the constructed command, but do not exec it"; "-verbose", Arg.Unit (fun () -> verbose := Verbose), " Show the constructed command and also exec it\nSTANDARD OPTIONS:"; ] in let (current,args) = (current, !argv) in parse_args ~current ~args arg_spec (fun s -> do_add_pass_file (Pass s)) ("usage: not-ocamlfind preprocess [options] file ..."); (* ---- Start requirements analysis ---- *) predicates := "byte" :: !predicates; if !syntax_preds <> [] then begin predicates := "syntax" :: !predicates; syntax_preds := "preprocessor" :: "syntax" :: !syntax_preds; end; (* check packages: *) check_package_list !packages; let eff_packages = package_deep_ancestors !predicates !packages in (* ---- End of requirements analysis ---- *) (* Add the pkg_ predicates: *) predicates := List.map (fun pkg -> "pkg_" ^ pkg) eff_packages @ !predicates; (* Check on [warning] directives: *) List.iter (fun pkg -> try let warning = package_property !predicates pkg "warning" in prerr_endline("ocamlfind: [WARNING] Package `" ^ pkg ^ "': " ^ warning) with Not_found -> () ) eff_packages; (* Check on [error] directives: *) List.iter (fun pkg -> try let error = package_property !predicates pkg "error" in if !ignore_error then prerr_endline("ocamlfind: [WARNING] Package `" ^ pkg ^ "' signals error: " ^ error) else failwith ("Error from package `" ^ pkg ^ "': " ^ error) with Not_found -> () ) eff_packages; if !verbose = Verbose then begin if !syntax_preds <> [] then print_string ("Effective set of preprocessor predicates: " ^ String.concat "," !syntax_preds ^ "\n"); print_string ("Effective set of compiler predicates: " ^ String.concat "," !predicates ^ "\n"); end; (* initl_file_name: the initialization code inserted at the end of * the cma/cmo list (initl = init last) *) let pp_command = process_pp_spec !syntax_preds !packages !pp_opts in let ppx_commands = process_ppx_spec !predicates !packages !ppx_opts in let pass_files' = List.flatten (List.map (function Pass s -> if s <> "" && s.[0] = '-' then [ "-"; String.sub s 1 (String.length s - 1) ] else [ resolve_path s ] | Impl s -> [ "-impl"; resolve_path s ] | Intf s -> [ "-intf"; resolve_path s ] | Cclib s -> [ "-cclib"; s ] ) !pass_files) in if pp_command <> [] && ppx_commands <> [] then prerr_endline("not-ocamlfind: [ERROR] both pp and ppx commands present (cannot preprocess)") ; if pp_command <> [] then let pp_command = pp_command@ pass_files' in run_command !verbose (List.hd pp_command) (List.tl pp_command) else begin let ppx_commands = except "-ppx" ppx_commands in List.iter (fun f -> let (suff, cmds, outf, tmpfiles) = ppx_invoke ppx_commands f in ppx_execute (suff, cmds, outf, tmpfiles) ) pass_files' ; end ;; (************************************************************************) module PackageGraph = struct open Graph module StringVertex = struct type t = string let compare = Stdlib.compare let hash = Hashtbl.hash let equal a b = (a = b) type label = t let create x = x let label x = x end module V = StringVertex module G = Imperative.Digraph.ConcreteBidirectional(V) module DotIn = struct type t = G.t module V = G.V module E = G.E let iter_vertex = G.iter_vertex let iter_edges_e = G.iter_edges_e let graph_attributes _ = [] let default_vertex_attributes _ = [] let vertex_name v = v let vertex_attributes _ = [] let get_subgraph _ = None let default_edge_attributes _ = [] let edge_attributes _ = [] end module GDot = Graph.Graphviz.Dot(DotIn) module DomG = Dominator.Make_graph(struct include G let empty () = create () let add_edge g v1 v2 = G.add_edge g v1 v2 ; g end) let to_dot ~dominator_from oc edges = let g = G.create () in List.iter (fun (s, dl) -> List.iter (fun d -> G.add_edge g s d) dl) edges ; let g = match dominator_from with Some v -> DomG.(compute_dom_graph g (compute_all g v).dom_tree) | None -> g in GDot.output_graph oc g ; flush oc end let size_of_package predicates p = match Findlib.package_directory p, Findlib.package_property predicates p "archive" with (dir, archives) -> let archives = Str.(split (regexp " +") archives) in let archives = List.map (fun a -> Printf.sprintf "%s/%s" dir a) archives in List.fold_left (fun acc f -> acc + Unix.(stat f).st_size) 0 archives | exception Not_found -> 0 let package_graph () = let packages = ref [] in let predicates = ref [] in let verbose = ref Normal in let syntax_preds = ref [] in let add_pkg = Arg.String (fun s -> packages := !packages @ (Fl_split.in_words s)) in let add_pred = Arg.String (fun s -> predicates := !predicates @ (Fl_split.in_words s)) in let add_syntax_pred = Arg.String (fun s -> begin syntax_preds := !syntax_preds @ (Fl_split.in_words s) ; predicates := !predicates @ (List.map (Printf.sprintf "syntax_%s") (Fl_split.in_words s)) ; end) in let ignore_error = ref false in let dominator_from = ref "" in let xdot = ref false in let arg_spec = [ "-package", add_pkg, " Refer to package when compiling"; "-predicates", add_pred, "

Add predicate

when resolving package properties"; "-syntax", add_syntax_pred, "

Use preprocessor with predicate

"; "-dominator-from", Set_string dominator_from, "

compute dominator graph from this package

"; "-ignore-error", Arg.Set ignore_error, " Ignore the 'error' directive in META files"; "-xdot", Arg.Set xdot, " invoke ``xdot'' on .dot file"; "-verbose", Arg.Unit (fun () -> verbose := Verbose), " Only show the constructed command, but do not exec it\nSTANDARD OPTIONS:"; ] in let (current,args) = (current, !argv) in parse_args ~current ~args arg_spec (fun s -> failwith (Printf.sprintf "Should not provide any files to the package-graph subcommand (only packages): %s" s)) ("usage: not-ocamlfind package-graph [options] -package "); (* ---- Start requirements analysis ---- *) if not (List.mem "native" !predicates) && not (List.mem "byte" !predicates) then predicates := "byte" :: !predicates; if !syntax_preds <> [] then begin predicates := "syntax" :: !predicates; syntax_preds := "preprocessor" :: "syntax" :: !syntax_preds; end; (* check packages: *) check_package_list !packages; let eff_packages = package_deep_ancestors !predicates !packages in (* ---- End of requirements analysis ---- *) (* Check on [warning] directives: *) List.iter (fun pkg -> try let warning = package_property !predicates pkg "warning" in prerr_endline("ocamlfind: [WARNING] Package `" ^ pkg ^ "': " ^ warning) with Not_found -> () ) eff_packages; (* Check on [error] directives: *) List.iter (fun pkg -> try let error = package_property !predicates pkg "error" in if !ignore_error then prerr_endline("ocamlfind: [WARNING] Package `" ^ pkg ^ "' signals error: " ^ error) else failwith ("Error from package `" ^ pkg ^ "': " ^ error) with Not_found -> () ) eff_packages; if !verbose = Verbose then begin if !syntax_preds <> [] then print_string ("Effective set of preprocessor predicates: " ^ String.concat "," !syntax_preds ^ "\n"); print_string ("Effective set of compiler predicates: " ^ String.concat "," !predicates ^ "\n"); end; (* initl_file_name: the initialization code inserted at the end of * the cma/cmo list (initl = init last) *) let package_graph = List.map (fun p -> (p, package_ancestors !predicates p)) eff_packages in let name2vertex = List.map (fun (p,_) -> let size = size_of_package !predicates p in let rhs = if size = 0 then Fmt.(str "\"%s\"" p) else Fmt.(str "\"%s: %a\"" p bi_byte_size size) in (p, rhs)) package_graph in (* let name2vertex = List.map (fun (p, _) -> (p, Printf.sprintf "\"%s\"" p)) package_graph in *) let n2v n = match List.assoc n name2vertex with v -> v | exception Not_found -> failwith (Printf.sprintf "package %s not in name2vertex map" n) in let g2 = List.map (fun (s,dl) -> (n2v s, List.map n2v dl)) package_graph in let dominator_from = match !dominator_from with "" -> None | s -> Some (n2v s) in if !xdot then begin let tmpfile = Filename.temp_file "graph" ".dot" in let oc = open_out tmpfile in PackageGraph.to_dot ~dominator_from:dominator_from oc g2 ; close_out oc ; ignore (Unix.system (Printf.sprintf "xdot %s" tmpfile)) ; ignore (Unix.unlink tmpfile) end else PackageGraph.to_dot ~dominator_from:dominator_from stdout g2 ;; (************************************************************************) let format_owner_file pkg file = let outpath = file ^ ".owner" in let contents = (pkg ^ "\n") in (outpath, contents) ;; let trim_cr s = let len = String.length s in if len > 0 && String.get s (len-1) = '\r' then String.sub s 0 (len-1) else s let find_owned_files pkg dir = let files = Array.to_list(Sys.readdir dir) in List.filter (fun file -> let owner_file = if Filename.check_suffix file ".owner" then file else file ^ ".owner" in (List.mem owner_file files) && ( try let fd = Unix.openfile (Filename.concat dir owner_file) [Unix.O_RDONLY] 0 in let f = Unix.in_channel_of_descr fd in try let line = trim_cr (input_line f) in let is_my_file = (line = pkg) in close_in f; is_my_file with | End_of_file -> close_in f; false | exc -> close_in f; raise exc with | Unix.Unix_error(Unix.ENOENT,_,_) -> (* the owner file might have been removed by a package removal that is being done in parallel *) false | Unix.Unix_error(code, _, arg) -> raise(sys_error code arg) ) ) files ;; exception Missing_archives of Fl_metascanner.pkg_expr let rec patch_archives pkgdir pkg = (* First remove all missing files from archive variables: *) let defs' = List.map (fun def -> if def.Fl_metascanner.def_var = "archive" then ( let files = Fl_split.in_words def.Fl_metascanner.def_value in let files' = List.filter (fun file -> let p = Findlib.resolve_path ~base:pkgdir file in Sys.file_exists p) files in { def with Fl_metascanner.def_value = String.concat " " files' } ) else def ) pkg.Fl_metascanner.pkg_defs in (* Remove empty archive variables: *) let defs'' = List.filter (fun def -> def.Fl_metascanner.def_var <> "archive" || Fl_split.in_words def.Fl_metascanner.def_value <> [] ) defs' in (* Return the package or raise Not_found if all archives vanished: *) let children = (* Recursive patch, remove all Not_found packages: *) List.flatten (List.map (fun (name, child) -> try [ name, patch_archives pkgdir child ] with Missing_archives _ -> [] ) pkg.Fl_metascanner.pkg_children) in let pkg' = { Fl_metascanner.pkg_defs = defs''; pkg_children = children } in if List.exists (fun def -> def.Fl_metascanner.def_var = "archive") defs'' then pkg' else raise (Missing_archives pkg') ;; let rec patch_pkg pkgdir pkg patches = match patches with | [] -> pkg | (`Version v) :: patches' -> let def = { Fl_metascanner.def_var = "version"; def_flav = `BaseDef; def_preds = []; def_value = v } in let defs = List.filter (fun d -> d.Fl_metascanner.def_var <> "version") pkg.Fl_metascanner.pkg_defs in let pkg' = { pkg with Fl_metascanner.pkg_defs = def :: defs } in patch_pkg pkgdir pkg' patches' | (`Rmpkg n) :: patches' -> let children = List.filter (fun (name,_) -> name <> n) pkg.Fl_metascanner.pkg_children in let pkg' = { pkg with Fl_metascanner.pkg_children = children } in patch_pkg pkgdir pkg' patches' | `Archives :: patches' -> let pkg' = try patch_archives pkgdir pkg with Missing_archives p -> p in patch_pkg pkgdir pkg' patches' ;; exception Skip_file;; type which = Auto | Dll | No_dll;; let meta_pkg meta_name = let f = open_in meta_name in try let pkg = Fl_metascanner.parse f in close_in f; pkg with | Failure s | Stream.Error s -> close_in f; failwith ("Cannot parse '" ^ meta_name ^ "': " ^ s) let char_lowercase_ascii c = (* Char.lowercase_ascii and String.lowercase_ascii first available in OCaml-4.03, but we want to support earlier versions too *) if (c >= 'A' && c <= 'Z') then Char.unsafe_chr(Char.code c + 32) else c let string_lowercase_ascii = String.map char_lowercase_ascii open Fsmod let prepare_remove_package ~destdir ~metadir ~ldconf ~pkgname = let meta_dot_pkg = "META." ^ pkgname in let has_metadir = metadir <> "" in let pkgdir = Filename.concat destdir pkgname in let dlldir = Filename.concat destdir Findlib_config.libexec_name in let have_libexec = Sys.file_exists dlldir in (* First remove the META file. If it is already gone, assume that a parallel running removal removed it already. *) let mods = ref [] in let push_rm f = if Sys.file_exists f then let digest = Digest.(f |> file |> to_hex) in mods := (f, FM_delete { name = f; checksum = digest }) :: !mods in let push_update f bytes = if Sys.file_exists f then let digest = Digest.(f |> file |> to_hex) in mods := (f, FM_update ({ name = f; checksum = digest}, bytes)) :: !mods in if has_metadir then push_rm (Filename.concat metadir meta_dot_pkg) else push_rm (Filename.concat pkgdir "META") ; (* Remove files from libexec directory: *) if have_libexec then begin let dll_files = find_owned_files pkgname dlldir in List.iter (fun file -> let absfile = Filename.concat dlldir file in push_rm absfile ) dll_files end; (* Remove the files from the package directory: *) if Sys.file_exists pkgdir then begin let files = Sys.readdir pkgdir in Array.iter (fun f -> if f <> "META" then push_rm (Filename.concat pkgdir f)) files; end else prerr_endline("ocamlfind: [WARNING] No such directory: " ^ pkgdir); (* Modify ld.conf *) if ldconf <> "ignore" && Sys.file_exists ldconf then begin let lines = read_ldconf ldconf in let d = Fl_split.norm_dir pkgdir in let exists = List.exists (fun p -> Fl_split.norm_dir p = d) lines in if exists then begin let lines' = List.filter (fun p -> Fl_split.norm_dir p <> d) lines in push_update ldconf (format_ldconf lines' []) end end; (* Check if there is a postremove script: *) let postremove = Filename.concat destdir "postremove" in if Sys.file_exists postremove then failwith "cannot reinstall-if-diff a package with a postremove script" ; List.rev !mods ;; let prepare_reinstall_if_diff_package () = let destdir = ref (default_location()) in let metadir = ref (meta_directory()) in let ldconf = ref (ocaml_ldconf()) in let don't_add_directory_directive = ref false in let pkgname = ref "" in let auto_files = ref [] in let dll_files = ref [] in let nodll_files = ref [] in let which = ref Auto in let debug = ref false in let keywords = [ "-destdir", (Arg.String (fun s -> destdir := s)), (" Set the destination directory (default: " ^ !destdir ^ ")"); "-metadir", (Arg.String (fun s -> metadir := s)), (" Install the META file into this directory (default: "^ (if !metadir = "" then "none" else !metadir) ^ ")"); "-ldconf", (Arg.String (fun s -> ldconf := s)), (" Update this ld.conf file (default: " ^ !ldconf ^ ")"); "-dont-add-directory-directive", (Arg.Set don't_add_directory_directive), " never append directory='...' to META"; "-dll", Arg.Unit (fun () -> which := Dll), " The following files are DLLs"; "-nodll", Arg.Unit (fun () -> which := No_dll), " The following files are not DLLs"; "-debug", Arg.Set debug, " Enable massive debug-logging"; ] in let errmsg = "usage: ocamlfind reinstall-if-diff [options] ..." in let install_args = except "-debug" (List.tl (remaining_args ())) in parse_args keywords (fun s -> if !pkgname = "" then pkgname := s else if Sys.file_exists s then match !which with Auto -> auto_files := s :: !auto_files | Dll -> dll_files := s :: !dll_files | No_dll -> nodll_files := s :: !nodll_files else failwith Fmt.(str "reinstall-if-diff: file (to be installed) %s does not exist" s) ) errmsg; if !pkgname = "" then (Arg.usage keywords errmsg; exit 1); if not (Fl_split.is_valid_package_name !pkgname) then failwith "Package names must not contain the character '.'!"; if !debug then Fmt.(pf stderr "removal_mods: START\n%!"); let removal_mods = prepare_remove_package ~destdir:!destdir ~metadir:!metadir ~ldconf:!ldconf ~pkgname:!pkgname in if !debug then Fmt.(pf stderr "removal_mods:\n%a\n%!" pp_t_pair_list removal_mods ) ; (* if this file is listed in the removal-mods, then we pretend it doesn't exist; otherwise we pass it along to Sys.file_exists *) let file_exists f = if List.mem_assoc f removal_mods then false else Sys.file_exists f in let read_file f = match List.assoc f removal_mods with FM_update (_, contents) -> contents | _ -> failwith "Internal error: can only read_file on a file that we're going to update" | exception Not_found -> failwith "Internal error: can only read_file on a file that we're going to update" in let install_mods = ref [] in let push_install ~srcf ~dstf = let digest = Digest.(srcf |> file |> to_hex) in install_mods := (dstf, FM_install { name = srcf; checksum = digest }) :: !install_mods in let push_create ~dstf ~contents = let digest = Digest.(contents |> string |> to_hex) in install_mods := (dstf, FM_create ({ name = dstf; checksum = digest }, contents)) :: !install_mods in let push_update f b = let digest = Digest.(f |> file |> to_hex) in install_mods := (f, FM_update ({ name = f; checksum = digest}, b)) :: !install_mods in let pkgdir = Filename.concat !destdir !pkgname in let dlldir = Filename.concat !destdir Findlib_config.libexec_name in let has_metadir = !metadir <> "" in let meta_dot_pkg = "META." ^ !pkgname in (* The list of all files to install: *) let full_list = !auto_files @ !dll_files @ !nodll_files in (* Check whether there are DLLs: *) let (l1,l2) = List.partition is_dll !auto_files in let dll_list = l1 @ !dll_files in let nodll_list = l2 @ !nodll_files in let have_libexec = Sys.file_exists dlldir in let pkgdir_list = if have_libexec then nodll_list else full_list in let pkgdir_eff_list = (* The files that will be placed into pkgdir: *) List.map (fun f -> if f = meta_dot_pkg then "META" else f) (List.filter (fun f -> not has_metadir || (f <> "META" && f <> meta_dot_pkg)) pkgdir_list) in (* Check whether META exists: (And check syntax) *) let meta_name = try List.find (fun p -> let b = Filename.basename p in b = "META" || b = meta_dot_pkg) nodll_list with | Not_found -> failwith "The META file is missing" in (* Check for frequent reasons why installation can go wrong *) if file_exists (Filename.concat !metadir meta_dot_pkg) then failwith ("Package " ^ !pkgname ^ " is already installed\n - (file " ^ Filename.concat !metadir meta_dot_pkg ^ " already exists)"); if file_exists (Filename.concat pkgdir "META") then failwith ("Package " ^ !pkgname ^ " is already installed\n - (file " ^ pkgdir ^ "/META already exists)"); List.iter (fun f -> let f' = Filename.concat pkgdir f in if file_exists f' then failwith ("Conflict with file: " ^ f')) pkgdir_eff_list; if have_libexec then begin List.iter (fun dll -> let b = Filename.basename dll in if file_exists (Filename.concat dlldir b) then failwith ("Conflict with another package: Library " ^ b ^ " is already installed"); ) dll_list end; (* Now copy the files into the package directory (except META): *) List.iter (fun srcf -> try let dstf = Filename.concat pkgdir srcf in if srcf = "META" || srcf = meta_dot_pkg then raise Skip_file ; if srcf = "postremove" then failwith "cannot reinstall-if-diff a package with a postremove script" ; if srcf = "postinstall" then failwith "cannot reinstall-if-diff a package with a postinstall script" ; push_install ~srcf ~dstf with Skip_file -> () ) pkgdir_list; (* Copy the DLLs into the libexec directory if necessary *) if have_libexec then begin List.iter (fun srcf -> let dstf = Filename.concat pkgdir srcf in push_install ~srcf ~dstf ; let (owner_file, contents) = format_owner_file !pkgname (Filename.concat dlldir (Filename.basename srcf)) in push_create ~dstf:owner_file ~contents ) dll_list end; (* Extend ld.conf if necessary: *) if dll_list <> [] && !ldconf <> "ignore" && not have_libexec then begin if Sys.file_exists !ldconf then begin let contents = read_file !ldconf in let lines = parse_ldconf contents in push_update !ldconf (format_ldconf lines [ pkgdir ]) end else prerr_endline("ocamlfind: [WARNING] You have installed DLLs but there is no ld.conf") end; if dll_list <> [] && have_libexec && !ldconf <> "ignore" then begin (* Check whether libexec is mentioned in ldconf *) (* FIXME: We have to be careful with case-insensitive filesystems. Currently, we only check for Win32, but also OS X may have ci filesystems. So some better check would be nice. *) let lines = read_ldconf !ldconf in let dlldir_norm = Fl_split.norm_dir dlldir in let dlldir_norm_lc = string_lowercase_ascii dlldir_norm in let ci_filesys = (Sys.os_type = "Win32") in let check_dir d = let d' = Fl_split.norm_dir d in (d' = dlldir_norm) || (ci_filesys && string_lowercase_ascii d' = dlldir_norm_lc) in if not (List.exists check_dir lines) then prerr_endline("ocamlfind: [WARNING] You have installed DLLs but the directory " ^ dlldir_norm ^ " is not mentioned in ld.conf"); end; (* Finally, write the META file: *) let write_meta append_directory dir name = let contents = file_contents meta_name in let contents = if append_directory then contents ^ "\ndirectory=\"" ^ pkgdir ^ "\" # auto-added by ocamlfind\n" else contents in push_create ~dstf:(Filename.concat dir name) ~contents in if has_metadir then write_meta true !metadir meta_dot_pkg else write_meta false pkgdir "META"; let remove_args = ["-destdir"; !destdir; !pkgname] in (!debug, List.rev !install_mods, install_args, removal_mods, remove_args) ;; let same_action (ifname, iact) (rfname, ract) = if ifname <> rfname then ( Fmt.(pf stderr "Files %s, %s at same position in sorted list of actions\n%!" ifname rfname) ; false ) else match iact, ract with FM_install {name=s2; checksum=sum2}, FM_delete { name=s1; checksum=sum1} when sum1=sum2 -> true | FM_create ({name=s2; checksum=sum2}, _), FM_delete { name=s1; checksum=sum1} when s1=s2 && sum1=sum2 -> true | _ -> Fmt.(pf stderr "File %s has incompatible {install, remove} actions: (%a,%, %a)\n%!" ifname pp iact pp ract) ; false ;; let is_same (install_mods, removal_mods) = let imap = List.sort Stdlib.compare install_mods in let rmap = List.sort Stdlib.compare removal_mods in let rec rerec = function ((ifname, iact)::it, (rfname, ract)::rt) -> if not (same_action (ifname, iact) (rfname, ract)) then false else rerec (it, rt) | ([], []) -> true | _ -> Fmt.(pf stderr "reinstall-if-diff: remove and install lists have differing lengths\n%!") ; false in rerec (imap, rmap) ;; let reinstall_if_diff () = let (debug, install_mods, install_args, removal_mods, remove_args) = prepare_reinstall_if_diff_package() in if debug then Fmt.(pf stderr "reinstall_if_diff\ninstall_mods:\n%a\ninstall_args: [%a]\nremoval_mods:\n%a\nremove_args: [%a]\n%!" pp_t_pair_list install_mods (list ~sep:(const string " ") string) install_args pp_t_pair_list removal_mods (list ~sep:(const string " ") string) remove_args ) ; if not (is_same (install_mods, removal_mods)) then begin run_command Verbose "ocamlfind" ("remove" :: remove_args) ; run_command Verbose "ocamlfind" ("install" :: install_args) end ;; let passthru () = run_command Normal "ocamlfind" (List.tl (Array.to_list !argv)) ;; let rec select_mode () = let k = !current in let m_string = try arg (k+1) with Not_found -> raise Usage in let m = match m_string with ("reinstall-if-diff") -> incr current; M_reinstall_if_diff | ("preprocess") -> incr current; M_preprocess | ("package-graph") -> incr current; M_package_graph | _ -> M_passthru in m ;; let _main av curr () = argv := av ; current := curr ; try let m = select_mode() in match m with M_reinstall_if_diff -> reinstall_if_diff() | M_preprocess -> preprocess () | M_package_graph -> package_graph () | M_passthru -> passthru() with Failure f -> prerr_endline ("ocamlfind: " ^ f); exit 2 | Sys_error f -> prerr_endline ("ocamlfind: " ^ f); exit 2 | Findlib.No_such_package(pkg,info) -> prerr_endline ("ocamlfind: Package `" ^ pkg ^ "' not found" ^ (if info <> "" then " - " ^ info else "")); exit 2 | Findlib.Package_loop pkg -> prerr_endline ("ocamlfind: Package `" ^ pkg ^ "' requires itself"); exit 2 | Silent_error -> exit 2 ;; let main ?(argv = Sys.argv) ?(current = !Arg.current) () = _main argv current () ;; not-ocamlfind-0.14/fsmod.ORIG.ml0000644000175000017500000000060714770304423015430 0ustar stephsteph module Pa_ppx_runtime = struct module Runtime = struct module Fmt = Fmt end end type file_t = { name : string ; checksum : string }[@@deriving show] type t = FM_delete of file_t | FM_install of file_t | FM_update of file_t * string | FM_create of file_t * string[@@deriving show] type t_pair = string * t[@@deriving show] type t_pair_list = t_pair list[@@deriving show] not-ocamlfind-0.14/fsmod.ml0000644000175000017500000000624314770304423014673 0ustar stephsteph module Pa_ppx_runtime = struct module Runtime = struct module Fmt = Fmt end end type file_t = { name : string; checksum : string }[@@deriving_inline show] let rec (pp_file_t : file_t Fmt.t) = fun (ofmt : Format.formatter) arg -> (fun ofmt ({name = v_name; checksum = v_checksum} : file_t) -> let open Pa_ppx_runtime.Runtime.Fmt in pf ofmt "@[<2>{ @[Fsmod.name =@ %a@];@ @[checksum =@ %a@] }@]" (fun ofmt arg -> let open Pa_ppx_runtime.Runtime.Fmt in pf ofmt "%S" arg) v_name (fun ofmt arg -> let open Pa_ppx_runtime.Runtime.Fmt in pf ofmt "%S" arg) v_checksum) ofmt arg[@@ocaml.warning "-39"] [@@ocaml.warning "-33"] and (show_file_t : file_t -> Stdlib.String.t) = fun arg -> Format.asprintf "%a" pp_file_t arg[@@ocaml.warning "-39"] [@@ocaml.warning "-33"] [@@@end] type t = FM_delete of file_t | FM_install of file_t | FM_update of file_t * string | FM_create of file_t * string[@@deriving_inline show] let rec (pp : t Fmt.t) = fun (ofmt : Format.formatter) arg -> (fun ofmt -> function FM_delete v0 -> let open Pa_ppx_runtime.Runtime.Fmt in pf ofmt "(@[<2>Fsmod.FM_delete@ %a)@]" pp_file_t v0 | FM_install v0 -> let open Pa_ppx_runtime.Runtime.Fmt in pf ofmt "(@[<2>Fsmod.FM_install@ %a)@]" pp_file_t v0 | FM_update (v0, v1) -> let open Pa_ppx_runtime.Runtime.Fmt in pf ofmt "(@[<2>Fsmod.FM_update@ (@,%a,@ %a@,))@]" pp_file_t v0 (fun ofmt arg -> let open Pa_ppx_runtime.Runtime.Fmt in pf ofmt "%S" arg) v1 | FM_create (v0, v1) -> let open Pa_ppx_runtime.Runtime.Fmt in pf ofmt "(@[<2>Fsmod.FM_create@ (@,%a,@ %a@,))@]" pp_file_t v0 (fun ofmt arg -> let open Pa_ppx_runtime.Runtime.Fmt in pf ofmt "%S" arg) v1) ofmt arg[@@ocaml.warning "-39"] [@@ocaml.warning "-33"] and (show : t -> Stdlib.String.t) = fun arg -> Format.asprintf "%a" pp arg[@@ocaml.warning "-39"] [@@ocaml.warning "-33"] [@@@end] type t_pair = string * t[@@deriving_inline show] let rec (pp_t_pair : t_pair Fmt.t) = fun (ofmt : Format.formatter) arg -> (fun (ofmt : Format.formatter) (v0, v1) -> let open Pa_ppx_runtime.Runtime.Fmt in pf ofmt "(@[%a,@ %a@])" (fun ofmt arg -> let open Pa_ppx_runtime.Runtime.Fmt in pf ofmt "%S" arg) v0 pp v1) ofmt arg[@@ocaml.warning "-39"] [@@ocaml.warning "-33"] and (show_t_pair : t_pair -> Stdlib.String.t) = fun arg -> Format.asprintf "%a" pp_t_pair arg[@@ocaml.warning "-39"] [@@ocaml.warning "-33"] [@@@end] type t_pair_list = t_pair list[@@deriving_inline show] let rec (pp_t_pair_list : t_pair_list Fmt.t) = fun (ofmt : Format.formatter) arg -> (fun (ofmt : Format.formatter) arg -> let open Pa_ppx_runtime.Runtime.Fmt in pf ofmt "@[<2>[%a@,]@]" (list ~sep:semi pp_t_pair) arg) ofmt arg[@@ocaml.warning "-39"] [@@ocaml.warning "-33"] and (show_t_pair_list : t_pair_list -> Stdlib.String.t) = fun arg -> Format.asprintf "%a" pp_t_pair_list arg[@@ocaml.warning "-39"] [@@ocaml.warning "-33"] [@@@end] not-ocamlfind-0.14/local-packages/0002755000175000017500000000000014770304423016074 5ustar stephstephnot-ocamlfind-0.14/local-packages/ocamlfind/0002755000175000017500000000000014770304423020030 5ustar stephstephnot-ocamlfind-0.14/local-packages/ocamlfind/.gitignore0000644000175000017500000000054714770304423022024 0ustar stephsteph*~ *.cmi *.cmo *.cma *.cmx *.o *.cmxa *.cmxs *.a *.so META Makefile.config Makefile.packages findlib.conf ocargs.log src/findlib/findlib_config.ml src/findlib/fl_meta.ml src/findlib/ocaml_args.ml src/findlib/ocamlfind src/findlib/topfind src/findlib/topfind.ml src/findlib/topfind.compat.in tools/extract_args/extract_args tools/extract_args/extract_args.ml not-ocamlfind-0.14/local-packages/ocamlfind/INSTALL0000644000175000017500000001233314770304423021061 0ustar stephstephThe installation procedure consists of the steps: 1) configure the "findlib" library 2) compile "findlib" and the "ocamlfind" frontend of "findlib" 3) install "findlib" and the core library configuration Optionally, you can run ./itest after step 2 to check the configuration. Problems with the configuration are unlikely, however. At the end of this file you find notes about MacOS and Windows. ---------------------------------------------------------------------- STEP 1: DEFAULT CONFIGURATION The findlib module and its ocamlfind frontend come with a "configure" script that should almost always be able to figure out a good configuration. Just type: ./configure First the linker options for the various core libraries are figured out, then reasonable installation paths are checked. If the results are not ok, you can modify them using the following options: -bindir set the location where the ocamlfind command should be installed. Default: same location as "ocamlc" -mandir set the location where the man page should be installed. Default: a heuristics, and "/usr/local/man" as fallback. -sitelib set the default "site-lib" directory. Default: For installations in the /usr hierarchy, "$stdlib/site-lib", where $stdlib is the location of Ocaml's standard library. For installations in the /opt hierarchy, "$stdlib/../site-lib", i.e. parallel to $stdlib. -config set the location of the configuration file. Default: /../etc/findlib.conf -no-topfind the "topfind" script is not installed in the standard library directory. (This is not a good idea in general, because #use "topfind" will not work when this option is enabled.) -with-toolbox also compile and install the "toolbox". This requires that labltk is available. The toolbox contains the "make_wizard" to easily create findlib-enabled Makefiles. -cygpath Cygwin environment only: If "ocamlc -where" does not output a Unix-style path, this option can be used to apply the "cygpath" command to it. Use this option if you see backslashes or drive letters in Makefile.config. ALTERNATIVES: If the "configure" script does not work properly (very unlikely), do cp Makefile.config.pattern Makefile.config and edit Makefile.config by hand. If the generated META files do not work, edit them (this is very very unlikely). Note: The META files are generated from the META.in files in the same directories by sed: sed -e 's/%%findlib_version%%//g' site-lib//META.in >site-lib//META You may invoke sed manually to create different META files, but this is currently not documented. ---------------------------------------------------------------------- STEP 2: COMPILATION After configuration has been done, compile with make all This creates findlib.cma, findlib_mt.cma (the thread-safe version), and ocamlfind. If you have ocamlopt, do also make opt This creates findlib.cmxa, findlib_mt.cmxa, and ocamlfind_opt. ---------------------------------------------------------------------- STEP 3: INSTALLATION Install the findlib library, the ocamlfind frontend, and the core library configurations with: make install (A "make uninstall" removes them.) With make clean the build directory is cleaned up. OPTIONAL (BUT RECOMMENDED): If you want a separate directory for DLLs, create this directory now: mkdir `ocamlfind printconf destdir`/stublibs If you do this, you must also tell OCaml that DLLs can be found in this directory: Add the absolute path of this directory to the ld.conf file (type "ocamlfind printconf ldconf" to get the location of the ld.conf file). Every line of this text file lists one possible directory for DLLs. ---------------------------------------------------------------------- MACOS X: Findlib can be installed as described. There is even a script to create a MacOS X package, use "make package-macosx" to invoke it. As I do not have access to a Mac box, I cannot test this script, but I fully trust the author that it works. ---------------------------------------------------------------------- WINDOWS: Ocaml for Windows exists in three flavours: (1) Ocaml as Cygwin program (2) Ocaml as Mingw program (i.e. the gcc toolchain is used but Ocaml is a native Windows program) (3) Ocaml as VC program In all three cases you need Cygwin to build and install findlib, because "configure" and the Makefile are both Cygwin scripts. The golden rule to make everything work is this: PASS CYGWIN-STYLE PATHS TO CONFIGURE! Even in cases (2) and (3)! That means use something like /cygdrive/c/path and not c:\path when you specify where -bindir, -config etc. are. The point is that "configure" itself is a Cygwin script, and therefore expects Cygwin input. At the right moment, the paths are back-translated to their Windows counterparts. Until OCaml 3.08 you must specify whether you have (2) or (3) by the configure switches - "-system mingw" for (2) - "-system win32" for (3) - nothing for (1) Since OCaml 3.09 this is no longer necessary because "ocamlc -config" outputs the required information. In previous versions of Findlib there was a single switch -cygpath for both (2) and (3). It is now interpreted as -system mingw (as it was meant as that). not-ocamlfind-0.14/local-packages/ocamlfind/LICENSE0000644000175000017500000000210114770304423021025 0ustar stephstephCopyright 1999 by Gerd Stolpmann The package "findlib" is copyright by Gerd Stolpmann. Permission is hereby granted, free of charge, to any person obtaining a copy of this document and the "findlib" software (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. The Software is provided ``as is'', without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall Gerd Stolpmann be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the Software or the use or other dealings in the software. not-ocamlfind-0.14/local-packages/ocamlfind/Makefile0000644000175000017500000001401314770304423021465 0ustar stephsteph# make all: compile to bytecode # make opt: compile to native code # make install: install bytecode and/or native code #---------------------------------------------------------------------- include Makefile.config -include Makefile.packages TOP=. .PHONY: all opt install uninstall clean all: for p in $(PARTS); do ( cd src/$$p; $(MAKE) all ) || exit; done $(MAKE) all-config opt: for p in $(PARTS); do ( cd src/$$p; $(MAKE) opt ) || exit; done install: check-installation $(INSTALLDIR) "$(DESTDIR)$(prefix)$(OCAMLFIND_BIN)" $(INSTALLDIR) "$(DESTDIR)$(prefix)$(OCAMLFIND_MAN)" $(MAKE) install-config for p in $(PARTS); do ( cd src/$$p; $(MAKE) install ); done $(MAKE) install-meta test ! -f 'site-lib-src/num-top/META' || { cd src/findlib; $(MAKE) install-num-top; } test ! -f 'site-lib-src/camlp4/META' || $(INSTALLFILE) tools/safe_camlp4 "$(DESTDIR)$(prefix)$(OCAMLFIND_BIN)" $(MAKE) install-doc uninstall: check-installation $(MAKE) uninstall-doc $(MAKE) uninstall-meta for p in `cd src; echo *`; do ( cd src/$$p; $(MAKE) uninstall ); done $(MAKE) uninstall-config clean: for p in `cd src; echo *`; do ( cd src/$$p; $(MAKE) clean ); done (cd itest-aux; $(MAKE) clean) (cd tools/extract_args; $(MAKE) clean) rm -f findlib.conf Makefile.packages .PHONY: release release: README ./release README: doc/README ln -s doc/README . .PHONY: all-config all-config: findlib.conf .PHONY: findlib-template findlib-template: findlib.conf.in USE_CYGPATH="$(USE_CYGPATH)"; \ export USE_CYGPATH; \ cat findlib.conf.in | \ $(SH) tools/patch '@SITELIB@' '$(FINDLIB_OCAML_SITELIB)' | \ $(SH) tools/patch '@FINDLIB_PATH@' '$(FINDLIB_PATH)' -p >findlib.conf if ./tools/cmd_from_same_dir ocamlc; then \ echo 'ocamlc="ocamlc.opt"' >>findlib.conf; \ fi if ./tools/cmd_from_same_dir ocamlopt; then \ echo 'ocamlopt="ocamlopt.opt"' >>findlib.conf; \ fi if ./tools/cmd_from_same_dir ocamldep; then \ echo 'ocamldep="ocamldep.opt"' >>findlib.conf; \ fi if ./tools/cmd_from_same_dir ocamldoc; then \ echo 'ocamldoc="ocamldoc.opt"' >>findlib.conf; \ fi .PHONY: findlib-relative findlib-relative: FINDLIB_OCAML_SITELIB=$(RELATIVE_OCAML_SITELIB) findlib-relative: findlib-template .PHONY: findlib-absolute findlib-absolute: FINDLIB_OCAML_SITELIB=$(OCAML_SITELIB) findlib-absolute: findlib-template findlib.conf: findlib.conf.in if [ "$(RELATIVE_PATHS)" = "true" ]; then \ $(MAKE) findlib-relative; \ else \ $(MAKE) findlib-absolute; \ fi .PHONY: install-doc install-doc: $(INSTALLDIR) "$(DESTDIR)$(prefix)$(OCAMLFIND_MAN)/man1" "$(DESTDIR)$(prefix)$(OCAMLFIND_MAN)/man3" "$(DESTDIR)$(prefix)$(OCAMLFIND_MAN)/man5" -$(CP) doc/ref-man/ocamlfind.1 "$(DESTDIR)$(prefix)$(OCAMLFIND_MAN)/man1" -$(CP) doc/ref-man/META.5 doc/ref-man/site-lib.5 doc/ref-man/findlib.conf.5 "$(DESTDIR)$(prefix)$(OCAMLFIND_MAN)/man5" .PHONY: uninstall-doc uninstall-doc: rm -f "$(DESTDIR)$(prefix)$(OCAMLFIND_MAN)/man1/ocamlfind.1" rm -f "$(DESTDIR)$(prefix)$(OCAMLFIND_MAN)/man3/Findlib.3" rm -f "$(DESTDIR)$(prefix)$(OCAMLFIND_MAN)/man3/Topfind.3" rm -f "$(DESTDIR)$(prefix)$(OCAMLFIND_MAN)/man5/META.5" rm -f "$(DESTDIR)$(prefix)$(OCAMLFIND_MAN)/man5/site-lib.5" .PHONY: check-installation check-installation: if [ "$(CHECK_BEFORE_INSTALL)" -eq 1 ]; then \ for x in camlp4 dbm graphics labltk num ocamlbuild; do \ if [ -f "$(prefix)$(OCAML_SITELIB)/$$x/META" ]; then \ if ! grep -Fq '[distributed with Ocaml]' "$(prefix)/$(OCAML_SITELIB)/$$x/META"; then \ rm -f site-lib-src/$$x/META; \ fi; \ fi; \ done; \ test -f "site-lib-src/num/META" || rm -f "site-lib-src/num-top/META"; \ fi echo 'SITELIB_META =' > Makefile.packages.in for x in `ls site-lib-src`; do test ! -f "site-lib-src/$$x/META" || echo $$x >> Makefile.packages.in; done tr '\n' ' ' < Makefile.packages.in > Makefile.packages rm Makefile.packages.in .PHONY: install-meta install-meta: for x in $(SITELIB_META); do $(INSTALLDIR) "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/$$x"; $(CP) site-lib-src/$$x/META "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/$$x/META.tmp" && mv "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/$$x/META.tmp" "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/$$x/META"; done $(INSTALLDIR) "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/findlib"; $(CP) Makefile.packages "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/findlib/Makefile.packages" .PHONY: uninstall-meta uninstall-meta: for x in $(SITELIB_META); do rm -rf "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/$$x"; done .PHONY: install-config install-config: $(INSTALLDIR) "`dirname \"$(DESTDIR)$(prefix)$(OCAMLFIND_CONF)\"`" @if [ -f "$(DESTDIR)$(prefix)$(OCAMLFIND_CONF)" ]; then echo "!!! Keeping old $(DESTDIR)$(prefix)$(OCAMLFIND_CONF) !!!"; fi test -f "$(DESTDIR)$(prefix)$(OCAMLFIND_CONF)" || $(CP) findlib.conf "$(DESTDIR)$(prefix)$(OCAMLFIND_CONF)" .PHONY: uninstall-config uninstall-config: @echo Leaving "$(OCAMLFIND_CONF)" installed, consider manual removal .PHONY: interface-lists interface-lists: d=`ocamlc -where`; \ for x in `ls site-lib-src`; do \ iflist=""; \ if [ ! -f "site-lib-src/$$x/interfaces.in" ]; then continue; fi; \ cma_spec=`cat site-lib-src/$$x/interfaces.in`; \ for cma in $$d/$$cma_spec; do \ intf=`ocamlobjinfo $$cma | \ grep 'Unit name:' | \ sed -e 's/^ Unit name: //' | \ sort | \ tr '\n' ' '`; \ iflist="$$iflist $$intf"; \ done; \ echo "$$iflist" >"site-lib-src/$$x/interfaces.out"; \ done ###################################################################### # The following is from Pietro Abata # to create MacOS X packages. I did not test it, just include it. .PHONY: package-macosx package-macosx: all opt $(INSTALLDIR) package-macosx/root export prefix=`pwd`/package-macosx/root && make install export VERSION=1.1.2 && sh tools/make-package-macosx clean-macosx: sudo rm -rf package-macosx not-ocamlfind-0.14/local-packages/ocamlfind/Makefile.config.pattern0000644000175000017500000000652314770304423024414 0ustar stephsteph# You can manually set up your configuration using this # pattern. The final name of the file must be "Makefile.config". # Note that there are other files containing parts of the # configuration, especially the site-lib/*/META files. # #---------------------------------------------------------------------- # Where the OCAML core is installed: #---------------------------------------------------------------------- OCAML_CORE_STDLIB=/usr/local/lib/ocaml OCAML_CORE_BIN=/usr/local/bin OCAML_CORE_MAN=/usr/local/man #---------------------------------------------------------------------- # Type of multi-threading support: either vm or posix # (Note: Since OCaml 3.07, "posix" includes "vm", because a build # supporting posix also supports vm.) #---------------------------------------------------------------------- OCAML_THREADS=vm #OCAML_THREADS=posix #---------------------------------------------------------------------- # Where the site-lib directory will be #---------------------------------------------------------------------- OCAML_SITELIB=/usr/local/lib/ocaml/site-lib #---------------------------------------------------------------------- # What the path setting will be #---------------------------------------------------------------------- FINDLIB_PATH=/usr/local/lib/ocaml/site-lib:/usr/local/lib/ocaml #---------------------------------------------------------------------- # Where binaries and manual pages will be installed #---------------------------------------------------------------------- OCAMLFIND_BIN=/usr/local/bin OCAMLFIND_MAN=/usr/local/man #---------------------------------------------------------------------- # The absolute location of the configuration file #---------------------------------------------------------------------- OCAMLFIND_CONF=/usr/local/etc/ocamlfind.conf #---------------------------------------------------------------------- # Autolinking is usually on #---------------------------------------------------------------------- OCAML_AUTOLINK=true #---------------------------------------------------------------------- # Windows only: set this to .exe #---------------------------------------------------------------------- EXEC_SUFFIX= #---------------------------------------------------------------------- # Windows MSVC port: set this to .lib #---------------------------------------------------------------------- LIB_SUFFIX=.a #---------------------------------------------------------------------- # Which parts are to be built: findlib, findlib-toolbox (space-separated # list) #---------------------------------------------------------------------- PARTS=findlib findlib-toolbox #---------------------------------------------------------------------- # Whether the "topfind" script is installed in $(OCAML_CORE_STDLIB): #---------------------------------------------------------------------- INSTALL_TOPFIND=1 #---------------------------------------------------------------------- # Whether the config and paths are looked up relative to the # installation #---------------------------------------------------------------------- RELATIVE_PATHS=0 RELATIVE_OCAML_SITELIB=$$PREFIX/lib #---------------------------------------------------------------------- # Whether make install should update Makefile.packages just before # running #---------------------------------------------------------------------- CHECK_BEFORE_INSTALL=0 not-ocamlfind-0.14/local-packages/ocamlfind/README.md0000644000175000017500000000035214770304423021305 0ustar stephsteph# Findlib - [Project page](http://projects.camlcity.org/projects/findlib.html) with links to download tarballs and documentation - [README.xml with changelog](doc/README.xml) - [Installation](INSTALL) - [License](LICENSE) not-ocamlfind-0.14/local-packages/ocamlfind/REVISIONS0000644000175000017500000000055514770304423021337 0ustar stephstephThe following table shows which Subversion revision of the repository corresponds with which released version of findlib. Released versions up to 0.9 are checked in into CVS, and not Subversion. Released version = Subversion revision ---------------------------------------------------------------------- 1.0 54 1.0.1 57 1.0.2 63 1.0.3 69 1.0.4 72 not-ocamlfind-0.14/local-packages/ocamlfind/TODO0000644000175000017500000000021414770304423020513 0ustar stephstephDocument archive(plugin) Suggestion (gasche): -show-command only outputs the constructed command, but does not run it. Get ready for -ppx not-ocamlfind-0.14/local-packages/ocamlfind/configure0000755000175000017500000005614414770304423021747 0ustar stephsteph#! /bin/sh # $Id$ # ---------------------------------------------------------------------- # # Some functions #set -x version="$(sed -ne 's/^version: *"\(.*\)\.git".*/\1/p' opam)" if test -z "$version"; then echo "Internal error: failed to parse version number from opam file" 1>&2 exit 1 fi # Remember the old IFS value: oldifs="$IFS" in_path () { # Does $1 exist in $PATH? IFS=":" for d in $PATH; do if test -x "$d/$1"; then IFS="$oldifs" return 0 fi done IFS="$oldifs" return 1 #--- The following is not portable enough: # if test -x `type -p ls`; then # # type -p works! # type -p $1 >/dev/null # else # # use 'which' instead # p=`which $1` # test -x "$p" # fi } get_path () { IFS=":" for d in $PATH; do if test -x "$d/$1"; then IFS="$oldifs" echo "$d/$1" return fi done IFS="$oldifs" #--- The following is not portable enough: # if test -x `type -p ls`; then # # type -p works! # type -p $1 # else # # use 'which' instead # p=`which $1` # test -x "$p" && echo $p # fi } get_stdlib () { # Older versions of ocamlc do not accept -where, so there is a fallback # method: ocamlc -where 2>/dev/null | tr -d '\r' || { ocamlc -v | sed -n -e "/Standard library directory/s/.*: \(.*\)/\1/p"; } } get_lib () { # $1: name of a library to search for # $2...: places to test libname="$1" while [ "$#" != "0" ]; do if [ -f "$1/lib${libname}.so" ] || [ -f "$1/lib${libname}.a" ]; then echo "$1" return 0 fi shift done return 1 } get_lib_file () { # $1: name of library without "lib" and suffix # $2: directory # returns full path of library if [ -f "$2/lib$1.so" ]; then echo "$2/lib$1.so" elif [ -f "$2/lib$1.a" ]; then echo "$2/lib$1.a" else echo "" fi } cygpath_to_unix () { v=$1 eval "p=\"\$$v\"" p="$(cygpath -w -s "$p")" p="$(cygpath -u "$p")" eval "$v=\"$p\"" } ###################################################################### # Here the main program begins: ###################################################################### # Interpret the command line ocamlfind_bin="" ocamlfind_man="" ocaml_sitelib="" ocamlfind_config="" with_toolbox=0 with_topfind=1 with_camlp4=1 with_relative_paths=0 custom=-custom system="" sh="" while [ "$#" != "0" ]; do case "$1" in -bindir) ocamlfind_bin=$2 shift 2 ;; -mandir) ocamlfind_man=$2 shift 2 ;; -sitelib) ocaml_sitelib=$2 shift 2 ;; -config) ocamlfind_config=$2 with_relative_paths=0 shift 2 ;; -no-custom) custom= shift ;; -cygpath) system=mingw shift ;; -system) system=$2 shift 2 ;; -with-toolbox) with_toolbox=1 shift ;; -with-relative-paths-at) with_relative_paths=1 ocaml_prefix=$2 shift 2 ;; -no-topfind) with_topfind=0 shift ;; -no-camlp4) with_camlp4=0 shift ;; -version) echo "$version" exit 0 ;; -h|-help|--help) echo "usage: configure [options]" 1>&2 echo " -bindir path where binaries are installed" 1>&2 echo " -mandir path where manual pages are installed" 1>&2 echo " -sitelib path set the location of the site-specific packages" 1>&2 echo " -config path set the location of the configuration file" 1>&2 echo " -no-custom don't link in custom runtime mode" 1>&2 echo " -system override system type (esp. mingw and win32)" 1>&2 echo " -with-toolbox also build the toolbox" 1>&2 echo " -with-relative-paths-at path load configuration relative to the installation path" 1>&2 echo " -no-topfind don't install topfind script into stdlib directory" 1>&2 echo " -no-camlp4 don't install the camlp4 META file" 1>&2 exit ;; *) echo "configure: run 'configure -h' to get help" 1>&2 exit 1 ;; esac done echo "Welcome to findlib version $version" echo "Configuring core..." ####################################################################### # inspect the system # Some standard Unix tools must be available: for tool in sed ocaml ocamlc uname rm make cat dirname basename; do if in_path $tool; then true; else echo "configure: $tool not in PATH; this is required" 1>&2 exit 1 fi done lib_suffix=$(ocamlc -config 2>/dev/null | tr -d '\r' | sed -n -e 's/^ext_lib: //p') # Check for Cygwin: exec_suffix= pure_mingw="no" mingw_lib= case $(uname) in CYGWIN*) exec_suffix=.exe echo "Cygwin build environment found; using .exe as suffix for binaries" ;; MSYS_NT*) exec_suffix=.exe echo "MSYS_NT build environment found; using .exe as suffix for binaries" ;; MINGW*) exec_suffix=.exe pure_mingw="yes" echo "MinGW build environment found; using .exe as suffix for binaries" mingw_lib=$(get_path gcc) mingw_lib=$(dirname "$mingw_lib")/../lib ;; *) true ;; esac ###################################################################### # Is the target Win32? use_cygpath=0 # Whether we have to translate Unix paths to/from Windows paths. if [ -z "$system" ]; then system=$(ocamlc -config 2>/dev/null | tr -d '\r' | sed -n -e 's/^system: //p') # This may be # - mingw or mingw64 # - win32 # - win64 # - cygwin # - some other string means Unix # - empty means ocamlc does not support -config fi path_sep=':' case "$system" in mingw|mingw64) if [ "$pure_mingw" = "no" ]; then # CYGWIN use_cygpath=1 fi ;; win32) use_cygpath=1;; win64) use_cygpath=1;; # A quirk of history means OCAMLPATH uses ; on Cygwin cygwin) path_sep=';';; esac ###################################################################### # check for presence of /bin/sh if [ ! -f /bin/sh ]; then sh="sh" fi ###################################################################### # Find out standard library location ocaml_core_stdlib=$(get_stdlib) ocaml_major="$(ocamlc -vnum 2>/dev/null | cut -f1 -d.)" if [ ! -d "$ocaml_core_stdlib" ]; then echo "configure: cannot determine ocaml's standard library directory" 1>&2 exit 1 fi if [ -z "$ocaml_major" ]; then ocaml_major=3; fi if [ ${use_cygpath} -gt 0 ]; then cygpath_to_unix ocaml_core_stdlib # This makes ocaml_core_stdlib a Unix-type path fi # Set site-lib directory: if [ -z "$ocaml_sitelib" ]; then case "$ocaml_core_stdlib" in /opt/*) ocaml_sitelib=$(dirname "${ocaml_core_stdlib}")/site-lib ;; *) ocaml_sitelib="${ocaml_core_stdlib}/site-lib" ;; esac fi ocamlpath="${ocaml_sitelib}" if [ ${use_cygpath} -gt 0 ]; then cygpath_to_unix ocamlpath fi if [ "$ocaml_major" -ge 5 ]; then # OCaml 5.0+ installs its own META files under the stdlib directory. # If findlib has been configured -sitelib $(ocamlc -where) then there's # nothing to do, but otherwise we need to put OCaml's Standard Library # into the path setting. if [ ! -e "${ocaml_sitelib}/stdlib.cmi" ]; then ocamlpath="${ocaml_core_stdlib}${path_sep}${ocamlpath}" fi fi # Find out the directory where ocamlc is: ocamlc=$(get_path ocamlc) ocaml_core_bin=$(dirname "${ocamlc}") # Set the directory of ocamlfind: test -n "$ocamlfind_bin" || ocamlfind_bin="$ocaml_core_bin" # Find the directory for the manual: # Fallback: ocaml_core_man=/usr/local/man d="$ocaml_core_bin" while [ "$d" != '/' ]; do f=0 if [ -d "$d/man/man1" ]; then if [ -f "$d/man/man1/ocamlc.1" ] || [ -f "$d/man/man1/ocamlc.1.gz" ] || [ -f "$d/man/man1/ocamlc.1.Z" ]; then f=1 fi else if [ -d "$d/man/mann" ]; then if [ -f "$d/man/mann/ocamlc.n" ] || [ -f "$d/man/mann/ocamlc.n.gz" ] || [ -f "$d/man/mann/ocamlc.n.Z" ]; then f=1 fi fi fi if [ "$f" = "1" ]; then ocaml_core_man="$d/man" d="/" else d=$(dirname "$d") fi done # Set the directory for ocamlfind's manuals: test -n "$ocamlfind_man" || ocamlfind_man="$ocaml_core_man" # Guess the right directory for the configuration file: if [ -z "${ocamlfind_config}" ]; then d="$ocaml_core_bin" case "$d" in */bin) if [ -f "$(dirname "$d")/lib/findlib.conf" ]; then ocamlfind_config="$(dirname "$d")/lib/findlib.conf" else ocamlfind_config="$(dirname "$d")/etc/findlib.conf" fi ;; *) ocamlfind_config=/usr/local/etc/findlib.conf # Fallback value ;; esac fi ###################################################################### # do we have #remove_directory? echo "Checking for #remove_directory..." have_remdir=1 ocaml itest-aux/remdir.ml >/dev/null 2>/dev/null || have_remdir=0 ###################################################################### # Test the threading model echo "Testing threading model..." if ocamlc -vmthread >/dev/null 2>/dev/null; then ocaml_threads="vm" else ocaml_threads="none" fi if ocamlc -config >/dev/null 2>/dev/null; then # Good. ocamlc tells us the threading model. if ocamlc -config | grep 'systhread_supported: true'; then ocaml_threads="posix" fi else # Old ocamlc do not have -config. rm -f itest-aux/simple ocamlc -w a -custom -thread -o itest-aux/simple -I +unix unix.cma threads.cma itest-aux/simple_threads.ml \ >itest-aux/err.out 2>&1 output=$(cat itest-aux/err.out) if [ -z "$output" ]; then ocaml_threads="posix" fi fi ###################################################################### # Does this version of OCaml support autolinking? # Works for OCaml >= 3.00 on. Because findlib can only be compiled # with these OCaml versions, we can safely assume that autolinking # is enabled. ocaml_autolink="true" ###################################################################### # Does this version of OCaml support DLLs? echo "Testing DLLs..." have_dlls="yes" ocaml -I +unix unix.cma itest-aux/simple.ml >/dev/null || have_dlls="no" ###################################################################### # Does this version of OCaml support extension points? echo "Testing whether ppxopt can be supported..." with_ppxopt=1 enable_topfind_ppxopt=true ocaml -I +compiler-libs itest-aux/ppx.ml >/dev/null || { with_ppxopt=0 enable_topfind_ppxopt=false } ###################################################################### # Check for -opaque echo "Checking for ocamlc -opaque..." opaque="-opaque" ocamlc -opaque -version >/dev/null 2>/dev/null || opaque="" ###################################################################### # Check for ocamlopt -g echo "Checking for ocamlopt -g..." native_debugging_info="-g" ocamlopt -g -version >/dev/null 2>/dev/null || native_debugging_info="" ###################################################################### # Configure libraries check_before_install=0 findlib_installed_meta='' if [ -d "${ocaml_sitelib}" ] && [ "${ocaml_major}" -lt 5 ]; then previous_config="${ocaml_sitelib}/findlib/Makefile.packages" if [ -f "${previous_config}" ]; then echo "Querying installation: found list of findlib-generated META files" eval "$(sed -ne 's/ /,/g' -e 's/^SITELIB_META,*=,*\([^,].*[^,]\),*/findlib_installed_meta="\1"/p' "$previous_config")" echo "Installation has: $findlib_installed_meta" else previous_config='' check_before_install=1 echo "Querying installation: META list not found" echo "make install will double-check installed META files" fi else previous_config='' fi echo "Configuring libraries..." # Only succeeds if ${ocaml_sitelib}/$1/META exists and we're **certain** # it wasn't installed by a previous findlib installation. is_third_party_META () { if [ $check_before_install -eq 0 ]; then if [ -f "${ocaml_sitelib}/$1/META" ]; then case ",$findlib_installed_meta," in *,$1,*) return 1;; *) return 0;; esac else return 1 fi else return 1 fi } check_library () { if is_third_party_META "$1"; then echo "$1: package already present" # Library is present - exit code is 0 because the library is found # (e.g. detection for Unix) but we don't actually add it to the # generated_META list. package_dir="${ocaml_sitelib}/$1" package_subdir="$1" package_key="$(echo "$1" | tr - _)" eval "${package_key}_dir=\"${package_dir}\"" eval "${package_key}_subdir=\"${package_subdir}\"" return 0 fi if [ -z "$3" ]; then check_library "$1" "$2" "$1.cmi" return $? fi package="$1" if [ -z "$2" ]; then msg='' else msg=" ($2)" fi shift 2 for file; do if [ -e "${ocaml_core_stdlib}/${file}" ]; then package_dir="$(dirname "${file}")" if [ "${package_dir}" = '.' ]; then echo "${package}: found" package_subdir='.' package_dir='^' else package_subdir="${package_dir}" package_dir="+${package_dir}" echo "${package}: found (in ${package_dir})" fi package_key="$(echo "${package}" | tr - _)" eval "${package_key}_dir=\"${package_dir}\"" eval "${package_key}_subdir=\"${package_subdir}\"" if [ "${ocaml_major}" -ge 5 ]; then return 0 fi if [ "$package" = 'num' ]; then generated_META="${generated_META} num num-top" numtop='num-top' else generated_META="${generated_META} ${package}" fi return 0 fi done echo "$package: not present${msg}" return 1 } if [ "${ocaml_major}" -ge 5 ]; then generated_META='' else generated_META='stdlib' fi numtop='' if ! check_library unix 'possible since 4.08' unix/unix.cmi unix.cmi; then echo "configure: ocamlfind requires OCaml's Unix library" 1>&2 exit 1 fi check_library dynlink '' dynlink/dynlink.cmi dynlink.cmi check_library bigarray 'possible since 4.08' check_library compiler-libs '' 'compiler-libs' check_library dbm 'normal since 4.00' check_library graphics 'normal since 4.09' check_library num 'normal since 4.06' check_library ocamlbuild 'normal since 4.03' ocamlbuild/ocamlbuildlib.cma check_library ocamldoc '' ocamldoc/odoc.cmi check_library raw_spacetime 'normal since 4.12' raw_spacetime_lib.cmxa check_library threads '' threads/thread.cmi vmthreads/thread.cmi; # Need to know if str and labltk are available for the toolbox if check_library str 'possible since 4.08' str/str.cmi str.cmi; then have_str=1 else have_str=0 fi if check_library labltk 'normal since 4.02' labltk/labltk.cma; then have_labltk=1 else have_labltk=0 fi # Dynlink check. have_natdynlink=0 natdynlink="" camlp4_dynlink="" if [ -f "${ocaml_core_stdlib}/${dynlink_subdir:?}/dynlink.cmxa" ]; then have_natdynlink=1 natdynlink="archive(native) = \"dynlink.cmxa\"" camlp4_dynlink="dynlink" echo "native dynlink: found" else natdynlink="archive(native) = \"\"" echo "native dynlink: not found" fi # Check on camlp4: if [ $with_camlp4 -eq 0 ]; then echo "camlp4: disabled" else if in_path camlp4; then if is_third_party_META camlp4; then echo "camlp4: third-party" fi camlp4_dir=$(camlp4 -where | tr -d '\r') if [ ${use_cygpath} -gt 0 ]; then camlp4_dir=$(echo x | env USE_CYGPATH=1 tools/patch x "$camlp4_dir") # This makes camlp4_dir a windows path elif [ "${pure_mingw}" = "yes" ]; then # Must double the backslahes camlp4_dir="$(echo "${camlp4_dir}" | sed -e 's;\\;\\\\;g')" fi camlp4_version=$(camlp4 -v 2>&1) if [ "$have_dlls" = "yes" ]; then camlp4_cmd="camlp4" else camlp4_cmd="safe_camlp4" fi # Check whether 3.09 or 3.10 style: if camlp4 -loaded-modules >/dev/null 2>/dev/null; then camlp4style=310 else camlp4style=309 fi generated_META="${generated_META} camlp4" rm -rf "site-lib-src/camlp4" mkdir "site-lib-src/camlp4" cp "site-lib-src/camlp4.$camlp4style/META.in" "site-lib-src/camlp4/" echo "camlp4: using $camlp4_cmd, style $camlp4style" else with_camlp4=0 echo "camlp4: not present (normal since OCaml-4.02)" fi fi # bytes? # (NB. This is always ours, and it doesn't go into generated_META) req_bytes="" if [ -f "${ocaml_core_stdlib}/bytes.cmi" ] || [ -f "${ocaml_core_stdlib}/stdlib__bytes.cmi" ] || [ -f "${ocaml_core_stdlib}/stdlib__Bytes.cmi" ]; then echo "bytes: found, installing fake library" lbytes="bytes" cbytes=0 else echo "bytes: not found, installing compat library" lbytes="" req_bytes="bytes" cbytes=1 fi if [ $with_toolbox -gt 0 ]; then if [ $have_str -eq 0 ] || [ $have_labltk -eq 0 ]; then echo "Sorry, toolbox requires str and labltk - omitting toolbox." with_toolbox=0 fi fi # Generate the META files now. for dir in site-lib-src/*; do # We do not really know if $dir is a directory. rm -f "$dir"/META done for lib in $generated_META $lbytes; do if="" if [ -f site-lib-src/"$lib"/interfaces.out ]; then if=$(cat site-lib-src/"$lib"/interfaces.out) fi sed \ -e "s|%%type_of_threads%%|${ocaml_threads}|g" \ -e "s|%%camlp4_dir%%|${camlp4_dir}|g" \ -e "s|%%camlp4_version%%|${camlp4_version}|g" \ -e "s|%%camlp4_cmd%%|${camlp4_cmd}|g" \ -e "s|%%camlp4_dynlink%%|${camlp4_dynlink}|g" \ -e "s|%%interfaces%%|${if}|g" \ -e "s|%%findlib_version%%|${version}|g" \ -e "s|%%natdynlink%%|${natdynlink}|g" \ -e "s|%%dynlink_dir%%|${dynlink_dir:?}|g" \ -e "s|%%unix_dir%%|${unix_dir:?}|g" \ -e "s|%%str_dir%%|${str_dir:?}|g" \ site-lib-src/"$lib"/META.in > site-lib-src/"$lib"/META echo "Configuration for $lib written to site-lib-src/$lib/META" done # create META from META.in in POSIX-compatible & safe way # see: https://www.shellcheck.net/wiki/SC2044 meta_subst="sed -e 's/@VERSION@/$version/g' \ -e 's/@REQUIRES@/${req_bytes}/g' \ \"\$1\" > \"\${1%.in}\"" find src -name 'META.in' -type f -exec sh -c "$meta_subst" sh {} \; ###################################################################### printf "Detecting compiler arguments: " if make -C tools/extract_args >ocargs.log 2>&1; then printf "(extractor built) " # ocamlbrowser does not work! if tools/extract_args/extract_args -o src/findlib/ocaml_args.ml ocamlc ocamlcp ocamloptp ocamlmklib ocamlmktop ocamlopt ocamldep ocamldoc >>ocargs.log 2>&1; then echo "ok" else echo "FAILED (see the file ocargs.log for details)" exit 1 fi else echo "FAILED (see the file ocargs.log for details)" exit 1 fi ###################################################################### # Write Makefile.config parts="findlib" ocamlfind_ocamlflags="-I +unix -I +dynlink" ocamlfind_archives="findlib.cma unix.cma" if [ $with_toolbox -gt 0 ]; then parts="$parts findlib-toolbox" fi if [ $cbytes -gt 0 ]; then # bytes first, because findlib needs it parts="bytes $parts" ocamlfind_ocamlflags="${ocamlfind_ocamlflags} -I ../bytes" ocamlfind_archives="bytes.cma ${ocamlfind_archives}" fi relative_site_lib=$(echo "${ocaml_sitelib}" | sed -e "s#^${ocaml_prefix}#\$PREFIX#") if [ $with_relative_paths -gt 0 ]; then # if configured with relative paths we add the relative path to the search path relative_paths="true" ocamlpath="${relative_site_lib}${path_sep}${ocamlpath}" else relative_paths="false" fi { echo "# Makefile.config written by configure" echo "OCAML_CORE_STDLIB=${ocaml_core_stdlib}" echo "OCAML_CORE_BIN=${ocaml_core_bin}" echo "OCAML_CORE_MAN=${ocaml_core_man}" echo "OCAML_SITELIB=${ocaml_sitelib}" echo "FINDLIB_PATH=${ocamlpath}" echo "OCAML_THREADS=${ocaml_threads}" echo "OCAMLFIND_BIN=${ocamlfind_bin}" echo "OCAMLFIND_MAN=${ocamlfind_man}" echo "OCAMLFIND_CONF=${ocamlfind_config}" echo "OCAMLFIND_OCAMLFLAGS=${ocamlfind_ocamlflags}" echo "OCAMLFIND_ARCHIVES=${ocamlfind_archives}" echo "OCAML_AUTOLINK=${ocaml_autolink}" echo "OCAML_REMOVE_DIRECTORY=${have_remdir}" echo "EXEC_SUFFIX=${exec_suffix}" echo "LIB_SUFFIX=${lib_suffix}" echo "CUSTOM=${custom}" echo "PARTS=${parts}" echo "INSTALL_TOPFIND=${with_topfind}" echo "RELATIVE_PATHS=${relative_paths}" echo "RELATIVE_OCAML_SITELIB=${relative_site_lib}" | sed -e "s/\\\$/\$\$/" echo "USE_CYGPATH=${use_cygpath}" echo "HAVE_NATDYNLINK=${have_natdynlink}" echo "VERSION=${version}" echo "ENABLE_TOPFIND_PPXOPT=${enable_topfind_ppxopt}" echo "SYSTEM=${system}" echo "NUMTOP=${numtop}" echo "SH=${sh}" if [ "$mingw_lib" != "" ]; then echo "OCAMLC_FLAGS=-I \"${mingw_lib}\"" echo "OCAMLOPT_FLAGS=-I \"${mingw_lib}\"" fi echo "OPAQUE=${opaque}" echo "OCAMLOPT_G=${native_debugging_info}" echo "CHECK_BEFORE_INSTALL=${check_before_install}" echo "CP = cp" echo "INSTALLDIR = install -d" echo "# change to INSTALLDIR = mkdir -p when BSD install is unavavailable" echo "INSTALLFILE = install -c" echo "# change to INSTALLFILE = cp when BSD install is unavailable" } > Makefile.config echo "SITELIB_META=${generated_META}" >Makefile.packages # All OK echo echo "About the OCAML core installation:" echo " Standard library: ${ocaml_core_stdlib}" echo " Binaries: ${ocaml_core_bin}" echo " Manual pages: ${ocaml_core_man}" echo " Multi-threading type: ${ocaml_threads}" echo "The directory of site-specific packages will be" echo " site-lib: ${ocaml_sitelib}" echo "The configuration file is written to:" echo " findlib config file: ${ocamlfind_config}" echo "Software will be installed:" echo " Libraries: in /findlib" echo " Binaries: ${ocamlfind_bin}" echo " Manual pages: ${ocamlfind_man}" if [ $with_topfind -gt 0 ]; then echo " topfind script: ${ocaml_core_stdlib}" else echo " topfind script: omitted" fi if [ $with_ppxopt -gt 0 ]; then echo "Topfind ppxopt support: yes" else echo "Topfind ppxopt support: no" fi if [ $with_toolbox -gt 0 ]; then echo "Toolbox: yes" else echo "Toolbox: no" fi if [ -z "$custom" ]; then echo "Link custom runtime: no" else echo "Link custom runtime: yes" fi if [ $cbytes -gt 0 ]; then echo "Need bytes compatibility: yes" else echo "Need bytes compatibility: no" fi echo echo "Configuration has been written to Makefile.config" echo echo "You can now do 'make all', and optionally 'make opt', to build ocamlfind." not-ocamlfind-0.14/local-packages/ocamlfind/doc/0002755000175000017500000000000014770304423020575 5ustar stephstephnot-ocamlfind-0.14/local-packages/ocamlfind/doc/DOCINFO0000644000175000017500000000100414770304423021572 0ustar stephstephTo build the html and manual pages from the SGML sources, you need the following tools: - The DocBook DTD (http://www.davenport.com) - James Clark's SGML tools (jade, sx suffice) (http://www.jclark.com) - Normal Walsh's DSSSL stylesheets to make the HTML pages (http://nwalsh.com/docbook/dsssl) - My db2man tool to make the manual pages (http://www.ocaml-programming.de/packages) The latter also requires Christian Lindig's XML parser (//http://www.cs.tu-bs.de/softech/people/lindig/software/tony.html). not-ocamlfind-0.14/local-packages/ocamlfind/doc/Makefile0000644000175000017500000000360114770304423022233 0ustar stephstephDOCBOOK_HTML = /usr/share/sgml/docbook/stylesheet/dsssl/modular/html DOCBOOK_PRINT = /usr/share/sgml/docbook/stylesheet/dsssl/modular/print SRC = $(PWD)/src EXPORTED = findlib.mli fl_package_base.mli fl_metascanner.mli \ fl_dynload.mli topfind.mli .PHONY: guide-html ref-html ref-man default: guide-html ref-html ref-man README QUICKSTART guide-html: guide-html/TIMESTAMP ref-html: ref-html/TIMESTAMP ref-man: ref-man/TIMESTAMP guide-html/TIMESTAMP: src/*.sgml src/*.mod QUICKSTART.xml common.xml config.xml mkdir -p guide-html cd guide-html; \ rm -f *.htm*; \ openjade -t sgml -D$(DOCBOOK_HTML) -D$(SRC) findlib.sgml; \ true readme -html QUICKSTART.xml >guide-html/quickstart.html touch guide-html/TIMESTAMP ref-html/TIMESTAMP: src/*.sgml src/*.mod common.xml config.xml $(EXPORTED:%=../src/findlib/%) mkdir -p ref-html cd ref-html; \ rm -f *.htm*; \ openjade -t sgml -D$(DOCBOOK_HTML) -D$(SRC) findlib_ref.sgml; \ true mkdir -p ref-html/lib cd ../src/findlib && \ ocamldoc -html -d $(PWD)/ref-html/lib -stars -t "The Findlib Library" $(EXPORTED) touch ref-html/TIMESTAMP src/findlib_reference.xml: src/*.sgml src/*.mod osx -D$(DOCBOOK_HTML) -D$(SRC) \ findlib_reference.sgml >src/findlib_reference.xml ; \ true ref-man/TIMESTAMP: src/findlib_reference.xml mkdir -p ref-man cd ref-man; \ rm -f *.[0-9] TIMESTAMP; \ db2man <../src/findlib_reference.xml touch ref-man/TIMESTAMP # Unfortunately, output of ocamldoc -man is too bad to be useful. # cd ../src/findlib && \ # ocamldoc -man -man-mini -d $(PWD)/ref-man -man-suffix 3 -stars -t "The Findlib Library" $(EXPORTED) .SUFFIXES: .xml .sgml .sgml.xml: sx -xndata $< >$@; true clean: rm -rf guide-html guide-man ref-html/TIMESTAMP rm -f src/*.xml distclean: rm -f src/*.xml rm -f src/*~ rm -f *~ QUICKSTART: QUICKSTART.xml readme -text QUICKSTART.xml >QUICKSTART README: README.xml readme -text README.xml >README not-ocamlfind-0.14/local-packages/ocamlfind/doc/QUICKSTART.xml0000644000175000017500000002014714770304423023013 0ustar stephsteph %common; up'> %config; ]> Intro

See the file INSTALL for instructions how to build and install findlib.

Findlib and the toploop

For a number of platforms, OCaml can load bytecode-compiled libraries dynamically. For these platforms, findlib is very simple to use as explained in the following. For other platforms, see the paragraph below about "custom toploops".

After the toploop has been started, it is possible to load the special findlib support:In previous versions, #use "findlib" loaded the library. However, this caused a name conflict for a certain type of installation. Because of this, the name of the loader script has been changed to "topfind", but "findlib", and "ocamlfind" (Debian) are also available for backwards compatibility. $ ocaml Objective Caml version 3.07 # #use "topfind";; 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 = () You can now list the available packages: # #list;; bigarray (version: [distributed with Ocaml]) camlp4 (version: Camlp4 version 3.03 ALPHA) dbm (version: [distributed with Ocaml]) dynlink (version: [distributed with Ocaml]) findlib (version: 0.6) graphics (version: [distributed with Ocaml]) labltk (version: [distributed with Ocaml]) netstring (version: 0.10) num (version: [distributed with Ocaml]) stdlib (version: [distributed with Ocaml]) str (version: [distributed with Ocaml]) threads (version: [distributed with Ocaml]) unix (version: [distributed with Ocaml]) xstrp4 (version: 1.1) and load packages by simply typing: # #require "netstring";; Loading /opt/ocaml/lib/unix.cma Loading /opt/ocaml/lib/str.cma Loading /opt/ocaml/site-lib/netstring/netstring.cma Loading /opt/ocaml/site-lib/netstring/netstring_top.cmo Findlib takes care to load packages that are required by loaded packages first. For example, "netstring" uses "unix" and "str" internally, but you do not need to load them because findlib does it for you. In this example you can also see that findlib loads netstring_top.cmo containing printers for the toploop.

You can also enable the Camlp4 parsers by simply typing # #camlp4o;; Loading /opt/ocaml-3.03a/lib/camlp4/camlp4o.cma Camlp4 Parsing version 3.03 ALPHA for the standard syntax or # #camlp4r;; Loading /opt/ocaml-3.03a/lib/camlp4/camlp4r.cma Camlp4 Parsing version 3.03 ALPHA for the revised syntax. (But you cannot switch between the syntaxes.)

Custom Toploops

For some platforms, OCaml does not implement loading external libraries (e.g. Cygwin). One has to create a so-called custom toploop that statically links with these libraries. Example: $ ocamlfind ocamlmktop -o mytop -package findlib,unix -linkpkg $ ./mytop Objective Caml version 3.07 # #use "topfind";; 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 = () Now "#require" works for all libraries referring to the special "unix" functions.

Findlib and scripts

The #require directive can also be used in scripts. Example: #use "topfind";; #require "netstring";; open Cgi;; ... This makes it possible to write scripts that do not contain #directory directives that are specific for certain installations.

For Unix environments, you can start scripts directly if you apply the following trick: #! /bin/sh # (* exec ocaml "$0" "$@" *) use "topfind";; #require "netstring";; open Cgi;; ... This works wherever OCaml is installed.

Compiling programs

Assumed you want to compile a program that uses the Netstring package. Do it the following way: $ ocamlfind ocamlc -package netstring -c myprogram.ml This way you do not need to add "-I" options to locate Netstring.

If you want to create an executable, do not forget to add the -linkpkg switch: $ ocamlfind ocamlc -o myprogram -package netstring -linkpkg myprogram.cmo This switch causes that the mentioned packages are added to the resulting executable.

If you want to include several packages, you can either add several "-package" options, or you can enumerate the packages separated by commas: -package netstring,labltk.

Camlp4

If you add a -syntax option, the compiler will be told to parse the source file using camlp4: $ ocamlfind ocamlc -package netstring -syntax camlp4o -c myprogram.ml Use -syntax camlp4o for the standard syntax or -syntax camlp4r for the revised syntax.

Additionally, you can mention packages that add new syntax features. The package xstrp4 is an example of this: $ ocamlfind ocamlc -package xstrp4,netstring -syntax camlp4o -c myprogram.ml Now you can use the $ notation that is implemented by xstrp4 in the source file myprogram.ml.

Note that you can also invoke ocamldep from ocamlfind: $ ocamlfind ocamldep -package xstrp4 -syntax camlp4o *.ml *.mli >.depend This enables the syntax extensions, too.

ocamlbrowser

Since findlib-0.7, it is also possible to start ocamlbrowser from ocamlfind. For example, $ ocamlfind browser -package xstrp4 adds the correct path specification such that the modules contained in the package xstrp4 are also displayed. With $ ocamlfind browser -all all package are added to the path spec.

The Makefile wizard

There is a wizard that makes it very easy to write Makefiles. Call the wizard by $ ocamlfind findlib/make_wizard (the wizard requires that the labltk library is available). A new window pops up, and by very few clicks you can describe your own library. Finally, a Makefile is written.

There is no magic!

Findlib is neither a patch of OCaml nor uses it internal features of the OCaml programming environment. It is only a convention to install software components in filesystem hierarchies, a library interpreting this convention, and some frontend applications making the library usable for you.

One important consequence is that you can only refer to those software components that have previously been installed in a way findlib understands. This convention is beyond the scope of this QUICKSTART guide, see the reference manual for details. You can always check whether findlib accepts a component as "findlib package" by the command $ ocamlfind list (this is the same as the #list directive in the toploop). If the package occurs in the list, it is found, otherwise not.

not-ocamlfind-0.14/local-packages/ocamlfind/doc/README.xml0000644000175000017500000006546114770304423022266 0ustar stephsteph %common; up'> %config; ]> Introduction

The "findlib" software provides a scheme to manage reusable software components in the form of libraries, and includes tools that support this scheme. A library installed as a findlib component is also called a package. The point is that the findlib scheme allows it to store metainformation about the library, especially how it can be used in programs. The packages are kept in the filesystem hierarchy, but the directory structure is defined by findlib, and there is no way to deviate from this standard. The library contains functions to look the directory up that stores a package, to query metainformation about a package, and to retrieve dependency information about multiple packages. There is also a tool that allows the user to enter queries on the command-line. In order to simplify compilation and linkage, there are new frontends of the various OCaml compilers that can directly deal with packages.

It is important to understand that findlib is not a general-purpose package manager (like rpm for Linux), and does not support the management of arbitrary files, but only OCaml libraries. However, there are lots of special functions for libraries. findlib is more comparable with Gnome's pkg-config and Perl's MakeMaker, but of course there are language-specific differences.

The metainformation includes:

  • The necessary command-line arguments to use a library.

  • Dependencies on other packages.

  • Version strings.

These data can be conditional. Possible conditions are certain environmental settings, such as whether the bytecode or the native code compiler is used, or whether the application is multi-threaded. It is also possible that a package behaves differently when a certain other package is selected.

There is special support for scripts. It is possible to load libraries into toploops, including all dependent libraries, with only one command.

Findlib has been developed since March 1999, and has matured for more than four years until the release of version 1.0. One of the important questions during this long period of development was which features are necessary and which not. The result is a utility that follows still simple concepts, but is flexible enough to allow even the description of complex libraries and complex interdependencies.

Documentation

See the file QUICKSTART for the most important findlib commands.

There is a User's Guide introducing into the concepts of findlib, especially explaining how to create packages.

The Reference Manual describes commands, directory structure, configuration files, and library routines in detail.

Installation

See the file INSTALL.

Download

The current version is announced in the Objective Caml Link Database.

Copyright and License Conditions

Findlib is copyright 1999-2012 by Gerd Stolpmann. See the file LICENSE for the MIT/X11 style license conditions. Contact me at gerd@gerd-stolpmann.de in case of questions.

List of Changes
  • 1.9.8:: A few build-related fixes.

  • 1.9.7:: Allow overriding low-level module loader in `Fl_dynload.load_packages`. This is very useful in JSOO where we may want to implement a `.cma` -> `.js` cache instead of calling `Dynlink.loadfile` dynamically. (Emilio J. Gallego Arias).

    Fix auto-detection of -opaque (Stephen Dolan)

    Fix linking of threads.cmxa in OCaml-5.2 (David Allsopp)

    Improved scripts (shellcheck) (Marek Kubica)

    Support for relocatable installations (Marek Kubica)

    Support OCAMLOPT_SHARED (Chen Qi)

    Avoid exception for PATH containing "." (Dmetry Bely)

    Fixes for Windows (David Allsopp)

    Typos in documentation (Antonin Décimo)

    Upgrade ocamlfind for OCaml-5 (David Allsopp)

  • 1.9.6:: Support for OCaml-5 (as far as foreseeable) (David Allsopp).

    Again buildable since OCaml-3.08 (David Allsopp).

    Fix an install problem when building with a system-provided OCaml compiler (Louis Gesbert).

  • 1.9.5:: fixes a bug in the scripting that slipped into 1.9.4

  • 1.9.4: Also finds the libraries str.cm(x)a, unix.cm(x)a, and dynlink.cm(x)a in subdirectories of the OCaml standard library, as needed for OCaml-4.14 (David Allsopp).

    Support for runtime_events (Patrick Ferris)

    Fix spelling of "OCaml" everywhere (Marek Kubica)

    Work around the deprecation of a POSIX shell feature (Issam Maghni)

    Support DESTDIR, and favor the "install" command for installation (Gerd Stolpmann on suggestion of Thomas Klausner)

  • 1.9.3: Fixes another build problem regarding OCaml-5.00

  • 1.9.2: Fixes a build problem regarding OCaml-5.00

  • 1.9.1: Fixes a few install-related issues, like missing files.

  • 1.9: Overhaul how separately installed packages (e.g. num) are handled (by David Allsopp).

    Switch to opam-2.0 file format (by David Allsopp).

    Fix an incomaptibility with ocaml-4.13 (by David Allsopp).

    Expose the native toplevel (by Louis Gesbert).

    Fix an incompatibility with "Jane Street Style" (by Mark Laws).

    Switch from m4 to sed (by kit-ty-kate).

  • 1.8.1: Adapted to upcoming ocaml-4.09.

    New API Findlib.list_packages' can specify a package prefix.

  • 1.8.0: Fix reinstallation of "num" for OCaml-4.06.

    Fix build with OCaml-4.07.

    The installation of graphics/META is now optional.

    Fix "ocamlfind query -d".

    The environment variable OCAMLFIND_IGNORE_DUPS_IN is now interpreted as a list of directories.

    Packages for "ocamlfind query" may now be separated by commas, too.

    New "warning" property for packages.

    Forgetting to pass -thread/-vmthread only prints a warning now, but doesn't stop the build.

    For dealing with case-sensitive filesystems it is now only tried to match ASCII characters, but not encoding-dependent characters.

  • 1.7.3: Fix regarding num-top: this library is now also optional, as num.

  • 1.7.2: Trying to protect against failures when several package installs are done in parallel.

    New subpackage "findlib.top" for the toploop (Jeremie Dimino).

    The "num" library is now optional.

    Shell scripts are started via "sh" command when there is no /bin/sh (ygrek)

  • 1.7.1: added missing file to tarball

  • 1.7.0: New command "ocamlfind printppx" that outputs how the ppx preprocessor would be called (Hendrik Tews).

    Support for the raw_spacetime library that comes with OCaml 4.04 (Gerd Stolpmann with help from Mark Shinwell).

    Require that ocamlc and ocamlc.opt are installed to the same directory for emitting the "opt" setting in the generated config file - same for ocamlopt.opt, ocamldep.opt, ocamldoc.opt.

  • 1.6.3:Fix: "ocamlfind printconf" respects the environment variable OCAMLFIND_CONF (reported by Andre)

    Build with -opaque (reported by hhugo)

    Preliminary support for native toplevel so far the toplevel is implemented symmetrically to the bytecode case (this is not correct in vanilla ocaml)

    New options: ocamlfind query -qe -qo

  • 1.6.2:Uninstalling findlib no longer uninstalls the ocamlbuild library by accident (Gabriel Scherer, Edwin Török)

    Adding an "ocamldoc" library, providing the cmi's for ocamldoc plugins (suggested by Armaël Guéneau)

    Support for OCaml-4.03: recognize that the new -color option has an argument (reported by Guillaume Bury)

  • 1.6.1: Just an important doc fix.

  • 1.6.0: Adding support for dynamically loading packages (François Bobot): new "plugin" variable, new Fl_dynload module.

    New command "ocamlfind lint" for checking META files (François Bobot).

    Also support MSYS_NT on Windows. Permit spaces in install paths (Christophe Troestler).

    Allow to query the location of the META file of a package: "ocamlfind query -format '%m'" (Gerd Stolpmann).

    Get the install path for the META file of packages: "ocamlfind printconf metapath" (Gerd Stolpmann).

  • 1.5.6: for MSVC build fixing bad filename suffix (Dmitry Bely).

    The switch -only-show did not work as described. (Error report from Bob Atkey.)

    Also support mingw64 as system type (Matthieu Dubuget).

  • 1.5.5: fixes a build problem for BSD systems

  • 1.5.4: New ppxopt META variables (Peter Zotov).

    Support for OCAMLFIND_TOOLCHAIN environment variable (Peter Zotov).

  • 1.5.3: The installation of "bytes" respects now $prefix and the configured destination.

    New option -pp for "ocamlfind query", to get preprocessor packages.

    Updated the compatibility Bytes module to support extend, init, mapi, blit_string (Gabriel Scherer).

  • 1.5.2: support for the query formats "%+a" and "%+A".

    Fix: the "ppx" property is now also path-expanded when interpreted in a toploop.

    Fix: implicit "ppx" is not path-expanded anymore.

    Fix: Build bytes.cmxs only if natdynlink is enabled (Andy Ray).

  • 1.5.1: includes a file that was missing in 1.5

  • 1.5: Including the "bytes" package that is either a compat package for ocaml < 4.02 or a fake package for ocaml >= 4.02. The package aims at helping to support the transition to the new "bytes" type for mutable strings.

    Also installing findlib.cmxs if OCaml supports it.

    Allowing to disable camlp4 (in prep for OCaml-4.02).

    The "ppx" package property can be specified for constructing ppx-type preprocessors (patches from Peter Zotov).

  • 1.4.1:ocamldoc: The order of -ppopt arguments was changed by ocamlfind, which is not correct. (Sylvain Le Gall and Jérémie Dimino.)

  • 1.4: Fixed performance bug when many arguments need to be processed (Jérôme Vouillon).

    Auto-configuring ocamldoc.opt if it is found (Christopher Zimmermann).

    New config switch -no-custom to prevent that "ocamlfind" is linked in custom-runtime mode (bytecode only) (Christopher Zimmermann).

    The library dbm is no longer part of OCaml, and now optional in findlib (Ashish Argawal).

    Support for ocamloptp.

    New function Topfind.log for controlling the verbosity (Jeremie Dimino).

    Rewritten Fl_metascanner without camlp4 (patch from Gabriel Scherer)

  • 1.3.3: OCaml-4: using the new #remove_directory directive if present.

    Better compatibility with the OCaml version from Homebrew.

  • 1.3.2: Handling of empty arguments (Wojciech Meyer).

    Added entry for camlp4.fulllib.

    New switch -add for "ocamlfind install" (Hans Ole Rafaelsen).

    Further fixes for ocaml-4.00.

    Fixing the recognition of double .cmi interface files.

    Fixing -dontlink (it is now deeply interpreted).

  • 1.3.1: Fixing a bug with ocamlmklib that slipped through in 1.3.0

  • 1.3.0: Fixes for ocaml-4.00 (especially topfind).

    Emitting an error if the configuration file does not exist.

    Emitting a warning if the selected toolchain does not exist.

    camlp4 is referenced by "+camlp4" in META.

    Including the sources for the documentation in the tarball.

    License change (simplification) for num_top_printers.mli.

    Fix ocamlmklib wrapper: processing contracted args (like -L/dir) correctly.

    Many wrappers get a new option -passrest instructing to pass all remaining options on the command-line unchanged to the invoked tool.

    Prettified -help output.

  • 1.2.8: Adding support for ocamlmklib (B. Meurer's patches)

    Fix for win32 in the configure script.

  • 1.2.7: Fix: if a META file defines several packages, and one of the packages has a broken dependency, ocamlfind used to report all errors even if the broken packages were not used. This is now changed - broken subpackages are ignored when they are not needed, in the same way as broken top-level packages are ignored when not needed. (Thanks to Sylvain Le Gall for reporting the problem.)

    Added -thread and -vmthread switches to "ocamlfind ocamldoc". These actually only add the right predicates. (Thanks to Vladimir Ivanov for pointing this problem out.)

    Package warnings can be emitted by "ocamlfind ocamldoc".

  • 1.2.6: adding META for ocamlbuild.

    Fixes for MinGW/MSYS platform.

    Improved messages.

  • 1.2.5: Fix: Again CR deletion... Turns out some OS do not understand '\r' but only '\015' (thanks to Isaiah Weiner).

    Support for Win64 (untested; thanks to David Allsopp).

    ocamlfind no longer emits auto-generated -ccopt options. These tend to accumulate, and it is possible that for large projects the maximum command line length is exceeded. Current versions of the OCaml compilers do not need these extra -ccopt anyway, so this code is completely dropped.

  • 1.2.4: Fix: Bigarray needs unix (Thanks to Markus Mottl).

    Fix: In the version of camlp4 provided by OCaml 3.11 various libraries do not contain dynlink anymore. Because of this, dynlink becomes a prerequisite of camlp4. (Thanks to Martin Jambon).

    Attempt: Fixing the space issue for paths (Win32). It is unclear whether it is solved. (Thanks to Christophe Troestler).

  • 1.2.3: Solving the CR deletion differently, to make OS X happy.

  • 1.2.2: Fix: Problem with CR character (Cygwin) (Thanks to David Allsopp).

    Fix: Case-insensitive filesystems (partially solved) (Thanks to David Allsopp).

    Fix: File name with backslashes at the end (Win32; thanks to Dmitry Grebeniuk).

  • 1.2.1: Fix: Camlp4 rules now activate the stream parser extension

  • 1.2: Fix in build scripts: Prepending $(prefix) when installing safe_camlp4 (thanks to Daniel Janus)

    Non-existing -I directories are ignored (thanks to Nicolas Pouillard)

    A script to create a MacOS X package (thanks to Pietro Abate)

    Better support for Windows (with help from Robert Roessler and David Allsopp)

    Support for camlp4 on OCaml 3.10

    Fix: "ocamlfind install" with "-patch" option writes now correct META file for the case that subpackages occur

    Adding environment variable OCAMLFIND_IGNORE_DUPS_IN to reduce the number of warnings ocamlfind emits

  • 1.1.2: Bugfix in the META parser: Backslashes are now correctly parsed. (Thanks to Martin Jambon for finding this problem.)

    Fixes for platforms that do not support dynamic loading of DLLs.

    Fixed extraction of camlp4 parameters from packages.

  • 1.1.1: Bugfixes only: Fixed detection of threading model for OCaml 3.09. Fixed alternate configuration files.

  • 1.1: Automatic detection of standard compiler options.

    Liberated the checks whether a package is already installed.

    The .opt compilers are entered into findlib.conf if available.

    New: "install" has -optional switch for optional files.

    New: "install" has -patch-version to patch the version into the installed META file.

    New: "install" has -patch-rmpkg to remove subpackages from the installed META file.

    New: "install" has -patch-archives which removes non-existing files from "archive" variables. This is experimental.

    New: subpackages can be disabled by exists_if.

    New: Support for toolchains.

    Fix for "remove": -destdir works again.

    Fix for "call": CTRL-C works when calling interactive commands.

    Fix for preprocessor packages: Dependencies on normal packages are resolved.

  • 1.0.4: Fix: In previous versions, "ocamlmktop" set the "toploop" predicate. It turned out, however, that the toploops generated in this way did not work properly. For this reason, "ocamlmktop" does not set "toploop" any more for link time, but instead a new predicate "create_toploop". When the toploop is executed, the predicate "toploop" is again added.

  • 1.0.3: Fix: The relative position of "-cclib -l" options on the command line is preserved. In previous versions, these options were moved to the beginning of the argument list. This did not work for static link editing; dynamic link editing was not affected.

    Fix: The automatic fixup of "threads" dependencies works again. In the previous version, this was broken.

    Addition: -format '%(name)' for ocamlfind query.

    Some minor improvements of the documentation.

  • 1.0.2: Fix: The alternate package layout did not fully work. This is repaired now, and there are some clarifications about relative directory paths in the documentation.

  • 1.0.1: Fix: Forgot to install some .cmi files

  • 1.0: It is now possible to divide the description of a package into subpackages (but there is still only one META file, but with enhanced syntax). This allows it to describe intra-package dependencies.

    Predicates in META files can be negated.

    The "error" variable allows you to detect conditions under which the library would not work, and to generate error messages.

    It is possible to refer to archive files installed in other packages.

    The set of predicates is extended by "package predicates" after the dependency analysis, making conditions expressible that depend on whether other packages are selected.

    The "+=" operator in META files adds words to variables rather than setting them.

    The "#thread" directive enables multi-threading in toploops and scripts, if possible.

    The "#predicates" directive simplifies the addition of predicates.

    Queries: The format specifier %D prints the description of the package. -long-format includes the description. Short options -r, -l, -d.

    ocamlfind list -describe prints package descriptions.

    Support for "ocamlfind ocamldoc". However, the implementation is quite sloppy.

    The configuration file is called "findlib.conf" by default, not "ocamlfind.conf".

    Removal of "ocamlfind guess".

    Support for #use "findlib" and #use "ocamlfind" has been removed. The only remaining way to load findlib is by #use "topfind".

    There is no longer a thread-safe version of findlib. The user has to ensure that only one thread uses findlib (which is usually trivial to achieve).

    ocamlmktop: Directories are no longer automatically added to the search path. This did not work anyway, and this change forces scripts to always invoke "#require" to load/enable libraries, for better uniformity.

    Fixes: num-top works. "ocamlfind ocamlopt -thread" generates a better error message on non-POSIX systems. "ocamlfind query -descendants" takes predicates into account (it did not do that in previous versions of findlib).

  • 0.9: Changes for OCaml 3.07 (-thread, -vmthread). Includes Zack's toploop printers for bigints.

  • 0.8 - 0.8.1: Renamed a lot of modules to avoid name clashes with OCaml core modules. Cygwin: Additional option -cygpath for "configure". The man pages have a NAME section. Bugfix in Makefile wizard.

  • 0.7 - 0.7.2: DLLs: There are now two styles of installation: DLLs can be installed in the package directories (like before), or in a shared directory "stublibs". For the first style, there is now an option "ldconf" that determines whether the ld.conf file is to be updated, and if so, which file. The latter style is enabled by simply creating a directory "stublibs" in the site-lib directory. (In the first version the directory was called "libexec". By user request, the name of the DLL directory has been changed to "stublibs".)

    "ocamlfind install" preserves now the mtime of the files.

    "ocamlfind printconf" is more flexible, and easier to call from scripts.

    "ocamlfind browser" calls ocamlbrowser with the right -I options.

    "ocamlfind query": -descendants implies now -recursive.

    "ocamlfind ocamldep": -native-filter and -bytecode-filter for more exact dependency generation.

    There may be now postinstall and postremove scripts.

    "ocamlfind pkg/cmd": This syntax can be used to call the program cmd that is installed in the package directory for pkg. Intended to simplify the invocation of programs that are installed in package directories and not in XXX/bin, which may be useful for package- related tools.

    Findlib has now a toolbox containing helpful programs besides ocamlfind. For the beginning, there is a Makefile wizard that can be called by "ocamlfind findlib/make_wizard".

    #use "topfind" instead of #use "findlib" to avoid name clashes in a certain configuration. #use "findlib" and #use "ocamlfind" are still supported for backward compatibility if the name clash does not occur.

    Fix: bytecode threads work again. (The wrong unix library was linked for recent OCaml versions.)

    Many smaller improvements; the docs have been updated.

  • 0.6 - 0.6.2: Minor changes for Ocaml-3.03-alpha (and later for 3.04). New #list directive. New: #use "findlib" loads the findlib directives into every toploop (Ocaml-3.03-alpha).

    The file ld.conf is automatically updated when DLLs are installed or removed.

    Fix: /tmp/findlib_initf* no longer overflows. The thread library is now always the first linked library.

  • 0.5 - 0.5.4: Findlib has now a configuration file (see documentation under findlib.conf). Much more environment variables. The location of the standard library is now configurable at runtime.

    The package search path can now be selected independently of the package installation directory.

    New commands: ocamlfind list, ocamlfind printconf, ocamlfind guess (See documentation under ocamlfind)

    Optional alternate directory layout: All META files go into a separate directory (see documentation under site-lib).

    Findlib works now only for OCaml 3; support for OCaml 2 has been dropped. As a consequence, the "configure" script could be simplified; it is no longer necessary to figure out the linker options.

    Improved support for camlp4: New directives #camlp4o and #camlp4r for the toploop.

    ocamlfind now detects whether two selected packages have equally named toplevel modules, and prints a warning in this case.

    There is a downstripped version ocamlfind-mini (see directory "mini"). This is a one-file script that can be easily distributed with any software. ocamlfind-mini has reduced functionality, but it is sufficient to compile and install a library. (But it does not support using a library.)

    Support for the Cygwin port of OCaml.

    Installation of packages: The file permissions are preserved when files are installed. However, the umask is applied. The "install" and "remove" subcommands have better diagnostics.

    ocamlfind ocamlmktop: Generates now initialization code for the include path. You don't need to call your toploop with -I options any more. Furthermore, this fixes some problems with packages that add printers to the toploop.

    New: ocamlfind ocamldep. ocamlfind is now prepared for the new -pp option of ocamldep (upcoming Ocaml 3.03).

    Installation of findlib: New PREFIX variable in Makefile to install locally.

    Fixes: itest. ocamlfind query -descendants works again.

  • 0.4: Experimental support for camlp4 (see FAQ section in the manual). New environment variable OCAMLFIND_COMMANDS (see ocamlfind(1)).

  • 0.3 - 0.3.1: Necessary updates for OCaml 3. Bugfix: Findlib did not work for bytecode threads. The reason was that findlib added the directory of the stdlib to the search path. Works now.

Older changes are no longer documented.

not-ocamlfind-0.14/local-packages/ocamlfind/doc/common.xml0000644000175000017500000002035014770304423022605 0ustar stephsteph Gerd Stolpmann'> not-ocamlfind-0.14/local-packages/ocamlfind/doc/config.xml0000644000175000017500000000114314770304423022561 0ustar stephsteph %readme:html:previous; %readme:html:up; %readme:html:next; '> "> %bar;"> not-ocamlfind-0.14/local-packages/ocamlfind/doc/readme.dtd0000644000175000017500000000116714770304423022532 0ustar stephsteph not-ocamlfind-0.14/local-packages/ocamlfind/doc/src/0002755000175000017500000000000014770304423021364 5ustar stephstephnot-ocamlfind-0.14/local-packages/ocamlfind/doc/src/findlib.dsl0000644000175000017500000000107214770304423023475 0ustar stephsteph ]> (define %footnotes-at-end% ;; Should footnotes appear at the end of HTML pages? #t) (define %html-ext% ;; Default extension for HTML output files ".html") (define %root-filename% ;; Name for the root HTML document "index") not-ocamlfind-0.14/local-packages/ocamlfind/doc/src/findlib.sgml0000644000175000017500000022461414770304423023666 0ustar stephsteph %gps.common; ]> The findlib User's Guide Gerd Stolpmann
gerd@gerd-stolpmann.de
1999-2014Gerd Stolpmann The "findlib" library provides a scheme to manage reusable software components (packages), and includes tools that support this scheme. Packages are collections of OCaml modules for which metainformation can be stored. The packages are kept in the filesystem hierarchy, but with strict directory structure. The library contains functions to look the directory up that stores a package, to query metainformation about a package, and to retrieve dependency information about multiple packages. There is also a tool that allows the user to enter queries on the command-line. In order to simplify compilation and linkage, there are new frontends of the various OCaml compilers that can directly deal with packages. Together with the packages metainformation is stored. This includes a version string, the archives the package consists of, and additional linker options. Packages can also be dependent on other packages. There is a query which finds out all predecessors of a list of packages and sorts them topologically. The new compiler frontends do this implicitly. Metainformation can be conditional, i.e. depend on a set of predicates. This is mainly used to be able to react on certain properties of the environment, such as if the bytecode or the native compiler is invoked, if the application is multi-threaded, and a few more. If the new compiler frontends are used, most predicates are found out automatically. There is special support for scripts. A new directive, "#require", loads packages into scripts. Download findlib This manual describes version &release.findlib; of the software package. It can be downloaded at &url.gps-ocaml-download; . The user's guide and the reference manual are included. Newest releases of "findlib" will be announced in The OCaml Link Database. Quickstart See also the Quickstart page for instructions for the most common cases. License This document, and the described software, "findlib", are copyright by Gerd Stolpmann. Permission is hereby granted, free of charge, to any person obtaining a copy of this document and the "findlib" software (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. The Software is provided ``as is'', without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall Gerd Stolpmann be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the Software or the use or other dealings in the software.
User's Guide Libraries and Packages Reusability is one of the keywords in software engineering today. It simply means to have source code that can be shared by several programs. Usually, modules are combined to libraries, and the library archive files can be linked into programs. As the idea might be simple, its practical implementation is complex because sharing of source code has an impact on all steps and phases in software production. This document only addresses the following administrative problems: Storing the libraries in file hierarchies Compiling and linking programs using such libraries Managing dependencies between libraries Objective Caml has a variety of language means to support reusability. Most important, polymorphic functions can be written which generalize the types of input arguments and the type of the result value. There are many examples in the core library such that I assume that the reader is familiar with this feature. Second, modules and functors must be mentioned which not only generalize types of values, but can even generalize structures, i.e. types with associated operations. Third, the class construct allows us to adopt the object-oriented techniques of abstraction such as inheritance and dynamic method lookup. In the following, we are only analyzing the problem of making and using libraries from a purely software-technical point of view. This means, we ignore how to make functions polymorphic, and how to create functors and classes. Instead, we only look at how to invoke the OCaml compiler to create, manage, and use libraries. Especially, we are interested in the administration of systems of libraries that have dependencies. One of the complex operations on such a system is the replacement of a library by a newer version. Because of the strict compatibility checks of OCaml, it is usually necessary to rebuild and reinstall all dependent libraries as well. With the help of findlib, one can find out which are the dependent libraries. (However, findlib does not provide a framework to rebuild them. For example, the GODI system includes such a framework.) The library is also called a "package" when it is seen as a removable and replaceable set of files. Findlib requires that there is a certain directory structure; it is not possible to install the files at arbitrary places (findlib does not even maintain a file list). For simplicity, every library is usually stored into its own directory, i.e. the library archive files and the interface files. From the perspective of the compiler, the library is made accessible by adding the package directory to the search path of the compiler. By doing so, the modules of the library are added to the namespace universe, and thus can be opened by modules using them. This means that the approach "one package = one directory" can be naturally translated into language operations modifying the namespace scope. When linking a program, it must be specified which link operation is necessary to use a certain library. Often, only a single archive file needs to be linked in, but sometimes additional archives or system libraries must be linked, too. Furthermore, the link operations often depends on certain conditions, e.g. whether a single- or multi-threaded program is being created. The findlib library is my suggestion for a package manager suitable for Objective Caml. It is a library (stored as a package itself) which can answer the following questions: If I want to use a package, which is the directory containing the compiled interfaces and implementations? - The package directory may vary from system to system, and this feature makes it easier to write Makefiles that run everywhere. Furthermore, OCaml can load modules dynamically, and it is not a good practice to compile in the location of such modules. The better way is to ask findlib where the module resides today. Which other packages must be linked in, too, if I want to use a certain package? Which archives need to be linked in, and which compiler options are necessary? If there is a version of the archive with additional properties, which file should I use? - Additional properties are at least: Thread-safety, using POSIX threads, and being gprof-enabled. It is simple to add more criterions. Furthermore, there is a frontend for this library called ocamlfind. It is a command-line interface for the library, but has also some additional abilities: It can invoke ocamlc, ocamlopt, ocamlmktop, and ocamlcp such that compiler arguments necessary to use a package or link it in are automatically added. It can install and uninstall packages. It can find out dependent packages. As you'll see in the following chapters, the usage of this library is really simple. If you want only to link in packages written by other people, you must only change the command that invokes the compiler, e.g. instead of calling "ocamlc program.ml" invoke "ocamlfind ocamlc -package name_of_package_to_use -linkpkg program.ml", and you can refer to the named package within program.ml. If you want to turn your collection of modules into a package, you need only to write one administrative file (META) containing all extra information such as required other packages. Using packages Listing the installed packages You can list which packages are installed by executing ocamlfind list You will get a list of names and version numbers. You can get a bit more information by passing the -describe option: ocamlfind list -describe Looking up package directories The package manager knows the preferred location for packages (this location is compiled in), which is usually /usr/local/lib/ocaml/site-lib. You can ask the package manager where package p is stored by simply typing ocamlfind query p and it will answer something like /usr/local/lib/ocaml/site-lib/p There is an environment variable OCAMLPATH which can specify further directories where packages are stored. (The search order is: first the directories in OCAMLPATH in turn, then the default path set in ocamlfind.conf) Historically, this kind of query was the first and only way of using ocamlfind, and because of the similarity to the Unix find command it got its name. Finding out package locations is a basic but nethertheless important feature because it hides the details of the filesystem hierarchy. It is sufficient only to know the name of the package, and if needed, you can use the lookup mechanism implemented in ocamlfind to get the concrete directory. How a package directory looks like Let us assume that the package p implements the modules M1 and M2. If you compile m1.mli and m2.mli you get the corresponding binary files m1.cmi and m2.cmi describing the interfaces of the modules. Of course, these cmi files must go into the package directory. It is recommended to put the source mli files into the directory, too, as they document the interface. Another product of the compilation are two cmo files, m1.cmo and m2.cmo (we assume the bytecode compiler, the native compiler would create m1.cmx and m2.cmx). It is possible to put these files directly into the directory, but there is a better way. As it makes only sense to use both modules (a very common assumption), they should first be archived by doing ocamlc -a -o p.cma m1.cmo m2.cmo The archive p.cma contains both cmo files, and preserves the order of the files. Assumed that in M2 there is a reference to an entity in M1, M2 depends on M1 and when linking a program using these modules, M1 must be mentioned first (e.g. ocamlc m1.cmo m2.cmo program.ml)Note that C linkers usually require the reverse order, but only for archive elements, i.e. files with suffix .a.. If you create the archive p.cma it contains already this dependency, and you need not to remember it when linking in the p.cma. So far the files m1.cmi, m2.cmi, and p.cma are needed, and m1.mli and m2.mli are recommended. Usually there is another file in the directory, META, containing additional information about the package. In our example, META looks like description = "Our super-duper package" requires = "" version = "1" archive(byte) = "p.cma" The variable "requires" contains a list of packages that are required by this package (the names may be separated by commas or spaces). As our package, p, does not depend on any other package, this list is empty. I'll explain what happens with non-empty lists below. The variable "version" is simply a version string, and "description" is a short comment on the package. The variable "archive" denotes the files that have to be actually linked in if the package is used. This is again a list of (file) names. In contrast to the other variables, "archive" has a condition, written in parentheses. This value of "archive" will only be used if the predicate "byte" is true; this predicate is usually given if the program is compiled to bytecode. If you have a native archive, p.cmxa, of the two modules M1 and M2, you can add another line to META: archive(native) = "p.cmxa" The correct value for the "archive" variable is selected upon the given set of predicates. Many packages can also be loaded at runtime with the Fl_dynload module. In this case, though, the variable "plugin" is used instead of "archive", e.g. plugin(byte) = "p.cma" plugin(native) = "p.cmxs" (You can create p.cmxs from p.cmxa with "ocamlopt -shared -linkall -o p.cmxs p.cmxa".) Note that "plugin" is entirely optional. Querying information stored in META files By setting some options of ocamlfind you can query the variables from the META files. For example, -long-format (or short -l) selects all interesting variables: ocamlfind query -long-format p This would answer something like: package: p description: Our super-duper package version: 1 archive(s): linkopts: location: /usr/local/lib/ocaml/site-lib/p The values of the "archive" variable are missing because no predicate has been set, without further options "ocamlfind query" operates with an empty set of predicates. To get the bytecode archive, run: ocamlfind query -long-format -predicates byte p You can set more than one predicate. It usually does not make sense, but you could for example select both bytecode and native archives by: ocamlfind query -long-format -predicates byte,native p As both settings for "archive" are now equally like, the extraction mechanism chooses simply the first. The general rule is that the first most special value is selected. How to compile and link a program that uses a package Now suppose you want to compile a program which calls functions of your new package p. If prog1.ml, prog2.ml, and prog3.ml are the three source files the program consists of, compile them with the commands ocamlfind ocamlc -package p -c prog1.ml ocamlfind ocamlc -package p -c prog2.ml ocamlfind ocamlc -package p -c prog3.ml The "ocamlfind ocamlc" invocation is a frontend to "ocamlc". Most arguments are directly passed to "ocamlc", but there are a few new options, and often some new options are implicitly added. Here, the new -package option is used, which adds search paths such that the modules of package p are found. Effectively, the following direct ocamlc invocations would be equivalent If you specify the -verbose option, the constructed command is printed to the terminal. Actually, there are some more implicitly added options, especially -ccopt -I<dir> for every package directory <dir>. This means that you can compile C programs accessing header files stored in the package directory. : ocamlc -I /usr/local/lib/ocaml/site-lib/p -c prog1.ml ocamlc -I /usr/local/lib/ocaml/site-lib/p -c prog2.ml ocamlc -I /usr/local/lib/ocaml/site-lib/p -c prog3.ml The -I option has the effect that the named directory is also searched when looking up cmi files. Because of this you can refer directly to the modules M1 and M2 in the program sources. In order to link the program use the following command: ocamlfind ocamlc -o program -package p -linkpkg prog1.cmo prog2.cmo prog3.cmo The -linkpkg option causes some more arguments to be added to the constructed ocamlc command. Especially, the name of the archive of p is extracted from the META file, and automatically inserted before the prog1.cmo argument. The resulting command looks like Again, the actual command contains even some more arguments... : ocamlc -o program -I /usr/local/lib/ocaml/site-lib/p p.cma prog1.cmo prog2.cmo prog3.cmo Please note that the bytecode archive p.cma has been selected, and not the native archive p.cmxa. As it is known that the bytecode compiler is used, the predicate "byte" is automatically set. Dependencies Often packages use other packages themselves. Let q be another package consisting of the single module M3 which contains references to M1 and M2. At the first glance, we can ignore this when describing the package, as we could always add "-package p" and "-package q" options when compiling programs using q. This solution is not optimal, as the user of a package must have knowledge about details of the package that should normally be hidden. When we introduced the notion of packages, one of the most important properties was that we can replace packages by improved versions. Imagine that q is replaced by q', but q' uses not only p but also r. Every program that used q and is now forced to use q' must be changed (at least in the Makefile) in order to link r, too. This is clearly not what is intended by packages. The far better solution is to store dependency information in the META files. The "requires" variable can list names of packages that are direct ancestors, i.e. referred directly. (Do not put indirect ancestors into this variable, for example further packages required by r when describing q - these are found out automatically.) The META file of q looks like: description = "Something that needs p" requires = "p" version = "1" archive(byte) = q.cma archive(native) = q.cmxa If you want to put several package names into "requires", separate them with commas or spaces. The "ocamlfind query" command ignores the "requires" value by default, you must add the -recursive option. In this case, all direct or indirect ancestors of the packages given on the command line are selected, too, and printed in topological order. For example, the command ocamlfind query -recursive -long-format -predicate byte q prints two records: package: p description: Our super-duper package version: 1 archive(s): p.cma linkopts: location: /usr/local/lib/ocaml/site-lib/p package: q description: Something that needs p version: 1 archive(s): q.cma linkopts: location: /usr/local/lib/ocaml/site-lib/p Without -recursive, only q would have been printed. The compiler frontend provided with ocamlfind always works recursively. In order to compile and link another.ml that uses q, the following command is sufficient: ocamlfind ocamlc -o another -package q -linkpkg another.ml It is not necessary to specify -package p in this statement as the dependency relation is always used to find out the actually meant set of packages. Linker options Beginning with OCaml 3.00, the compiler itself has an interesting feature called "automatic linking" that makes the following mechanism superfluous in most cases. Automatic linking means that it is possible to store the linker options into the cma or cmxa file such that the compiler itself knows which options are necessary. Of course, the following mechanism still works, and it is still helpful when conditional linking is required. OCaml has a C interface which means that C libraries can be linked in and C functions can be declared as new language primitives. Using such libraries requires special linker options. Some of the core libraries distributed with OCaml are partly implemented in C and thus additional libraries must be specified in the linking phase of the program. For example, the "str" library providing regular expressions requires to be linked as follows: ocamlc -o prog str.cma my_file1.cmo my_file2.cmo -cclib -lstr The -cclib option passes the following argument directly to the underlying C linker which has the effect that libstr.a is linked in, too. The "-cclib -lstr" is directly associated with str.cma as the latter simply cannot be used without the former. Assume you would write a META file describing str. That "str.cma" should be linked in as archive is clear; the "-cclib -lstr" can be specified in another variable called "linkopts". The META file would look like: requires = "" version = "str from ocaml 2.02" archive(byte) = "str.cma" archive(native) = "str.cmxa" linkopts = "-cclib -lstr" This has the effect that specifying -linkpkg in one of the compiler frontends not only chooses one of the archive files, but also extracts the necessary linker options from the META file. The above example can also be compiled with: ocamlfind ocamlc -o prog -package str -linkpkg my_file1.cmo my_file2.cmo Most people will never write META files with "linkopts" settings. But this feature is very useful at least for the core libraries such as str. Because of this, the "findlib" distribution comes with META files for the core libraries in order to hide the linker options. This means that you can already use the packages "str", "dbm", "dynlink", "graphics", "num", "threads", "unix", and "camltk", and that the appropriate archives and linker options are automatically extracted. Dependency analysis of packages Querying ancestors Every package denotes in its META file only the list of direct ancestors. The theoretical model of the dependency relation is a directed acyclic graph (DAG), with the packages as vertices and edges from packages to their direct ancestors. The graph must be acyclic because OCaml does not allow cyclic dependencies between modules. What happens if you query something like ocamlfind query -recursive p1 p2 ... pN is that the named packages p1 to pN are marked in the graph, and that repeatedly all direct ancestors of marked packages are marked, too, until there is not any marked package remaining with an unmarked ancestor. All marked packages are then printed in topological order. This simply means that for the printed packages p1 to pM holds that if pI is printed before pJ then pI is a (possibly indirect) ancestor of pJ. The topological order plays a role when the link command is constructed by "ocamlfind ocamlc", as Ocaml requires that archives must be linked in topological order. For example, the link statement ocamlfind ocamlc -o another -package q -linkpkg another.ml must be turned into the effective command ocamlc -o another [...more options...] p.cma q.cma another.ml and not ocamlc -o another [...more options...] q.cma p.cma another.ml because there are references from q.cma to p.cma. In C, there is a similar requirement when linking static archives. The linker backend ld wants the archives in reversed topological order, i.e. the deepest ancestor must come last in the list of linked archives. Because of this, the additional linker options specified in the "linkopts" variable are passed in reversed order to the underlying linker. This means that you can refer to C libraries of ancestor packages of p in C libraries provided in p. Note that most operating systems do not require any specific order for dynamically linked C libraries (the exception is, surprise!, AIX). Querying descendants It is often useful to find out the descendants of a package, i.e. all direct or indirect users of the package. There is another "ocamlfind" subcommand that allows us to query descendants. For example, to get the direct and indirect users of p, type in ocamlfind query -descendants p The set of packages that are possible descendants is determined as follows: All packages located in directories mentioned in the environment variable OCAMLPATH are candidates. Note that only package directories containing META files are taken. The packages in the default package directory are candidates, too. If there are two packages with the same name, only the first counts, i.e. the first in OCAMLPATH, then the one in the default directory. After this set has been determined, the complete dependency graph is constructed on it. As the descendants are queried, the dependencies are read in the inverse way compared with queries of the ancestors. A new frontend for ocamlc Compiling and linking There are compiler frontends for the four compilers ocamlc, ocamlopt, ocamlmktop, and ocamlcp. They are simply called by specifying the name of the compiler as first argument to ocamlfind, i.e. ocamlfind ocamlc ...arguments... ocamlfind ocamlopt ...arguments... ocamlfind ocamlmktop ...arguments... ocamlfind ocamlcp ...arguments... In addition to the compiler options handled by the compilers themselves, the following options are available: -package <name>: Causes that the package <name> is added to the package list, and that -I options are added for every package, and all direct or indirect ancestors. -linkpkg: Causes that the archives of the packages in the package list and all their direct or indirect ancestors are added in topological order to the command line before the first file to compile or to link. Packages specified by -dontlink are not linked in, though. Furthermore, the linker options of these packages are added in reverse topological order at the end of the command line. -predicates <predicate-list>: The named predicates are included in the list of predicates. Note that there are some predicates set by default, see below. -dontlink <name>: Specifies that the package <name> and all its direct or indirect ancestors should not be linked in. -passopt <opt>: The option <opt> is passed directly to the underlying compiler. This is especially needed to pass undocumented options to the compiler. If you only want to compile, i.e. the -c option is in effect, you normally only need the -package option. Depending on the compiler and on the given options, some predicates are set by default: byte: The predicate "byte" is set when ocamlc, ocamlcp, or ocamlmktop is used to compile or link. native: The predicate "native" is set when ocamlopt is used to compile or to link. toploop: The predicate "toploop" is set when a toploop is being executed create_toploop: The predicate "toploop" is set when ocamlmktop is used to compile or to link a toploop gprof: The predicate "gprof" is set when ocamlopt with -p option is invoked. mt: The predicate "mt" is set when the -thread or the -vmthread option is in effect. mt_posix: The predicate "mt_posix" is set together with "mt" if the POSIX thread implementation is selected. mt_vm: The predicate "mt_vm" is set together with "mt" if the bytecode thread implementation is selected. autolink: The predicate "autolink" is set if the OCaml compiler can perform automatic linking. This predicate is never set if the -noautolink option is in effect. Toploops and runtime systems Dynamic toploops Recent versions of OCaml support dynamic loading of stub libraries (but only for the more widely used operating systems). This means that one can start a toploop by running $ ocaml Objective Caml version 3.07+2 # _ and that it is now possible to load .cma archive files referring to shared C libraries ("DLLs"). In older versions of OCaml this was not possible and one had to create a so-called custom toploop with the ocamlmktop command. This method is still supported and explained below; however, nowadays it is often not necessary to do so. For the modern way, findlib includes a small script called "topfind" (i.e. "ocamlfind for the toploop") that can be directly loaded into the toploop: # #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 = () # _ A number of additional directives are now available. The "#require" directive loads additional packages (with all dependencies): # #require "q1,q2,...,qM";; "#require" loads the listed packages and all their ancestors in the right order, but leaves packages out that have already been loaded. Scripts can now simply load and document which packages are used by a "#require" directive right at the beginning of the script. The #list directive lists the available packages as "ocamlfind list" would do it. If you need additional predicates, you can set them with #predicates. Note that this should be done before the first package is loaded in order to ensure a consistent library system. The #thread directive enables multi-threading if possible. Note that this is only supported for installations basing on the POSIX thread library. (However, if you have only have VM threads, you can still create a custom toploop supporting threads. See below.) Furthermore, the #thread directive should be executed before any packages are loaded. The #camlp4o and #camlp4r directives load the camlp4 syntax parsers for the standard and the revised syntax, respectively. Especially when developing packages, it is sometimes necessary to reload all dynamically loaded packages in the toploop. This can be forced by Topfind.reset();; which causes the "#require" directive to load all packages again. The Topfind module implements all the mentioned directives. Custom toploops It is very simple to create toploops. In order to make a toploop executable that includes directly the packages p1,p2,..,pN simply execute the command ocamlfind ocamlmktop -o toploop -package p1,p2,...,pN,findlib -linkpkg (Maybe you have to add the -custom switch.) Note that one of the packages should be "findlib" itself, because this adds the additional directives mentioned above, i.e. you can directly use these directives without #use "topfind" (but running "topfind" is harmless). Note that such a toploop includes the code of the packages given on the command line, but that it does not automatically add the package directories to the search path (in previous versions of findlib this was tried, but it never really worked). To do so, you still have to #require the packages. In order to create a toploop supporting VM-style threads, use the command ocamlfind ocamlmktop -o toploop -package p1,p2,...,pN,findlib,threads -vmthread -linkpkg Now the #thread directive will work and enable the access to the multi-threading modules. Runtime systems Building of runtime systems is supported, too. For example, you can run ocamlfind ocamlc -o runtime -make-runtime -package p1,p2,...,pN -linkpkg but the problem is which options to specify when a program is linked for this runtime system. If you executed ocamlfind ocamlc -o program -use-runtime runtime -package p1,p2,...,pN\ -linkpkg m1.cmo ... mM.cmo it would be tried to link the archives from the packages again into the bytecode binary. Because of this, it is necessary to suppress linking in packages of the runtime system when linking binaries for a runtime system. The -dontlink option can be used for this: ocamlfind ocamlc -o program -use-runtime runtime -package p1,p2,...,pN\ -dontlink p1,p2,...,pN -linkpkg m1.cmo ... mM.cmo Note that the -package option can enumerate more packages than -dontlink, and in this case the additional packages are actually linked in as they are not contained in the runtime system. Multi-threaded applications If an already existing package is planned to be used in a multi-threaded environment, some language constructs must be replaced by different ones. For example, global variables must be protected by locks (mutexes). Because of this it is common practice to provide two versions of such packages, one for single-, one for multi-threaded applications (or, another technique, there is a special add-on module that initializes a library for multi-threaded usage). The predicate "mt" should be used to recognize multi-threaded applications. For example, a package could consist of two archives, p.cma, and p_mt.cma, where the latter archive is designed for multi-threaded execution. The META file would contain the following lines causing that always the appropriate archive is linked: archive(byte) = "p.cma" archive(byte,mt) = "p_mt.cma" When querying the package database the option "-predicates mt" must be included in the commands in order to select the appropriate entries. When compiling or linking it is necessary to specify either the "-thread" or the "-vmthread" option anyway. The compiler frontends detects these options, and automatically set the "mt" predicate. The following command is an example for this; note that the "threads" package means the standard library of Ocaml providing thread support: ocamlfind ocamlc -thread -package threads,p,q -c x.ml For some operating systems, Ocaml supports the native multithreading libraries conforming to the POSIX interface. As the linker options are generally different, another predicate must be set to get these libraries linked in. The predicate "mt_posix" indicates POSIX threads while "mt_vm" indicates bytecode (virtual machine) threads. Support for gprof-enabled modules When a program is compiled and linked with ocamlopt, gprof-style profiling can be enabled by selecting the -p option. This means that the resulting archives are different, and that it would be useful if there were another predicate in order to select such archives. The predicate "gprof" can be used for this. It is automatically set if the -p option turns on the gprof-mode in an ocamlopt invocation. Complex packages The standard predicates Settings in the META file have usually the form: varname ( predname1, predname2, ... ) = "value" The names in the parentheses are called formal predicates and express a condition which must hold such that the value on the right side is selected. When querying information you can specify a set of actual predicates that are assumed to be true. There are the following standard predicates: The "byte" predicate means that the bytecode compiler is used. The "native" predicate means that the native compiler is used. The "toploop" predicate means that the toploop is available in the linked program. The "mt" predicate means that the program is multi-threaded. The "mt_posix" predicate means that in the case "mt" is set, too, the POSIX libraries are used to implement threads. The "mt_vm" predicate means that in the case "mt" is set, too, the VM-based libraries are used to implement threads. The "gprof" predicate means that in the case "native" is set, too, the program is compiled for profiling The "autolink" predicate indicates that ocamlc is able to perform automatic linking. It is possible to have more predicates indicating different environments; just use them, it is not necessary to declare them anywhere. The value which is selected for a variable depends on the set of assumed predicates. In order to get selected, all formal predicates must be included in the set of actual predicates; if still multiple values fulfill this condition, the value with the maximum number of formal predicates is used; and if still in doubt, the first of these in the META file is taken. It is possible to negate a formal predicate: Just prepend a minus sign to it, e.g. var(p,-q). In this case, it is required that the negated predicates are false (not contained in the set of actual predicates). For all variables that are evaluated after the dependency analysis, findlib adds the so-called package predicates to the set of actual predicates. For every selected package p the predicate pkg_p (with the fixed prefix "pkg_") is added. One application of this are compatibility checks: The special error variable is evaluated after dependency analysis, but before anything else is done. For example, to state that package p is incompatible with package q one can add to the META file of p: error(pkg_q) = "Package p is incompatible with q" The value of error is printed as message in the case the condition is true. Defining additional predicates Additional predicates can be simply used without any declaration, i.e. you can freely invent new predicates. One application of them is to express conditional linkage. For example, one may provide archives for various conditions, such as a production archive, and a development archive. A single new predicate, "development", would be sufficient to express this: archive(byte) = "p_production.cma" archive(byte,development) = "p_development.cma" When linking, include a "-predicates development" argument in the compiler command to select the development archive, otherwise the production archive is taken. Predicates could also be used to select among several implementations of the same module. Define simply one predicate per implementation, e.g. "p_impl1", "p_impl2", and "p_impl3", and specify the archives for every implementation separately: archive(byte,p_impl1) = "p_impl1.cma" archive(byte,p_impl2) = "p_impl2.cma" archive(byte,p_impl3) = "p_impl3.cma" In the case that the implementations have different dependencies, simply provide multiple "requires" variables: requires(p_impl1) = "q" requires(p_impl2) = "q,r" requires(p_impl3) = "r,s" Sometimes, the implementations require different linker options. In this case, define several versions of the "linkopts" variable just like in the "requires" example. Note that predicates are global identifiers that can be potentially applied to every selected package. In the case that a predicate is only meaningful for a single package, it is common practice to choose the package name as prefix of the predicate name (e.g. "netstring_minimum" is a predicate usually only applied to the "netstring" package). Predicates could be used to select which features of a library are linked. For example, archive(byte) = "p_basic.cma" archive(byte,p_extension) = "p_basic.cma p_ext.cma" would add the p_ext.cma archive only if the p_extension predicate were set. It is considered as bad practice to select extensions of libraries by predicates. Findlib provides the construct of subpackages for this purpose. Appending to variables The syntax varname ( predname1, predname2, ... ) += "value" (note the "+=" operator) can be used to append values to variables depending on whether predicates are true. The "+=" lines in the META file are evaluated one after the other, and every line is selected for which the formal predicates are satisfied, and these lines are added to the current value of the variable. This is different from the "=" operator where only the most specific assignment is taken. The values are considered as space-separated words when they are appended, i.e. the new words are added to the list of current words. For example, in the hypothetic META file var(p) += "a" var(p,q) += "b" the value of var is "a b" if both p and q are true, and the value is only "a" is only p is true (and the value is empty otherwise). If the operator "=" had been used, the value would have been only "b" when both p and q are true. In the case that there both "=" and "+=" settings for the same variable, a special algorithm is used: First the most specific "=" setting is determined, and second all matching "+=" settings are appended in the order they appear in the file. Finally, here is a real-world example. Imagine you have an archive p.cma and a special extension for the toploop, p_top.cma. Furthermore, there is a special debugging version p_dev.cma that replaces p.cma during development. You can now simply write archive(byte) = "p.cma" archive(byte,development) = "p_dev.cma" archive(byte,toploop) += "p_top.cma" to select either p.cma or p_dev.cma, and append p_top.cma for toploops to whatever was selected in the first step. Subpackages Sometimes a package consists of several archive files that are closely related. It is now possible to express dependencies between these archives by splitting the package into several parts called subpackages. For example, package p consists of a base archive p_base.cma, and two extensions p_ext1.cma and p_ext2.cma that both require the base archive but are independent of each other. This META file expresses this dependency directly: # META file of package p: requires = "p.base" package "base" ( archive(byte) = "p_base.cma" ) package "ext1" ( requires = "p.base" archive(byte) = "p_ext1.cma" ) package "ext2" ( requires = "p.base" archive(byte) = "p_ext2.cma" ) If installed as package "p", this definition actually defines four logical packages: "p" (the main package), "p.base", "p.ext1", and "p.ext2" (the subpackages). These four entities only share the META file in which they are declared, and the directory where the archive files are stored, but all other properties can be individually set for each package. This also means that all package dependencies must explicitly added by "requires" variables, as there are no implied dependencies. In this example, the main package and "p.ext1" and "p.ext2" are all dependent on "p.base". The users of this installation can refer to all four packages. This means that ocamlfind ocamlc -package p -linkpkg ... links only p_base.cma into the final program, while ocamlfind ocamlc -package p.ext1 -linkpkg ... selects both p_base.cma and p_ext1.cma. Glue code Imagine we have two packages p and q that are normally independent, i.e. one can link p without q, and q without p. However, when both p and q are used in the same program, it is expected that they cooperate with each other. Of course, this situation can be modeled with the help of subpackages (a real-world example of this are p=lablgtk and q=lablgl). The idea is as follows: p has a subpackage p.for_q that contains code with special features for q, and q has a subpackage q.use_p that depends on p, p.for_q, and q, and that contains the code using the special features of p. Expressed in META files, p would define # META file for p: requires = "..." archive = "..." package "for_q" ( requires = "p" archive = "..." ) and q would define # META file for q: requires = "..." archive = "..." package "use_p" ( requires = "q,p.for_q" archive = "..." ) Of course, the program using both libraries must explicitly enable the subpackages by mentioning "q.use_p" on the ocamlfind command line, otherwise the glue code would be omitted. Unfortunately, it is not possible to use the package predicates pkg_p and pkg_q to add archives depending on whether the other package is also selected. The problem is that the order cannot be specified, i.e. whether p must be linked first or q. Plugins (Since findlib-1.6.) Plugins are packages that can be loaded at runtime. Plugins are intended as a mechanism for loading add-on code into executables. Technically, there is some overlap with the concept of a "shared library". Note, however, that there is no universal support for plugins, as it is unimplemented on some platforms, and only poorly on some others (including x86 in the 32 bit case). Also, there must always be an explicit "load" statement in the loading executable. You cannot link an executable directly against plugins. Preparing a plugin For bytecode there is no problem to load cma files at runtime. For native-code, though, you need to convert cmxa files into cmxs files first: ocamlopt -shared -linkall -o m.cmxs m.cmxa As mentioned, be prepared that this command fails on platforms where plugins are unavailable. The cmxs files can then be referenced from META. We don't use the "archive" variable in this case but "plugin": plugin(byte) = "m.cma" plugin(native) = "m.cmxs" Before findlib-1.6, there was some half-official convention using the "plugin" predicate. This is still supported, but deprecated: archive(byte) = "m.cma" archive(native,plugin) = "m.cmxs" Load-time dependencies Plugins can be, of course, be dependent on other plugins. You run into a problem, though, when you make a plugin dependent on a package that doesn't qualify as plugin (i.e. lacks the "plugin" definition). In this case, the loader simply skips the dependency, and you cannot load the plugin. Because of this dependency issue, it is recommended to add the "plugin" variable to all packages that are installed on a system, because this does not only allow it to load all packages at runtime, but also to use these packages as dependency of the actual plugin code. That said, you just need to add a "requires" directive, e.g. requires = "pkg1" plugin(byte) = "m.cma" plugin(native) = "m.cmxs" How to load a plugin Linking an executable that can load a plugin: An executable must link the package "findlib.dynload". This does not only add the loader, but also special initialization code to the executable: ocamlfind ocamlopt -o program -package findlib.dynload -linkpkg ... In particular, this records the packages that are already included into the executable (in-core packages). If a plugin is now dependent on such a package, this is recognized, and the package is not loaded (which would not work anyway). Now, you can load a plugin "foo" with: Fl_dynload.load_packages ["foo"] This loads the cma or cmxs files, and runs the initialization code of all top-level definitions of the included modules. Of course, you can also call load_packages from a library if "findlib.dynload" is a required package of the library package. Fat plugins Sometimes it is handy to create plugins that already include all the required packages. The plugin acts more like a dynamically loadable executable that already includes whatever it needs. You can create such a "fat" plugin with: ocamlfind ocamlopt -shared -linkpkg -linkall -o m.cmxs -package p1,p2,p3 m.cmxa In this case, the "requires" line in the META file should remain empty. Note, however, that you cannot handle packages this way that are already linked into the main program, because it is invalid to load a module that is already part of the main executable. Let's assume that the executable links in q1, q2, and q3. Then, you need to exclude these packages from the plugin. The -dont-link option comes handy in this case: ocamlfind ocamlopt -shared -linkpkg -linkall -o m.cmxs -package p1,p2,p3 -dont-link q1,q2,q3 m.cmxa This excludes q1,q2,q3 even if these packages occur as dependencies of p1,p2,p3. In this case, though, you need to put q1,q2,q3 into the "requires" field of META. Lint (Since findlib-1.6.) As it has become more and more complicated to write correct META files there is now some support for recognizing typical problems. Just use ocamlfind lint META to check the file META in the current directory. The tool reports problematic lines in META, e.g. archive(byte,plugin) = "oUnit.cma" This specification of dynamic loading is deprecated, you should add a "plugin(...)" variable. archive(native,plugin) = "oUnit.cmxs" This specification of dynamic loading is deprecated, you should add a "plugin(...)" variable. How to create your own packages Installing and removing packages The ocamlfind command can install and remove packages. For example, to install a package p containing the files META, m1.cmi, m2.cmi, p.cma, run ocamlfind install p META m1.cmi m2.cmi p.cma This installs the files into the default location for new packages (set in ocamlfind.conf). If you have files that are not always built, add these after the -optional switch: ocamlfind install p META m1.cmi m2.cmi p.cma -optional p.cmxa p.cmxs To remove the package, run ocamlfind remove p Note that every package must have a META file, it is not possible to omit it. Change your Makefile Here is a commented version of a Makefile that may be used to compile and link a package. It describes the frequent case that the package simply consists of a bundle of modules that are dependent on other packages. First, some general definitions. NAME is the name of the package. The OBJECTS variable enumerates the bytecode objects, whereas XOBJECTS names the native objects. The same naming convention is used for ARCHIVE and XARCHIVE, specifying the resulting bytecode, resp. native archive file. The REQUIRES variable lists the names of the packages that are needed for this package. If you need additional predicates, put them into the PREDICATES variable. NAME = p OCAMLC = ocamlfind ocamlc OCAMLOPT = ocamlfind ocamlopt OCAMLDEP = ocamldep OBJECTS = p1.cmo p2.cmo XOBJECTS = p1.cmx p2.cmx ARCHIVE = $(NAME).cma XARCHIVE = $(NAME).cmxa SARCHIVE = $(NAME).cmxs REQUIRES = unix str q r s PREDICATES = The default goal is "all", causing the bytecode archive to be created. In order to get a native archive, choose "opt" as second goal. (The ".PHONY" line is a declaration meaningful for GNU-make; "all" and "opt" are only virtual goals as there no files "all", or "opt" which is indicated by making them dependents of ".PHONY".) .PHONY: all opt all: $(ARCHIVE) opt: $(XARCHIVE) $(SARCHIVE) The following two rules create the bytecode resp. native archive from the objects. $(ARCHIVE): $(OBJECTS) $(OCAMLC) -a -o $(ARCHIVE) -package "$(REQUIRES)" -linkpkg \ -predicates "$(PREDICATES)" $(OBJECTS) $(XARCHIVE): $(XOBJECTS) $(OCAMLOPT) -a -o $(XARCHIVE) -package "$(REQUIRES)" -linkpkg \ -predicates "$(PREDICATES)" $(XOBJECTS) $(SARCHIVE): $(XARCHIVE) $(OCAMLOPT) -shared -o $(SARCHIVE) $(XARCHIVE) || true Note that the cmxs archive is optional: we just ignore the error when it cannot be built. These rules compile the modules independently. The lines similar to ".ml.cmo" must be read: "How to transform files with suffix .ml into files with suffix .cmo". The corresponding command can refer to the input file as "$<" and to the output file(s) as "$@". .SUFFIXES: .cmo .cmi .cmx .ml .mli .ml.cmo: $(OCAMLC) -package "$(REQUIRES)" -predicates "$(PREDICATES)" \ -c $< .mli.cmi: $(OCAMLC) -package "$(REQUIRES)" -predicates "$(PREDICATES)" \ -c $< .ml.cmx: $(OCAMLOPT) -package "$(REQUIRES)" -predicates "$(PREDICATES)" \ -c $< The "depend" goal is the file describing the dependencies within the package; it is created by ocamldep. depend: *.ml *.mli $(OCAMLDEP) *.ml *.mli >depend include depend The "install" rule is a bit tricky. First it is tested if there is a native archive to install, and if so, the variable "extra" contains the corresponding files. The "ocamlfind install" command creates a new package directory and puts the given files into it. .PHONY: install uninstall install: all ocamlfind install $(NAME) *.mli *.cmi $(ARCHIVE) META \ -optional $(XARCHIVE) $(SARCHIVE) uninstall: ocamlfind remove $(NAME) Last but not least a cleanup rule: .PHONY: clean rm -f *.cmi *.cmo *.cmx *.cma *.cmxa *.a Using the Makefile wizard Especially for beginners, the findlib distribution includes a GUI to create Makefiles. As this is an optional feature, it must have been selected when findlib was built (option -with-toolbox). To invoke the GUI, run the command $ ocamlfind findlib/make_wizard (Btw, this is the general syntax to run executables installed in package directories.) The wizard starts, and allows you to describe your project. When you save the result, not only a "Makefile" is created, but also the file ".make-wizard" containing the state. If you later start the wizard again, this file will be automatically loaded, and you can modify your definition. The wizard consists of seven (hopefully self-explanatory) pages you can fill out. The basic idea is that the .ml, .mli, .mly, and .mll files in the current directory are compiled to a .cma or .cmxa archive, and that optionally executables are created from this archive and from additional modules (main programs). This scheme can be both used for libraries and application programs. You can choose packages you want to use in your library or program by clicking at them in a selection box. The camlp4 syntax parsers can be optionally enabled. The modules to be compiled can be picked from the current directory, they must be selected in the right order, however. The generated "Makefile" defines a number of logical targets (like "all", "opt", etc) that are explained at the beginning of the file. The file is fully commented, and not very difficult to understand. Only traditional Makefile syntax is used, so it is expected that it works for every version of the "make" utility. When you build the project, the META file is created dynamically. If you do not like this, set the variable MAKE_META to the empty string. (It is a good idea to put such setting into a second file, and enter the name of this file into the box "Local extensions in" of the wizard, so you can generate the "Makefile" again without overwriting your own modifications. This second file can override the setting in the generated "Makefile".) FAQs Does findlib support the autolink feature of OCaml 3? Short answer: Findlib is compatible with autolink The new archive format introduced with OCaml 3 can store the linker options that are necessary to link an archive. For example: ocamlc -a -o myarchive.cma mymodule.cmo -cclib -lmylibrary This command does not only create the new archive myarchive.cma, but it also writes into a special section of that file that the linker option -cclib -lmylibrary is necessary to link this archive. This means for findlib that most of the "linkopts" attributes in META files have become superfluous: The compiler itself already knows the linker options, we do not need to tell the compiler the options. We could simply leave all "linkopts" attributes out. Of course, the "linkopts" feature of findlib still works. This is necessary because findlib should keep the compatibility with older software, and because "linkopts" is more powerful (you can have conditional linker options). If you have software that must run in both OCaml 2 and OCaml 3 environments, you can make your "linkopts" attribute dependent on the "autolink" predicate. For example: linkopts = "-cclib -lmylibrary" linkopts(autolink) = "" The findlib installation for OCaml 3 will take the second line which is reasonable because ocamlc already knows how to link; the installation for OCaml 2 never sets the "autolink" predicate and therefore uses the first line. Why does findlib not automatically include the -custom option if linked with C code? Short answer: Because there are several ways of linking, and findlib is not the right instance to find out the right way Recent versions of OCaml support DLLs, at least for some platforms. Here, the option -custom is not necessary at all, because the C libraries can be looked up and loaded at runtime. The option -custom would have the effect of forcing static linking. But even for platforms without DLL support, there are two alternatives. One possibility is to use -custom, and the other is to create runtime systems with -make-runtime, and reference them with -use-runtime. Fortunately, recent versions of OCaml select now themselves -custom automatically if -make-runtime is omitted, so findlib needs not to bother with it. Does findlib support linking of applications as well as packages? Short answer: Yes, but it is not very obvious Applications also depend on other components, they have predicates, sometimes they need linker options; there seems to be only little difference between applications (stand-alone programs) and packages. If you want to use the findlib mechanisms for applications, too, the following trick helps. The environment variable OCAMLPATH may contain a colon-separated path of possible sitelib locations. It is allowed to include "." into the path (Shell commands follow): OCAMLPATH=. export OCAMLPATH This makes ".", i.e. your current directory, another sitelib location. You may now put the components of your applications into subdirectories together with META files; the hierarchy might look as follows: ./Makefile global Makefile ./localpkg1/META first local package directory: Contains META ./localpkg1/... ... and more ./localpkg2/META second local package dir: Contains META ./localpkg2/... ... and more ... From findlib's point of view, these directories are now package directories, and you can refer to them on the command line: ocamlfind ocamlc -o ... -linkpkg -package localpkg1,localpkg2,... If you do not want subdirectories, you can also refer to the META file in the same directory by the name ".", e.g.: ocamlfind ocamlc -o ... -linkpkg -package . In this case, the linking information will be taken from ./META. Does Findlib support camlp4? Short answer: Yes, but there is only little documentation. Since Findlib-0.4, there is some experimental camlp4 support. For example, the following compiler invocation chooses the revised syntax: ocamlfind ocamlc -syntax camlp4r -package camlp4 -c file.ml As you can see, camlp4 must be included as package, and the -syntax option must specify which syntax is selected (either camlp4o or camlp4r). If you want to pass additional options to the preprocessor, you can use the -ppopt option: ocamlfind ocamlc -syntax camlp4r -package camlp4 -ppopt pa_ifdef.cmo -c file.ml From the toploop, the following commands work: $ ocaml Objective Caml version 3.07+2 # #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 = () # #camlp4o;; (* or camlp4r *) /opt/godi/lib/ocaml/std-lib/camlp4: added to search path /opt/godi/lib/ocaml/std-lib/camlp4/camlp4o.cma: loaded Camlp4 Parsing version 3.07+2 # _ The concept If you have a -syntax option on the command line, ocamlfind will generate a -pp parameter and pass it to the invoked compiler. This is performed as follows: The specified packages are inspected under a certain set of predicates, the syntax predicates. The syntax predicates are syntax, preprocessor, and the predicates following -syntax. The predicate syntax simply means that the -syntax option has been specified. The predicate preprocessor means that the preprocessor command is being constructed. The predicates added by -syntax may be used to distinguish between syntax variants (currently camlp4o and camlp4r). The packages are searched for a variable preprocessor; normally the camlp4 package defines it as (see its META file): preprocessor = "camlp4 -nolib" Now that the name of the preprocessor command is known, the arguments of the command are looked up. The META files are evaluated under the syntax predicates, and all archive variables are collected and passed as arguments to the preprocessor. For example, the camlp4 package defines: archive(syntax,preprocessor,camlp4o) = "pa_o.cmo pa_op.cmo pr_dump.cmo" archive(syntax,preprocessor,camlp4r) = "pa_r.cmo pa_rp.cmo pr_dump.cmo" Note that the predicate preprocessor prevents ocamlfind from including these archives into the regular list of archives to link. How to write a META file for your own syntax extension Suppose you have two archives: pa_myext.cma contains the extension code of camlp4, and run_myext.cma contains runtime material that must be present in programs compiled with your extensions. Your META file should look as follows: requires = "camlp4" archive(syntax,toploop) = "pa_myext.cma run_myext.cma" archive(syntax,preprocessor) = "pa_myext.cma" archive(syntax,byte) = "run_myext.cma" archive(syntax,native) = "run_myext.cmxa" You may add dependencies on camlp4o or camlp4r if you have archives only working for one of the two syntax variants. To compile a program using your syntax extension package, one should use: ocamlfind ocamlc -package yourname -syntax variant ... Example The package xstrp4 defines a syntax extension allowing $-substitutions in OCaml strings. Version 1.0 of this package takes advantage from the new camlp4 support of findlib; you may have a look at it for an example. You can find xstrp4 here. Does Findlib support ppx-style preprocessors? Short answer: Yes, but there is only little documentation. Since findlib-1.5, ppx-style preprocessors are supported to some extent. A package can now define a "ppx" property which is simply a command to run as preprocessor (the command gets the marshalled AST as input, and must generate the transformed AST in its output; see the -ppx option of ocamlc/ocamlopt). A META file can simply look like: ppx = "./command" when "command" is installed in the package directory (but you can also omit "./" to search it, and you can prefix it with "@name/" if the command is taken from another package "name"). For more complex scenarios, additional options or arguments for the ppx preprocessor can be specified in descendant packages with the "ppxopt" property. Package "A" might provide a generic ppx preprocessor with a META file containing ppx = "./generic_ppx" Package B might instantiate that preprocessor with requires = "A" ppxopt = "A,ppx_b.cmo" In this case "ocamlfind ocamlc -package B" would add -ppx "path_to_A/genric_ppx ppx_b.cmo" to the ocamlc invocation. The format of the "ppxopt" property is specified in the findlib reference manual. This feature is still a bit experimental. Why do some people install the .cmx files? In principle, it is not necessary to install the .cmx files created by the ocamlopt compiler, as the .a and .cmxa files already contain the assembly code and all needed auxiliary information. However, it may be sensible to install the .cmx files, too. They contain the intermediate code of small functions that are candidates for inlining, and installing them allows the compiler to do inlining even across library boundaries. Note that only very small functions can be inlined at all, and that there are language elements that prevent inlining (e.g. raising an exception with an argument), so it makes only sense when the library actually has such functions and really profits from inlining. Inlining has also disadvantages: The library can no longer be replaced by a different version even if the interface remains exactly the same, because code using the library may have inlined code of the old version. How do I express conflicts? A conflict means that a certain combination of packages and package features will not work. A number of conflict conditions can be expressed: To state that a package will not work if a certain predicate is set, use the error variable. For example, when package p does not work for multi-threaded programs: error(mt) = "Package p is incompatible with multi-threaded programs" This works for other standard predicates, too. To state that a package will not work together with another package, it is possible to make error dependent on package predicates. For example, when package p does not work together with q: error(pkg_q) = "Package p is incompatible with package q" This also works with subpackages (e.g. pkg_q.q_sub). If an error is too much, it might be a good idea to just inform the user about possible problems. In this case you can emit a warning instead: warning(pkg_q) = "Using package p and q together is a really bad idea" Note that such error conditions should only be added if there is absolutely no chance to get the combination of packages and features running. For example, in the case of multi-threaded programs it is often possible to add wrappers around unsafe libraries to fix the incompatibility. It is not possible to express incompatibilities between package versions. Such incompatibilities should be detected when software is installed, not when it is used.
not-ocamlfind-0.14/local-packages/ocamlfind/doc/src/findlib_conf.mod0000644000175000017500000002645614770304423024514 0ustar stephsteph findlib.conf 5 The findlib package manager for OCaml findlib.conf [Configuration of findlib/ocamlfind] GENERAL There are three possibilities to configure the findlib library: Build time: Before findlib is compiled, a "configure" script is invoked to figure out the settings that are most likely to work on the system. Most settings are simply entered into text files and can easily be changed after installation. The following properties cannot be changed later because they are compiled into the resulting binaries: The default location of the configuration file findlib.conf. However, you can set a different location by the environment variable OCAMLFIND_CONF. Whether the installed OCaml version supports autolinking or not. Configuration file findlib.conf: An initial version of this file is generated by the configure script, but you are free to modify it later. Most important, this file contains the system-wide search path used to look up packages, and the default location where to install new packages. All files with the suffix ".conf" found in the directory findlib.conf.d are also scanned for parameters. Environment variables: The settings of findlib.conf can be overridden by environment variables. Last but not least, several settings can also be passed as command-line options, or by invoking the function Findlib.init. findlib.conf The directory containing findlib.conf is determined at build time (by running the configure script), the fallback default is /usr/local/etc. You can set a different location by changing the environment variable OCAMLFIND_CONF which must contain the absolute path of findlib.conf. The file has the same syntax as META, i.e. it consists of a number of lines with the format variable = "value" Here is the list of allowed variables: path The search path for META files/package directories. The variable enumerates directories which are separated by colons (Windows: semicolons), and these directories are tried in turn to find a certain package. More exactly, if d is such a directory and p the searched package, the search algorithm will first check whether d/p/META exists. In this case, this META file is taken, and d/p is the package directory. Second, the algorithm tries d/META.p, but the package directory must be specified in this META.p file by a directory directive. Note that the first found META file is taken, so the order of the directories in the search path counts. This variable is required. Example: path = "/usr/local/lib/ocaml/site-lib:/usr/lib/ocaml/site-lib" destdir This variable determines the location where ocamlfind install puts the packages by default: If d is this directory, and p the package to install, a new subdirectory d/p will be created containing all the files of the package. Example: destdir = "/usr/local/lib/ocaml/site-lib" This variable is required. metadir If set, the command ocamlfind install will put the META files of packages into this directory (files are named META.p where p=package name); otherwise the META files are put into the package directories like any other file. Example: metadir = "/var/lib/findlib/metaregistry" This variable is optional. It is not used by default. ocamlc, ocamlopt, ocamlcp, ocamlmktop, ocamldoc, ocamldep, ocamlbrowser If you want to call other executables than "ocamlc", "ocamlopt", "ocamlcp", "ocamlmktop", "ocamldoc", "ocamldep", and "ocamlbrowser", you can set the names of the executables here. The command ocamlfind looks into these four variables to determine the names of the compilers to call. Example: ocamlc = "ocamlc.opt" ocamlopt = "ocamlopt.opt" ocamlcp = "ocamlcp.opt" ocamlmktop = "ocamlmktop.opt" This variable is optional. It is not used by default. stdlib This variable determines the location of the standard library. This must be the same directory for which the OCaml compilers are configured. This variable is optional. It is not recommend to set this variable unless you know what you are doing! ldconf This variable determines the location of the ld.conf file. This must be the same file the OCaml compilers read in; it is updated by ocamlfind when installing and removing packages. You can set this variable to the special value "ignore" to disable the automatic modification of the ld.conf file. If not set, the ld.conf file is assumed to reside in the OCaml standard library directory. This variable is optional. It is not recommended to set this variable unless you know what you are doing! Toolchains: It is possible to have variants of the original configuration. These variants are called "toolchains" because they are intended to select different compilers, e.g. patched compilers. In order to set a variable for a certain toolchain, use the syntax variable(toolchain) = "value" For example: ocamlc(mypatch) = "ocamlc-mypatch" When the toolchain "mypatch" is selected, this compiler will be used instead of the standard one. In order to switch to a certain toolchain, use the -toolchain option of ocamlfind. Environment A number of environment variables modifies the behaviour of findlib/ocamlfind: OCAMLFIND_CONF This variable overrides the location of the configuration file findlib.conf. It must contain the absolute path name of this file. OCAMLFIND_TOOLCHAIN This variable sets the currently selected toolchain when a -toolchain option is not passed on the command line. OCAMLPATH This variable may contain an additional search path for package directories. It is treated as if the directories were prepended to the configuration variable path. OCAMLFIND_DESTDIR This variable overrides the configuration variable destdir. OCAMLFIND_METADIR This variable overrides the configuration variable metadir. OCAMLFIND_COMMANDS This variable overrides the configuration variables ocamlc, ocamlopt, ocamlcp, ocamlmktop, ocamldoc, ocamldep, and/or ocamlbrowser. Its value must conform to the syntax ocamlc=name ocamlopt=name ocamlcp=name ocamlmktop=name ocamldoc=name ocamldep=name ocamlbrowser=name Example: ocamlc=ocamlc-3.00 ocamlopt=ocamlopt-3.00 ocamlcp=ocamlcp-3.00 ocamlmktop=ocamlmktop-3.00 CAMLLIB or OCAMLLIB This variable overrides the configuration variable stdlib. OCAMLFIND_LDCONF This variable overrides the configuration variable ldconf. OCAMLFIND_IGNORE_DUPS_IN This variable instructs findlib not to emit warnings that packages or module occur several times. The variable must be set to the directory where the packages reside that are to be ignored for this warning. not-ocamlfind-0.14/local-packages/ocamlfind/doc/src/findlib_meta.mod0000644000175000017500000003302414770304423024502 0ustar stephsteph META 5 The findlib package manager for OCaml META [File that specifies metainformation of OCaml packages] GRAMMAR metafile ::= entry* entry ::= assignment | addition | subpackage subpackage ::= "package" pkgname '(' metafile ')' assignment ::= variable_name [ formal_predicates ] '=' value addition ::= variable_name [ formal_predicates ] '+=' value formal_predicates ::= '(' formal_predicate { ',' formal_predicate } ')' variable_name ::= name formal_predicate ::= name | '-' name name ::= [ 'A'-'Z' 'a'-'z' '0'-'9' '_' '.' ]+ pkgname ::= '"' (character but not '.')* '"' value ::= '"' character* '"' DESCRIPTION If a package directory contains a file with the fixed name "META" it is interpreted as described here. The file is a sequence of entries following the given grammar; every entry defines a variable under a certain condition given by the list of formal predicates, or it introduces a subpackage. There is a list of predefined variables and a list of standard predicates. These variables define: required packages, description, version information, directories, archive files, and linker options. The predicates denote circumstances of the application of the variables: whether the bytecode or the native compiler is used, if there is a toploop compiled in, details of multi-threading execution, details of profiling. DETAILS OF THE FILE FORMAT The file consists of a sequence of entries which must be formed as the grammar prescribes. The lexical tokens are names, values, and interpunctuation like '(', ',' and so on. Note that linefeeds do not play a special role, i.e. an entry definition may be given in more than one line, or several definitions may occur on a single line. There may be comments which begin with '#' and run until the end of the line. Names are sequences of the characters A-Z, a-z, 0-9, or _. Names containing capital letters and names beginning with digits are allowed but not recommended. Values are enclosed between double quotes. Values may contain any character. The characters " and \ must be preceded by backslashes. Package names must not contain the '.' character because it is used as delimiter of compound names. MAIN PACKAGES AND SUBPACKAGES The outermost variable assignments and additions belong to the main package. The name of the main package is not defined within META; it is either the name of the directory containing META or the suffix of the META file (if the name of the META file is formed like META.name). The keyword package starts the definition of a subpackage. There must not be two such definitions with the same name. Within the parentheses, the variable assignments and additions refer to the subpackage. It is allowed that a subpackage contains further subpackages. The package name following package is the local name relative to the main package, i.e. the name of the main package is not mentioned. At all other places, however, the subpackage must be prefixed by the name of the containing package, separated by a '.'. Subpackages are independent of the containing package, except that the subpackage points to the same installation directory as the containing package (i.e. the location of the installation directory is inherited from the containing package). SEMANTICS OF VARIABLE DEFINITIONS In order to determine the value of a variable, first all assignments are inspected, and the most specific assignment is taken (if there is none, the empty string will be taken as value). In a second step, all additions are gone through one after the other in the order they occur in the file, and the values of all matching additions are appended to the current value. In the following, it is further clarified which assignment is the most specific, which additions actually match, and how the details of the value addition look like. The most specific assignment is selected upon a set of actual predicates, i.e. the set of predicates that are assumed to be true. The predicates occurring in the definitions of assignments and additions are called formal predicates. They may be positive or negative; the latter are prepended by a '-' sign. In order to determine the value after the evaluation of the assignments, the following rules apply: An assignment can only be used if all positive formal predicates are included in the set of actual predicates, and if all negative formal predicates are not included in the set of actual predicates. Such an assignment is called applicable. If there is no such assignment, the variable will have no value. If there is more than one applicable assignment, the definition with the biggest number of formal predicates is selected. If there is still more than one applicable assignment, both applicable and with a maximum number of formal predicates, the definition that is defined first is selected. An addition is matching when all positive formal predicates are included in the set of actual predicates, and all negative formal predicates are not included. The value of an addition is appended to the current value with implicit white space as separator. VARIABLES There is a set of variables with predefined meaning: The variable "directory" redefines the location of the package directory. Normally, the META file is the first file read in the package directory, and before any other file is read, the "directory" variable is evaluated in order to see if the package directory must be changed. The value of the "directory" variable is determined with an empty set of actual predicates. The value must be either: an absolute path name of the alternate directory, or a path name relative to the stdlib directory of OCaml (written "+path"), or a normal relative path name (without special syntax). In the latter case, the interpretation depends on whether it is contained in a main or sub package, and whether the standard repository layout or the alternate layout is in effect (see site-lib for these terms). For a main package in standard layout the base directory is the directory physically containing the META file, and the relative path is interpreted for this base directory. For a main package in alternate layout the base directory is the directory physically containing the META.pkg files. The base directory for subpackages is the package directory of the containing package. (In the case that a subpackage definition does not have a "directory" setting, the subpackage simply inherits the package directory of the containing package. By writing a "directory" directive one can change this location again.) The variable "requires" specifies the list of required packages. The names of the packages must be separated by white space and/or commas. The names must be fully qualified (i.e. when they refer to a subpackage, the names of all containing packages must be prepended, separated by '.'). The variable "description" may include a short description of the package (displayed by ocamlfind list). The variable "version" specifies the version string. The variable "archive" specifies the list of archive files. These files should be given either as (1) plain names without any directory information; they are only searched in the package directory. (2) Or they have the form "+path" in which case the files are looked up relative to the standard library. (3) Or they have the form "@name/file" in which case the files are looked up in the package directory of another package. (4) Or they are given as absolute paths. The names of the files must be separated by white space and/or commas. In the preprocessor stage, the archive files are passed as extensions to the preprocessor (camlp4) call. In the linker stage (-linkpkg), the archive files are linked. In the compiler stage, the archive files are ignored. Note that "archive" should only be used for archive files that are intended to be included in executables or loaded into toploops. For modules loaded at runtime there is the separate variable "plugin". The variable "plugin" specifies the plugin archives of the package. These can be dynamically loaded with the Fl_dynload module. The plugin archives can have ".cmo", ".cma", or ".cmxs" suffix. The variable "linkopts" specifies additional linker options. The variable "error" can be used to signal error conditions. When this variable is applicable, the ocaml compilers are stopped, and an error message is printed. The message is the value of the variable. The variable "warning" can be used to signal warnings. When this variable is applicable, the warning is printed, but the compilation continues. The message is the value of the variable. The variable "exists_if" can be used to disable subpackages. The value of "exists_if" is a file; the subpackage is hidden if this file does not exist. You can also enumerate several files, and the subpackage is hidden if none of the files exist. The variable "ppx" is a command that is added to the compiler invocation via the -ppx option (available since OCaml-4.01). If the command is relative to the current directory (e.g. ./cmd), the command is expected in the package directory. The special forms as defined for "archive" are also available (e.g. @otherpkg/cmd). Additional arguments can be specified on the ocamlfind command line with the -ppxopt option or the "ppxopt" variable. The variable "ppxopt" is a set of options that are added to the ppx rewriter invocation. The contents of the variable consists of one or several whitespace-separated parts. Every part consists of several comma-separated subparts; the first subpart indicates the package that contains the ppx rewriter invocation, the rest contain the options to be appended. If the option is a path relative to the current directory (e.g. ./foo.cma), the path is expanded relative to the package directory. The special forms as defined for "archive" are also available (e.g. @otherpkg/foo.cma). It is possible to define additional variables but there is currently no software interpreting them. PREDICATES There is a list of standard predicates: The "byte" predicate means that the bytecode compiler is used. The "native" predicate means that the native compiler is used. The "toploop" predicate means that the toploop is available in the linked program. It is only set when the toploop is running, not when the toploop is generated. The "create_toploop" predicate means that a toploop is created (using ocamlmktop). The "mt" predicate means that the program is multi-threaded. The "mt_posix" predicate means that in the case "mt" is set, too, the POSIX libraries are used to implement threads. The "mt_vm" predicate means that in the case "mt" is set, too, the VM-based libraries are used to implement threads. The "gprof" predicate means that in the case "native" is set, too, the program is compiled for profiling The "autolink" predicate means that ocamlc can/will perform automatic linking. The "preprocessor" predicate means that the META variables are scanned for preprocessor options. The "syntax" predicate means that the -syntax option is present on the command line. Legacy: The "plugin" predicate could be used in some versions of findlib to select cmxs archives instead of cmxa archives. This use is still possible but discouraged. In addition to these predicates, there are package predicates for every package that is finally selected. Of course, this kind of predicate must not be used to select "directory" and "requires" variables, but for the other variables they are perfectly valid. The package predicates have the form "pkg_" plus the name of the package (fully qualified). not-ocamlfind-0.14/local-packages/ocamlfind/doc/src/findlib_mli.mod0000644000175000017500000001233614770304423024340 0ustar stephsteph Findlib 3 The findlib package manager for OCaml Findlib [Module for package management] SIGNATURE module Findlib : sig (* Note: This signature is incomplete. See findlib.mli for the * full signature. *) end PACKAGING The Findlib module is part of the "findlib" package. In order to link it in, it is sufficient to link "findlib" in, e.g. ocamlfind ocamlc options -package findlib -linkpkg options There are archives for the bytecode compiler and for the native compiler; for single-threaded and for multi-threaded applications, and there is a special addition for toploops. DESCRIPTION The Findlib module is the primary interface of the findlib library. It contains functions to lookup packages, to interpret files, and to determine the ancestors of packages. <anchor id="Findlib.package-directory"> Findlib.package_directory <replaceable>pkg</replaceable> val package_directory : string -> string Gets the absolute path of the directory where the package pkg is stored. The exception Not_found is raised if the package could not be found. Other exceptions may occur as file I/O is done. <anchor id="Findlib.package-property"> Findlib.package_property <replaceable>predicates</replaceable> <replaceable>pkg</replaceable> <replaceable>variable</replaceable> val package_property : string list -> string -> string -> string Determines the value of the variable defined in the file of package pkg with the given set of predicates. The exception Not_found is raised if the package or the variable could not be found. Other exceptions may occur as file I/O is done. Examples Get the value of the "requires" variable of package "p" with an empty set of predicates: Findlib.package_property [] "p" "requires" Get the value of the "archive" variable of package "p" for multi-threaded bytecode applications: Findlib.package_property [ "mt"; "byte" ] "p" "archive" <anchor id="Findlib.package-ancestors"> Findlib.package_ancestors <replaceable>predicates</replaceable> <replaceable>pkg</replaceable> val package_ancestors : string list -> string -> string list Determines the direct ancestors of package pkg for the set of predicates. The returned list has no specific order. The exception Not_found is raised if the package could not be found. The exception Failure is raised if one of the ancestors could not be found, or if a circular dependency has been detected. Other exceptions may occur as file I/O is done. <anchor id="Findlib.package-deep-ancestors"> Findlib.package_deep_ancestors <replaceable>predicates</replaceable> <replaceable>pkglist</replaceable> val package_deep_ancestors : string list -> string list -> string list Determines the list of direct or indirect ancestors of the packages in pkglist for the set of predicates. The returned list is topologically sorted. The exception Not_found is raised if the package could not be found. The exception Failure is raised if one of the ancestors could not be found, or if a circular dependency has been detected. Other exceptions may occur as file I/O is done. <anchor id="Findlib.default-location"> Findlib.default_location () val default_location : unit -> string Gets the default location where new packages will be installed. not-ocamlfind-0.14/local-packages/ocamlfind/doc/src/findlib_ocamlfind.mod0000644000175000017500000013525114770304423025515 0ustar stephsteph ocamlfind 1 The findlib package manager for OCaml ocamlfind [Command-line interface of the Package manager] SYNOPSIS ocamlfind query [-help | other options] package_name ... or: ocamlfind ocamlc [-help | other options] file ... or: ocamlfind ocamlcp [-help | other options] file ... or: ocamlfind ocamlmktop [-help | other options] file ... or: ocamlfind ocamlopt [-help | other options] file ... or: ocamlfind ocamldoc [-help | other options] file ... or: ocamlfind ocamldep [-help | other options] file ... or: ocamlfind ocamlmklib [-help | other options] file ... or: ocamlfind ocamlbrowser [-help | other options] or: ocamlfind install [-help | other options] package_name file ... or: ocamlfind remove [-help | other options] package_name or: ocamlfind lint META or: ocamlfind list [-describe] or: ocamlfind printppx [-help | other options] package_name ... or: ocamlfind printconf [ variable ] or: ocamlfind package/command arg ... Optional toolchain selection by: ocamlfind -toolchain name ... <anchor id="ocamlfind.query"> THE "query" SUBCOMMAND Synopsis ocamlfind query [ -predicates p | -format f | -long-format | -l | -i-format | -l-format | -a-format | -o-format | -p-format | -prefix p | -separator s | -suffix s | -pp | -descendants | -d | -recursive | -r -qe | -qo] package ... Description This command looks packages up, sorts them optionally, and prints attributes of them. If the option -recursive (short: -r) is not specified, exactly the packages given on the command line are looked up; if -recursive is present, the packages and all their ancestors, or if -descendants (short: -d) is present, too, all their descendants are printed. Package lookup and the selection of the attributes of the packages can be modified by specifying predicates; without a -predicates option the empty set of predicates is used. Note that even the lookup is influenced by the set of actual predicates as the "requires" variables may be conditional. What is printed about a package depends on the specified format; there are a number of options that modify the format. Some formats denote sets of values (such as -format %a), in which case multiple output records are printed for every package. (It is even possible to specify formats denoting the Cartesian product of sets, such as -format %a%o, but this does not make sense.) Before the first output record the prefix is printed, and the suffix after the last record. Between two records the separator is printed. Options -predicates p Sets the set of actual predicates. The argument p is a list of predicate names separated by commas and/or whitespace. If multiple -predicates options are given, the union of all specified sets is effectively used. -format f Sets the format to the string f. Characters preceded by a percent sign are interpreted as placeholders; all other characters mean themselves. The defined placeholders are listed below. The default format is "%d". -long-format or -l Sets the format such that all relevant variables are printed. -i-format Same as -format "-I %d", i.e. directory options for ocamlc are printed. -l-format Same as -format "-ccopt -L%d", i.e. directory options for the linker backend are printed. -a-format Same as -format "%+a", i.e. archive file names are printed. -o-format Same as -format "%o", i.e. linker options are printed. -p-format Same as -format "%p", i.e. package names are printed. -prefix p Sets the prefix that is printed before the first output record to the given string. The default prefix is the empty string. -suffix s Sets the suffix that is printed after the last output record to the given string. The default suffix is the empty string. -separator s Sets the separator that is printed between output records to the given string. The default separator is a linefeed character. -recursive or -r Not only the packages given on the command line are queried but also all ancestors or descendants. If the option -descendants is specified, too, the descendants are printed, otherwise the ancestors. The packages are topologically sorted. -descendants -d Instead of the ancestors the descendants of the given packages are queried. This option implies -recursive. -pp Query preprocessor packages (camlp4 syntax extensions). Normally it is not needed to set -predicates, except you need the archives (then add -predicates byte). This option implies -recursive. -qe Do not print most errors to stderr, just set the exit code -qo Do not print the regular output. Placeholders meaningful in the -format option %% Replaced by a single percent sign %p Replaced by the package name %d Replaced by the package directory %m Replaced by the path to the META file (new since findlib-1.6) %D Replaced by the package description %v Replaced by the version string %a Replaced by the archive filename. If there is more than one archive, a separate output record is printed for every archive. %+a Like %a, but the filenames are converted to absolute paths ("+" and "@" notations are resolved) %A Replaced by the list of archive filenames. %+A Like %A, but the filenames are converted to absolute paths ("+" and "@" notations are resolved) %o Replaced by one linker option. If there is more than one option, a separate output record is printed for every option. %O Replaced by the list of linker options. %(property) Replaced by the value of the property named in parentheses, or the empty string if not defined. <anchor id="ocamlfind.ocamlc"> <anchor id="ocamlfind.ocamlcp"> <anchor id="ocamlfind.ocamlopt"> <anchor id="ocamlfind.ocamlmktop"> THE SUBCOMMANDS "ocamlc", "ocamlcp", "ocamlopt", and "ocamlmktop" Synopsis ocamlfind ( ocamlc | ocamlcp | ocamlopt | ocamlmktop ) [ -package package-name-list | -linkpkg | -predicates pred-name-list | -dontlink package-name-list | -syntax pred-name-list | -ppopt camlp4-arg | -ppxopt package,arg | -dllpath-pkg package-name-list | -dllpath-all | -passopt arg | -passrest arg... | -only-show | standard-option ] file ... Description These subcommands are drivers for the compilers with the same names, i.e. "ocamlfind ocamlc" is a driver for "ocamlc", and so on. The subcommands understand all documented options of the compilers (here called standard-options), but also a few more options. If these subcommands are invoked only with standard options, they behave as if the underlying compiler had been called directly. The extra options modify this. Internally, these subcommands transform the given list of options and file arguments into an invocation of the driven compiler. This transformation only adds options and files, and the relative order of the options and files passed directly is unchanged. If there are -package options, additional directory search specifiers will be included ("-I", and "-ccopt -I"), such that files of all named packages and all ancestors can be found. The -linkpkg option causes that the packages listed in the -package options and all necessary ancestors are linked in. This means that the archive files implementing the packages are inserted into the list of file arguments. As the package database is queried a set of predicates is needed. Most predicates are set automatically, see below, but additional predicates can be given by a -predicates option. If there is a -syntax option, the drivers assume that a preprocessor is to be used. In this case, the preprocessor command is built first in a preprocessor stage, and this command is passed to the compiler using the -pp option. The set of predicates in the preprocessor stage is different from the set in the compiler/linker stage. Options for compiling and linking Here, only the additional options not interpreted by the compiler but by the driver itself, and options with additional effects are explained. Some options are only meaningful for the preprocessor call, and are explained below. -package package-name-list Adds the listed package names to the set of included packages. The package names may be separated by commas and/or whitespace. In the transformed command, for every package of the set of included packages and for any ancestor a directory search option is inserted after the already given options. This means that "-I" and "-ccopt -I" options are added for every package directory. -linkpkg Causes that in the transformed command all archives of the packages specified by -packages and all their ancestors are added to the file arguments. More precisely, these archives are inserted before the first given file argument. Furthermore, "-ccopt -L" options for all package directories, and the linker options of the selected packages are added, too. Note that the archives are inserted in topological order while the linker options are added in reverse toplogical order. -predicates pred-name-list Adds the given predicates to the set of actual predicates. The predicates must be separated by commas and/or whitespace. -dontlink package-name-list This option modifies the behaviour of -linkpkg. Packages specified here and all ancestors are not linked in. Again the packages are separated by commas and/or whitespace. -dllpath-pkg package-name-list For these packages -dllpath options are added to the compiler command. This may be useful when the ld.conf file is not properly configured. -dllpath-all For all linked packages -dllpath options are added to the compiler command. This may be useful when the ld.conf file is not properly configured. -passopt arg The argument arg is passed directly to the underlying compiler. This is needed to specify undocumented compiler options. -passrest arg... All following arguments arg... are passed directly to the underlying compiler. This is needed to specify undocumented compiler options. -only-show Only prints the constructed command (ocamlc/ocamlopt) to stdout, but does not execute the command. (This is for the unlikely event that you need a wrapper around ocamlfind.) -verbose This standard option is interpreted by the driver, too. -thread This standard option causes that the predicate "mt" is added to the set of actual predicates. If POSIX threads are available, the predicate "mt_posix" is selected, too. If only VM threads are available, the predicate "mt_vm" is included into the set, and the compiler switch is changed into -vmthread. Note that the presence of the "mt" predicate triggers special fixup of the dependency graph (see below). -vmthread This standard option causes that the predicates "mt" and "mt_vm" are added to the set of actual predicates. Note that the presence of the "mt" predicate triggers special fixup of the dependency graph (see below). -p This standard option of "ocamlopt" causes that the predicate "gprof" is added to the set of actual predicates. Options for preprocessing The options relevant for the preprocessor are the following: -package package-name-list These packages are considered while looking up the preprocessor arguments. (It does not cause problems that the same -package option is used for this purpose, because the set of predicates is different.) It is recommended to mention at least camlp4 here if the preprocessor is going to be used. -syntax pred-name-list These predicates are assumed to be true in addition to the standard preprocessor predicates. See below for a list. -ppopt camlp4-arg This argument is passed to the camlp4 call. -ppxopt package,arg Add arg to the ppx preprocessor invocation specified via the "ppx" property in the META file of package. Predicates for compiling and linking byte The "byte" predicate means that one of the bytecode compilers is used. It is automatically included into the predicate set if the "ocamlc", "ocamlcp", or "ocamlmktop" compiler is used. native The "native" predicate means that the native compiler is used. It is automatically included into the predicate set if the "ocamlopt" compiler is used. toploop The "toploop" predicate means that the toploop is available in the linked program. This predicate is only set when the toploop is actually being executed, not when the toploop is created (this changed in version 1.0.4 of findlib). create_toploop This predicate means that a toploop is being created (using ocamlmktop). mt The "mt" predicate means that the program is multi-threaded. It is automatically included into the predicate set if the -thread option is given. mt_posix The "mt_posix" predicate means that in the case "mt" is set, too, the POSIX libraries are used to implement threads. "mt_posix" is automatically included into the predicate set if the variable "type_of_threads" in the META description of the "threads" package has the value "posix". This is normally the case if "findlib" is configured for POSIX threads. mt_vm The "mt_vm" predicate means that in the case "mt" is set, too, the VM thread emulation is used to implement multi-threading. gprof The "gprof" predicate means that in the case "native" is set, too, the program is compiled for profiling. It is automatically included into the predicate set if "ocamlopt" is used and the -p option is in effect. autolink The "autolink" predicate means that ocamlc is able to perform automatic linking. It is automatically included into the predicate set if ocamlc knows automatic linking (from version 3.00), but it is not set if the -noautolink option is set. syntax This predicate is set if there is a -syntax option. It is set both for the preprocessor and the compiler/linker stage, and it can be used to find out whether the preprocessor is enabled or not. Predicates for preprocessing preprocessor This predicate is always set while looking up the preprocessor arguments. It can be used to distinguish between the preprocessor stage and the compiler/linker stage. syntax This predicate is set if there is a -syntax option. It is set both for the preprocessor and the compiler/linker stage, and it can be used to find out whether the preprocessor is enabled or not. camlp4o This is the reserved predicate for the standard OCaml syntax. It can be used in the -syntax predicate list. camlp4r This is the reserved predicate for the revised OCaml syntax. It can be used in the -syntax predicate list. Special behaviour of "ocamlmktop" As there is a special module Topfind that supports loading of packages in scripts, the "ocamlmktop" subcommand can add initialization code for this module. This extra code is linked into the executable if "findlib" is in the set of effectively linked packages. Fixup of the dependency graph for multi-threading For a number of reasons the presence of the "mt" predicate triggers that (1) the package "threads" is added to the list of required packages and (2) the package "threads" becomes prerequisite of all other packages (except of itself and a few hardcoded exceptions). The effect is that the options -thread and -vmthread automatically select the "threads" package, and that "threads" is inserted at the right position in the package list. Extended file naming At a number of places one can not only refer to files by absolute or relative path names, but also by extended names. These have two major forms: "+name" refers to the subdirectory name of the standard library directory, and "@name" refers to the package directory of the package name. Both forms can be continued by a path, e.g. "@netstring/netstring_top.cma". You can use extended names: (1) With -I options, (2) as normal file arguments of the compiler, (3) in the "archive" property of packages. How to set the names of the compiler executables Normally, the OCaml bytecode compiler can be called under the name ocamlc. However, this is not always true; sometimes a different name is chosen. You can instruct ocamlfind to call executables with other names than ocamlc, ocamlopt, ocamlmktop, and ocamlcp. If present, the environment variable OCAMLFIND_COMMANDS is interpreted as a mapping from the standard names to the actual names of the executables. It must have the following format: standardname1=actualname1 standardname2=actualname2 ... Example: You may set OCAMLFIND_COMMANDS as follows: OCAMLFIND_COMMANDS='ocamlc=ocamlc-3.00 ocamlopt=ocamlopt-3.00' export OCAMLFIND_COMMANDS Alternatively, you can change the configuration file findlib.conf. <anchor id="ocamlfind.ocamlmklib"> THE SUBCOMMAND "ocamlmklib" Synopsis ocamlfind ocamlmklib [ -package package-name-list | -predicates pred-name-list | -dllpath-pkg package-name-list | -dllpath-all | -passopt arg | -passrest arg... | standard-option ] file ... Description This is a wrapper around ocamlmklib, and creates library archives and DLLs. In addition to the standard options, one can use -package to add the search path of packages. Note that no predicates are set by default - the wrapper does not know whether this is about byte or native code linking. This wrapper is mostly provided for completeness. <anchor id="ocamlfind.ocamldep"> THE "ocamldep" SUBCOMMAND Synopsis ocamlfind ocamldep [-package package-name-list | -syntax pred-name-list | -ppopt camlp4-arg | -passopt arg | -passrest arg... | -verbose | standard-option] file ... Description This command is a driver for the tool ocamldep of the OCaml distribution. This driver is only useful in conjunction with the preprocessor camlp4; otherwise it does not provide more functions than ocamldep itself. Options Here, only the additional options not interpreted by ocamldep but by the driver itself, and options with additional effects are explained. -package package-name-list The packages named here are only used to look up the preprocessor options. The package camlp4 should be specified anyway, but further packages that add capabilities to the preprocessor can also be passed. -syntax pred-name-list The predicates that are in effect during the look-up of the preprocessor options. At least, either camlp4o (selecting the normal syntax), or camlp4r (selecting the revised syntax) should be specified. -ppopt camlp4-arg An option that is passed through to the camlp4 call. -passopt arg An option that is passed through to the ocamldep call. -passrest arg... All further arguments are passed down to ocamldep unprocessed -verbose Displays the resulting ocamldep command (for debugging) Example A typical way of using this driver: ocamlfind ocamldep -package camlp4,xstrp4 -syntax camlp4r file1.ml file2.ml This command outputs the dependencies of file1.ml and file2.ml, although these modules make use of the syntax extensions provided by xstrp4 and are written in revised syntax. <anchor id="ocamlfind.ocamlbrowser"> THE "ocamlbrowser" SUBCOMMAND Synopsis ocamlfind ocamlbrowser [-package package-name-list | -all | -passopt arg -passrest ] Description This driver calls the ocamlbrowser with package options. With -package, the specified packages are included into the search path of the browser, and the modules of these packages become visible (in addition to the standard library). The option -all causes that all packages are selected that are managed by findlib. As for other drivers, the options -passopt and -passrest can be used to pass arguments directly to the ocamlbrowser program. <anchor id="ocamlfind.ocamldoc"> THE SUBCOMMAND "ocamldoc" Synopsis ocamlfind ocamldoc [ -package package-name-list | -predicates pred-name-list | -syntax pred-name-list | -ppopt camlp4-arg | standard-option ] file ... Description This subcommand is a driver for ocamldoc. It undestands all options ocamldoc supports plus the mentioned findlib options. Basically, the -package options are translated into -I options, and the selected syntax options are translated into camlp4 options. Options Here, only the additional options not interpreted by ocamldep but by the driver itself, and options with additional effects are explained. -package package-name-list Adds the listed package names to the set of included packages. The package names may be separated by commas and/or whitespace. In the transformed command, for every package of the set of included packages and for any ancestor a directory search option is inserted after the already given options. This means that "-I" options are added for every package directory. -predicates pred-name-list Adds the given predicates to the set of actual predicates. The predicates must be separated by commas and/or whitespace. -syntax pred-name-list The predicates that are in effect during the look-up of the preprocessor options. At least, either camlp4o (selecting the normal syntax), or camlp4r (selecting the revised syntax) should be specified. -ppopt camlp4-arg An option that is passed through to the camlp4 call. <anchor id="ocamlfind.install"> THE "install" SUBCOMMAND Synopsis ocamlfind install [ -destdir directory ] [ -metadir directory ] [ -ldconf path ] [ -dont-add-directory-directive ] [ -patch-version string ] [ -patch-rmpkg name ] [ -patch-archives ] [ -dll ] [ -nodll ] [ -optional ] [ -add ] package_name file ... Description This subcommand installs a new package either at the default location (see the variable destdir of findlib.conf), or in the directory specified by the -destdir option. This means that a new package directory is created and that the files on the command line are copied to this directory. It is required that a META file is one of the files copied to the target directory. Note that package directories should be flat (no subdirectories). Existing packages are never overwritten. It is possible to have a separate directory for all the META files. If you want that, you have either to set the variable metadir of findlib.conf, or to specify the -metadir option. In this case, the file called META is copied to the specified directory and renamed to META.p (where p is the package name), while all the other files are copied to the package directory as usual. Furthermore, the META file is modified such that the directory variable contains the path of the package directory. The option -dont-add-directory-directive prevents the installer from adding a directory variable. If there are files ending in the suffixes .so or .dll, the package directory will be added to the DLL configuration file ld.conf, such that the dynamic loader can find the DLL. The location of this file can be overridden by the -ldconf option. To turn this feature off, use "-ldconf ignore"; this causes that the ld.conf file is not modified. However, if there is a stublibs directory in site-lib, the DLLs are not installed in the package directory, but in this directory that is shared by all packages that are installed at the same location. In this case, the configuration file ld.conf is not modified, so you do not need to say "-ldconf ignore" if you prefer this style of installation. The options -dll and -nodll can be used to control exactly which files are considered as DLLs and which not. By default, the mentioned suffix rule is in effect: files ending in ".so" (Unix) or ".dll" (Windows) are DLLs. The switch -dll changes this, and all following files are considered as DLLs, regardless of their suffix. The switch -nodll expresses that the following files are not DLLs, even if they have a DLL-like suffix. For example, in the following call the files f1 and f2 are handled by the suffix rule; f3 and f4 are DLLs anyway; and f5 and f6 are not DLLs: ocamlfind install p f1 f2 -dll f3 f4 -nodll f5 f6 The switch -optional declares that all following files are optional, i.e. the command will not fail if files do not exist. The -patch options may be used to change the contents of the META files while it is being installed. The option -patch-version changes the contents of the top-level "version" variable. The option -patch-rmpkg removes the given subpackage. The option -patch-archives is experimental, in particular it removes all non-existing files from "archive" variables, and even whole subpackages if the archives are missing. The effect of -add is to add further files to an already installed packages. <anchor id="ocamlfind.remove"> THE "remove" SUBCOMMAND Synopsis ocamlfind remove [ -destdir directory ] [ -metadir directory ] [ -ldconf path ] package_name Description The package will removed if it is installed at the default location (see the variable destdir of findlib.conf). If the package resides at a different location, it will not be removed by default; however, you can pass an alternate directory for packages by the -destdir option. (This must be the same directory as specified at installation time.) Note that package directories should be flat (no subdirectories); this subcommand cannot remove deep package directories. If you have a separate directory for META files, you must either configure this directory by the metadir variable of findlib.conf, or by specifying the -metadir option. The command does not fail if the package and/or the META file cannot be located. You will get a warning only in this case. If the package directory is mentioned in the ld.conf configuration file for DLLs, it will be tried to remove this entry from the file. The location of this file can be overridden by the -ldconf option. To turn this feature off, use "-ldconf ignore"; this causes that the ld.conf file is not modified. If there is a stublibs directory, it is checked whether the package owns any of the files in this directory, and the owned files will be deleted. <anchor id="ocamlfind.list"> THE "list" SUBCOMMAND Synopsis ocamlfind list [-describe] Description This command lists all packages in the search path. The option -describe outputs the package descriptions, too. <anchor id="ocamlfind.printppx"> THE "printppx" SUBCOMMAND Synopsis ocamlfind printppx [ -predicates pred-name-list ] [ -ppxopt package,arg ] package ... Description This command prints the ppx preprocessor options as they would occur in an OCaml compiler invocation for the packages listed in the command. The output includes one "-ppx" option for each preprocessor. The possible options have the same meaning as for "ocamlfind ocamlc". The option "-predicates" adds assumed predicates and "-ppxopt package,arg" adds "arg" to the ppx invocation of package package. The output of "ocamlfind printppx" will contain quotes """ for ppx commands that contain space-separated arguments. In this case $(ocamlfind printppx ...) won't work as naively expected, because many shells (including bash and dash) perform field splitting on the result of command substitutions without honoring quotes. <anchor id="ocamlfind.lint"> THE "lint" SUBCOMMAND Synopsis ocamlfind lint file Description Checks the META file, and reports possible problems. <anchor id="ocamlfind.printconf"> THE "printconf" SUBCOMMAND Synopsis ocamlfind printconf [ conf | path | destdir | metadir | metapath | stdlib | ldconf ] Description This command prints the effective configuration after reading the configuration file, and after applying the various environment variables overriding settings. When called without arguments, the command prints all configuration options in a human-readable form. When called with an argument, only the value of the requested option is printed without explaining texts: conf Prints the location of the configuration file findlib.conf path Prints the search path for packages. The members of the path are separated by linefeeds. destdir Prints the location where package are installed and removed by default. metadir Prints the location where META files are installed and removed (if the alternative layout is used). metapath Prints the path where the META file is installed for a fictive package. The name of the package is marked with '%s' in the path. For instance, this command could output "/some/path/%s/META" or "/some/path/META.%s", depending on the layout. stdlib Prints the location of the standard library. ldconf Prints the location of the ld.conf file <anchor id="ocamlfind.pkgcmd"> THE SUBCOMMAND CALLING PACKAGE PROGRAMS Synopsis ocamlfind pkg/cmd argument ... Description This subcommand is useful to call programs that are installed in package directories. It looks up the directory for pkg and calls the command named cmd in this directory. The remaining arguments are passed to this command. argv(0) contains the absolute path to the command, and argv(1) and the following argv entries contain the arguments. The working directory is not changed. Example: To call the program "x" that is installed in package "p", with arguments "y" and "z", run: ocamlfind p/x y z CONFIGURATION FILE, ENVIRONMENT VARIABLES The configuration file and environment variables are documented in the manual page for findlib.conf. <anchor id="ocamlfind.toolchain"> HOW TO SET THE TOOLCHAIN Synopsis ocamlfind -toolchain name ... Description The -toolchain option can be given before any other command, e.g. ocamlfind -toolchain foo ocamlc -c file.ml compiles file.ml with toolchain "foo". By selecting toolchains one can switch to different command sets. For instance, the toolchain "foo" may consist of a patched ocamlc compiler. See findlib.conf how to configure toolchains. not-ocamlfind-0.14/local-packages/ocamlfind/doc/src/findlib_ref.dsl0000644000175000017500000000107214770304423024331 0ustar stephsteph ]> (define %footnotes-at-end% ;; Should footnotes appear at the end of HTML pages? #t) (define %html-ext% ;; Default extension for HTML output files ".html") (define %root-filename% ;; Name for the root HTML document "index") not-ocamlfind-0.14/local-packages/ocamlfind/doc/src/findlib_ref.sgml0000644000175000017500000000234414770304423024514 0ustar stephsteph %gps.common; ]> The findlib Reference Manual Gerd Stolpmann
gerd@gerd-stolpmann.de
1999-2003Gerd Stolpmann
Commands &findlibocamlfind; Files &findlibmeta; &findlibconf; &findlibsitelib; Library The findlib library The findlib library
not-ocamlfind-0.14/local-packages/ocamlfind/doc/src/findlib_reference.sgml0000644000175000017500000000077114770304423025700 0ustar stephsteph ]> Reference &findlibocamlfind; &findlibmeta; &findlibconf; &findlibsitelib; not-ocamlfind-0.14/local-packages/ocamlfind/doc/src/findlib_sitelib.mod0000644000175000017500000001136214770304423025210 0ustar stephsteph site-lib 5 The findlib package manager for OCaml site-lib [Location of package directories] STANDARD LAYOUT ...somewhere in the filesystem hierarchy... | \ site-lib | +- (optional) stublibs +- (optional) postinstall +- (optional) postremove | +- package1 | | | +- META | +- archive files | +- interface definitions | +- package2 + : : \ packageN DESCRIPTION Every installation of "findlib" has a default location for package directories, which is normally a directory called "site-lib". The location can be set by the configuration variables path (used to look up packages), and destdir (used to install new packages); see findlib.conf. The name of a package is the name of the package directory. For example, if destdir=/usr/local/lib/ocaml/site-lib, the package p will be installed in the subdirectory /usr/local/lib/ocaml/site-lib/p. This subdirectory must contain the META file and all other files belonging to the package. Package names must not contain the '.' character. The variable destdir specifies the directory for new packages. You can only have one such directory at a time; but of course you can change this directory in findlib.conf. The command ocamlfind install puts new packages into this directory; it is recommended to use this command for installation because it ensures that the directory layout is right. For searching packages, findlib uses (only) the variable path which may name several locations to look at. For systems with DLL support another directory may exist: stublibs. If present, findlib will install DLLs into this directory that is shared by all packages at the same site-lib location. Findlib remembers which DLL belongs to which package by special files with the suffix ".owner"; e.g. for the DLL "dllpcre.so" there is another file "dllpcre.so.owner" containing the string "pcre", so findlib knows that the package "pcre" owns this DLL. It is not possible that a DLL is owned by several packages. If the stublibs directory does not exist, DLLs are installed regularly in the package directories like any other file. For special needs, a postinstall and/or a postremove script may be installed in the site-lib directory. These scripts are invoked after installation or removal of a package, respectively. ALTERNATE LAYOUT ...somewhere in the filesystem hierarchy... | \ site-lib | +- (optional) stublibs +- (optional) postinstall +- (optional) postremove | +- package1 | | | +- archive files | +- interface definitions | +- package2 + : : \ : packageN | \ metaregistry | +- META.package1 +- META.package2 + : \ META.packageN This is an alternate directory layout collecting all META files in one directory. You can configure this layout by setting path to the absolute location of metaregistry. Findlib recognizes that there are META files in this directory and uses them; it is not necessary to include site-lib into the path. In order to work, the META files must contain a directory directive pointing to the corresponding package directory that resides below site-lib. The command ocamlfind install copes with this layout, too. The variable destdir must contain the absolute location of site-lib, and the variable metadir must contain the absolute location of metaregistry. Note that ocamlfind install automatically adds a directory directive to the META file, so you need not do it manually. not-ocamlfind-0.14/local-packages/ocamlfind/doc/src/findlib_topfind.mod0000644000175000017500000002120314770304423025213 0ustar stephsteph Topfind 3 The findlib package manager for OCaml Topfind [Module to load packages into toploops] SIGNATURE module Topfind : sig end DIRECTIVES PACKAGING The Topfind module is part of the "findlib" package. The module depends on the presence of a toploop. When building a toploop, it is automatically linked in if "findlib" is linked in, e.g. ocamlfind ocamlmktop options -package findlib -linkpkg options When the platform supports DLLs, another possibility to get a toploop with findlib directives is to load the file "topfind" (normally installed in the standard library directory): ~ > ocaml Objective Caml version 3.04 # #use "topfind";; 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) Topfind.reset();; to force that packages will be reloaded - : unit = () # _ This works even in scripts (but the startup message is suppressed in this case). The module is not thread-safe; if used in a multi-threaded script, all packgage loading must have happened before the first thread forks. DESCRIPTION The Topfind module contains some functions simplifying package loading in scripts. Most important, there is a new directive "#require" for the same purpose. The Topfind module needs some initialization, in particular the predicates variable needs to be set, and the packages already compiled into the toploop needs to be declared by the don't_load function. If the toploop has been built by , the necessary initialization is automatically compiled in. <anchor id="Topfind.predicates"> The variable Topfind.predicates val predicates : string list ref The variable contains the set of predicates that is assumed when packages are loaded. <anchor id="Topfind.add-predicates"> Topfind.add_predicates <replaceable>predlist</replaceable> val add_predicates : string list -> unit This function adds the passed predicates predlist to the variable predicates. <anchor id="Topfind.syntax"> Topfind.syntax <replaceable>variant</replaceable> val syntax : string -> unit This function emulates the -syntax command line switch of ocamlfind. <anchor id="Topfind.standard-syntax"> Topfind.standard_syntax () val standard_syntax : unit -> unit The same as syntax "camlp4o". <anchor id="Topfind.revised-syntax"> Topfind.revised_syntax () val revised_syntax : unit -> unit The same as syntax "camlp4r". <anchor id="Topfind.dont-load"> Topfind.don't_load <replaceable>pkglist</replaceable> val don't_load : string list -> unit Declares the packages enumerated in pkglist as being linked into the toploop. <anchor id="Topfind.dont-load-deeply"> Topfind.don't_load_deeply <replaceable>pkglist</replaceable> val don't_load_deeply : string list -> unit Declares the packages enumerated in pkglist and all direct and indirect ancestors as being linked into the toploop. <anchor id="Topfind.load"> Topfind.load <replaceable>pkglist</replaceable> val load : string list -> unit The packages enumerated in pkglist are loaded in turn; packages that have already been loaded or that have been declared as linked in are skipped. <anchor id="Topfind.load-deeply"> Topfind.load_deeply <replaceable>pkglist</replaceable> val load_deeply : string list -> unit The packages enumerated in pkglist and all direct or indirect ancestors are loaded in topological order; packages that have already been loaded or that have been declared as linked in are skipped. <anchor id="Topfind.reset"> Topfind.reset () val reset : unit -> unit This function causes that Topfind forgets that any package has already been loaded. Information about packages linked into the toploop remain intact. The effect of this function is that all dynamically loaded packages will be loaded again when load, load_deeply functions, or the #require directive are executed. <anchor id="Topfind.require"> #require "<replaceable>package-name-list</replaceable>";; #require "package-name-list";; The argument of the directive is a list of package names, separated by commas and/or whitespace. The directive has the same effect as load_deeply, i.e. the listed packages and all direct or indirect ancestors are loaded in topological order; packages that have already been loaded or that have been declared as linked in are skipped. <anchor id="Topfind.camlp4o"> #camlp4o ;; #camlp4o ;; Selects the standard syntax and loads the camlp4 preprocessor. <anchor id="Topfind.camlp4r"> #camlp4r ;; #camlp4r ;; Selects the revised syntax and loads the camlp4 preprocessor. <anchor id="Topfind.list"> #list ;; #list ;; Lists the packages that are in the search path. not-ocamlfind-0.14/local-packages/ocamlfind/findlib-ppc.patch0000644000175000017500000001456414770304423023250 0ustar stephstephdiff -ur --unidirectional-new-file findlib-1.1.2pl1/Makefile findlib-1.1.2pl1.modify/Makefile --- findlib-1.1.2pl1/Makefile 2006-01-17 10:04:50.000000000 +1100 +++ findlib-1.1.2pl1.modify/Makefile 2006-10-23 11:50:38.000000000 +1000 @@ -17,12 +17,15 @@ for p in $(PARTS); do ( cd src/$$p; $(MAKE) opt ); done install: + mkdir -p $(prefix)$(OCAMLFIND_BIN) + mkdir -p $(prefix)$(OCAMLFIND_LIB) + mkdir -p $(prefix)$(OCAMLFIND_MAN) for p in $(PARTS); do ( cd src/$$p; $(MAKE) install ); done $(MAKE) install-doc $(MAKE) install-meta cd src/findlib; $(MAKE) install-num-top $(MAKE) install-config - cp tools/safe_camlp4 $(OCAMLFIND_BIN) + cp tools/safe_camlp4 $(prefix)$(OCAMLFIND_BIN) uninstall: $(MAKE) uninstall-doc @@ -30,12 +33,26 @@ for p in `cd src; echo *`; do ( cd src/$$p; $(MAKE) uninstall ); done $(MAKE) uninstall-config -clean: +clean: clean-macosx for p in `cd src; echo *`; do ( cd src/$$p; $(MAKE) clean ); done (cd itest-aux; $(MAKE) clean) (cd tools/extract_args; $(MAKE) clean) rm -f findlib.conf +# Make MacOS X package + +.PHONY: package-macosx + +package-macosx: all opt + mkdir -p package-macosx/root + export prefix=`pwd`/package-macosx/root && make install + export VERSION=1.1.2 && tools/make-package-macosx + #rm -rf package-macosx/root + +clean-macosx: + sudo rm -rf package-macosx + #rm -rf package-macosx/*.pkg package-macosx/*.dmg + .PHONY: release release: README ./release diff -ur --unidirectional-new-file findlib-1.1.2pl1/configure findlib-1.1.2pl1.modify/configure --- findlib-1.1.2pl1/configure 2006-01-17 10:04:49.000000000 +1100 +++ findlib-1.1.2pl1.modify/configure 2006-10-23 11:50:43.000000000 +1000 @@ -427,6 +427,7 @@ echo "EXEC_SUFFIX=${exec_suffix}" >>Makefile.config echo "PARTS=${parts}" >>Makefile.config echo "INSTALL_TOPFIND=${with_topfind}" >>Makefile.config +echo "VERSION=${version}" >> Makefile.config # All OK diff -ur --unidirectional-new-file findlib-1.1.2pl1/tools/make-package-macosx findlib-1.1.2pl1.modify/tools/make-package-macosx --- findlib-1.1.2pl1/tools/make-package-macosx 1970-01-01 10:00:00.000000000 +1000 +++ findlib-1.1.2pl1.modify/tools/make-package-macosx 2006-10-23 11:50:52.000000000 +1000 @@ -0,0 +1,119 @@ +#!/bin/sh + +######################################################################### +# # +# Objective Caml # +# # +# Damien Doligez, projet Moscova, INRIA Rocquencourt # +# # +# Copyright 2003 Institut National de Recherche en Informatique et # +# en Automatique. All rights reserved. This file is distributed # +# under the terms of the Q Public License version 1.0. # +# # +######################################################################### + +# $Id: make-package-macosx,v 1.10.2.2 2006/01/04 13:05:49 doligez Exp $ +# adapted to findlib by Pietro.Abate + +set -x + +cd package-macosx +rm -rf findlib.pkg findlib-rw.dmg +mkdir -p resources + +cat >Description.plist < + + + + IFPkgDescriptionDeleteWarning + + IFPkgDescriptionDescription + The findlib library manager + IFPkgDescriptionTitle + Findlib + IFPkgDescriptionVersion + ${VERSION} + + +EOF + +cat >Info.plist < + + + + CFBundleGetInfoString + The findlib library manager ${VERSION} + CFBundleIdentifier + http://www.ocaml-programming.de/packages/ + CFBundleName + Findlib + CFBundleShortVersionString + ${VERSION} + IFPkgFlagAllowBackRev + + IFPkgFlagAuthorizationAction + AdminAuthorization + IFPkgFlagDefaultLocation + / + IFPkgFlagInstallFat + + IFPkgFlagIsRequired + + IFPkgFlagRelocatable + + IFPkgFlagRestartAction + NoRestart + IFPkgFlagRootVolumeOnly + + IFPkgFlagUpdateInstalledLanguages + + IFPkgFormatVersion + 0.10000000149011612 + + +EOF + +# stop here -> | +cat >resources/ReadMe.txt <&2 + exit 3 +fi +open "/Volumes/Findlib" +hdiutil detach $name + +rm -rf "findlib-${VERSION}.dmg" +hdiutil convert findlib-rw.dmg -format UDZO -o "findlib-${VERSION}.dmg" not-ocamlfind-0.14/local-packages/ocamlfind/findlib.conf.in0000644000175000017500000000005214770304423022706 0ustar stephstephdestdir="@SITELIB@" path="@FINDLIB_PATH@" not-ocamlfind-0.14/local-packages/ocamlfind/findlib.files0000644000175000017500000000670614770304423022472 0ustar stephsteph# SYNTAX OF findlib.files: # # d DIRPATH # # include this subdirectory # # f FILEPATH # # include this file (or symlink) # # x FILEPATH # # exclude this file # # p DIRPATH/FILEPATTERN # # include all files of the directory that match the regular expression # FILEPATTERN (Str-type regexp) # # w DIRPATH/FILEPATTERN # # output a warning if one of the matching files matches # # Exclusions must be mentioned before inclusions. f configure f opam f ocamlfind.install f findlib.conf.in f INSTALL f LICENSE f Makefile f Makefile.config.pattern f itest f ocaml-stub d itest-aux f itest-aux/Makefile p itest-aux/.*\.ml d mini f mini/README f mini/ocamlfind-mini d tools f tools/collect_files f tools/file_exists d tools/extract_args f tools/extract_args/Makefile f tools/extract_args/extract_args.mll f tools/safe_camlp4 f tools/make-package-macosx f tools/patch f tools/cmd_from_same_dir d site-lib-src d site-lib-src/bigarray f site-lib-src/bigarray/META.in f site-lib-src/bigarray/interfaces.in d site-lib-src/camlp4.309 f site-lib-src/camlp4.309/META.in d site-lib-src/camlp4.310 f site-lib-src/camlp4.310/META.in d site-lib-src/dbm f site-lib-src/dbm/META.in f site-lib-src/dbm/interfaces.in d site-lib-src/dynlink f site-lib-src/dynlink/META.in f site-lib-src/dynlink/interfaces.in d site-lib-src/graphics f site-lib-src/graphics/META.in f site-lib-src/graphics/interfaces.in d site-lib-src/labltk f site-lib-src/labltk/META.in f site-lib-src/labltk/interfaces.in d site-lib-src/num f site-lib-src/num/META.in f site-lib-src/num/interfaces.in d site-lib-src/num-top f site-lib-src/num-top/META.in d site-lib-src/stdlib f site-lib-src/stdlib/META.in f site-lib-src/stdlib/interfaces.in d site-lib-src/str f site-lib-src/str/META.in f site-lib-src/str/interfaces.in d site-lib-src/threads f site-lib-src/threads/META.in f site-lib-src/threads/interfaces.in d site-lib-src/unix f site-lib-src/unix/META.in f site-lib-src/unix/interfaces.in d site-lib-src/ocamlbuild f site-lib-src/ocamlbuild/META.in d site-lib-src/ocamldoc f site-lib-src/ocamldoc/META.in d site-lib-src/compiler-libs f site-lib-src/compiler-libs/META.in d site-lib-src/bytes f site-lib-src/bytes/META.in f site-lib-src/bytes/interfaces.in d site-lib-src/raw_spacetime f site-lib-src/raw_spacetime/interfaces.in f site-lib-src/raw_spacetime/META.in d src d src/findlib f src/findlib/Makefile f src/findlib/META.in f src/findlib/findlib_config.mlp f src/findlib/topfind.ml.in x src/findlib/fl_meta.ml x src/findlib/findlib_config.ml x src/findlib/ocaml_args.ml x src/findlib/topfind.ml f src/findlib/topfind.in p src/findlib/.*\.ml p src/findlib/.*\.mli p src/findlib/.*\.mll p src/findlib/.*\.src p src/findlib/.*\.p d src/findlib-toolbox f src/findlib-toolbox/Makefile f src/findlib-toolbox/make_wizard.ml f src/findlib-toolbox/make_wizard.pattern d src/bytes f src/bytes/Makefile f src/bytes/README f src/bytes/bytes.ml f src/bytes/META d doc f doc/DOCINFO f doc/QUICKSTART f doc/README p doc/.*\.xml p doc/.*\.dtd f doc/Makefile d doc/guide-html f doc/guide-html/index.html p doc/guide-html/.*\.html f doc/guide-html/TIMESTAMP d doc/ref-html d doc/ref-html/lib f doc/ref-html/index.html p doc/ref-html/.*\.html f doc/ref-html/TIMESTAMP f doc/ref-html/lib/index.html p doc/ref-html/lib/.*\.html p doc/ref-html/lib/.*\.css d doc/ref-man f doc/ref-man/ocamlfind.1 f doc/ref-man/findlib.conf.5 f doc/ref-man/META.5 f doc/ref-man/site-lib.5 f doc/ref-man/TIMESTAMP d doc/src p doc/src/.*\.dsl p doc/src/.*\.mod p doc/src/.*\.sgml p doc/src/.*\.xml not-ocamlfind-0.14/local-packages/ocamlfind/itest0000755000175000017500000000435414770304423021112 0ustar stephsteph#! /bin/sh # $Id$ # ---------------------------------------------------------------------- # case `uname` in CYGWIN*) execsuffix=.exe ;; *) execsuffix= ;; esac ocamlfind="src/findlib/ocamlfind${execsuffix}" PATH="./tools:$PATH" export PATH check_linkage () { p=$1 shift rm -f itest-aux/simple $ocamlfind ocamlc -linkall -linkpkg -custom "$@" -o itest-aux/simple itest-aux/simple_$p.ml >itest-aux/err.out 2>&1 output=`cat itest-aux/err.out | sed -e '/WARNING.*/ d'` error=0 if [ -n "$output" ]; then echo "* When trying to compile with" echo " $ocamlfind ocamlc -linkall -linkpkg -custom "$@" -o itest-aux/simple itest-aux/simple_$p.ml" echo " an error has occurred. The error error message has been written" echo " to itest-aux/err.out." error=1 fi if [ "$error" = "0" ]; then result=`itest-aux/simple${execsuffix}` [ "x$result" = "xOK" ] else return $error fi } problems () { echo "* This test failed. Please check the settings in site-lib-src/$1/META," echo " especially the 'linkopts' variable, and try again. You can invoke" echo " this test directly by: ./itest $1" } do_test () { case "$1" in dbm|graphics|num|str|unix|bigarray|labltk) echo "* Checking linker options for $1 library" rm -f itest-aux/testdb* if check_linkage $1 -package $1; then echo "ok" else problems $1 fi ;; threads) echo "* Checking linker options for threads library" if check_linkage $1 -package $1 -thread; then echo "ok" else problems $1 fi ;; camlp4) echo "* Checking options for camlp4 preprocessor" if check_linkage $1 -package $1 -syntax camlp4r; then echo "ok" else problems $1 fi ;; *) echo "unknown test: $1" ;; esac } OCAMLPATH="./site-lib-src" export OCAMLPATH if [ ! -f "$ocamlfind" ]; then echo "Sorry, you must first compile the library before you can invoke" 1>&2 echo "the integration test." 1>&2 exit 1 fi if [ "$#" = "0" ]; then for t in unix str dbm graphics num threads bigarray labltk camlp4; do if [ -f "site-lib-src/$t/META" ]; then echo "------------------------------------------------------------------------------" do_test $t echo fi done else do_test $1 fi not-ocamlfind-0.14/local-packages/ocamlfind/itest-aux/0002755000175000017500000000000014770304423021753 5ustar stephstephnot-ocamlfind-0.14/local-packages/ocamlfind/itest-aux/Makefile0000644000175000017500000000016114770304423023407 0ustar stephstephall: clean: rm -f simple simple.exe *.cmi *.cmo *.cma *.cmx *.o *.obj *.a *.lib rm -f err.out rm -f testdb* not-ocamlfind-0.14/local-packages/ocamlfind/itest-aux/os_type.ml0000644000175000017500000000003514770304423023763 0ustar stephstephprint_endline Sys.os_type ;; not-ocamlfind-0.14/local-packages/ocamlfind/itest-aux/ppx.ml0000644000175000017500000000003414770304423023107 0ustar stephstephToploop.preprocess_phrase;; not-ocamlfind-0.14/local-packages/ocamlfind/itest-aux/remdir.ml0000644000175000017500000000003114770304423023557 0ustar stephsteph#remove_directory ".";; not-ocamlfind-0.14/local-packages/ocamlfind/itest-aux/simple.ml0000644000175000017500000000002714770304423023573 0ustar stephstephprint_string "OK\n";; not-ocamlfind-0.14/local-packages/ocamlfind/itest-aux/simple_bigarray.ml0000644000175000017500000000015714770304423025457 0ustar stephstephopen Bigarray.Array1;; let a = create Bigarray.int Bigarray.c_layout 4 in a.{0} <- 5 ;; print_endline "OK";; not-ocamlfind-0.14/local-packages/ocamlfind/itest-aux/simple_camlp4.ml0000644000175000017500000000010114770304423025024 0ustar stephsteph(* This is revised syntax: *) value x = 1; print_endline "OK"; not-ocamlfind-0.14/local-packages/ocamlfind/itest-aux/simple_camltk.ml0000644000175000017500000000014314770304423025125 0ustar stephstephopen Tk;; let top = openTk() in Frx_after.idle closeTk; mainLoop() ;; print_string "OK\n" ;; not-ocamlfind-0.14/local-packages/ocamlfind/itest-aux/simple_dbm.ml0000644000175000017500000000024714770304423024421 0ustar stephsteph(try Sys.remove "itest-aux/testdb.db" with _ -> ()); let _ = Dbm.opendbm "itest-aux/testdb" [ Dbm.Dbm_rdwr; Dbm.Dbm_create ] 0o777 in print_string "OK\n";; not-ocamlfind-0.14/local-packages/ocamlfind/itest-aux/simple_graphics.ml0000644000175000017500000000006014770304423025450 0ustar stephstephGraphics.open_graph ""; print_string "OK\n";; not-ocamlfind-0.14/local-packages/ocamlfind/itest-aux/simple_labltk.ml0000644000175000017500000000012014770304423025116 0ustar stephstephopen Tk;; let _ = openTk() in update(); closeTk() ;; print_string "OK\n" ;; not-ocamlfind-0.14/local-packages/ocamlfind/itest-aux/simple_num.ml0000644000175000017500000000006414770304423024453 0ustar stephstephlet _ = Num.num_of_int 5 in print_string "OK\n";; not-ocamlfind-0.14/local-packages/ocamlfind/itest-aux/simple_str.ml0000644000175000017500000000006314770304423024463 0ustar stephstephlet _ = Str.regexp ".*" in print_string "OK\n";; not-ocamlfind-0.14/local-packages/ocamlfind/itest-aux/simple_threads.ml0000644000175000017500000000037614770304423025314 0ustar stephstephlet tl = List.map (fun _ -> Thread.create (fun () -> for i = 1 to 1000 do let _ = 1+1 in () done) ()) [ (); (); (); (); () ] in List.iter Thread.join tl ;; print_string "OK\n";; not-ocamlfind-0.14/local-packages/ocamlfind/itest-aux/simple_unix.ml0000644000175000017500000000006114770304423024634 0ustar stephstephlet _ = Unix.getpid() in print_string "OK\n";; not-ocamlfind-0.14/local-packages/ocamlfind/mini/0002755000175000017500000000000014770304423020764 5ustar stephstephnot-ocamlfind-0.14/local-packages/ocamlfind/mini/README0000644000175000017500000000662414770304423021652 0ustar stephsteph---------------------------------------------------------------------- ocamlfind-mini ---------------------------------------------------------------------- ocamlfind-mini is an OCaml script that implements a subset of the full functionality of ocamlfind. It consists only of one file, so it is easy to distribute it with any software. The subset is normally sufficient to compile a library and to install the library; but it is insufficient to link the library into an executable. ---------------------------------------------------------------------- SUPPORTED OPERATING SYSTEMS: ---------------------------------------------------------------------- For Unixes, the script runs out of the box. It uses the ocaml system found in the command path. I think the script also runs in Windows, but I have not yet checked that. Anyway, you cannot call it directly, but by doing ocaml ocamlfind-mini ... Macintosh is not supported; I don't have enough knowledge for a Mac port. ---------------------------------------------------------------------- FUNCTIONALITY: ---------------------------------------------------------------------- Overall: The configuration file ocamlfind.conf is ignored. However, some environment variables are respected (see below). A package directory is recognized by checking whether there is a META file in it. However, the contents of that file are ignored. The following subset has been implemented: - ocamlfind-mini [ocamlc|ocamlopt|ocamlcp|ocamlmktop] ... The -package option works, but you must set the environment variable OCAMLPATH (see below). The options -linkpkg, -predicates, -dontlink, -syntax, -ppopt are rejected. This normally means that you can compile modules as in: ocamlfind-mini ocamlc -c -package p1,p2,p3 my_module.ml However, you cannot create executables because -linkpkg is not supported. Note that ocamlfind-mini is unable to figure out the prerequisite packages, so the -package option must enumerate _all_ needed packages. Note that ocamlfind-mini does not support the alternate directory layout where all META files are collected in one directory. - ocamlfind-mini install ... Installs the files in the package directory for . You must help ocamlfind-mini by specifying the destination directory: * Setting the -destdir option: ocamlfind-mini install -destdir ... This command installs the new package into /. * Setting the OCAMLFIND_DESTDIR variable: export OCAMLFIND_DESTDIR= ocamlfind-mini install ... This command installs the new package into /, too. - ocamlfind-mini remove Removes the package . Again, you must specify the destination directory by either setting the -destdir option or by setting the OCAMLFIND_DESTDIR variable. ---------------------------------------------------------------------- ENVIRONMENT: ---------------------------------------------------------------------- The following variables are supported: - OCAMLPATH A colon (Win: semicolon)-separated list of directories: OCAMLPATH=::... When ocamlfind-mini searches a package , it checks whether //META exists for K=1, 2, ... - OCAMLFIND_DESTDIR The destination directory for "install" and "remove". - OCAMLFIND_METADIR The destination directory for META files. It is not recommended to set this variable. not-ocamlfind-0.14/local-packages/ocamlfind/mini/ocamlfind-mini0000755000175000017500000006022014770304423023576 0ustar stephsteph#! /bin/sh # (* exec ocaml "$0" "$@" *) directory ".";; (* $Id$ * ---------------------------------------------------------------------- * *) (**********************************************************************) (* Module split, rev. 1.2 *) module Split = struct let in_words s = (* splits s in words separated by commas and/or whitespace *) let l = String.length s in let rec split i j = if j < l then match s.[j] with (' '|'\t'|'\n'|'\r'|',') -> if i split i (j+1) else if i if i split i (j+1) else if i ':' | "Cygwin" -> ';' (* You might want to change this *) | "Win32" -> ';' | "MacOS" -> failwith "Findlib: I do not know what is the correct path separator for MacOS. If you can help me, write a mail to gerd@gerd-stolpmann.de" | _ -> failwith "Findlib: unknown operating system" ;; let path str = (* split "str" into parts separated by "path_separator" *) let l = String.length str in let rec split_up j k = if k < l then begin let c = str.[k] in if c = path_separator then begin if k - j > 0 then String.sub str j (k-j) :: split_up (k+1) (k+1) else split_up (k+1) (k+1) end else split_up j (k+1) end else if k - j > 0 then [ String.sub str j (k-j) ] else [] in split_up 0 0 ;; end;; (**********************************************************************) exception Usage;; type mode = M_use | M_query | M_install | M_remove | M_compiler of string | M_printconf | M_guess | M_list ;; let rec remove_dups l = match l with x :: l' -> if List.mem x l' then remove_dups l' else x::remove_dups l' | [] -> [] ;; let arg n = if n < Array.length Sys.argv then Sys.argv.(n) else raise Not_found ;; (**********************************************************************) let ocaml_stdlib_default = "/usr/local/lib/ocaml";; let ocaml_stdlib = begin (* Execute "ocamlc -v" and read the stdlib directory *) let filename = Filename.temp_file "ocamlfind." ".dat" in let command = "ocamlc -v >" ^ filename in (* SYS *) let n = Sys.command command in if n <> 0 then begin prerr_endline ("ocamlfind-mini: [WARNING] Cannot determine directory of stdlib; using " ^ ocaml_stdlib_default ^ " by default"); ocaml_stdlib_default end else begin (* Search the line "Standard library directory: " *) let tag = "Standard library directory: " in let taglen = String.length tag in let f = open_in filename in let dir = ref ocaml_stdlib_default in try while true do let s = input_line f in if String.length s >= taglen && String.sub s 0 taglen = tag then begin dir := String.sub s taglen (String.length s - taglen); raise Exit; end done; assert false with Exit -> close_in f; (try Sys.remove filename with _ -> ()); !dir | End_of_file -> close_in f; prerr_endline ("ocamlfind-mini: [WARNING] Cannot determine directory of stdlib; using " ^ ocaml_stdlib_default ^ " by default"); ocaml_stdlib_default end end ;; let ocamlpath = try Split.path (Sys.getenv "OCAMLPATH") with Not_found -> (* Use stdlib as default: *) [ ocaml_stdlib ] ;; let env_destdir = try Sys.getenv "OCAMLFIND_DESTDIR" with Not_found -> "";; let env_metadir = try Sys.getenv "OCAMLFIND_METADIR" with Not_found -> "";; let core_packages = [ "bigarray", ocaml_stdlib; "dbm", ocaml_stdlib; "dynlink", ocaml_stdlib; "graphics", ocaml_stdlib; "labltk", (Filename.concat ocaml_stdlib "labltk"); "num", ocaml_stdlib; "stdlib", ocaml_stdlib; "str", ocaml_stdlib; "threads", (Filename.concat ocaml_stdlib "threads"); "unix", ocaml_stdlib; ] ;; (**********************************************************************) let package_directory pkg = let rec lookup path = match path with | [] -> raise Not_found | dir :: path' -> let pkgdir = Filename.concat dir pkg in let meta = Filename.concat pkgdir "META" in if Sys.file_exists meta then pkgdir else lookup path' in try List.assoc pkg core_packages with Not_found -> lookup ocamlpath ;; (**********************************************************************) let use_package prefix pkgnames = let pdirs = List.map (fun pname -> try "-I " ^ package_directory pname with Not_found -> failwith ("Cannot find package " ^ pname ^ " (check environment variable OCAMLPATH)")) pkgnames in print_endline (prefix ^ String.concat " " pdirs) ;; (**************** OCAMLC/OCAMLMKTOP/OCAMLOPT subcommands ****************) type pass_file_t = Pass of string | Impl of string | Intf of string ;; let ocamlc which () = Arg.current := 1; let switches = ref [] in let pass_options = ref [] in let pass_files = ref [] in let incpath = ref [] in let packages = ref [] in let add_switch name = Arg.Unit (fun () -> switches := name :: !switches; pass_options := !pass_options @ [name]) in let add_spec_fn name s = pass_options := !pass_options @ [name; s] in let add_spec name = Arg.String (add_spec_fn name) in let add_pkg = Arg.String (fun s -> packages := !packages @ (Split.in_words s)) in Arg.parse (List.flatten [ [ "-package", add_pkg, " Refer to package when compiling"; "-linkpkg", Arg.Unit(fun _ -> raise (Arg.Bad "Not supported: -linkpkg")), " Link the packages in (NOT SUPPORTED)"; "-predicates", Arg.String(fun _ -> raise (Arg.Bad "Not supported: -predicates")), "

Add predicate

when resolving package properties (NOT SUPPORTED)"; "-dontlink", Arg.String(fun _ -> raise (Arg.Bad "Not supported: -dontlink")), " Do not link in package and its ancestors (NOT SUPPORTED)"; "-syntax", Arg.String(fun _ -> raise (Arg.Bad "Not supported: -syntax")), "

Use preprocessor with predicate

(NOT SUPPORTED)"; "-ppopt", Arg.String(fun _ -> raise (Arg.Bad "Not supported: -ppopt")), " Append option to preprocessor invocation (NOT SUPPORTED)"; "-passopt", Arg.String (fun s -> pass_options := !pass_options @ [s]), " Pass option directly to ocamlc/opt/mktop\nSTANDARD OPTIONS:"; "-a", add_switch "-a", " Build a library"; "-c", add_switch "-c", " Compile only (do not link)"; "-cc", add_spec "-cc", " Use as the C compiler and linker"; "-cclib", add_spec "-cclib", " Pass option to the C linker"; "-ccopt", add_spec "-ccopt", " Pass option to the C compiler and linker"; ]; if which = "ocamlopt" then [ "-compact", add_switch "-compact", " Optimize code size rather than speed" ] else []; if which <> "ocamlopt" then [ "-custom", add_switch "-custom", " Link in custom mode"; "-g", add_switch "-g", " Save debugging information"; ] else []; [ "-i", add_switch "-i", " Print the types"; "-I", (Arg.String (fun s -> incpath := s :: !incpath; add_spec_fn "-I" s)), "

Add to the list of include directories"; "-impl", Arg.String (fun s -> pass_files := !pass_files @ [ Impl s ]), " Compile as a .ml file"; ] ; if which = "ocamlopt" then [ "-inline", add_spec "-inline", " Set aggressiveness of inlining to "; ] else []; [ "-intf", Arg.String (fun s -> pass_files := !pass_files @ [ Intf s ]), " Compile as a .mli file"; "-intf-suffix", add_spec "-intf-suffix", " Suffix for interface file (default: .mli)"; "-intf_suffix", add_spec "-intf_suffix", " same as -intf-suffix"; "-labels", add_switch "-labels", " Use commuting label mode"; "-linkall", add_switch "-linkall", " Link all modules, even unused ones"; ] ; if which <> "ocamlopt" then [ "-make-runtime", add_switch "-make-runtime", " Build a runtime system"; "-make_runtime", add_switch "-make_runtime", " same as -make-runtime"; ] else []; [ "-noautolink", add_switch "-noautolink", " Don't automatically link C libraries specif'd in .cma files"; "-noassert", add_switch "-noassert", " Do not compile assertion checks"; "-o", add_spec "-o", " Set output file name to "; "-output-obj", add_switch "-output-obj", " Output a C object file instead of an executable"; ]; if which = "ocamlopt" then [ "-p", add_switch "-p", " Compile/link with profiling support for \"gprof\" (implies -predicates gprof)"; ] else if which = "ocamlcp" then [ "-p", add_spec "-p", " [afilmt] Profile constructs specified by argument: a Everything f Function calls i if ... then ... else l while, for m match ... with t try ... with"; ] else []; [ "-pp", Arg.String (fun s -> add_spec_fn "-pp" s), " Pipe sources through preprocessor "; "-rectypes", add_switch "-rectypes", " Allow arbitrary recursive types"; ] ; if which = "ocamlopt" then [ "-S", add_switch "-S", " Keep intermediate assembly file"; ] else []; [ "-thread", add_switch "-thread", " Use thread-safe standard library (implies -predicate mt)"; "-unsafe", add_switch "-unsafe", " No bounds checking on array and string access"; ] ; if which <> "ocamlopt" then [ "-use-runtime", add_spec "-use-runtime", " Generate bytecode for the given runtime system"; "-use_runtime", add_spec "-use_runtime", " same as -use-runtime"; ] else []; [ "-v", add_switch "-v", " Print compiler version number"; "-verbose", add_switch "-verbose", " Print calls to external commands"; "-w", add_spec "-w", " Enable or disable warnings according to : A/a enable/disable all warnings C/c enable/disable suspicious comment F/f enable/disable partially applied function M/m enable/disable overridden methods P/p enable/disable partial match S/s enable/disable non-unit statement U/u enable/disable unused match case V/v enable/disable hidden instance variables X/x enable/disable all other warnings default setting is A (all warnings enabled)"; "-warn-error", add_spec "-warn-error", " Turn these warnings into errors"; "-where", add_switch "-where", " Print standard library directory"; "-", Arg.String (fun s -> pass_files := !pass_files @ [ Pass s ]), " Treat as a file name (even if it starts with `-')"; ] ]) (fun s -> pass_files := !pass_files @ [ Pass s]) ("usage: ocamlfind-mini " ^ which ^ " [options] file ..."); begin match which with "ocamlc" | "ocamlcp" | "ocamlmktop" | "ocamlopt" -> () | _ -> failwith "unsupported backend" end; let verbose = List.mem "-verbose" !switches in (* check packages: *) List.iter (fun pkg -> try let _ = package_directory pkg in () with Not_found -> failwith ("package '" ^ pkg ^ "' not found (check environment variable OCAMLPATH)")) !packages; let eff_packages = !packages in let eff_packages_dl = remove_dups (List.map package_directory eff_packages) in let stdlibdir = (* normalized form of the stdlib directory *) let d = ocaml_stdlib in if d <> "" & d.[String.length d - 1] = '/' then String.sub d 0 (String.length d - 1) else d in let stdlibdirslash = stdlibdir ^ "/" in let i_options = List.flatten (List.map (fun pkgdir -> if pkgdir = stdlibdir or pkgdir = stdlibdirslash then [] else [ "-I"; pkgdir; "-ccopt"; "-I" ^ pkgdir; ]) eff_packages_dl) in let pass_files' = List.flatten (List.map (function Pass s -> if s.[0] = '-' then [ "-"; String.sub s 1 (String.length s - 1) ] else [ s ] | Impl s -> [ "-impl"; s ] | Intf s -> [ "-intf"; s ] ) !pass_files) in let arguments = !pass_options @ i_options @ pass_files' in let actual_command = which in if verbose then print_string ("+ " ^ actual_command ^ " " ^ String.concat " " arguments ^ "\n"); flush stdout; let argstring = String.concat " " (List.map Filename.quote arguments) in let status = Sys.command (actual_command ^ " " ^ argstring) in begin match status with 0 -> () | n -> if verbose then print_string (actual_command ^ " returned with exit code " ^ string_of_int n ^ "\n"); exit n end; ;; (************************************************************************) let make_directory dirname = (* Invoke the mkdir command *) let cmd = match Sys.os_type with "Unix" -> "mkdir" | "Cygwin" -> "mkdir" (* don't really know *) | "Win32" -> "md" | "MacOS" -> failwith "make_directory not implemented for MacOS" | _ -> failwith "Findlib: unknown operating system" in let c = Sys.command (cmd ^ " " ^ Filename.quote dirname) in if c <> 0 then failwith ("Cannot make directory " ^ dirname) ;; let remove_directory dirname = (* Invoke the rmdir command *) let cmd = match Sys.os_type with "Unix" -> "rmdir" | "Cygwin" -> "rmdir" (* don't really know *) | "Win32" -> "rd" | "MacOS" -> failwith "remove_directory not implemented for MacOS" | _ -> failwith "Findlib: unknown operating system" in let c = Sys.command (cmd ^ " " ^ Filename.quote dirname) in if c <> 0 then failwith ("Cannot remove directory " ^ dirname) ;; let list_dir dirname = let rec rd_dir f = try let s = input_line f in if s = "" then rd_dir f else s::rd_dir f with End_of_file -> close_in f; [] in (* Invoke the ls command *) let cmd = match Sys.os_type with "Unix" -> "ls -1" | "Cygwin" -> "ls -1" (* don't really know *) | "Win32" -> "dir /b" | "MacOS" -> failwith "list_dir not implemented for MacOS" | _ -> failwith "Findlib: unknown operating system" in let filename = Filename.temp_file "ocamlfind." ".dat" in let fullcmd = cmd ^ " " ^ Filename.quote dirname ^ " >" ^ filename in let n = Sys.command fullcmd in if n <> 0 then failwith ("Cannot execute: " ^ fullcmd); let f = open_in filename in let l = rd_dir f in close_in f; (try Sys.remove filename with _ -> ()); l ;; let copy_file ?(rename = (fun name -> name)) ?(append = "") src dstdir = (* A system-independent function to copy the file src to dstdir *) let outname = rename (Filename.basename src) in let ch_in = open_in_bin src in try let outpath = Filename.concat dstdir outname in if Sys.file_exists outpath then prerr_endline ("ocamlfind-mini: [WARNING] Overwriting file " ^ outpath); let ch_out = open_out_bin outpath in try let buflen = 4096 in let buf = Bytes.create buflen in let pos = ref 0 in let len = ref (input ch_in buf 0 buflen) in while !len > 0 do output ch_out buf !pos !len; len := input ch_in buf !pos buflen; done; output_string ch_out append; close_out ch_out; close_in ch_in; prerr_endline("Installed " ^ outpath); with exc -> close_out ch_out; raise exc with exc -> close_in ch_in; raise exc ;; let install_create_directory pkgname dstdir = if Sys.file_exists dstdir then failwith ("Package " ^ pkgname ^ " is already installed; please remove it first"); make_directory dstdir ;; exception Skip_file;; let install_package () = let destdir = ref (env_destdir) in let metadir = ref (env_metadir) in let don't_add_directory_directive = ref false in let pkgname = ref "" in let files = ref [] in let keywords = [ "-destdir", (Arg.String (fun s -> destdir := s)), " Set the destination directory"; "-metadir", (Arg.String (fun s -> metadir := s)), " Install the META file into this directory"; "-dont-add-directory-directive", (Arg.Set don't_add_directory_directive), " never append directory='...' to META"; ] in let errmsg = "usage: ocamlfind-mini install [options] ..." in Arg.current := 1; Arg.parse keywords (fun s -> if !pkgname = "" then pkgname := s else files := s :: !files ) errmsg; if !pkgname = "" then (Arg.usage keywords errmsg; exit 1); (* Check destdir: *) if !destdir = "" then failwith ("No destination directory. Either specify the -destdir option, or set the environment variable OCAMLFIND_DESTDIR"); if not (Sys.file_exists !destdir) then failwith ("The destination directory " ^ !destdir ^ " does not exist"); (* Check whether META exists: *) let meta_dot_pkg = "META." ^ !pkgname in let has_meta = List.exists (fun p -> let b = Filename.basename p in b = "META" || b = meta_dot_pkg) !files in if not has_meta then failwith "The META file is missing"; (* Check that there is no meta_dot_pkg: *) if Sys.file_exists (Filename.concat !metadir meta_dot_pkg) then failwith ("Package " ^ !pkgname ^ " is already installed; please remove it first"); (* Create the package directory: *) let pkgdir = Filename.concat !destdir !pkgname in install_create_directory !pkgname pkgdir; (* Now copy the files into the package directory: *) let has_metadir = !metadir <> "" in List.iter (fun p -> try copy_file ~rename: (fun f -> if has_metadir then begin if f = "META" || f = meta_dot_pkg then raise Skip_file else f end else if f = meta_dot_pkg then "META" else f) p pkgdir with Skip_file -> () ) !files; (* Finally copy META into metadir, if this has been requested *) if has_metadir then begin List.iter (fun p -> let b = Filename.basename p in if b = "META" || b = meta_dot_pkg then copy_file ~rename: (fun f -> if f = "META" then meta_dot_pkg else f) ~append: ("\ndirectory=\"" ^ pkgdir ^ "\" # auto-added by ocamlfind-mini\n") p !metadir ) !files end ;; let remove_package () = let destdir = ref (env_destdir) in let metadir = ref (env_metadir) in let pkgname = ref "" in let keywords = [ "-destdir", (Arg.String (fun s -> destdir := s)), " Set the destination directory"; "-metadir", (Arg.String (fun s -> metadir := s)), " Remove the META file from this directory"; ] in let errmsg = "usage: ocamlfind-mini remove [options] " in Arg.current := 1; Arg.parse keywords (fun s -> if !pkgname = "" then pkgname := s else raise (Arg.Bad "too many arguments") ) errmsg; if !pkgname = "" then (Arg.usage keywords errmsg; exit 1); (* Check destdir: *) if !destdir = "" then failwith ("No destination directory. Either specify the -destdir option, or set the environment variable OCAMLFIND_DESTDIR"); if not (Sys.file_exists !destdir) then failwith ("The destination directory " ^ !destdir ^ " does not exist"); let meta_dot_pkg = "META." ^ !pkgname in let has_metadir = !metadir <> "" in (* If there is a metadir, remove the META file from it: *) if has_metadir then begin let f = Filename.concat !metadir meta_dot_pkg in if Sys.file_exists f then begin Sys.remove f; prerr_endline ("Removed " ^ f); end else prerr_endline ("ocamlfind-mini: [WARNING] No such file: " ^ f) end; (* Remove the files from the package directory: *) let pkgdir = Filename.concat !destdir !pkgname in if Sys.file_exists pkgdir then begin let files = list_dir pkgdir in List.iter (fun f -> Sys.remove (Filename.concat pkgdir f)) files; remove_directory pkgdir; prerr_endline ("Removed " ^ pkgdir) end else prerr_endline("ocamlfind-mini: [WARNING] No such directory: " ^ pkgdir); ;; let select_mode() = let m_string = try arg 1 with Not_found -> raise Usage in let m = match m_string with ("use"|"-use") -> M_use | ("query"|"-query") -> M_query | ("install"|"-install") -> M_install | ("remove"|"-remove") -> M_remove | ("ocamlc"|"-ocamlc") -> M_compiler "ocamlc" | ("ocamlcp"|"-ocamlcp") -> M_compiler "ocamlcp" | ("ocamlmktop"|"-ocamlmktop") -> M_compiler "ocamlmktop" | ("ocamlopt"|"-ocamlopt") -> M_compiler "ocamlopt" | ("printconf"|"-printconf") -> M_printconf | ("guess"|"-guess") -> M_guess | ("list"|"-list") -> M_list | _ -> raise Usage in m ;; let sorry() = prerr_endline "ocamlfind-mini: sorry, this function is not implemented in the reduced version of ocamlfind"; exit 1 ;; let main() = try let m = select_mode() in let l = Array.length Sys.argv in let rest = Array.sub Sys.argv 2 (l-2) in match m with M_use -> if rest = [| |] then raise Usage; if rest.(0) = "-p" then begin if l<4 then raise Usage; use_package rest.(1) (List.tl(List.tl(Array.to_list rest))) end else use_package "" (Array.to_list rest) | M_query -> sorry() | M_install -> install_package() | M_remove -> remove_package () | M_printconf -> sorry() | M_guess -> sorry() | M_list -> sorry() | M_compiler which -> ocamlc which () with Usage -> prerr_endline "usage: ocamlfind-mini ocamlc [-help | other options] ..."; prerr_endline " or: ocamlfind-mini ocamlcp [-help | other options] ..."; prerr_endline " or: ocamlfind-mini ocamlmktop [-help | other options] ..."; prerr_endline " or: ocamlfind-mini ocamlopt [-help | other options] ..."; prerr_endline " or: ocamlfind-mini install [-help | other options] ..."; prerr_endline " or: ocamlfind-mini remove [-help | other options] "; exit 2 | Failure f -> prerr_endline ("ocamlfind-mini: " ^ f); exit 2 ;; try Sys.catch_break true; main() with any -> prerr_endline ("Uncaught exception: " ^ Printexc.to_string any); let raise_again = try ignore(Sys.getenv "OCAMLFIND_DEBUG"); true with Not_found -> false in if raise_again then raise any; exit 3 ;; (* ====================================================================== * History: * * $Log: ocamlfind-mini,v $ * Revision 1.4 2001/03/10 08:15:24 gerd * -warn-error * * Revision 1.3 2001/03/06 20:18:03 gerd * Option -where. * * Revision 1.2 2001/03/04 19:03:56 gerd * list_dir: deletes the temp file after use * * Revision 1.1 2001/03/04 19:01:21 gerd * Initial revision. * *) not-ocamlfind-0.14/local-packages/ocamlfind/ocaml-stub0000755000175000017500000000014314770304423022020 0ustar stephsteph#!/bin/sh BINDIR=$(dirname "$(command -v ocamlc)") "$BINDIR/ocaml" -I "$OCAML_TOPLEVEL_PATH" "$@" not-ocamlfind-0.14/local-packages/ocamlfind/ocamlfind.install0000644000175000017500000000022714770304423023353 0ustar stephstephbin: [ "src/findlib/ocamlfind" {"ocamlfind"} "?src/findlib/ocamlfind_opt" {"ocamlfind"} "?tools/safe_camlp4" ] toplevel: ["src/findlib/topfind"] not-ocamlfind-0.14/local-packages/ocamlfind/opam0000644000175000017500000000222214770304423020703 0ustar stephstephopam-version: "2.0" name: "ocamlfind" version: "1.9.8.git" license: "MIT" synopsis: "A library manager for OCaml" maintainer: "Thomas Gazagnaire " authors: "Gerd Stolpmann " homepage: "http://projects.camlcity.org/projects/findlib.html" bug-reports: "https://github.com/ocaml/ocamlfind/issues" dev-repo: "git+https://github.com/ocaml/ocamlfind.git" description: """ Findlib is a library manager for OCaml. It provides a convention how to store libraries, and a file format ("META") to describe the properties of libraries. There is also a tool (ocamlfind) for interpreting the META files, so that it is very easy to use libraries in programs and scripts. """ build: [ [ "./configure" "-bindir" bin "-sitelib" lib "-mandir" man "-config" "%{lib}%/findlib.conf" "-no-custom" "-no-camlp4" {!ocaml:preinstalled & ocaml:version >= "4.02.0"} "-no-topfind" {ocaml:preinstalled} ] [make "all"] [make "opt"] {ocaml:native} ] install: [ [make "install"] ["install" "-m" "0755" "ocaml-stub" "%{bin}%/ocaml"] {ocaml:preinstalled} ] depends: [ "ocaml" {>= "3.08.0"} ] depopts: ["graphics"] not-ocamlfind-0.14/local-packages/ocamlfind/patches/0002755000175000017500000000000014770304423021457 5ustar stephstephnot-ocamlfind-0.14/local-packages/ocamlfind/patches/findlib-1.1-win32.diff0000644000175000017500000000416714770304423025163 0ustar stephsteph--- ./itest-aux/simple_dbm.ml.orig 2005-11-07 13:38:01.203976400 +0100 +++ ./itest-aux/simple_dbm.ml 2005-11-07 13:38:11.498265600 +0100 @@ -1,9 +1,9 @@ -(try +(try Sys.remove "itest-aux/testdb.db" -with +with _ -> ()); -let dbm = +let _dbm = Dbm.opendbm "itest-aux/testdb" [ Dbm.Dbm_rdwr; Dbm.Dbm_create ] 0o777 in print_string "OK\n";; --- ./itest-aux/simple_labltk.ml.orig 2005-11-07 13:39:25.931584300 +0100 +++ ./itest-aux/simple_labltk.ml 2005-11-07 13:39:34.954108200 +0100 @@ -1,6 +1,6 @@ open Tk;; -let top = openTk() in +let _top = openTk() in update(); closeTk() ;; --- ./itest-aux/simple_num.ml.orig 2005-11-07 13:39:00.956917700 +0100 +++ ./itest-aux/simple_num.ml 2005-11-07 13:39:05.973881600 +0100 @@ -1,4 +1,4 @@ -let n = Num.num_of_int 5 in +let _n = Num.num_of_int 5 in print_string "OK\n";; --- ./itest-aux/simple_str.ml.orig 2005-11-07 13:35:56.037998100 +0100 +++ ./itest-aux/simple_str.ml 2005-11-07 13:35:58.661692300 +0100 @@ -1,4 +1,4 @@ -let b = Str.regexp ".*" in +let _b = Str.regexp ".*" in print_string "OK\n";; --- ./itest-aux/simple_unix.ml.orig 2005-11-07 13:37:28.257845000 +0100 +++ ./itest-aux/simple_unix.ml 2005-11-07 13:37:34.927235600 +0100 @@ -1,4 +1,4 @@ -let p = Unix.getpid() in +let _p = Unix.getpid() in print_string "OK\n";; --- ./tools/extract_args/extract_args.ml.orig 2005-11-07 13:27:58.494279900 +0100 +++ ./tools/extract_args/extract_args.ml 2005-11-07 13:32:33.393117500 +0100 @@ -25,13 +25,17 @@ let get_help cmd = let temp_file = - Filename.temp_file "findlib" ".txt" in + Filename.temp_file "findlib" ".txt" + and quote s = + match Sys.os_type with + "Win32" -> s + | _ -> Filename.quote s in let help_out = try let code = - Sys.command (sprintf "%s -help >%s" - (Filename.quote cmd) - (Filename.quote temp_file)) in + Sys.command (sprintf "%s -help >%s" + (quote cmd) + (quote temp_file)) in if code <> 0 then raise Not_found; (* Assume command does not exist! *) let lines = read_lines temp_file in not-ocamlfind-0.14/local-packages/ocamlfind/release0000755000175000017500000000155314770304423021400 0ustar stephsteph#! /bin/sh set -e version=`./configure -version 2>/dev/null` destdir="findlib-$version" mkdir -p packages rm -rf "packages/$destdir" makepkg -spec findlib.files -intree . -outtree "packages/$destdir" (cd packages; tar czf "$destdir.tar.gz" "$destdir") echo "Wrote packages/$destdir.tar.gz" # Checking git: master="$(git branch | grep '* master')" if [ -z "$master" ]; then echo "Error: not on master branch" exit 1 fi status="$(git status -uno -s)" if [ -n "$status" ]; then echo "Error: git status not clean" exit 1 else printf "Tag revision (y/n)? " read answer case "$answer" in y|Y|yes|YES) git tag -a -m "findlib-$version" findlib-$version git push --tags origin master echo "New tag: findlib-$version" ;; *) echo "Nothing tagged." ;; esac fi not-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/0002755000175000017500000000000014770304423022325 5ustar stephstephnot-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/bigarray/0002755000175000017500000000000014770304423024125 5ustar stephstephnot-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/bigarray/META.in0000644000175000017500000000053114770304423025200 0ustar stephsteph# Specifications for the "bigarray" library: requires = "unix" version = "[distributed with Ocaml]" description = "Large statically allocated arrays" directory = "^" browse_interfaces = "%%interfaces%%" archive(byte) = "bigarray.cma" archive(native) = "bigarray.cmxa" plugin(byte) = "bigarray.cma" plugin(native) = "bigarray.cmxs" linkopts = "" not-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/bigarray/interfaces.in0000644000175000017500000000001514770304423026572 0ustar stephstephbigarray.cma not-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/bytes/0002755000175000017500000000000014770304423023453 5ustar stephstephnot-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/bytes/META.in0000644000175000017500000000022114770304423024522 0ustar stephstephname="bytes" version="[distributed with OCaml 4.02 or above]" description="dummy backward-compatibility package for mutable strings" requires="" not-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/bytes/README0000644000175000017500000000066614770304423024341 0ustar stephstephdummy forward-compatibility package for the standard Bytes module Starting from 4.02, the OCaml standard library splits String into two modules, String for now-immutable strings and Bytes for mutable byte sequences. A 'bytes' package is made available to older OCaml version that wish to use a Bytes module. This dummy 'bytes' package, intended to be installed on 4.02 and above, makes user-code depending on 'bytes' forward-compatible. not-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/bytes/interfaces.in0000644000175000017500000000001314770304423026116 0ustar stephstephbytes.cmo not-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/bytes/interfaces.out0000644000175000017500000000000714770304423026322 0ustar stephstephBytes not-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/camlp4.309/0002755000175000017500000000000014770304423024017 5ustar stephstephnot-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/camlp4.309/META.in0000644000175000017500000000623214770304423025076 0ustar stephsteph# Specifications for the "camlp4" preprocessor: requires = "" version = "[distributed with Ocaml]" description = "Base for Camlp4 syntax extensions" directory = "%%camlp4_dir%%" # For the toploop: archive(byte,toploop,camlp4o) = "camlp4o.cma" archive(byte,toploop,camlp4r) = "camlp4r.cma" # Scheme-like syntax: # Do #predicates "syntax,camlp4scheme", followed by #require "camlp4" archive(byte,toploop,camlp4scheme) = "camlp4sch.cma" # Standard ML-like syntax: # Do #predicates "syntax,camlp4sml", followed by #require "camlp4" archive(byte,toploop,camlp4sml) = "gramlib.cma camlp4_top.cma pa_sml.cmo" # Lisp-like syntax: # Do #predicates "syntax,camlp4lisp", followed by #require "camlp4" archive(byte,toploop,camlp4lisp) = "gramlib.cma camlp4_top.cma pa_lisp.cmo" # For the preprocessor itself: archive(syntax,preprocessor,camlp4o) = "pa_o.cmo pa_op.cmo pr_dump.cmo" archive(syntax,preprocessor,camlp4r) = "pa_r.cmo pa_rp.cmo pr_dump.cmo" archive(syntax,preprocessor,camlp4sml) = "pa_sml.cmo pr_dump.cmo" archive(syntax,preprocessor,camlp4scheme) = "pa_scheme.cmo pr_dump.cmo" archive(syntax,preprocessor,camlp4lisp) = "pa_lisp.cmo pr_dump.cmo" preprocessor = "%%camlp4_cmd%% -nolib" package "gramlib" ( requires(toploop) = "camlp4" version = "[distributed with Ocaml]" description = "Grammar library to create syntax extensions" archive(byte) = "gramlib.cma" archive(byte,toploop) = "" # already contained in camlp4*.cma archive(native) = "gramlib.cmxa" ) package "quotations" ( requires = "camlp4" version = "[distributed with Ocaml]" description = "Syntax extension: Quotations to create AST nodes" archive(syntax,preprocessor) = "q_MLast.cmo" archive(syntax,toploop) = "q_MLast.cmo" ) package "phony_quotations" ( requires = "camlp4" version = "[distributed with Ocaml]" description = "Syntax extension: Phony quotations" archive(syntax,preprocessor) = "q_phony.cmo" archive(syntax,toploop) = "q_phony.cmo" ) package "extend" ( requires = "camlp4" version = "[distributed with Ocaml]" description = "Syntax extension: EXTEND the camlp4 grammar" archive(syntax,preprocessor) = "pa_extend.cmo" archive(syntax,toploop) = "pa_extend.cmo" ) package "extfun" ( requires = "camlp4" version = "[distributed with Ocaml]" description = "Syntax extension: Extensible functions" archive(syntax,preprocessor) = "pa_extfun.cmo" archive(syntax,toploop) = "pa_extfun.cmo" ) package "fstream" ( requires = "camlp4" version = "[distributed with Ocaml]" description = "Syntax extension: Functional stream parsers" archive(syntax,preprocessor) = "pa_fstream.cmo" archive(syntax,toploop) = "pa_fstream.cmo" ) package "macro" ( requires = "camlp4" version = "[distributed with Ocaml]" description = "Syntax extension: Conditional compilation" archive(syntax,preprocessor) = "pa_macro.cmo" archive(syntax,toploop) = "pa_macro.cmo" ) package "unit_constraints" ( requires = "camlp4" version = "[distributed with Ocaml]" description = "Syntax extension: Type constraints of type unit (revised syntax only)" archive(syntax,preprocessor,camlp4r) = "pa_ru.cmo" archive(syntax,toploop,camlp4r) = "pa_ru.cmo" error(syntax,-camlp4r) = "Not available" ) not-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/camlp4.310/0002755000175000017500000000000014770304423024007 5ustar stephstephnot-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/camlp4.310/META.in0000644000175000017500000001251314770304423025065 0ustar stephsteph# Specifications for the "camlp4" preprocessor: requires = "" version = "[distributed with Ocaml]" description = "Base for Camlp4 syntax extensions" directory = "+camlp4" # For the toploop: requires(byte,toploop) = "%%camlp4_dynlink%%" archive(byte,toploop,camlp4o) = "camlp4o.cma" archive(byte,toploop,camlp4r) = "camlp4r.cma" # For the preprocessor itself: archive(syntax,preprocessor,camlp4o) = "-parser o -parser op -printer p" archive(syntax,preprocessor,camlp4r) = "-parser r -parser rp -printer p" preprocessor = "%%camlp4_cmd%%" package "lib" ( requires = "camlp4 %%camlp4_dynlink%%" version = "[distributed with Ocaml]" description = "Camlp4 library" archive(byte) = "camlp4lib.cma" archive(byte,toploop) = "" # already contained in camlp4*.cma archive(native) = "camlp4lib.cmxa" ) package "gramlib" ( requires = "camlp4.lib" version = "[distributed with Ocaml]" description = "Compatibility name for camlp4.lib" ) # don't use camlp4.lib and camlp4.fulllib together package "fulllib" ( requires = "camlp4 %%camlp4_dynlink%%" version = "[distributed with Ocaml]" description = "Camlp4 library" error(pkg_camlp4.lib) = "camlp4.lib and camlp4.fulllib are incompatible" archive(byte) = "camlp4fulllib.cma" archive(byte,toploop) = "" # already contained in camlp4*.cma archive(native) = "camlp4fulllib.cmxa" ) package "quotations" ( version = "[distributed with Ocaml]" description = "Syntax extension: Quotations to create AST nodes" requires = "camlp4.quotations.r" # backward compat # We must have a non-empty archive, otherwise this pkg is ignored # for constructing the preprocessor command. We can pass -ignore arg # to camlp4 as dummy argument: archive(syntax,preprocessor) = "-ignore foo" package "o" ( requires = "camlp4" version = "[distributed with Ocaml]" description = "Syntax extension: Quotations to create AST nodes (original syntax)" archive(syntax,preprocessor) = "-parser Camlp4QuotationCommon -parser Camlp4OCamlOriginalQuotationExpander" archive(syntax,toploop) = "Camlp4Parsers/Camlp4QuotationCommon.cmo Camlp4Parsers/Camlp4OCamlOriginalQuotationExpander.cmo" ) package "r" ( requires = "camlp4" version = "[distributed with Ocaml]" description = "Syntax extension: Quotations to create AST nodes (revised syntax)" archive(syntax,preprocessor) = "-parser Camlp4QuotationCommon -parser Camlp4OCamlRevisedQuotationExpander" archive(syntax,toploop) = "Camlp4Parsers/Camlp4QuotationCommon.cmo Camlp4Parsers/Camlp4OCamlRevisedQuotationExpander.cmo" ) ) package "extend" ( requires = "camlp4" version = "[distributed with Ocaml]" description = "Syntax extension: EXTEND the camlp4 grammar" archive(syntax,preprocessor) = "-parser Camlp4GrammarParser" archive(syntax,toploop) = "Camlp4Parsers/Camlp4GrammarParser.cmo" ) package "listcomprehension" ( requires = "camlp4" version = "[distributed with Ocaml]" description = "Syntax extension for list comprehensions" archive(syntax,preprocessor) = "-parser Camlp4ListComprehension" archive(syntax,toploop) = "Camlp4Parsers/Camlp4ListComprehension.cmo" ) package "macro" ( requires = "camlp4" version = "[distributed with Ocaml]" description = "Syntax extension: Conditional compilation" archive(syntax,preprocessor) = "-parser Camlp4MacroParser" archive(syntax,toploop) = "Camlp4Parsers/Camlp4MacroParser.cmo" ) package "mapgenerator" ( requires = "camlp4" version = "[distributed with Ocaml]" description = "Syntax filter: Traverse data structure (map style)" archive(syntax,preprocessor) = "-filter Camlp4MapGenerator" archive(syntax,toploop) = "Camlp4Filters/Camlp4MapGenerator.cmo" ) package "foldgenerator" ( requires = "camlp4" version = "[distributed with Ocaml]" description = "Syntax filter: Traverse data structure (fold style)" archive(syntax,preprocessor) = "-filter Camlp4FoldGenerator" archive(syntax,toploop) = "Camlp4Filters/Camlp4FoldGenerator.cmo" ) package "metagenerator" ( requires = "camlp4" version = "[distributed with Ocaml]" description = "Syntax filter: Generate AST generator for data structure" archive(syntax,preprocessor) = "-filter Camlp4MetaGenerator" archive(syntax,toploop) = "Camlp4Filters/Camlp4MetaGenerator.cmo" ) package "locationstripper" ( requires = "camlp4" version = "[distributed with Ocaml]" description = "Syntax filter: Remove location info from AST" archive(syntax,preprocessor) = "-filter Camlp4LocationStripper" archive(syntax,toploop) = "Camlp4Filters/Camlp4LocationStripper.cmo" ) package "tracer" ( requires = "camlp4" version = "[distributed with Ocaml]" description = "Syntax filter: Trace execution" archive(syntax,preprocessor) = "-filter Camlp4Tracer" archive(syntax,toploop) = "Camlp4Filters/Camlp4Tracer.cmo" ) package "exceptiontracer" ( requires = "camlp4" version = "[distributed with Ocaml]" description = "Syntax filter: Trace exception execution" archive(syntax,preprocessor) = "-filter Camlp4ExceptionTracer" archive(syntax,toploop) = "Camlp4Filters/Camlp4ExceptionTracer.cmo" ) package "profiler" ( requires = "camlp4" version = "[distributed with Ocaml]" description = "Syntax filter: Count events during execution" archive(syntax,preprocessor) = "-filter Camlp4Profiler" archive(syntax,toploop) = "Camlp4Filters/Camlp4Profiler.cmo" archive(byte) = "camlp4prof.cmo" archive(native) = "camlp4prof.cmx" ) not-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/compiler-libs/0002755000175000017500000000000014770304423025066 5ustar stephstephnot-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/compiler-libs/META.in0000644000175000017500000000231214770304423026140 0ustar stephsteph# The compiler itself requires = "" version = "[distributed with Ocaml]" description = "compiler-libs support library" directory= "+compiler-libs" package "common" ( requires = "compiler-libs" version = "[distributed with Ocaml]" description = "Common compiler routines" archive(byte) = "ocamlcommon.cma" archive(native) = "ocamlcommon.cmxa" ) package "bytecomp" ( requires = "compiler-libs.common" version = "[distributed with Ocaml]" description = "Bytecode compiler" archive(byte) = "ocamlbytecomp.cma" archive(native) = "ocamlbytecomp.cmxa" ) package "optcomp" ( requires = "compiler-libs.common" version = "[distributed with Ocaml]" description = "Native-code compiler" archive(byte) = "ocamloptcomp.cma" archive(native) = "ocamloptcomp.cmxa" exists_if = "ocamloptcomp.cma" ) package "toplevel" ( requires = "compiler-libs.bytecomp" version = "[distributed with Ocaml]" description = "Toplevel interactions" archive(byte) = "ocamltoplevel.cma" ) package "native-toplevel" ( requires = "compiler-libs.optcomp dynlink" version = "[distributed with Ocaml]" description = "Toplevel interactions" archive(native) = "ocamltoplevel.cmxa" exists_if = "ocamltoplevel.cmxa" ) not-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/dbm/0002755000175000017500000000000014770304423023067 5ustar stephstephnot-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/dbm/META.in0000644000175000017500000000044314770304423024144 0ustar stephsteph# Specification for the "dbm" library requires = "" version = "[distributed with Ocaml]" description = "Access to NDBM databases" directory = "^" browse_interfaces = "%%interfaces%%" archive(byte) = "dbm.cma" archive(native) = "dbm.cmxa" plugin(byte) = "dbm.cma" plugin(native) = "dbm.cmxs" not-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/dbm/interfaces.in0000644000175000017500000000001014770304423025527 0ustar stephstephdbm.cma not-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/dynlink/0002755000175000017500000000000014770304423023775 5ustar stephstephnot-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/dynlink/META.in0000644000175000017500000000041314770304423025047 0ustar stephsteph# Specifications for the "dynlink" library: requires = "" version = "[distributed with Ocaml]" description = "Dynamic loading and linking of object files" directory = "%%dynlink_dir%%" browse_interfaces = "%%interfaces%%" archive(byte) = "dynlink.cma" %%natdynlink%% not-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/dynlink/interfaces.in0000644000175000017500000000001414770304423026441 0ustar stephstephdynlink.cma not-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/graphics/0002755000175000017500000000000014770304423024125 5ustar stephstephnot-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/graphics/META.in0000644000175000017500000000050114770304423025175 0ustar stephsteph# Specifications for the "graphics" library: requires = "" version = "[distributed with Ocaml]" description = "Portable drawing primitives" directory = "^" browse_interfaces = "%%interfaces%%" archive(byte) = "graphics.cma" archive(native) = "graphics.cmxa" plugin(byte) = "graphics.cma" plugin(native) = "graphics.cmxs" not-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/graphics/interfaces.in0000644000175000017500000000001614770304423026573 0ustar stephstephgraphics.cma not-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/labltk/0002755000175000017500000000000014770304423023576 5ustar stephstephnot-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/labltk/META.in0000644000175000017500000000041614770304423024653 0ustar stephsteph# Specifications for the "labltk" library: requires = "" version = "[distributed with Ocaml]" description = "The Tk windowing toolkit" directory = "+labltk" browse_interfaces = "%%interfaces%%" archive(byte) = "labltk.cma" archive(native) = "labltk.cmxa" linkopts = "" not-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/labltk/interfaces.in0000644000175000017500000000001614770304423026244 0ustar stephstephlabltk/*.cma not-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/num-top/0002755000175000017500000000000014770304423023724 5ustar stephstephnot-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/num-top/META.in0000644000175000017500000000027614770304423025005 0ustar stephsteph# Specification for the "num-top" library add-on: requires = "num.core" version = "%%findlib_version%%" description = "Add-on for num inside toploops" archive(byte,toploop) = "num_top.cma" not-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/num/0002755000175000017500000000000014770304423023124 5ustar stephstephnot-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/num/META.in0000644000175000017500000000063614770304423024205 0ustar stephsteph# Specification for the "num" library: requires = "num.core" requires(toploop) = "num.core,num-top" version = "[distributed with Ocaml]" description = "Arbitrary-precision rational arithmetic" package "core" ( directory = "^" version = "[internal]" browse_interfaces = "%%interfaces%%" archive(byte) = "nums.cma" archive(native) = "nums.cmxa" plugin(byte) = "nums.cma" plugin(native) = "nums.cmxs" ) not-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/num/interfaces.in0000644000175000017500000000001114770304423025565 0ustar stephstephnums.cma not-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/ocamlbuild/0002755000175000017500000000000014770304423024440 5ustar stephstephnot-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/ocamlbuild/META.in0000644000175000017500000000036414770304423025517 0ustar stephsteph# Specification for the "ocamlbuild" library requires = "unix" version = "[distributed with Ocaml]" description = "ocamlbuild support library" directory= "^ocamlbuild" archive(byte) = "ocamlbuildlib.cma" archive(native) = "ocamlbuildlib.cmxa" not-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/ocamldoc/0002755000175000017500000000000014770304423024106 5ustar stephstephnot-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/ocamldoc/META.in0000644000175000017500000000025414770304423025163 0ustar stephsteph# Specification for the "ocamldoc" library requires = "compiler-libs" version = "[distributed with Ocaml]" description = "ocamldoc plugin interface" directory= "^ocamldoc" not-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/raw_spacetime/0002755000175000017500000000000014770304423025150 5ustar stephstephnot-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/raw_spacetime/META.in0000644000175000017500000000056614770304423026233 0ustar stephsteph# Specifications for the "spacetime" library: requires = "" description = "Support library for the spacetime profiler" version = "[distributed with Ocaml]" directory = "^" browse_interfaces = "%%interfaces%%" archive(byte) = "raw_spacetime_lib.cma" archive(native) = "raw_spacetime_lib.cmxa" plugin(byte) = "raw_spacetime_lib.cma" plugin(native) = "raw_spacetime_lib.cmxs" not-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/raw_spacetime/interfaces.in0000644000175000017500000000002614770304423027617 0ustar stephstephraw_spacetime_lib.cma not-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/stdlib/0002755000175000017500000000000014770304423023606 5ustar stephstephnot-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/stdlib/META.in0000644000175000017500000000034314770304423024662 0ustar stephsteph# Specifications for the standard library: # (Only included because of findlib-browser) requires = "" description = "Standard library" version = "[distributed with Ocaml]" directory = "^" browse_interfaces = "%%interfaces%%" not-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/stdlib/interfaces.in0000644000175000017500000000001314770304423026251 0ustar stephstephstdlib.cma not-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/str/0002755000175000017500000000000014770304423023135 5ustar stephstephnot-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/str/META.in0000644000175000017500000000050214770304423024206 0ustar stephsteph# Specifications for the "str" library: requires = "" description = "Regular expressions and string processing" version = "[distributed with Ocaml]" directory = "%%str_dir%%" browse_interfaces = "%%interfaces%%" archive(byte) = "str.cma" archive(native) = "str.cmxa" plugin(byte) = "str.cma" plugin(native) = "str.cmxs" not-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/str/interfaces.in0000644000175000017500000000001014770304423025575 0ustar stephstephstr.cma not-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/threads/0002755000175000017500000000000014770304423023757 5ustar stephstephnot-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/threads/META.in0000644000175000017500000000176214770304423025041 0ustar stephsteph# Specifications for the "threads" library: version = "[distributed with Ocaml]" description = "Multi-threading" requires(mt,mt_vm) = "threads.vm" requires(mt,mt_posix) = "threads.posix" directory = "^" type_of_threads = "%%type_of_threads%%" browse_interfaces = "%%interfaces%%" warning(-mt) = "Linking problems may arise because of the missing -thread or -vmthread switch" warning(-mt_vm,-mt_posix) = "Linking problems may arise because of the missing -thread or -vmthread switch" package "vm" ( # --- Bytecode-only threads: requires = "unix" directory = "+vmthreads" exists_if = "threads.cma" archive(byte,mt,mt_vm) = "threads.cma" version = "[internal]" ) package "posix" ( # --- POSIX-threads: requires = "unix" directory = "+threads" exists_if = "threads.cma" archive(byte,mt,mt_posix) = "threads.cma" archive(native,mt,mt_posix) = "threads.cmxa" version = "[internal]" ) package "none" ( error = "threading is not supported on this platform" version = "[internal]" ) not-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/threads/interfaces.in0000644000175000017500000000002714770304423026427 0ustar stephstephvmthreads/threads.cma not-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/unix/0002755000175000017500000000000014770304423023310 5ustar stephstephnot-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/unix/META.in0000644000175000017500000000060414770304423024364 0ustar stephsteph# Specifications for the "unix" library: requires = "" description = "Unix system calls" version = "[distributed with Ocaml]" directory = "%%unix_dir%%" browse_interfaces = "%%interfaces%%" archive(byte) = "unix.cma" archive(native) = "unix.cmxa" archive(byte,mt_vm) = "vmthreads/unix.cma" plugin(byte) = "unix.cma" plugin(native) = "unix.cmxs" plugin(byte,mt_vm) = "vmthreads/unix.cma" not-ocamlfind-0.14/local-packages/ocamlfind/site-lib-src/unix/interfaces.in0000644000175000017500000000001114770304423025751 0ustar stephstephunix.cma not-ocamlfind-0.14/local-packages/ocamlfind/src/0002755000175000017500000000000014770304423020617 5ustar stephstephnot-ocamlfind-0.14/local-packages/ocamlfind/src/bytes/0002755000175000017500000000000014770304423021745 5ustar stephstephnot-ocamlfind-0.14/local-packages/ocamlfind/src/bytes/META0000644000175000017500000000041214770304423022411 0ustar stephstephname="bytes" version="[OCaml strictly before 4.02]" description="backward-compatibility package for mutable strings" requires="" browse_interfaces = "String" archive(byte)="bytes.cma" archive(native)="bytes.cmxa" plugin(byte)="bytes.cma" plugin(native)="bytes.cmxs" not-ocamlfind-0.14/local-packages/ocamlfind/src/bytes/Makefile0000644000175000017500000000205714770304423023407 0ustar stephstephBYTE_FILES=bytes.cmi bytes.cma NATIVE_FILES=bytes.cmx bytes$(LIB_SUFFIX) bytes.cmxa NATIVE_FILES_DYNLINK=bytes.cmxs TOP=../.. include $(TOP)/Makefile.config OCAMLC = ocamlc OCAMLOPT = ocamlopt $(OCAMLOPT_G) OCAMLOPT_SHARED = $(OCAMLOPT) build: all opt all: $(OCAMLC) -a -o bytes.cma bytes.ml opt: $(OCAMLOPT) -a -o bytes.cmxa bytes.ml if [ $(HAVE_NATDYNLINK) -gt 0 ]; then \ $(OCAMLOPT_SHARED) -shared -o bytes.cmxs bytes.cmxa; \ fi install: all $(INSTALLDIR) "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/bytes" $(CP) META $(BYTE_FILES) "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/bytes/" for f in $(NATIVE_FILES) $(NATIVE_FILES_DYNLINK); do if [ -f "$$f" ]; then $(CP) $$f "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/bytes/"; fi; done uninstall: rm -rf "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/bytes" # install-self and uninstall-self use ocamlfind already. This is a bit # questionable here. install-self: all ocamlfind install bytes META $(BYTE_FILES) -optional $(NATIVE_FILES) $(NATIVE_FILES_DYNLINK) uninstall-self: ocamlfind remove bytes clean: ocamlbuild -clean not-ocamlfind-0.14/local-packages/ocamlfind/src/bytes/README0000644000175000017500000000056614770304423022632 0ustar stephstephbackward-compatibility package for the standard Bytes module of 4.02 Starting from 4.02, the OCaml standard library splits String into two modules, String for now-immutable strings and Bytes for mutable byte sequences. This package exports a Bytes package mimicking the new interface to older OCaml version, letting you write code using Bytes that works with OCaml < 4.02. not-ocamlfind-0.14/local-packages/ocamlfind/src/bytes/bytes.ml0000644000175000017500000000142514770304423023425 0ustar stephstephinclude String let empty = "" let of_string = copy let to_string = copy let sub_string = sub let blit_string = blit let unsafe_to_string : t -> string = fun s -> s let unsafe_of_string : string -> t = fun s -> s let extend s left right = (* length of the final string *) let dstlen = left + length s + right in (* length of the included portion of the input string *) let srclen = min 0 left + length s + min 0 right in let t = create dstlen in if srclen > 0 then blit s (max 0 (-left)) t (max 0 left) srclen; t let init len f = let s = create len in for i = 0 to len - 1 do set s i (f i); done; s let mapi f input = let output = create (length input) in for i = 0 to length input - 1 do output.[i] <- f i input.[i]; done; output let cat = (^) not-ocamlfind-0.14/local-packages/ocamlfind/src/findlib-toolbox/0002755000175000017500000000000014770304423023712 5ustar stephstephnot-ocamlfind-0.14/local-packages/ocamlfind/src/findlib-toolbox/Makefile0000644000175000017500000000221714770304423025352 0ustar stephstephTOP=../.. include $(TOP)/Makefile.config .PHONY: all opt install uninstall clean all: make_wizard$(EXEC_SUFFIX) opt: true make_wizard$(EXEC_SUFFIX): make_wizard.ml ocamlc -o make_wizard$(EXEC_SUFFIX) -I +unix -I +labltk -I ../findlib \ unix.cma str.cma labltk.cma findlib.cma make_wizard.ml install: $(INSTALLFILE) make_wizard$(EXEC_SUFFIX) make_wizard.pattern $(DESTDIR)$(prefix)$(OCAML_SITELIB)/findlib/ # uninstall: Nothing to do, because the removal of the findlib core also # deinstalls the make_wizard uninstall: true # ---------------------------------------------------------------------- tree: lx_spots.mli lx_spots.ml lx_tree.mli lx_tree.ml test_tree.ml ocamlfind ocamlc -o tree -package labltk,unix,str -linkpkg \ lx_spots.mli lx_spots.ml lx_tree.mli lx_tree.ml test_tree.ml tree_editor: lx_spots.mli lx_spots.ml lx_tree.mli lx_tree.ml tree_editor.ml ocamlfind ocamlc -o tree_editor -package labltk,unix,str -linkpkg \ lx_spots.mli lx_spots.ml lx_tree.mli lx_tree.ml tree_editor.ml # ---------------------------------------------------------------------- clean: rm -f *.cmi *.cmo rm -f make_wizard$(EXEC_SUFFIX) # tree tree_editor not-ocamlfind-0.14/local-packages/ocamlfind/src/findlib-toolbox/directory.xpm0000644000175000017500000000045314770304423026444 0ustar stephsteph#define directory_width 16 #define directory_height 16 static unsigned char directory_bits[] = { 0xf8, 0x01, 0xfc, 0x03, 0xfe, 0x7f, 0x01, 0x80, 0x55, 0xd5, 0x01, 0x80, 0xab, 0xaa, 0x01, 0x80, 0x55, 0xd5, 0x01, 0x80, 0xab, 0xaa, 0x01, 0x80, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; not-ocamlfind-0.14/local-packages/ocamlfind/src/findlib-toolbox/make_wizard.ml0000644000175000017500000013121714770304423026544 0ustar stephsteph(* $Id$ * ---------------------------------------------------------------------- * *) open Tk;; open Widget;; (**********************************************************************) (* GLOBAL VARIABLES *) (**********************************************************************) (* General *) let wiz_package_name = ref "";; let wiz_package_version = ref "";; let wiz_package_description = ref "";; (* Preprocessor *) let wiz_enable_camlp4 = ref false;; let wiz_camlp4_syntax = ref "camlp4o";; let wiz_camlp4_extensions = ref [];; (* list of package names *) let wiz_camlp4_selected = ref [];; (* subset of wiz_camlp4_extensions *) let wiz_camlp4_options = ref "";; (* Prerequisites *) let wiz_all_packages = ref [];; (* list of package names *) let wiz_required_packages = ref [];; (* subset of wiz_all_packages *) (* Build Library *) let wiz_available = ref [];; (* list of module names *) let wiz_byte_enable = ref true;; let wiz_nat_enable = ref true;; let wiz_objects = ref [];; (* subset of wiz_available *) let wiz_source_suffixes = ref ".ml .mli .mll .mly";; (* Build Executables *) let wiz_executables = ref [];; (* list of executable names *) let wiz_exec_objects = (ref [] : (string * (string list ref)) list ref);; (* an alist: for every executable, the corresponding list of modules is * stored. *) let wiz_exec_native = (ref [] : (string * bool ref) list ref);; (* an alist: for every executable, whether it is natively compiled or not *) (* Generate *) let wiz_makefile_name = ref "Makefile";; let wiz_local_makefile_name = ref "";; let wiz_make_default = ref "byte" ;; (**********************************************************************) (* AUXILIARY FUNCTIONS *) (**********************************************************************) let find_pos x l = let rec find k l = match l with h :: l' -> if x = h then k else find (k+1) l' | [] -> raise Not_found in find 0 l ;; let rec delete_at k l = match l with h :: l' -> if k <= 0 then l' else h :: (delete_at (k-1) l') | [] -> [] ;; let rec insert_at k x l = if k <= 0 then x :: l else match l with h :: l' -> h :: (insert_at (k-1) x l') | [] -> [] (* insert beyond end *) ;; let rec remove_dups l = (* Remove duplicate members in a sorted list *) match l with x :: (y :: l' as l1) when x = y -> remove_dups l1 | x :: l' -> x :: remove_dups l' | [] -> [] ;; (**********************************************************************) (* SAVE/LOAD STATE *) (**********************************************************************) let save_var name printer out var = output_string out ("V" ^ name ^ "\n"); printer out var ;; let save_string out var = (* [var] must not contain linefeeds *) output_string out ("S" ^ var ^ "\n") ;; let save_bool out var = output_string out ("B" ^ string_of_bool var ^ "\n") ;; let save_list printer out var = output_string out ("L" ^ string_of_int (List.length var) ^ "\n"); List.iter (printer out) var ;; let save_pair lprinter rprinter out (lvar,rvar) = output_string out "P\n"; lprinter out lvar; rprinter out rvar ;; let save_ref printer out var = (* Actually doesn't save the reference! *) printer out !var ;; let save_state out = save_var "wiz_package_name" save_string out !wiz_package_name; save_var "wiz_package_version" save_string out !wiz_package_version; save_var "wiz_package_description" save_string out !wiz_package_description; save_var "wiz_enable_camlp4" save_bool out !wiz_enable_camlp4; save_var "wiz_camlp4_syntax" save_string out !wiz_camlp4_syntax; save_var "wiz_camlp4_extensions" (save_list save_string) out !wiz_camlp4_extensions; save_var "wiz_camlp4_selected" (save_list save_string) out !wiz_camlp4_selected; save_var "wiz_camlp4_options" save_string out !wiz_camlp4_options; save_var "wiz_all_packages" (save_list save_string) out !wiz_all_packages; save_var "wiz_required_packages" (save_list save_string) out !wiz_required_packages; save_var "wiz_available" (save_list save_string) out !wiz_available; save_var "wiz_byte_enable" save_bool out !wiz_byte_enable; save_var "wiz_nat_enable" save_bool out !wiz_nat_enable; save_var "wiz_objects" (save_list save_string) out !wiz_objects; save_var "wiz_source_suffixes" save_string out !wiz_source_suffixes; save_var "wiz_executables" (save_list save_string) out !wiz_executables; save_var "wiz_exec_objects" (save_list (save_pair save_string (save_ref (save_list save_string)))) out !wiz_exec_objects; save_var "wiz_exec_native" (save_list (save_pair save_string (save_ref save_bool))) out !wiz_exec_native; save_var "wiz_makefile_name" save_string out !wiz_makefile_name; save_var "wiz_local_makefile_name" save_string out !wiz_local_makefile_name; save_var "wiz_make_default" save_string out !wiz_make_default; ;; let save() = let f = open_out ".make-wizard" in save_state f; close_out f ;; let check_char inch c_expected = let c = input_char inch in if c <> c_expected then failwith "Cannot read .make-wizard" ;; let load_string inch = check_char inch 'S'; let line = input_line inch in (* prerr_endline ("String = " ^ line); *) line ;; let load_bool inch = check_char inch 'B'; bool_of_string(input_line inch) ;; let load_list parse inch = check_char inch 'L'; let n = int_of_string(input_line inch) in let l = ref [] in for i = 1 to n do l := parse inch :: !l; done; List.rev !l ;; let load_pair lparse rparse inch = check_char inch 'P'; ignore(input_line inch); let l = lparse inch in let r = rparse inch in (l,r) ;; let load_ref parse inch = ref(parse inch) ;; let load_var var parse inch = let value = parse inch in var := value ;; let load_variables spec inch = try while true do try check_char inch 'V'; let name = input_line inch in (* prerr_endline name;*) let loader = List.assoc name spec in (* or Not_found *) loader inch with Not_found -> () done; assert false with End_of_file -> () ;; let load_state inch = load_variables [ "wiz_package_name", (load_var wiz_package_name load_string); "wiz_package_version", (load_var wiz_package_version load_string); "wiz_package_description", (load_var wiz_package_description load_string); "wiz_enable_camlp4", (load_var wiz_enable_camlp4 load_bool); "wiz_camlp4_syntax", (load_var wiz_camlp4_syntax load_string); "wiz_camlp4_extensions", (load_var wiz_camlp4_extensions (load_list load_string)); "wiz_camlp4_selected", (load_var wiz_camlp4_selected (load_list load_string)); "wiz_camlp4_options", (load_var wiz_camlp4_options load_string); "wiz_all_packages", (load_var wiz_all_packages (load_list load_string)); "wiz_required_packages", (load_var wiz_required_packages (load_list load_string)); "wiz_available", (load_var wiz_available (load_list load_string)); "wiz_byte_enable", (load_var wiz_byte_enable load_bool); "wiz_nat_enable", (load_var wiz_nat_enable load_bool); "wiz_objects", (load_var wiz_objects (load_list load_string)); "wiz_source_suffixes", (load_var wiz_source_suffixes load_string); "wiz_executables", (load_var wiz_executables (load_list load_string)); "wiz_exec_objects", (load_var wiz_exec_objects (load_list (load_pair load_string (load_ref (load_list load_string))))); "wiz_exec_native", (load_var wiz_exec_native (load_list (load_pair load_string (load_ref load_bool)))); "wiz_makefile_name", (load_var wiz_makefile_name load_string); "wiz_local_makefile_name", (load_var wiz_local_makefile_name load_string); "wiz_make_default", (load_var wiz_make_default load_string); ] inch ;; let load() = let f = open_in ".make-wizard" in load_state f; close_in f ;; (**********************************************************************) (* PARSE PATTERN FILE *) (**********************************************************************) type sectiondata = Sect_const of string | Sect_var of string let section_re = Str.regexp "^\\[\\([A-Za-z_0-9-]+\\)\\]$" ;; let var_re = Str.regexp "\\[\\([A-Za-z_0-9-]+\\)\\]" ;; let parse_pattern inch = let rec parse_section name sect = try let line = input_line inch in if String.length line >= 2 && line.[0] = '#' && line.[1] = '#' then (* Comment line *) parse_section name sect else if Str.string_match section_re line 0 then (* New section begins *) let name' = Str.matched_group 1 line in (name, List.rev sect) :: parse_section name' [] else (* Normal data region *) let plist = Str.full_split var_re line in let slist = List.map (function Str.Text t -> Sect_const t | Str.Delim d -> Sect_var (String.sub d 1 (String.length d - 2)) ) plist @ [ Sect_const "\n" ] in parse_section name (List.rev slist @ sect) with End_of_file -> [ name, List.rev sect ] in parse_section "_preamble_" [] ;; let load_pattern() = let where = Filename.dirname (Sys.argv.(0)) in let name = Filename.concat where "make_wizard.pattern" in let f = open_in name in let p = parse_pattern f in close_in f; p ;; (**********************************************************************) (* MAKEFILE GENERATOR *) (**********************************************************************) let dollar_re = Str.regexp "\\$";; let meta_re = Str.regexp "[\\\\\\\"]";; let mkquote s = (* Quote "$" *) Str.global_replace dollar_re "$$" s ;; let metaquote s = (* Quote backslash and double quotes for META files *) Str.global_replace meta_re "\\\\0" s ;; let makemake() = let b = Buffer.create 1024 in let sections = load_pattern() in let write section vars = let sectlist = try List.assoc section sections with Not_found -> failwith ("Cannot find section: " ^ section) in List.iter (function Sect_const s -> Buffer.add_string b s | Sect_var v -> let s = try List.assoc v vars with Not_found -> failwith ("No such variable: " ^ v) in Buffer.add_string b s ) sectlist in let is_byte_exec execname = try not (!(List.assoc execname !wiz_exec_native)) with Not_found -> true in let byte_execs = List.map fst (List.filter (fun (execname,_) -> is_byte_exec execname) !wiz_exec_objects ) in let nat_execs = List.map fst (List.filter (fun (execname,_) -> not(is_byte_exec execname)) !wiz_exec_objects ) in let byte_exec_modules = remove_dups (List.sort compare (List.flatten (List.map (fun (_, l) -> !l) (List.filter (fun (execname, _) -> is_byte_exec execname) !wiz_exec_objects ) ) ) ) in let nat_exec_modules = remove_dups (List.sort compare (List.flatten (List.map (fun (_, l) -> !l) (List.filter (fun (execname, _) -> not(is_byte_exec execname)) !wiz_exec_objects ) ) ) ) in let required_packages = (* magically add "camlp4" if missing *) if !wiz_enable_camlp4 then ( ( if not (List.mem "camlp4" !wiz_required_packages) then [ "camlp4" ] else [] ) @ !wiz_camlp4_selected @ !wiz_required_packages ) else !wiz_required_packages in let variables = [ "name", mkquote !wiz_package_name; "makefile_name", mkquote !wiz_makefile_name; "version", mkquote(metaquote !wiz_package_version); "description", mkquote(metaquote !wiz_package_description); "byte_objects", String.concat " " (List.map (fun m -> String.uncapitalize m ^ ".cmo") !wiz_objects); "nat_objects", String.concat " " (List.map (fun m -> String.uncapitalize m ^ ".cmx") !wiz_objects); "byte_executables", String.concat " " byte_execs; "byte_exec_objects", String.concat " " (List.map (fun m -> String.uncapitalize m ^ ".cmo") byte_exec_modules); "nat_executables", String.concat " " nat_execs; "nat_exec_objects", String.concat " " (List.map (fun m -> String.uncapitalize m ^ ".cmx") nat_exec_modules); "prereqs", String.concat " " required_packages; "ppopts", if !wiz_enable_camlp4 then "-syntax " ^ !wiz_camlp4_syntax ^ (String.concat " " (List.map (fun opt -> " -ppopt " ^ mkquote(Filename.quote opt)) (Fl_split.in_words_ws !wiz_camlp4_options) )) else ""; "mtopts", if List.mem "threads" !wiz_required_packages then "-thread" else ""; "default_target", !wiz_make_default; ] in write "intro" variables; write "def_general" variables; if !wiz_byte_enable then write "def_byte_archive" variables; if !wiz_nat_enable then write "def_native_archive" variables; write "def_byte_exec" variables; write "def_nat_exec" variables; write "def_props" variables; write "def_tools" variables; write "rules" variables; write "default_target" variables; write "suffix_rules" variables; write "generate" variables; List.iter (fun (execname, modlist) -> let switches = if is_byte_exec execname then "-bytecode-filter" else "-native-filter" in let deptargets = String.concat " " (List.map (fun m -> let m' = String.uncapitalize m in m' ^ ".ml " ^ m' ^ ".mli") !modlist) in write "makemake_exec" ( [ "switches", switches; "execname", execname; "deptargets", deptargets ] @ variables ) ) !wiz_exec_objects; write "byte" variables; write "opt" variables; if !wiz_byte_enable then write "byte_archive" variables; if !wiz_nat_enable then write "native_archive" variables; List.iter (fun (execname, modlist) -> if is_byte_exec execname then begin let execobjs = String.concat " " (List.map (fun m -> String.uncapitalize m ^ ".cmo") !modlist) in write "byte_exec" ( ["execname", execname; "execobjs", execobjs ] @ variables ) end ) !wiz_exec_objects; List.iter (fun (execname, modlist) -> if not (is_byte_exec execname) then begin let execobjs = String.concat " " (List.map (fun m -> String.uncapitalize m ^ ".cmx") !modlist) in write "nat_exec" ( ["execname", execname; "execobjs", execobjs ] @ variables ) end ) !wiz_exec_objects; write "clean" variables; write "install" variables; if !wiz_local_makefile_name<> "" && Sys.file_exists !wiz_local_makefile_name then begin write "local" variables; let f = open_in !wiz_local_makefile_name in try while true do let s = input_line f in Buffer.add_string b s; Buffer.add_char b '\n'; done; assert false with End_of_file -> close_in f end; Buffer.contents b ;; (**********************************************************************) (* GUI *) (**********************************************************************) let headline_font = "-*-helvetica-bold-r-normal-*-*-140-*-*-*-*-iso8859-1" ;; let font = "-*-helvetica-medium-r-normal-*-*-120-*-*-*-*-iso8859-1" ;; (**********************************************************************) let top = ref Widget.default_toplevel;; let topframe = ref Widget.dummy;; let screens = ref [];; let current_screen = ref 0;; let ( !! ) = fun x -> !(!x);; let add_screen func = screens := !screens @ [ func ] ;; let add_headline frame text = let s1 = Frame.create ~height:15 frame in let w = Label.create ~text ~font:headline_font ~anchor:`W frame in let s2 = Frame.create ~height:10 frame in pack [ s1 ]; pack ~anchor:`W [ w ]; pack [ s2 ] ;; let add_para frame text = let s1 = Frame.create ~height:5 frame in let w = Message.create ~padx:0 ~text ~font ~anchor:`W ~width:(pixels (`Pt 400.0)) frame in let s2 = Frame.create ~height:5 frame in pack [ s1 ]; pack ~anchor:`W [ w ]; pack [ s2 ] ;; let dialog ~parent ~title ~message ~buttons ?(default = (-1)) () = (* Like Dialog.create, but our own style. *) let popup = Toplevel.create parent in Wm.title_set popup title; Wm.transient_set popup ~master:(Winfo.toplevel parent); add_headline popup title; add_para popup message; let f_buttons = Frame.create popup in let n = ref 0 in let r = ref (-1) in List.iter (fun text -> let k = !n in let b = Button.create ~font ~text ~command:(fun () -> r := k; destroy popup) f_buttons in (* --- Default buttons not yet supported because of deficiency in * labltk: if k = default then Button.configure ~default:`Active b; *) pack ~side:`Left [b]; incr n; ) buttons; pack [f_buttons]; Grab.set popup; Tkwait.window popup; !r ;; let ask_and_save frame = let reply = dialog ~parent:frame ~title:"Save .make-wizard?" ~message:"Do you want to save the current state in the file .make-wizard?" ~buttons:["Yes"; "No"; "Cancel"] ~default:0 () in if reply = 0 then save(); reply < 2 ;; let string_tv ?(onchange = fun () -> ()) frame v = let textvariable = Textvariable.create ~on:frame () in Textvariable.set textvariable !v; let rec set_handle() = Textvariable.handle textvariable ~callback:(fun () -> v := Textvariable.get textvariable; onchange(); set_handle()); in set_handle(); textvariable ;; let bool_tv ?(onchange = fun () -> ()) frame v = let textvariable = Textvariable.create ~on:frame () in Textvariable.set textvariable (if !v then "1" else "0"); let rec set_handle() = Textvariable.handle textvariable ~callback:(fun () -> v := Textvariable.get textvariable = "1"; onchange(); set_handle()); in set_handle(); textvariable ;; let label_box frame box = let sub = Frame.create frame in let row = ref 0 in List.iter (fun (l, v) -> let label = Label.create ~font ~text:l ~anchor:`E sub in let textvariable = string_tv frame v in let var = Entry.create ~font ~textvariable ~width:40 sub in grid ~row:!row ~column:0 ~sticky:"e" [ label ]; grid ~row:!row ~column:1 ~sticky:"w" [ var ]; incr row; ) box; pack ~anchor:`W [ sub ] ;; let scrolled_listbox ?(click = fun _ _ -> ()) ?(context = fun _ _ -> ()) ?(separator = true) ?(height = 8) frame = let f = Frame.create frame in let lb = Listbox.create ~selectmode:`Multiple ~width:20 ~height ~exportselection:false f in let sb = Scrollbar.create ~orient:`Vertical ~command:(Listbox.yview lb) f in Listbox.configure ~yscrollcommand:(Scrollbar.set sb) ~font lb; let sep = Frame.create ~width:30 f in pack ~side:`Left [ lb ]; pack ~side:`Left ~fill:`Y [ sb ]; if separator then pack ~side:`Left [ sep ]; bind ~events:[ `ButtonPressDetail 1 ] ~fields:[ `MouseY ] ~action:(fun einfo -> let `Num row = Listbox.nearest lb ~y:(einfo.Tk.ev_MouseY) in Timer.set ~ms:0 ~callback:(fun () -> click lb row) ) lb; bind ~events:[ `ButtonPressDetail 3 ] ~fields:[ `MouseY ] ~action:(fun einfo -> let `Num row = Listbox.nearest lb ~y:(einfo.Tk.ev_MouseY) in Timer.set ~ms:0 ~callback:(fun () -> context lb row) ) lb; (f, lb) ;; let listbox_select lb selection = Listbox.selection_clear lb ~first:(`Num 0) ~last:`End; for i = 0 to Listbox.size lb do let s = Listbox.get lb (`Num i) in if List.mem s selection then Listbox.selection_set lb ~first:(`Num i) ~last:(`Num i) done ;; let listbox_get_selection lb = List.map (fun index -> Listbox.get lb ~index) (Listbox.curselection lb) ;; let indented_cond_frame frame enablers = (* Returns a subframe of [frame] that is only mapped if the boolean * variable [!enable] is true. [enable_text] is the text for the * checkbox that toggles [!enable]. *) let onchange_enable = ref (fun () -> ()) in List.iter (fun (enable, enable_text) -> let enable_tv = bool_tv ~onchange:(fun () -> !onchange_enable()) frame enable in let cb = Checkbutton.create ~font ~text:enable_text ~variable:enable_tv frame in pack ~anchor:`W [cb]; ) enablers; let is_enabled() = let p = ref false in List.iter (fun (enable, _) -> p := !p || !enable) enablers; !p in let frame' = Frame.create frame in let indent = Frame.create ~width:30 frame' in let frame'' = Frame.create frame' in pack ~anchor:`W [frame']; let frame''_is_packed = ref false in let frame''_pack b = if b <> !frame''_is_packed then begin if b then pack ~side:`Left [indent; frame''] else Pack.forget [ frame'' ]; frame''_is_packed := b end in frame''_pack (is_enabled()); onchange_enable := (fun () -> frame''_pack (is_enabled())); frame'' ;; let double_listbox frame available objects scan = let boxes = Frame.create frame in let (f_left,lb_left) = scrolled_listbox boxes in let (f_right,lb_right) = scrolled_listbox ~separator:false boxes in let f_buttons = Frame.create boxes in let b_add = Button.create ~font ~text:"Add >>" f_buttons in let b_del = Button.create ~font ~text:"<< Del" f_buttons in let b_up = Button.create ~font ~text:"Up ^" f_buttons in let b_down= Button.create ~font ~text:"Down v" f_buttons in let b_scan= Button.create ~font ~text:"Rescan" f_buttons in let f_sep = Frame.create ~width:30 boxes in pack ~fill:`X [ b_add; b_del; b_up; b_down; b_scan ]; pack ~side:`Left [ coe f_left; coe f_buttons; coe f_sep; coe f_right ]; pack [ boxes ]; let update() = let still_available = (* available - objects *) List.filter (fun m -> not (List.mem m !!objects)) !!available in Listbox.delete lb_left ~first:(`Num 0) ~last:`End; Listbox.insert lb_left ~index:`End ~texts:still_available; Listbox.delete lb_right ~first:(`Num 0) ~last:`End; Listbox.insert lb_right ~index:`End ~texts:!!objects; in let rescan() = !available := scan(); update() in let add() = if Listbox.curselection lb_left = [] then begin let popup = Toplevel.create frame in Wm.title_set popup "Add File"; Wm.transient_set popup ~master:(Winfo.toplevel frame); add_headline popup "Add File"; add_para popup "Enter the name of the module to add. Note that you can also select the modules in the left box and press 'Add' to quickly move the modules to the right box."; let modname = ref "" in label_box popup [ "Name of new module: ", modname ]; let p_buttons = Frame.create popup in let b_ok = Button.create ~font ~text:"OK" ~command:(fun () -> if !modname <> "" then !objects := !!objects @ [ !modname ]; update(); destroy popup) p_buttons in let b_cancel = Button.create ~font ~text:"Cancel" ~command:(fun () -> destroy popup) p_buttons in pack ~side:`Left [b_ok; b_cancel]; add_para popup ""; pack [p_buttons]; end else begin let items = List.map (fun index -> Listbox.get lb_left ~index) (Listbox.curselection lb_left) in !objects := !!objects @ items; update() end in let del() = if Listbox.curselection lb_right = [] then begin ignore (dialog ~parent:!top ~title:"Nothing selected" ~message:"Please select the modules you want to delete in the right box!" ~buttons:[ "OK" ] ~default:0 ()) end else begin let items = List.map (fun index -> Listbox.get lb_right ~index) (Listbox.curselection lb_right) in !objects := List.filter (fun m -> not (List.mem m items)) !!objects; update() end in let move_dlg() = ignore (dialog ~parent:!top ~title:"Bad Selection" ~message:"Please select the (single) module you want to move in the right box!" ~buttons:[ "OK" ] ~default:0 ()) in let move g () = if List.length (Listbox.curselection lb_right) <> 1 then move_dlg() else begin let index = List.hd (Listbox.curselection lb_right) in let `Num n = index in let n' = g n in if n' >= 0 && n' < List.length !!objects then begin let item = Listbox.get lb_right ~index:(index :> Tk.listbox_index) in !objects := delete_at n !!objects; !objects := insert_at n' item !!objects; update(); Listbox.selection_set lb_right ~first:(`Num n') ~last:(`Num n'); end end in if !!available = [] then rescan() else update(); Button.configure ~command:add b_add; Button.configure ~command:del b_del; Button.configure ~command:(move pred) b_up; Button.configure ~command:(move succ) b_down; Button.configure ~command:rescan b_scan; (* Returns the [update] function *) update ;; let redraw() = destroy !topframe; let f = Frame.create !top in let f1 = Frame.create ~width:5 f in let f2 = Frame.create f in let f3 = Frame.create ~width:5 f in pack ~expand:true ~fill:`Y [f]; pack ~side:`Left [f1]; pack ~side:`Left ~fill:`Y [f2]; pack ~side:`Left [f3]; let func = List.nth !screens !current_screen in topframe := coe f; func f2 ;; let footer frame = let box = Frame.create frame in pack ~side:`Bottom ~fill:`X [box]; let sep1 = Frame.create ~height:15 box in let b = Frame.create ~height:1 ~background:`Black box in let sep2 = Frame.create ~height:15 box in pack [ sep1 ]; pack ~fill:`X ~expand:true [b]; pack [ sep2 ]; let f = Frame.create box in let m1 = Frame.create f in pack ~fill:`X ~expand:true ~side:`Left [ m1 ]; let prev_b = Button.create ~font ~text:"Previous" ~state:`Disabled ~command:(fun () -> decr current_screen; redraw()) m1 in pack ~side:`Left [prev_b]; if !current_screen > 0 then Button.configure ~state:`Normal prev_b; let m2 = Frame.create f in let k = ref 0 in List.iter (fun scr -> let k' = !k in let b = Button.create ~font ~text:(string_of_int (!k+1)) ~command:(fun () -> current_screen := k'; redraw()) m2 in if k' = !current_screen then Button.configure ~background:`Blue ~activebackground:`Blue ~foreground:`White b; pack ~side:`Left [b]; incr k ) !screens; pack ~side:`Left [m2]; let m3 = Frame.create f in pack ~fill:`X ~expand:true ~side:`Left [ m3 ]; let next_b = Button.create ~font ~text:"Next" ~state:`Disabled ~command:(fun () -> incr current_screen; redraw()) m3 in pack ~side:`Right [next_b]; if !current_screen < List.length !screens - 1 then Button.configure ~state:`Normal next_b; pack ~fill:`X [ f ] ;; (**********************************************************************) let first_time = ref true;; let intro_screen frame = add_headline frame "The Makefile and META wizard"; add_para frame "This wizard helps you creating Makefiles and META \ files for simple projects. It assumes that all your source files \ reside in a single directory, and that all source files are OCaml \ files (no support for mixed OCaml/C projects). ocamllex, ocamlyacc, \ and camlp4 are supported."; add_para frame "The wizard generates a Makefile, and the Makefile \ produces the META file. The Makefile is not perfect, and is not the ideal \ choice for everybody, but it is a starting point for your project. \ You can later fine-tune the contents of the Makefile by adding your own rules, \ and by overriding the definitions. The Makefile is commented, and not \ overly complicated."; add_para frame "The settings you enter here can be stored in a file \ containing the state of the wizard. This file is called .make-wizard. \ It is recommended to use this feature to save the state between the \ wizard sessions."; (* "" *) footer frame; update(); if !first_time && Sys.file_exists ".make-wizard" then begin match dialog ~parent:frame ~title:"Load .make-wizard?" ~message:"Do you want to load the file .make-wizard, and continue your last session?" ~buttons:[ "Yes, please load the file"; "No, start with empty fields" ] ~default:0 () with 0 -> load() | _ -> () end; first_time := false; ;; add_screen intro_screen;; (**********************************************************************) let general_screen frame = add_headline frame "General"; add_para frame "Please enter the name of the package, the version number, \ and the description first. The name must be a single, alphanumeric string \ (including _ and -). The version is an arbitrary string, like the description. \ All fields are mandatory."; (* "" *) label_box frame [ "Package name: ", wiz_package_name; "Package version: ", wiz_package_version; "Package description: ", wiz_package_description ]; footer frame ;; add_screen general_screen;; (**********************************************************************) let pkginfo lb row = (* when the user right-clicks at a listbox row *) let pkg = Listbox.get lb (`Num row) in let version = try Findlib.package_property [] pkg "version" with Not_found -> "N/A" in let description = try Findlib.package_property [] pkg "description" with Not_found -> "N/A" in let popup = Toplevel.create !top in Wm.transient_set popup ~master:(Winfo.toplevel !top); let f = Frame.create popup in let title = "About " ^ pkg ^ " (" ^ version ^ ")" in add_headline f title; Wm.title_set popup title; add_para f ("Description: " ^ description); add_para f "Modules:"; let click sublb _ = Listbox.selection_clear sublb ~first:(`Num 0) ~last:`End in let (f_sublb, sublb) = scrolled_listbox ~click f in let modules = try Fl_split.in_words (Findlib.package_property [] pkg "browse_interfaces") with Not_found -> let dir = Findlib.package_directory pkg in let files = Array.to_list(Sys.readdir dir) in List.map (fun name -> String.capitalize (Filename.chop_suffix name ".cmi")) (List.filter (fun name -> Filename.check_suffix name ".cmi") files ) in Listbox.insert sublb ~index:`End ~texts:modules; pack ~anchor:`W [ f_sublb ]; pack ~anchor:`W [ f ]; let close = Button.create ~text:"Close" ~font ~command:(fun () -> destroy popup) f_sublb in pack ~anchor:`Nw ~fill:`X [close] ;; (**********************************************************************) let preprocessor_scan_extensions() = (* Find out all packages with a "preprocessor" predicate *) let packages = Fl_package_base.list_packages() in let plist = List.filter (fun pkg -> try let _ = Findlib.package_property [ "preprocessor"; "syntax" ] pkg "archive" in true with Not_found -> false ) packages in (* Add all selected extensions, if they do not occur yet: *) let plist' = List.filter (fun pkg -> not (List.mem pkg plist) ) !wiz_camlp4_selected in List.sort Pervasives.compare (plist @ plist') ;; let preprocessor_screen frame = add_headline frame "Preprocessing"; add_para frame "Here you can specify whether your source files are \ preprocessed by camlp4. Simply skip this page if you do not want to \ invoke a preprocessor, or if you don't know what this means."; (* "" *) let frame'' = indented_cond_frame frame [ wiz_enable_camlp4, "Enable camlp4" ] in let tv = string_tv frame'' wiz_camlp4_syntax in let rb_o = Radiobutton.create ~font ~text:"Standard syntax" ~variable:tv ~value:"camlp4o" frame'' in let rb_r = Radiobutton.create ~font ~text:"Revised syntax" ~variable:tv ~value:"camlp4r" frame'' in pack ~anchor:`W [rb_o; rb_r]; add_para frame'' "Use the following packaged syntax extensions (click the \ right mouse button to find out more about a package):"; (* "" *) if !wiz_camlp4_extensions = [] then wiz_camlp4_extensions := preprocessor_scan_extensions(); let click lb row = (* when the user clicks at a listbox row *) wiz_camlp4_selected := listbox_get_selection lb; in let (f_lb,lb) = scrolled_listbox ~click ~context:pkginfo frame'' in Listbox.insert lb ~index:`End ~texts:!wiz_camlp4_extensions; listbox_select lb !wiz_camlp4_selected; pack ~anchor:`W [f_lb]; let rescan = Button.create ~text:"Rescan" ~font ~command:(fun () -> wiz_camlp4_extensions := preprocessor_scan_extensions(); Listbox.delete lb ~first:(`Num 0) ~last:`End; Listbox.insert lb ~index:`End ~texts:!wiz_camlp4_extensions; listbox_select lb !wiz_camlp4_selected; ) f_lb in let clear = Button.create ~text:"Clear" ~font ~command:(fun () -> wiz_camlp4_selected := []; listbox_select lb []) f_lb in pack ~anchor:`Nw ~fill:`X [ rescan; clear ]; add_para frame'' "Specify here further options to the camlp4 invocation. \ For example, you can load camlp4 modules like pa_ifdef.cmo, and pass the -D \ options to it."; (* "" *) label_box frame'' [ "Camlp4 options: ", wiz_camlp4_options ]; footer frame ;; add_screen preprocessor_screen;; (**********************************************************************) let prerequisites_scan_packages() = (* Find out all packages *) List.sort Pervasives.compare (Fl_package_base.list_packages()) ;; let prerequisites_screen frame = add_headline frame "Prerequisites"; add_para frame "If your modules use packages, you can specify these \ prerequisites here. It is sufficient to select the packages on which \ your modules depend directly. Indirect dependencies can be resolved \ by findlib automatically. Click the right mouse button to find out \ more about a package."; (* "" *) if !wiz_all_packages = [] then wiz_all_packages := prerequisites_scan_packages(); let click lb row = (* when the user clicks at a listbox row *) wiz_required_packages := listbox_get_selection lb; in let (f_lb,lb) = scrolled_listbox ~height:18 ~click ~context:pkginfo frame in Listbox.insert lb ~index:`End ~texts:!wiz_all_packages; listbox_select lb !wiz_required_packages; pack ~anchor:`W [f_lb]; let rescan = Button.create ~text:"Rescan" ~font ~command:(fun () -> wiz_all_packages := prerequisites_scan_packages(); Listbox.delete lb ~first:(`Num 0) ~last:`End; Listbox.insert lb ~index:`End ~texts:!wiz_all_packages; listbox_select lb !wiz_required_packages; ) f_lb in let clear = Button.create ~text:"Clear" ~font ~command:(fun () -> wiz_required_packages := []; listbox_select lb []) f_lb in pack ~anchor:`Nw ~fill:`X [ rescan; clear ]; footer frame ;; add_screen prerequisites_screen;; (**********************************************************************) let buildlib_scan_modules() = let files = Array.to_list(Sys.readdir ".") in let suffixes = Fl_split.in_words_ws !wiz_source_suffixes in let files' = List.filter (fun f -> List.exists (Filename.check_suffix f) suffixes ) files in let files'' = List.map (fun f -> String.capitalize (Filename.chop_extension f) ) files' in remove_dups (List.sort Pervasives.compare files'') ;; let buildlib_screen frame = add_headline frame "Build Library"; add_para frame "The next question is how to build the library, i.e. the \ cma or cmxa archive. It is recommended to create such an archive even if \ the real target of the build process is an executable, because you can load \ it into the toploop at once. However, make sure that you do not put the \ main program of the executable into the archive, as it is usually stripped \ off from the executable, and nothing would happen when you start it."; (* add_para frame "You can select whether you want to create only a bytecode \ archive, a native archive, or both. In the latter case, the simplest way \ is to begin with the bytecode archive, and to copy your specification to \ the native box by pressing the button \"Like bytecode\"."; add_para frame "If you do not want to create an archive at all, \ skip this page."; *) (* "" *) let frame' = indented_cond_frame frame [ wiz_byte_enable, "Enable bytecode archive"; wiz_nat_enable, "Enable native archive"; ] in add_para frame' "Move the available modules to the right-hand box in the required order."; let update = double_listbox frame' (ref wiz_available) (ref wiz_objects) buildlib_scan_modules in add_para frame "By default, only the suffixes .ml, .mli, .mll, and .mly are used to recognize source code files. You can add here additional suffixes (this requires that you extend the Makefile by your own rules)."; label_box frame [ "Source code suffixes: ", wiz_source_suffixes ]; footer frame ;; add_screen buildlib_screen;; (**********************************************************************) let enter_name parent followup = let popup = Toplevel.create parent in let title = "New Executable" in Wm.transient_set popup ~master:(Winfo.toplevel parent); Wm.title_set popup title; let frame = Frame.create popup in pack [frame]; add_headline frame title; add_para frame "Of course, the new executable must have a name."; let name = ref "" in label_box frame [ "Name: ", name ]; pack [ Frame.create ~height:10 frame ]; let buttons = Frame.create frame in let ok_b = Button.create ~font ~text:"OK" ~command:(fun () -> destroy popup; followup !name) buttons in let cancel_b = Button.create ~font ~text:"Cancel" ~command:(fun () -> destroy popup) buttons in pack ~side:`Left [ ok_b; cancel_b ]; pack [buttons] ;; let buildexec_screen frame = add_headline frame "Build Executables"; add_para frame "You can specify the executables to build in the following \ way. Press \"New\" and enter the name of the executable, then add the modules \ to link in the box that appears. The cma/cmxa archive from the previous \ screen is linked anyway, so its modules cannot be selected again."; add_para frame "Leave the list of executables empty if you do not want to \ build any."; (* "" *) let update_listbox = ref (fun () -> ()) in let show = ref (fun _ -> ()) in let hide = ref (fun _ -> ()) in let click lb row = let name = Listbox.get lb ~index:(`Num row) in !show name in let newexec() = enter_name frame (fun name -> (* This function is called after the user pressed "OK" *) if List.mem name !wiz_executables then begin (* It is not allowed to enter the same name twice *) ignore( dialog ~parent:frame ~title:"Already exists" ~message:"This name already exists!" ~buttons:["OK"] ()) end else begin wiz_executables := List.sort Pervasives.compare (name :: !wiz_executables); wiz_exec_objects := (name, ref []) :: !wiz_exec_objects; wiz_exec_native := (name, ref false) :: !wiz_exec_native; !update_listbox(); !show name end ) in let remexec lb () = let sel = listbox_get_selection lb in if sel = [] then begin ignore( dialog ~parent:frame ~title:"Nothing selected" ~message:"Select the executable to remove first!" ~buttons:["OK"] ()) end else begin wiz_executables := List.filter (fun n -> not (List.mem n sel)) !wiz_executables; wiz_exec_objects := List.filter (fun (n,_) -> not (List.mem n sel)) !wiz_exec_objects; wiz_exec_native := List.filter (fun (n,_) -> not (List.mem n sel)) !wiz_exec_native; !update_listbox(); !hide() end in let (f_lb,lb) = scrolled_listbox ~click ~height:3 frame in Listbox.configure ~selectmode:`Single lb; Listbox.insert lb ~index:`End ~texts:!wiz_executables; pack ~anchor:`W [f_lb]; let new_b = Button.create ~font ~text:"New" ~command:newexec f_lb in let remove_b = Button.create ~font ~text:"Remove" ~command:(remexec lb) f_lb in pack ~anchor:`Nw ~fill:`X [ new_b; remove_b ]; let f1 = Frame.create frame in pack [f1]; let frame' = Frame.create f1 in let frame'_packed = ref false in let modbox_available = ref (ref []) in let modbox_objects = ref (ref []) in let modbox_scan() = let mlist = buildlib_scan_modules() in List.filter (fun m -> not (List.mem m !wiz_objects)) mlist in add_para frame' "Move the available modules to the right-hand box in the required order."; let update_modbox = double_listbox frame' modbox_available modbox_objects modbox_scan in add_para frame' "Select the type of the executable:"; let radio = Frame.create frame' in let type_ref = ref false in let type_ref_ref = ref type_ref in let type_tv = bool_tv ~onchange:(fun () -> !type_ref_ref := !type_ref) frame' type_ref in let byte_r = Radiobutton.create ~font ~text:"Bytecode executable" ~variable:type_tv ~value:"0" radio in let nat_r = Radiobutton.create ~font ~text:"Native executable" ~variable:type_tv ~value:"1" radio in pack ~side:`Left [byte_r; nat_r ]; pack ~anchor:`W [radio]; let update_radio() = Textvariable.set type_tv (if !!type_ref_ref then "1" else "0") in footer frame; update_listbox := (fun () -> Listbox.delete lb ~first:(`Num 0) ~last:`End; Listbox.insert lb ~index:`End ~texts:!wiz_executables; ); show := (fun name -> let k = find_pos name !wiz_executables in Listbox.selection_clear lb ~first:( `Num 0 ) ~last:`End; Listbox.selection_set lb ~first:(`Num k) ~last:(`Num k); if not !frame'_packed then ( pack [frame']; frame'_packed := true; ); modbox_objects := List.assoc name !wiz_exec_objects; type_ref_ref := List.assoc name !wiz_exec_native; update_modbox(); update_radio() ); hide := (fun () -> if !frame'_packed then ( Pack.forget [frame']; frame'_packed := false; ); ) ;; add_screen buildexec_screen;; (**********************************************************************) let generate_screen frame = add_headline frame "Generate Makefile"; add_para frame "Finally, the Makefile can be generated from your inputs. \ You can set the name of the Makefile to a non-standard name. Furthermore, \ you can specify a second file that will be appended to the generated Makefile, \ this is useful to extend the Makefile rules by your own additions."; (* "" *) label_box frame [ "Name of Makefile: ", wiz_makefile_name; "Local extensions in: ", wiz_local_makefile_name ; "Default target of 'make': ", wiz_make_default; ]; add_para frame ""; let show_b = Button.create ~font ~text:"Show Makefile" ~command:(fun () -> let maketext = makemake() in let popup = Toplevel.create frame in Wm.title_set popup "Generated Makefile"; add_headline popup "Generated Makefile"; let t = Text.create ~width:80 ~height:25 popup in pack [t]; Text.insert ~index:(`End,[]) ~text:maketext t; ) frame in let save_b = Button.create ~font ~text:"Save Makefile" ~command:(fun () -> let maketext = makemake() in let cont = not (Sys.file_exists !wiz_makefile_name) || ( dialog ~parent:frame ~title:"File already exists" ~message:("The file " ^ !wiz_makefile_name ^ " already exists. Overwrite?") ~buttons:[ "OK"; "Cancel" ] () = 0) in if cont then begin let f = open_out !wiz_makefile_name in output_string f maketext; close_out f end ) frame in pack [show_b; save_b]; add_headline frame "Quit"; add_para frame "The following button quits the wizard. You are asked whether you want to save the state first."; let quit_b = Button.create ~font ~text:"Finish & Quit" ~command:(fun () -> if ask_and_save frame then destroy !top) frame in pack [show_b; quit_b]; footer frame ;; add_screen generate_screen;; (**********************************************************************) Findlib.init(); top := openTk(); (* current_screen := 5; *) Wm.title_set !top "findlib/make-wizard"; Wm.protocol_set !top ~name:"WM_DELETE_WINDOW" ~command:(fun () -> if ask_and_save !top then destroy !top); Toplevel.configure ~width:(pixels(`Pt 450.0)) ~height:(pixels (`Pt 650.0)) (Winfo.toplevel !top); Pack.propagate_set !top false; topframe := coe(Frame.create !top); redraw(); mainLoop();; (* ====================================================================== * History: * * $Log: make_wizard.ml,v $ * Revision 1.3 2002/09/22 20:12:35 gerd * Renamed modules (prefix fl_) * * Revision 1.2 2002/07/29 19:52:23 gerd * Fixes for OCaml 3.05 * * Revision 1.1 2002/05/26 14:09:07 gerd * Renaming * * Revision 1.1 2002/05/05 20:40:26 gerd * Initial revision * * *) not-ocamlfind-0.14/local-packages/ocamlfind/src/findlib-toolbox/make_wizard.pattern0000644000175000017500000003454114770304423027613 0ustar stephsteph## $Id$ ## ---------------------------------------------------------------------- ## ## This is the pattern for the Makefile. It consists of several sections, ## every section begins with [name] on a single line, and ends where the ## next section starts. Inside the sections, variables are written as ## [name], too. ## Comments that must not be copied to the output file begin with two ## hash marks. [intro] # ---------------------------------------------------------------------- # How to build the package [name]: # ---------------------------------------------------------------------- # # make: Same as "make all" # make all: Normally "make byte", but can also be set to "make opt" # make byte: Makes the bytecode archive and the bytecode executables # make opt: Makes the native archive and the native executable # make install: Install all installable files as package # make uninstall: Uninstall the package # make clean: Delete all files that can be remade # # The usual order of invocation is: # - make byte # - (optionally) make opt # - make install # - make clean # # You may want to give the -s option if you do not want to see the details # of the build process (e.g. make -s all). # # ---------------------------------------------------------------------- # Important for developers # ---------------------------------------------------------------------- # # This Makefile writes a copy of itself with appended dependencies. # The copy is usually stored in the file .make-wizard.[makefile_name]. # If you want to invoke "make" for targets where the dependencies are # involved, you have to specify -f .make-wizard.[makefile_name] on # the command line, e.g. # # make -f .make-wizard.[makefile_name] sample.cmo # # Otherwise, the dependencies are ignored, and you get errors that are # hard to explain. # # If you want to modify this Makefile, it is a good idea to put the # modifications into a second file, and to enable the local Makefile # extension in the wizard. This effects that the modifications are appended # to this Makefile, so you can add rules and override variables without # coming into conflict with the wizard. [def_general] # ---------------------------------------------------------------------- # Definitions # ---------------------------------------------------------------------- NAME = [name] # The name of the package. MFNAME = [makefile_name] # The name of this Makefile. (You must change this definition if you rename # the Makefile!) MF2NAME = .make-wizard.$(MFNAME) # The name of the generated Makefile (a copy of this Makefile plus the # dependencies) TEMPNAME = .make-wizard.temps # The name of a file containing the names of temporary files VERSION = [version] # The version of this package DESCRIPTION = [description] # The description of this package GENERATOR_EXTS = .mll .mly # These suffixes indicate that a generator must be called for them MAKE_META = _meta # Make the META file by this rule. (An empty definition turns META generation # off.) INSTALL = _findlib_install # Which rule to use for installation UNINSTALL = _findlib_uninstall # Which rule to use for deinstallation MAKEMAKE_HOOK = # Set this to the name of a rule to add your own definitions to $(MF2NAME) ## The def_byte_archive section is only included if the byte archive is ## enabled: [def_byte_archive] BYTE_ARCHIVE = $(NAME).cma # The name of the resulting bytecode archive. BYTE_OBJECTS = [byte_objects] # The cmo objects that are linked together, and are put into the byte archive. BYTE_FILES = $(BYTE_OBJECTS) $(BYTE_OBJECTS:.cmo=.cmi) $(BYTE_ARCHIVE) # The files that are generated in order to make the byte archive. Note # that .ml and .mli files are missing that are generated from # .mly and .mll files. BYTE_INST = $(BYTE_OBJECTS:cmo=cmi) $(BYTE_OBJECTS:.cmo=.mli) $(BYTE_ARCHIVE) # The files that will be installed after the byte archive is made. Not # every file exists. ## The def_native_archive section is only included if the native archive is ## enabled: [def_native_archive] NAT_ARCHIVE = $(NAME).cmxa # The name of the resulting native archive. NAT_OBJECTS = [nat_objects] # The cmx objects that are linked together, and are put into the native archive. NAT_FILES = $(NAT_OBJECTS) $(NAT_OBJECTS:.cmx=.o) $(NAT_OBJECTS:.cmo=.cmi) \ $(NAT_ARCHIVE) $(NAT_ARCHIVE:.cmxa=.a) # The files that are generated in order to make the native archive. Note # that .ml and .mli files are missing that are generated from # .mly and .mll files. NAT_INST = $(NAT_OBJECTS:.cmo=.cmi) $(NAT_OBJECTS:.cmo=.mli) $(NAT_ARCHIVE) \ $(NAT_ARCHIVE:.cmxa=.a) # The files that will be installed after the native archive is made. Not # every file exists. [def_byte_exec] BYTE_EXEC_TARGETS = [byte_executables] # The list of bytecode executables. BYTE_EXEC_OBJECTS = [byte_exec_objects] # The list of cmo modules that are linked into bytecode executables BYTE_EXEC_FILES = $(BYTE_EXEC_OBJECTS) $(BYTE_EXEC_OBJECTS:.cmo=.cmi) \ $(BYTE_EXEC_TARGETS) # The list of files that are generated in order to make the bytecode # executables. Note that .ml and .mli files are missing that are generated # from .mly and .mll files. BYTE_EXEC_INST = $(BYTE_EXEC_TARGETS) # The files to install as bytecode executables. [def_nat_exec] NAT_EXEC_TARGETS = [nat_executables] # The list of native executables. NAT_EXEC_OBJECTS = [nat_exec_objects] # The list of cmx modules that are linked into native executables NAT_EXEC_FILES = $(NAT_EXEC_OBJECTS) $(NAT_EXEC_OBJECTS:.cmx=.cmi) \ $(NAT_EXEC_OBJECTS:.cmx=.o) $(NAT_EXEC_TARGETS) # The list of files that are generated in order to make the native # executables. Note that .ml and .mli files are missing that are generated # from .mly and .mll files. NAT_EXEC_INST = $(NAT_EXEC_TARGETS) # The files to install as native executables. [def_props] PREREQUISITES = [prereqs] # The required packages. PPOPTS = [ppopts] # Preprocessor options. MTOPTS = [mtopts] # Multi-threading options INCOPTS = # -I options (currently unused, but this may change in the future) OTHER_INST = META # Files to install that are not mentioned in the other XXX_INST variables #TASKBYTELINKOPTS = -custom # Uncomment this line to create stand-alone executables [def_tools] # Tools and tasks: "Tools" are the commands to call, and "tasks" are the tools # to use for certain situations. OCAMLFIND = ocamlfind OCAMLLEX = ocamllex OCAMLYACC = ocamlyacc OCAMLDEP = $(OCAMLFIND) ocamldep OCAMLC = $(OCAMLFIND) ocamlc OCAMLCP = $(OCAMLFIND) ocamlcp OCAMLOPT = $(OCAMLFIND) ocamlopt # # These are the tools. TASKLEX = $(OCAMLLEX) $(TASKLEXOPTS) TASKYACC = $(OCAMLYACC) $(TASKYACCOPTS) TASKDEP = $(OCAMLDEP) $(INCOPTS) $(PPOPTS) -package "$(PREREQUISITES)" $(TASKDEPOPTS) TASKCI = $(OCAMLC) $(INCOPTS) $(PPOPTS) -package "$(PREREQUISITES)" -c $(TASKCIOPTS) TASKBYTECO = $(OCAMLC) $(INCOPTS) $(PPOPTS) $(MTOPTS) -package "$(PREREQUISITES)" -c -g $(TASKBYTECOOPTS) TASKBYTELINK = $(OCAMLC) $(INCOPTS) $(PPOPTS) $(MTOPTS) -package "$(PREREQUISITES)" -linkpkg $(TASKBYTELINKOPTS) TASKBYTEAR = $(OCAMLC) -a $(TASKBYTEAROPTS) TASKNATCO = $(OCAMLOPT) $(INCOPTS) $(PPOPTS) $(MTOPTS) -package "$(PREREQUISITES)" -c $(TASKNATCOOPTS) TASKNATLINK = $(OCAMLOPT) $(INCOPTS) $(PPOPTS) $(MTOPTS) -package "$(PREREQUISITES)" -linkpkg $(TASKNATLINKOPTS) TASKNATAR = $(OCAMLOPT) -a $(TASKNATAROPTS) TASKINSTALL = $(OCAMLFIND) install $(NAME) $(TASKINSTALLOPTS) TASKREMOVE = $(OCAMLFIND) remove $(NAME) $(TASKREMOVEOPTS) # # These are the tasks. The names mean the following: # TASKLEX: Used to create a lexer # TASKYACC: Used to create a parser # TASKDEP: Used to analyze the dependencies # TASKCI: Used to compile interface files # TASKBYTECO, TASKNATCO: Used to compile implementation files # TASKBYTELINK, TASKNATLINK: Used to create executables # TASKBYTEAR, TASKNATAR: Used to create archives # TASKINSTALL: Used to install the package # TASKREMOVE: Used to remove the package # INCOPTS: -I options # PPOPTS: Options to specify the preprocessor # MTOPTS: -thread (if necessary) # NATONLY: -native (if necessary) # For every task , there is a variable for task-specific options OPTS. [rules] # ---------------------------------------------------------------------- # Rules # ---------------------------------------------------------------------- [default_target] .PHONY: all all: [default_target] [suffix_rules] # The suffix rules: They specify how to make a file ending in suffix X from # a source file ending in suffix Y. For every suffix rule, there is a task # defining what to do. .SUFFIXES: .ml .mli .cmo .cmx .cmi .mll .mly .mli.cmi: @echo "" $(TASKCI) $< .ml.cmo: @echo "" $(TASKBYTECO) $< .ml.cmx: @echo "" $(TASKNATCO) $< # The generator rules record the generated files: The "grep" checks whether # the filename already occurs in $(TEMPNAME), and the "echo" appends the # filename when missing. .mll.ml: @echo "" $(TASKLEX) $< touch $(TEMPNAME) grep -F -x -q -e "$@" $(TEMPNAME) || echo "$@" >>$(TEMPNAME) .mly.ml: @echo "" $(TASKYACC) $< touch $(TEMPNAME) grep -F -x -q -e "$@" $(TEMPNAME) || echo "$@" >>$(TEMPNAME) # The _dummy rule does nothing: _dummy: : [generate] # The following rule checks which lex and yacc targets exist, and calls # MAKE recursively. .PHONY: _meta _meta: @echo "" echo "name = \"$(NAME)\"" >META echo "version = \"$(VERSION)\"" >>META echo "description = \"$(DESCRIPTION)\"" >>META echo "requires = \"$(PREREQUISITES)\"" >>META test -z "$(BYTE_ARCHIVE)" || \ echo "archive(byte) = \"$(BYTE_ARCHIVE)\"" >>META test -z "$(NAT_ARCHIVE)" || \ echo "archive(native) = \"$(NAT_ARCHIVE)\"" >>META .PHONY: _generator _generator: $(MAKE_META) @echo "" targets=$$( \ { \ for obj in _dummy $(BYTE_OBJECTS) $(BYTE_EXEC_OBJECTS); do \ test "_dummy" != "$$obj" || continue; \ for ext in $(GENERATOR_EXTS); do \ if [ -f "$${obj%.cmo}$$ext" ]; then \ echo "$${obj%.cmo}.ml"; \ fi; \ done; \ done && \ for obj in _dummy $(NAT_OBJECTS) $(NAT_EXEC_OBJECTS); do \ test "_dummy" != "$$obj" || continue; \ for ext in $(GENERATOR_EXTS); do \ if [ -f "$${obj%.cmx}$$ext" ]; then \ echo "$${obj%.cmx}.ml"; \ fi; \ done; \ done; \ } | sort | uniq \ ) && \ { test -z "$$targets" || $(MAKE) -f $(MFNAME) $$targets; } # The following rule calls ocamldep for the right files, and creates # a file that consists of the contents of this Makefile, and of the output # of ocamldep. .PHONY: _makemake _makemake: _generator @echo "" cat $(MFNAME) >$(MF2NAME) test -z "$(MAKEMAKE_HOOK)" || $(MAKE) -f $(MFNAME) $(MAKEMAKE_HOOK) echo "# ---------------------------------------- dependencies:" >>$(MF2NAME) targets=$$( \ { \ nat=-native-filter && \ byte=-bytecode-filter && \ for obj in _dummy $(BYTE_OBJECTS); do \ test "_dummy" != "$$obj" || continue; \ echo "$${obj%.cmo}.ml"; \ echo "$${obj%.cmo}.mli"; \ nat=""; \ done && \ for obj in _dummy $(NAT_OBJECTS); do \ test "_dummy" != "$$obj" || continue; \ echo "$${obj%.cmx}.ml"; \ echo "$${obj%.cmx}.mli"; \ byte=""; \ done; \ echo "$$byte $$nat"; \ } | sort | uniq \ ) && \ $(TASKDEP) $$targets >>$(MF2NAME) ## The following section is appended to _makemake for every executable: [makemake_exec] echo "# --- dependencies for [execname]:" >>$(MF2NAME) $(TASKDEP) [switches] [deptargets] >>$(MF2NAME) ## Begin next section immediately to avoid empty lines: [dummy] [byte] .PHONY: byte byte: _byte .PHONY: _byte _byte: _makemake @echo "" if [ -n "$(BYTE_ARCHIVE)" ]; then \ $(MAKE) -f $(MF2NAME) $(BYTE_ARCHIVE); \ fi if [ -n "$(BYTE_EXEC_TARGETS)" ]; then \ $(MAKE) -f $(MF2NAME) $(BYTE_EXEC_TARGETS); \ fi @echo "" [opt] .PHONY: opt opt: _opt .PHONY: _opt _opt: _makemake @echo "" if [ -n "$(NAT_ARCHIVE)" ]; then \ $(MAKE) -f $(MF2NAME) $(NAT_ARCHIVE); \ fi if [ -n "$(NAT_EXEC_TARGETS)" ]; then \ $(MAKE) -f $(MF2NAME) $(NAT_EXEC_TARGETS); \ fi @echo "" [byte_archive] $(BYTE_ARCHIVE): $(BYTE_OBJECTS) @echo "" $(TASKBYTEAR) -o $(BYTE_ARCHIVE) $(BYTE_OBJECTS) [native_archive] $(NAT_ARCHIVE): $(NAT_OBJECTS) @echo "" $(TASKNATAR) -o $(NAT_ARCHIVE) $(NAT_OBJECTS) ## The following section is included for every bytecode executable again. [byte_exec] [execname]: $(BYTE_ARCHIVE) [execobjs] @echo "" $(TASKBYTELINK) -o [execname] $(BYTE_ARCHIVE) [execobjs] [nat_exec] [execname]: $(NAT_ARCHIVE) [execobjs] @echo "" $(TASKNATLINK) -o [execname] $(NAT_ARCHIVE) [execobjs] [clean] .PHONY: clean clean: @echo "" touch $(TEMPNAME) rm -f $(BYTE_FILES) $(NAT_FILES) $(BYTE_EXEC_FILES) $(NAT_EXEC_FILES) rm -f $(MF2NAME) cat $(TEMPNAME) | xargs rm -f rm -f $(TEMPNAME) .PHONY: CLEAN CLEAN: clean .PHONY: distclean distclean: clean [install] .PHONY: install install: $(INSTALL) .PHONY: _findlib_install _findlib_install: @echo "" files=$$( \ for f in $(BYTE_INST) $(NAT_INST) $(BYTE_EXEC_INST) $(NAT_EXEC_INST) $(OTHER_INST); do \ if [ -f "$$f" ]; then echo $$f; fi; \ done; \ ) && \ $(TASKINSTALL) $$files .PHONY: uninstall uninstall: $(UNINSTALL) .PHONY: _findlib_uninstall _findlib_uninstall: @echo "" $(TASKREMOVE) # The following rules just print some variables. .PHONY: _print_name _print_name: echo "$(NAME)" .PHONY: _print_version _print_version: echo "$(VERSION)" [local] # ---------------------------------------------------------------------- # Local additions # ---------------------------------------------------------------------- [trailer] ## ====================================================================== ## History: ## ## $Log: make_wizard.pattern,v $ ## Revision 1.2 2003/01/13 00:37:45 gerd ## Bugfix NATIVE_ARCHIVE ==> NAT_ARCHIVE (reported by ## Matt Gushee) ## ## Revision 1.1 2002/05/26 14:09:07 gerd ## Renaming ## ## Revision 1.1 2002/05/05 20:40:26 gerd ## Initial revision ## ## not-ocamlfind-0.14/local-packages/ocamlfind/src/findlib-toolbox/selected.xpm0000644000175000017500000000045014770304423026225 0ustar stephsteph#define selected_width 16 #define selected_height 16 static unsigned char selected_bits[] = { 0x55, 0x55, 0x00, 0x80, 0x01, 0x1c, 0x00, 0x82, 0x01, 0x02, 0x00, 0x81, 0x01, 0x01, 0x80, 0x80, 0x81, 0x00, 0x98, 0x80, 0xa1, 0x00, 0xa0, 0x80, 0xc1, 0x00, 0xc0, 0x80, 0x01, 0x00, 0xaa, 0xaa}; not-ocamlfind-0.14/local-packages/ocamlfind/src/findlib-toolbox/tree_editor.ml0000644000175000017500000006137614770304423026564 0ustar stephsteph(* $Id$ * ---------------------------------------------------------------------- * *) module Filesys = struct let join_path path = if path = [ "" ] then "/" else String.concat "/" path (* TODO *) let split_re = Str.regexp "/" (* TODO *) let split_path s = Str.split split_re s let list path = let path_name = join_path path in let d = Unix.opendir path_name in let l = ref [] in try while true do let e = Unix.readdir d in if e <> "." && e <> ".." then l := e :: !l done; assert false with End_of_file -> Unix.closedir d; List.sort Pervasives.compare !l | err -> Unix.closedir d; raise err let is_directory path = let path_name = join_path path in try (Unix.lstat path_name).Unix.st_kind = Unix.S_DIR with _ -> false let is_container path = let path_name = join_path path in try (Unix.stat path_name).Unix.st_kind = Unix.S_DIR with _ -> false end ;; module Filetree_dlg = struct open Lx_tree.Types;; open Tk;; open Widget;; type node = { path : string list; mutable name : string; } let some = function Some x -> x | None -> assert false let selected = ref [] let name_tv = lazy(Textvariable.create()) let listbox = ref None let dir_label = ref None let ok_button = ref None let cb_enable_ok = ref (fun _ -> true) let update_ok_button() = let dir = Filesys.join_path !selected in let name = Textvariable.get (Lazy.force name_tv) in prerr_endline ("Name: " ^ name); let en = !selected <> [] && name <> "" && !cb_enable_ok (Filename.concat dir name) in Button.configure ~state:(if en then `Normal else `Disabled) (some !ok_button) let update_listbox d = (* Fill listbox: *) let files = Filesys.list [d] in let reg_files = List.filter (fun file -> not(Filesys.is_container [d;file])) files in Listbox.delete (some !listbox) ~first:(`Num 0) ~last:`End; Listbox.insert (some !listbox) ~index:`End ~texts:reg_files; (* Set label: *) Label.configure ~text:(d ^ ":") (some !dir_label) let node_action tw tree ev evinfo = selected := tree.node.path; Lx_tree.update tw; let dir = Filesys.join_path tree.node.path in update_listbox dir; update_ok_button() let display_node tw tree = let (foreground,background) = if tree.node.path = !selected then (Some `White, Some `Blue) else (None, None) in Lx_tree.display_text ?foreground ?background ~events:[ `ButtonPress ] ~action:node_action tree.node.name let rescan_node tw tree = let files = Filesys.list tree.node.path in let subnodes = List.map (fun name -> { path = tree.node.path @ [name]; name = name; } ) files in let dirs = List.filter (fun n -> Filesys.is_container n.path) subnodes in let subtrees = List.map (fun n -> { node = n; children = []; show = false; scanned = false; interactive = true; } ) dirs in tree.children <- subtrees let rec make_tree_from_path ?(loc = []) p = match p with p1 :: pr -> { node = { path = loc @ [p1]; name = p1; }; children = (if pr = [] then [] else [ make_tree_from_path ~loc:(loc@[p1]) pr ]); show = true; scanned = true; interactive = true; } | [] -> assert false let open_dialog ?(title = "Browse...") ?(enable_ok = fun _ -> true) parent = selected := []; Textvariable.set (Lazy.force name_tv) ""; let top = Toplevel.create parent in Wm.transient_set top ~master:parent; Wm.title_set top title; cb_enable_ok := enable_ok; let l1 = Label.create ~text:"Directories:" top in pack ~anchor:`W [ l1 ]; let dir_tree = make_tree_from_path ("" :: Filesys.split_path (Sys.getcwd())) in dir_tree.node.name <- ""; let tframe = Frame.create top in let tw = Lx_tree.create ~display:display_node ~rescan:rescan_node ~width:300 ~height:300 dir_tree tframe in let sbar = Scrollbar.create ~orient:`Vertical tframe in let canvas = Lx_tree.canvas tw in Canvas.configure ~yscrollcommand:(Scrollbar.set sbar) ~relief:`Sunken ~borderwidth:3 canvas; Scrollbar.configure ~command:(Canvas.yview canvas) sbar; pack ~side:`Left ~fill:`Both ~expand:true [canvas]; pack ~side:`Left ~fill:`Y [ sbar]; pack ~anchor:`W ~fill:`X [tframe]; (* Listbox *) let lab = Label.create ~text:(" ") top in let lbf = Frame.create top in let lb = Listbox.create ~height:10 ~font:"fixed" ~exportselection:false lbf in let lbs = Scrollbar.create lbf in Listbox.configure ~yscrollcommand:(Scrollbar.set lbs) lb; Scrollbar.configure ~command:(Listbox.yview lb) lbs; pack ~anchor:`W [lab]; pack ~anchor:`W ~fill:`X [lbf]; pack ~side:`Left ~expand:true ~fill:`X [lb]; pack ~side:`Left ~fill:`Y [lbs]; listbox := Some lb; dir_label := Some lab; (* Entry: *) let lab' = Label.create ~text:"Filename:" top in let ent = Entry.create ~font:"fixed" ~textvariable:(Lazy.force name_tv) top in pack ~anchor:`W [lab']; pack ~anchor:`W ~fill:`X [ent]; (* Link listbox and entry: *) Tk.bind ~events:[ `ButtonReleaseDetail 1 ] ~action:(fun _ -> match Listbox.curselection lb with [] -> () | hd :: _ -> let s = Listbox.get lb ~index:hd in Textvariable.set (Lazy.force name_tv) s; update_ok_button() ) lb; Tk.bind ~events:[ `KeyPress ] ~action:(fun _ -> Timer.set ~ms:0 ~callback:update_ok_button) ent; let result = ref None in let buttons = Frame.create top in let ok_b = Button.create ~text:"OK" ~state:`Disabled ~command:(fun _ -> let name = Textvariable.get (Lazy.force name_tv) in if name <> "" then begin result := Some (Filesys.join_path !selected, name); Tk.destroy top end else Bell.ring() ) buttons in let cancel_b = Button.create ~text:"Cancel" ~command:(fun _ -> Tk.destroy top) buttons in pack ~expand:true ~fill:`X [buttons]; pack ~side:`Left [ ok_b; cancel_b ]; ok_button := Some ok_b; Grab.set top; Tkwait.window top; !result (* returns None if canceled, or Some (dir, name) *) end ;; module S = struct type t = string let compare = compare end ;; module StringSet = Set.Make(S) ;; open Lx_tree.Types;; open Tk;; open Widget;; let some = Filetree_dlg.some;; type filetype = Regular | Directory | Absent ;; type node = { path : string list; name : string; (* last component of [path] *) mutable is_dir : bool; (* from file list *) mutable selected : bool; (* from file list *) mutable realtype : filetype; (* from file system *) } ;; type file_tree = node tree ;; type state = { mutable current_directory : string; mutable list_file : string; (* relative to current_directory *) mutable tree_widget : node tree_widget option; mutable info_widget : label widget option; mutable dir_context_menu : menu widget option; mutable dir_context_suffix_menu : menu widget option; mutable dir_context_unsuffix_menu : menu widget option; mutable file_context_menu : menu widget option; mutable context_menu_tree : node tree; mutable modified : bool; topwdg : toplevel widget; workframe : frame widget; directory_xpm : image; selected_xpm : image; unselected_xpm : image; mutable display : node tree_widget -> file_tree -> node display_item; } ;; let dummy_tree = { node = { path = []; name = ""; is_dir = false; selected = false; realtype = Regular; }; children = []; show = false; scanned = false; interactive = false; } ;; let rescan_node tw tree = let files = Filesys.list tree.node.path in let missing_files = List.map (fun child -> child.node.name) (List.filter (fun child -> child.node.selected && not(List.mem child.node.name files) ) tree.children ) in let all_files = List.sort compare (files @ missing_files) in let old_children = tree.children in let new_children = List.map (fun filename -> try (* maybe the new child is the old child: *) List.find (fun old_child -> old_child.node.name = filename) old_children with Not_found -> let new_path = tree.node.path @ [filename] in let is_dir = Filesys.is_directory new_path in let new_tree = { node = { path = new_path; name = filename; is_dir = is_dir; selected = false; realtype = Regular; (* Will be updated below *) }; children = []; scanned = not is_dir; show = false; interactive = true; } in new_tree ) all_files in (* Update the [realtype] flag: *) List.iter (fun child -> child.node.realtype <- if List.mem child.node.name files then (if Filesys.is_directory child.node.path then Directory else Regular) else Absent ) new_children; (* Store the result: *) tree.children <- new_children ;; let rec selected_files_exist tree = tree.node.selected || selected_files_exist_in_children tree and selected_files_exist_in_children tree = List.exists selected_files_exist tree.children ;; let rec expand ?(all = false) tw tree = let show = tree.node.is_dir && (all || selected_files_exist_in_children tree) in tree.show <- tree.show || show; if show then rescan_node tw tree; List.iter (fun child -> expand ~all tw child) tree.children ;; let rec collapse tw tree = tree.show <- false; List.iter (fun child -> collapse tw child) tree.children ;; let suffix_re = Str.regexp "\\.[^.]+$";; let rec find_suffixes ?(recursive = false) tw tree = assert(tree.node.is_dir); rescan_node tw tree; (* questionable *) tree.show <- true; let files = List.map (fun ch -> ch.node.name) tree.children in let suff = List.filter (fun s -> s <> "" ) (List.map (fun name -> try let k = Str.search_forward suffix_re name 0 in String.sub name k (String.length name - k) with Not_found -> "" ) files ) in let suff_set = ref (StringSet.empty) in List.iter (fun s -> suff_set := StringSet.add s !suff_set) suff; if recursive then begin List.iter (fun child -> if child.node.is_dir then suff_set := StringSet.union !suff_set (find_suffixes ~recursive tw child) ) tree.children end; !suff_set ;; let rec select_suffixes ?(recursive = false) ?(unselect=false) suffix tree = prerr_endline "select_suffixes"; List.iter (fun child -> let child_suff = try let name = child.node.name in let k = Str.search_forward suffix_re name 0 in String.sub name k (String.length name - k) with Not_found -> "" in if child_suff = suffix && not (child.node.is_dir) then child.node.selected <- not unselect; if recursive && child.node.is_dir then select_suffixes ~recursive ~unselect suffix child ) tree.children ;; let rec select_all ?(recursive = false) ?(unselect=false) tree = prerr_endline "select_all"; List.iter (fun child -> if not (child.node.is_dir) then child.node.selected <- not unselect; if recursive && child.node.is_dir then select_all ~recursive ~unselect child ) tree.children ;; let set_suffix_menu ?unselect tw menu tree = Menu.delete menu ~first:(`Num 0) ~last:`End; let suffixes = find_suffixes tw tree in StringSet.iter (fun s -> Menu.add_command ~label:s ~command:(fun () -> select_suffixes ?unselect s tree; Lx_tree.update tw) menu ) suffixes ;; let node_action st tw tree ev evinfo = (* prerr_endline "node_action"; *) match (ev : Lx_spots.supported_event) with `ButtonPress -> begin match evinfo.ev_ButtonNumber with 1 -> (* prerr_endline ("name=" ^ node.node.name); *) if not(tree.node.is_dir) then begin (* prerr_endline "invert!"; *) tree.node.selected <- not tree.node.selected; st.modified <- true; prerr_endline ("update"); Lx_tree.update tw; prerr_endline ("/update"); end | 3 -> (* Context menu *) let menu = if tree.node.is_dir then ( set_suffix_menu tw (some st.dir_context_suffix_menu) tree; set_suffix_menu ~unselect:true tw (some st.dir_context_unsuffix_menu) tree; st.dir_context_menu ) else st.file_context_menu in st.context_menu_tree <- tree; ( match menu with Some m -> Menu.popup ~x:(evinfo.ev_RootX) ~y:(evinfo.ev_RootY) m; | None -> () ) | _ -> () end | `Enter -> begin match st.info_widget with Some label -> let text = match tree.node.realtype, tree.node.is_dir with Regular,false -> tree.node.name ^ ": File is " ^ (if tree.node.selected then "selected" else "not selected") | Regular,true -> tree.node.name ^ ": Listed as file, but now a directory" | Directory,true -> tree.node.name ^ ": Directory" | Directory,false -> tree.node.name ^ ": Listed as directory, but now a file" | Absent, _ -> tree.node.name ^ ": does not exist" in Label.configure ~text label | None -> () end | `Leave -> begin match st.info_widget with Some label -> Label.configure ~text:" " label | None -> () end | _ -> () ;; let display_node st = let node_action_st = node_action st in fun tw tree -> let node = tree.node in let image = if node.is_dir then st.directory_xpm else if node.selected then st.selected_xpm else st.unselected_xpm in let foreground = (* Blue means: A selected regular file * Black means: A non selected regular file * Red means a problem: * - The file does not exist * - The file has the wrong type *) match (node.realtype, node.is_dir) with (Regular, false) -> (if node.selected then Some `Blue else None) | (Directory, true) -> None (* directories can never be selected *) | _ -> Some(`Red) in let events = [ `ButtonPress; `Enter; `Leave ] in Lx_tree.display_text ~image ~events ~action:node_action_st ?foreground node.name ;; let neutral_frame wdg = Frame.create ~highlightthickness:0 ~borderwidth:0 wdg ;; let save st = let rec write_file file path tree = let full_name = if path = "" then tree.node.name else Filename.concat path tree.node.name in if not tree.node.is_dir && tree.node.selected then begin output_string file full_name; output_string file "\n"; end; List.iter (fun child -> write_file file full_name child) tree.children in match st.tree_widget with Some tw -> let tree = Lx_tree.tree tw in let filename = Filename.concat st.current_directory st.list_file in let file = open_out filename in List.iter (fun child -> write_file file "" child) tree.children; close_out file; st.modified <- false; | None -> () ;; let q_save st = (* Question: save current file list? Returns [true] if the operation * can be continued *) if st.modified then begin let choice = Dialog.create ~parent:st.topwdg ~title:"Save?" ~message:"The current tree is modified. Save it to disk?" ~buttons:[ "Yes"; "No"; "Cancel" ] () in match choice with 0 -> save st; true | 1 -> true | 2 -> false end else true ;; let drop st = st.list_file <- ""; st.modified <- false; Frame.configure ~width:400 ~height:600 st.workframe; List.iter destroy (Winfo.children st.workframe); st.tree_widget <- None ;; let create_work_tree st top_node = let tree_frame = neutral_frame st.workframe in let info_frame = neutral_frame st.workframe in let sbar = Scrollbar.create ~orient:`Vertical tree_frame in let info_label = Label.create ~highlightthickness:0 ~borderwidth:0 ~justify:`Left ~text:" " info_frame in pack ~anchor:`W ~ipady:4 ~ipadx:4 ~side:`Left [info_label]; let width = Winfo.reqwidth st.workframe - Winfo.reqwidth sbar in let height = Winfo.reqheight st.workframe - Winfo.reqwidth info_label - 14 in (* TODO: why 14? I think that 8 pixels = 2*ipady is the right value. *) let tw = Lx_tree.create ~display:st.display ~rescan:rescan_node ~width ~height ~background:`White ~font:"9x15" top_node tree_frame in let canvas = Lx_tree.canvas tw in Canvas.configure ~yscrollcommand:(Scrollbar.set sbar) canvas; Scrollbar.configure ~command:(Canvas.yview canvas) sbar; Canvas.configure ~highlightthickness:0 canvas; pack ~side:`Left ~fill:`Both ~expand:true [canvas]; pack ~side:`Left ~fill:`Y [ sbar]; pack ~anchor:`W [tree_frame; info_frame ]; st.tree_widget <- Some tw; st.info_widget <- Some info_label; let dcm = Menu.create ~tearoff:false st.workframe in let dcm_suffix = Menu.create ~tearoff:false dcm in let dcm_unsuffix = Menu.create ~tearoff:false dcm in Menu.add_cascade ~label:"Select by suffix" ~menu:dcm_suffix dcm; Menu.add_cascade ~label:"Unselect by suffix" ~menu:dcm_unsuffix dcm; (* Menu.add_command ~label:".ml" dcm_suffix; Menu.add_command ~label:".mli" dcm_suffix; Menu.add_command ~label:".mly" dcm_suffix; *) Menu.add_command ~label:"Select all files" ~command:(fun () -> select_all st.context_menu_tree; Lx_tree.update tw) dcm; Menu.add_command ~label:"Unselect all files" ~command:(fun () -> select_all ~unselect:true st.context_menu_tree; Lx_tree.update tw) dcm; Menu.add_separator dcm; Menu.add_command ~label:"Rescan directory" ~command:(fun () -> rescan_node tw st.context_menu_tree; Lx_tree.update tw ) dcm; Menu.add_separator dcm; Menu.add_command ~label:"Expand all" ~command:(fun () -> expand ~all:true tw st.context_menu_tree; Lx_tree.update tw ) dcm; Menu.add_command ~label:"Expand as needed" ~command:(fun () -> expand tw st.context_menu_tree; Lx_tree.update tw ) dcm; Menu.add_command ~label:"Collapse" ~command:(fun () -> collapse tw st.context_menu_tree; Lx_tree.update tw ) dcm; st.dir_context_menu <- Some dcm; st.dir_context_suffix_menu <- Some dcm_suffix; st.dir_context_unsuffix_menu <- Some dcm_unsuffix; ;; let file_new st () = let enable_ok filename = not(Sys.file_exists filename) in if q_save st then begin match Filetree_dlg.open_dialog ~title:"New tree" ~enable_ok st.topwdg with Some (dir, name) -> drop st; st.current_directory <- dir; st.list_file <- name; let basename = Filename.basename dir in let initial_node = { node = { name = basename; path = [ dir ]; is_dir = true; realtype = Directory; selected = false; }; children = []; show = false; scanned = false; interactive = true; } in let filename = Filename.concat dir name in Unix.close(Unix.openfile filename [Unix.O_RDWR; Unix.O_CREAT] 0o666); create_work_tree st initial_node | None -> () end ;; let strip_ws_re = Str.regexp "^[ \r\n\t]*\\(.*\\)[ \r\n\t]*$";; let strip_ws s = if Str.string_match strip_ws_re s 0 then Str.matched_group 1 s else assert false ;; let file_open st () = let rec enter_path path node = match path with n :: path' -> begin try let child = List.find (fun ch -> ch.node.name = n) node.children in (* or Not_found *) if path' <> [] then begin child.node.is_dir <- true; end; enter_path path' child with Not_found -> let child = { node = { name = n; path = node.node.path @ [n]; is_dir = (path' <> []); realtype = Regular; (* Will be updated later *) selected = true; }; children = []; show = false; scanned = path' = []; interactive = true; } in node.children <- child :: node.children; enter_path path' child end | [] -> () in let rec read_file file initial_node = let line = strip_ws (input_line file) in if line = "" then read_file file initial_node else begin let path = Filesys.split_path line in enter_path path initial_node; read_file file initial_node end in let enable_ok filename = Sys.file_exists filename in if q_save st then begin match Filetree_dlg.open_dialog ~title:"Open tree" ~enable_ok st.topwdg with Some (dir, name) -> drop st; st.current_directory <- dir; st.list_file <- name; let basename = Filename.basename dir in let initial_node = { node = { name = basename; path = [ dir ]; is_dir = true; realtype = Directory; selected = false; }; children = []; show = false; scanned = false; interactive = true; } in let filename = Filename.concat dir name in let file = open_in filename in (try read_file file initial_node with End_of_file -> ()); close_in file; create_work_tree st initial_node | None -> () end ;; let file_save st () = save st; ignore(Dialog.create ~parent:st.topwdg ~title:"Saved" ~message:"Tree saved." ~buttons:[ "OK" ] ()); ;; let file_quit st () = if q_save st then destroy st.topwdg ;; let view_expand ?all st () = match st.tree_widget with Some tw -> expand ?all tw (Lx_tree.tree tw); Lx_tree.update tw | None -> () ;; let view_collapse st () = match st.tree_widget with Some tw -> collapse tw (Lx_tree.tree tw); Lx_tree.update tw | None -> () ;; let init_application top = let directory_xpm = Imagebitmap.create ~file:"directory.xpm" ~background:`White () in let selected_xpm = Imagebitmap.create ~file:"selected.xpm" ~background:`White () in let unselected_xpm = Imagebitmap.create ~file:"unselected.xpm" ~background:`White () in (* Create the work frame, 400 x 600 pixels *) let workframe = Frame.create ~width:400 ~height:600 top in (* Create the state record: *) let st = { current_directory = Sys.getcwd(); list_file = ""; tree_widget = None; info_widget = None; dir_context_menu = None; dir_context_suffix_menu = None; dir_context_unsuffix_menu = None; file_context_menu = None; context_menu_tree = dummy_tree; modified = false; workframe = workframe; topwdg = top; directory_xpm = directory_xpm; selected_xpm = selected_xpm; unselected_xpm = unselected_xpm; display = (fun _ _ -> Lx_tree.display_text ""); } in st.display <- display_node st; (* Because there are currently no toplevel menubars in labltk (they appeared * first in Tk 8.0), we simulate them using a frame. *) let menuframe = Frame.create ~relief:`Groove ~borderwidth:2 top in let file_mb = Menubutton.create ~text:"File" menuframe in let file_m = Menu.create file_mb in Menu.add_command ~label:"New Tree" ~command:(file_new st) file_m; Menu.add_command ~label:"Open" ~command:(file_open st) file_m; Menu.add_command ~label:"Check" file_m; Menu.add_command ~label:"Save" ~command:(file_save st) file_m; Menu.add_command ~label:"Quit" ~command:(file_quit st) file_m; Menubutton.configure ~menu:file_m file_mb; Wm.protocol_set top ~name:"WM_DELETE_WINDOW" ~command:(file_quit st); (* let edit_mb = Menubutton.create ~text:"Edit" menuframe in let edit_m = Menu.create edit_mb in (* Undo? *) Menu.add_command ~label:"Select by suffix" edit_m; Menu.add_command ~label:"Select by regexp" edit_m; Menu.add_command ~label:"Select all" edit_m; Menubutton.configure ~menu:edit_m edit_mb; *) let view_mb = Menubutton.create ~text:"View" menuframe in let view_m = Menu.create view_mb in Menu.add_command ~label:"Expand all" ~command:(view_expand ~all:true st) view_m; Menu.add_command ~label:"Expand as needed" ~command:(view_expand st) view_m; Menu.add_command ~label:"Collapse all" ~command:(view_collapse st) view_m; Menubutton.configure ~menu:view_m view_mb; pack ~side:`Left [file_mb; (* edit_mb; *) view_mb]; pack ~anchor:`W ~fill:`X [menuframe]; pack ~anchor:`W [workframe] ;; let top_window = openTk() in init_application top_window; Sys.catch_break true; try mainLoop() with Sys.Break -> prerr_endline "EXIT"; () ;; (* ====================================================================== * History: * * $Log: tree_editor.ml,v $ * Revision 1.1 2002/06/08 19:39:53 gerd * Initial revision. * * *) not-ocamlfind-0.14/local-packages/ocamlfind/src/findlib-toolbox/unselected.xpm0000644000175000017500000000045614770304423026576 0ustar stephsteph#define unselected_width 16 #define unselected_height 16 static unsigned char unselected_bits[] = { 0x55, 0x55, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0xaa, 0xaa}; not-ocamlfind-0.14/local-packages/ocamlfind/src/findlib/0002755000175000017500000000000014770304423022226 5ustar stephstephnot-ocamlfind-0.14/local-packages/ocamlfind/src/findlib/META.in0000644000175000017500000000176114770304423023307 0ustar stephsteph# specifications for "findlib": description = "Package manager" requires = "findlib.internal" requires(toploop) += "findlib.top" requires(create_toploop) += "findlib.top" version = "@VERSION@" package "internal" ( version = "@VERSION@" description = "Package manager" requires = "@REQUIRES@" archive(byte) = "findlib.cma" archive(native) = "findlib.cmxa" plugin(byte) = "findlib.cma" plugin(native) = "findlib.cmxs" ) package "dynload" ( version = "@VERSION@" description = "Package manager dynamic loader" requires = "findlib dynlink" archive(byte) = "findlib_dynload.cma" archive(native) = "findlib_dynload.cmxa" #Even if it strange and discouraged to dynload this package plugin(byte) = "findlib_dynload.cma" plugin(native) = "findlib_dynload.cmxs" linkopts = "-linkall" ) package "top" ( version = "@VERSION@" description = "Package manager toplevel support" requires = "findlib.internal" archive(byte) = "findlib_top.cma" archive(native) = "findlib_top.cmxa" ) not-ocamlfind-0.14/local-packages/ocamlfind/src/findlib/Makefile0000644000175000017500000001640114770304423023666 0ustar stephsteph# make all: compile to bytecode # make opt: compile to native code # make install: install bytecode and/or native code # # See Makefile.config for configurable variables. # Runtime configurations might also be necessary in the site-lib/*/META # files. #---------------------------------------------------------------------- TOP=../.. include $(TOP)/Makefile.config NAME = findlib # Need compiler-libs since ocaml-4.00 OCAMLC = ocamlc -I +compiler-libs OCAMLOPT = ocamlopt -I +compiler-libs $(OCAMLOPT_G) OCAMLOPT_SHARED = $(OCAMLOPT) OCAMLDEP = ocamldep OCAMLLEX = ocamllex #CAMLP4O = camlp4 pa_o.cmo pa_op.cmo pr_o.cmo -- #CAMLP4O = camlp4 pa_o.cmo pa_op.cmo pr_dump.cmo -- OBJECTS = fl_compat.cmo fl_split.cmo findlib_config.cmo \ fl_metatoken.cmo fl_meta.cmo fl_metascanner.cmo fl_topo.cmo \ fl_package_base.cmo findlib.cmo fl_args.cmo fl_lint.cmo TOBJECTS = topfind.cmo XOBJECTS = $(OBJECTS:.cmo=.cmx) TXOBJECTS = $(TOBJECTS:.cmo=.cmx) OCAMLFIND_OBJECTS = ocaml_args.cmo frontend.cmo OCAMLFIND_XOBJECTS = $(OCAMLFIND_OBJECTS:.cmo=.cmx) # OCAMLFIND_ARCHIVES: set in Makefile.config OCAMLFIND_XARCHIVES = $(OCAMLFIND_ARCHIVES:.cma=.cmxa) NUMTOP_OBJECTS = num_top_printers.cmo num_top.cmo DYNLOAD_OBJECTS = fl_dynload.cmo DYNLOAD_XOBJECTS = $(DYNLOAD_OBJECTS:.cmo=.cmx) all: ocamlfind$(EXEC_SUFFIX) findlib.cma findlib_top.cma topfind $(NUMTOP) \ findlib_dynload.cma opt: ocamlfind_opt$(EXEC_SUFFIX) findlib.cmxa findlib_top.cmxa topfind \ findlib_dynload.cmxa num-top: num_top.cma ocamlfind$(EXEC_SUFFIX): findlib.cma $(OCAMLFIND_OBJECTS) $(OCAMLC) $(CUSTOM) -o ocamlfind$(EXEC_SUFFIX) -g $(OCAMLFIND_ARCHIVES) \ $(OCAMLC_FLAGS) $(OCAMLFIND_OCAMLFLAGS) $(OCAMLFIND_OBJECTS) ocamlfind_opt$(EXEC_SUFFIX): findlib.cmxa $(OCAMLFIND_XOBJECTS) $(OCAMLOPT) -o ocamlfind_opt$(EXEC_SUFFIX) $(OCAMLFIND_XARCHIVES) \ $(OCAMLOPT_FLAGS) $(OCAMLFIND_OCAMLFLAGS) $(OCAMLFIND_XOBJECTS) test_parser$(EXEC_SUFFIX): fl_metascanner.cmx test_parser.cmx fl_metatoken.cmx fl_meta.cmx $(OCAMLOPT) -o test_parser$(EXEC_SUFFIX) fl_meta.cmx fl_metatoken.cmx fl_metascanner.cmx test_parser.cmx findlib.cma: $(OBJECTS) $(OCAMLC) -a -o findlib.cma $(OBJECTS) findlib_top.cma: $(TOBJECTS) $(OCAMLC) -a -o findlib_top.cma $(TOBJECTS) findlib.cmxa: $(XOBJECTS) $(OCAMLOPT) -a -o findlib.cmxa $(XOBJECTS) if [ $(HAVE_NATDYNLINK) -gt 0 ]; then \ $(OCAMLOPT_SHARED) -shared -o findlib.cmxs $(XOBJECTS); \ fi findlib_top.cmxa: $(TXOBJECTS) $(OCAMLOPT) -a -o findlib_top.cmxa $(TXOBJECTS) if [ $(HAVE_NATDYNLINK) -gt 0 ]; then \ $(OCAMLOPT_SHARED) -shared -o findlib_top.cmxs $(TXOBJECTS); \ fi findlib_dynload.cma: $(DYNLOAD_OBJECTS) $(OCAMLC) -a -o findlib_dynload.cma $(DYNLOAD_OBJECTS) findlib_dynload.cmxa: $(DYNLOAD_XOBJECTS) $(OCAMLOPT) -a -o findlib_dynload.cmxa $(DYNLOAD_XOBJECTS) if [ $(HAVE_NATDYNLINK) -gt 0 ]; then \ $(OCAMLOPT_SHARED) -shared -o findlib_dynload.cmxs $(DYNLOAD_XOBJECTS); \ fi findlib_config.ml: findlib_config.mlp $(TOP)/Makefile.config USE_CYGPATH="$(USE_CYGPATH)"; \ export USE_CYGPATH; \ cat findlib_config.mlp | \ $(SH) $(TOP)/tools/patch '@CONFIGFILE@' '$(OCAMLFIND_CONF)' | \ $(SH) $(TOP)/tools/patch '@STDLIB@' '$(OCAML_CORE_STDLIB)' | \ $(SH) $(TOP)/tools/patch '@RELATIVE_PATHS@' '$(RELATIVE_PATHS)' | \ sed -e 's;@AUTOLINK@;$(OCAML_AUTOLINK);g' \ -e 's;@SYSTEM@;$(SYSTEM);g' \ >findlib_config.ml topfind.ml: topfind.ml.in if [ "$(ENABLE_TOPFIND_PPXOPT)" = "true" ]; then \ cp topfind.ml.in topfind.ml; \ else \ sed -e '/PPXOPT_BEGIN/,/PPXOPT_END/ d' topfind.ml.in \ > topfind.ml ; \ fi topfind.compat.in: topfind.in if [ "$(OCAML_REMOVE_DIRECTORY)" = "1" ]; then \ cp topfind.in topfind.compat.in; \ else \ sed -e '/REMOVE_DIRECTORY_BEGIN/,/REMOVE_DIRECTORY_END/ d' $< \ > $@ ; \ fi topfind: topfind.compat.in USE_CYGPATH="$(USE_CYGPATH)"; \ export USE_CYGPATH; \ cat topfind.compat.in | \ $(SH) $(TOP)/tools/patch '@SITELIB@' '$(OCAML_SITELIB)' | \ $(SH) $(TOP)/tools/patch '@RELATIVE_PATHS@' '$(RELATIVE_PATHS)' \ >topfind num_top.cma: $(NUMTOP_OBJECTS) $(OCAMLC) -a -o num_top.cma $(NUMTOP_OBJECTS) clean: rm -f *.cmi *.cmo *.cma *.cmx *.a *.lib *.o *.obj *.cmxa \ fl_meta.ml findlib_config.ml topfind.ml topfind.compat.in topfind \ ocamlfind$(EXEC_SUFFIX) ocamlfind_opt$(EXEC_SUFFIX) install: all $(INSTALLDIR) "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/$(NAME)" $(INSTALLDIR) "$(DESTDIR)$(prefix)$(OCAMLFIND_BIN)" test $(INSTALL_TOPFIND) -eq 0 || $(INSTALLDIR) "$(DESTDIR)$(prefix)$(OCAML_CORE_STDLIB)" test $(INSTALL_TOPFIND) -eq 0 || $(CP) topfind "$(DESTDIR)$(prefix)$(OCAML_CORE_STDLIB)/" files=`$(SH) $(TOP)/tools/collect_files $(TOP)/Makefile.config \ findlib.cmi findlib.mli findlib.cma findlib.cmxa findlib$(LIB_SUFFIX) findlib.cmxs \ findlib_config.cmi findlib_config.ml topfind.cmi topfind.mli \ fl_args.cmi fl_lint.cmi fl_meta.cmi fl_split.cmi fl_topo.cmi ocaml_args.cmi \ fl_package_base.mli fl_package_base.cmi fl_metascanner.mli fl_metascanner.cmi \ fl_metatoken.cmi findlib_top.cma findlib_top.cmxa findlib_top$(LIB_SUFFIX) findlib_top.cmxs \ findlib_dynload.cma findlib_dynload.cmxa findlib_dynload$(LIB_SUFFIX) findlib_dynload.cmxs fl_dynload.mli fl_dynload.cmi \ META` && \ $(CP) $$files "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/$(NAME)/" f="ocamlfind$(EXEC_SUFFIX)"; { test -f ocamlfind_opt$(EXEC_SUFFIX) && f="ocamlfind_opt$(EXEC_SUFFIX)"; }; \ $(INSTALLFILE) $$f "$(DESTDIR)$(prefix)$(OCAMLFIND_BIN)/ocamlfind$(EXEC_SUFFIX)" # the following "if" block is only needed for 4.00beta2 if [ $(OCAML_REMOVE_DIRECTORY) -eq 0 -a -f "$(OCAML_CORE_STDLIB)/compiler-libs/topdirs.cmi" ]; then \ cd "$(OCAML_CORE_STDLIB)/compiler-libs/"; \ $(CP) topdirs.cmi toploop.cmi "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/$(NAME)/"; \ fi install-num-top: $(INSTALLDIR) "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/num-top" $(CP) num_top.cma num_top.cmi num_top_printers.cmi \ "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/num-top/" # Note: uninstall-num-top is part of the removal of the META files. uninstall: rm -f $(DESTDIR)$(prefix)$(OCAML_CORE_STDLIB)/findlib rm -rf $(DESTDIR)$(prefix)$(OCAML_SITELIB)/$(NAME) rm -f $(DESTDIR)$(prefix)$(OCAMLFIND_BIN)/ocamlfind$(EXEC_SUFFIX) depend: *.ml *.mli fl_meta.ml fl_metascanner.ml findlib_config.ml topfind.ml $(OCAMLDEP) *.ml *.mli >depend # Some 'make' implementations require that .SUFFIXES must occur before # the first suffix rule. (E.g. AIX) .SUFFIXES: .mll .cmo .cmi .cmx .ml .mli # .src .ml.cmx: $(OCAMLOPT) $(OPAQUE) $(OCAMLOPT_FLAGS) $(OCAMLFIND_OCAMLFLAGS) -c $< .ml.cmo: $(OCAMLC) $(OPAQUE) $(OCAMLC_FLAGS) $(OCAMLFIND_OCAMLFLAGS) -g -c $< .mli.cmi: $(OCAMLC) $(OPAQUE) $(OCAMLC_FLAGS) $(OCAMLFIND_OCAMLFLAGS) -c $< #.src.ml: # $(CAMLP4O) -impl $< -o $@ # Solaris make does not like the suffix rule .mll.ml, # so I replaced it by its single application: fl_meta.ml: fl_meta.mll $(OCAMLLEX) fl_meta.mll # Don't remove fl_metascanner.ml: .PRECIOUS: fl_metascanner.ml include depend not-ocamlfind-0.14/local-packages/ocamlfind/src/findlib/depend0000644000175000017500000000443514770304423023414 0ustar stephstephfindlib.cmo : \ fl_split.cmo \ fl_package_base.cmi \ fl_metascanner.cmi \ fl_compat.cmo \ findlib_config.cmo \ findlib.cmi findlib.cmx : \ fl_split.cmx \ fl_package_base.cmx \ fl_metascanner.cmx \ fl_compat.cmx \ findlib_config.cmx \ findlib.cmi findlib.cmi : findlib_config.cmo : \ fl_split.cmo \ fl_compat.cmo findlib_config.cmx : \ fl_split.cmx \ fl_compat.cmx fl_args.cmo : fl_args.cmx : fl_compat.cmo : fl_compat.cmx : fl_dynload.cmo : \ fl_split.cmo \ findlib.cmi \ fl_dynload.cmi fl_dynload.cmx : \ fl_split.cmx \ findlib.cmx \ fl_dynload.cmi fl_dynload.cmi : fl_lint.cmo : \ fl_metascanner.cmi fl_lint.cmx : \ fl_metascanner.cmx fl_meta.cmo : \ fl_metatoken.cmo fl_meta.cmx : \ fl_metatoken.cmx fl_metascanner.cmo : \ fl_metatoken.cmo \ fl_meta.cmo \ fl_metascanner.cmi fl_metascanner.cmx : \ fl_metatoken.cmx \ fl_meta.cmx \ fl_metascanner.cmi fl_metascanner.cmi : \ fl_metatoken.cmo fl_metatoken.cmo : fl_metatoken.cmx : fl_package_base.cmo : \ fl_topo.cmi \ fl_split.cmo \ fl_metascanner.cmi \ fl_package_base.cmi fl_package_base.cmx : \ fl_topo.cmx \ fl_split.cmx \ fl_metascanner.cmx \ fl_package_base.cmi fl_package_base.cmi : \ fl_metascanner.cmi fl_split.cmo : fl_split.cmx : fl_topo.cmo : \ fl_topo.cmi fl_topo.cmx : \ fl_topo.cmi fl_topo.cmi : frontend.cmo : \ ocaml_args.cmo \ fl_split.cmo \ fl_package_base.cmi \ fl_metascanner.cmi \ fl_lint.cmo \ fl_args.cmo \ findlib_config.cmo \ findlib.cmi frontend.cmx : \ ocaml_args.cmx \ fl_split.cmx \ fl_package_base.cmx \ fl_metascanner.cmx \ fl_lint.cmx \ fl_args.cmx \ findlib_config.cmx \ findlib.cmx num_top.cmo : \ num_top.cmi num_top.cmx : \ num_top.cmi num_top.cmi : num_top_printers.cmo : \ num_top_printers.cmi num_top_printers.cmx : \ num_top_printers.cmi num_top_printers.cmi : ocaml_args.cmo : ocaml_args.cmx : test_parser.cmo : \ fl_metascanner.cmi test_parser.cmx : \ fl_metascanner.cmx topfind.cmo : \ fl_split.cmo \ fl_package_base.cmi \ findlib.cmi \ topfind.cmi topfind.cmx : \ fl_split.cmx \ fl_package_base.cmx \ findlib.cmx \ topfind.cmi topfind.cmi : not-ocamlfind-0.14/local-packages/ocamlfind/src/findlib/findlib.ml0000644000175000017500000003475214770304423024200 0ustar stephsteph(* $Id$ * ---------------------------------------------------------------------- * *) open Fl_compat module StrSet = Set.Make(String) exception No_such_package = Fl_package_base.No_such_package exception Package_loop = Fl_package_base.Package_loop type formal_pred = [ `Pred of string | `NegPred of string ] let init_called = ref false ;; let conf_config_file = ref "";; let conf_default_location = ref "";; let conf_meta_directory = ref "";; let conf_search_path = ref [];; let conf_command = ref [];; let conf_stdlib = ref "";; let conf_ldconf = ref "";; let conf_ignore_dups_in = ref ([] : string list);; let ocamlc_default = "ocamlc";; let ocamlopt_default = "ocamlopt";; let ocamlcp_default = "ocamlcp";; let ocamloptp_default = "ocamloptp";; let ocamlmklib_default = "ocamlmklib";; let ocamlmktop_default = "ocamlmktop";; let ocamldep_default = "ocamldep";; let ocamlbrowser_default = "ocamlbrowser";; let ocamldoc_default = "ocamldoc";; let init_manually ?(ocamlc_command = ocamlc_default) ?(ocamlopt_command = ocamlopt_default) ?(ocamlcp_command = ocamlcp_default) ?(ocamloptp_command = ocamloptp_default) ?(ocamlmklib_command = ocamlmklib_default) ?(ocamlmktop_command = ocamlmktop_default) ?(ocamldep_command = ocamldep_default) ?(ocamlbrowser_command = ocamlbrowser_default) ?(ocamldoc_command = ocamldoc_default) ?ignore_dups_in ?(ignore_dups_in_list = []) ?(stdlib = Findlib_config.ocaml_stdlib) ?(ldconf = Findlib_config.ocaml_ldconf) ?config ~install_dir ~meta_dir ~search_path () = conf_command := [ `ocamlc, ocamlc_command; `ocamlopt, ocamlopt_command; `ocamlcp, ocamlcp_command; `ocamloptp, ocamloptp_command; `ocamlmklib, ocamlmklib_command; `ocamlmktop, ocamlmktop_command; `ocamldep, ocamldep_command; `ocamlbrowser, ocamlbrowser_command; `ocamldoc, ocamldoc_command; ]; let config = match config with | Some config -> config | None -> Lazy.force Findlib_config.config_file in conf_config_file := config; conf_search_path := search_path; conf_default_location := install_dir; conf_meta_directory := meta_dir; conf_stdlib := stdlib; conf_ldconf := ldconf; conf_ignore_dups_in := ( match ignore_dups_in with | None -> [] | Some d -> [d] ) @ ignore_dups_in_list; Fl_package_base.init !conf_search_path stdlib !conf_ignore_dups_in; init_called := true ;; let command_names cmd_spec = try let cmd_list = Fl_split.in_words cmd_spec in List.map (fun cmd_setting -> try (* cmd_setting: formal_name=actual_name *) let l = String.length cmd_setting in let n = String.index cmd_setting '=' in let cmd_formal_name = String.sub cmd_setting 0 n in let cmd_actual_name = String.sub cmd_setting (n+1) (l-n-1) in cmd_formal_name, cmd_actual_name with Not_found -> prerr_endline ("Warning: Please check the environment variable OCAMLFIND_COMMANDS"); "", "" ) cmd_list with Not_found -> [] ;; let auto_config_file() = let p = ( try Sys.getenv "OCAMLFIND_CONF" with Not_found -> "") in if p = "" then Lazy.force Findlib_config.config_file else p let path_to_relocate path = let prefix = "$PREFIX" in let len = String.length prefix in match String.starts_with ~prefix path with | false -> None | true -> Some (String.sub path len (String.length path - len)) let relocate_paths paths = let paths = String.split_on_char Fl_split.path_separator paths |> List.filter_map (fun path -> match path_to_relocate path with | None -> Some path | Some path -> ( match Lazy.force Findlib_config.location with | Some install_location -> Some (Filename.concat install_location path) | None -> None)) in let sep = String.make 1 Fl_split.path_separator in String.concat sep paths ;; let init ?env_ocamlpath ?env_ocamlfind_destdir ?env_ocamlfind_metadir ?env_ocamlfind_commands ?env_ocamlfind_ignore_dups_in ?env_ocamlfind_ignore_dups_in_list ?env_camllib ?env_ldconf ?config ?toolchain () = let config_file = match config with Some f -> f | None -> auto_config_file() in let configd_file = config_file ^ ".d" in let vars_of_file f = let ch = open_in f in try let vars = (Fl_metascanner.parse ch).Fl_metascanner.pkg_defs in close_in ch; vars with | error -> close_in ch; raise error in let vars_of_dir d = let files = Array.to_list (Sys.readdir d) in List.flatten (List.map (fun file -> if Filename.check_suffix file ".conf" then vars_of_file (Filename.concat d file) else [] ) files) in let config_preds = match toolchain with | None -> (try [Sys.getenv "OCAMLFIND_TOOLCHAIN"] with Not_found -> []) | Some p -> [p] in let sys_ocamlc, sys_ocamlopt, sys_ocamlcp, sys_ocamloptp, sys_ocamlmklib, sys_ocamlmktop, sys_ocamldep, sys_ocamlbrowser, sys_ocamldoc, sys_search_path, sys_destdir, sys_metadir, sys_stdlib, sys_ldconf = ( let config_vars = if config_file <> "" && not(Sys.file_exists config_file) && not(Sys.file_exists configd_file) then failwith("Config file not found - neither " ^ config_file ^ " nor the directory " ^ configd_file); if Sys.file_exists config_file then vars_of_file config_file else [] in let configd_vars = if Sys.file_exists configd_file then vars_of_dir configd_file else [] in let vars = config_vars @ configd_vars in if vars <> [] then ( let found = ref false in let lookup name default = let explicit_preds = List.for_all (fun p -> Fl_metascanner.predicate_exists p vars) config_preds in found := !found || explicit_preds; try Fl_metascanner.lookup name config_preds vars |> relocate_paths with Not_found -> default in let config_tuple = ( (lookup "ocamlc" ocamlc_default), (lookup "ocamlopt" ocamlopt_default), (lookup "ocamlcp" ocamlcp_default), (lookup "ocamloptp" ocamloptp_default), (lookup "ocamlmklib" ocamlmklib_default), (lookup "ocamlmktop" ocamlmktop_default), (lookup "ocamldep" ocamldep_default), (lookup "ocamlbrowser" ocamlbrowser_default), (lookup "ocamldoc" ocamldoc_default), Fl_split.path (lookup "path" ""), (lookup "destdir" ""), (lookup "metadir" "none"), (lookup "stdlib" Findlib_config.ocaml_stdlib), (lookup "ldconf" Findlib_config.ocaml_ldconf) ) in if not !found && config_preds <> [] then prerr_endline("ocamlfind: [WARNING] Undefined toolchain: " ^ String.concat "" config_preds); config_tuple ) else ( ocamlc_default, ocamlopt_default, ocamlcp_default, ocamloptp_default, ocamlmklib_default, ocamlmktop_default, ocamldep_default, ocamlbrowser_default, ocamldoc_default, [], "", "none", Findlib_config.ocaml_stdlib, Findlib_config.ocaml_ldconf ) ) in let env_commands = match env_ocamlfind_commands with Some x -> command_names x | None -> command_names (try Sys.getenv "OCAMLFIND_COMMANDS" with Not_found -> "") in let env_destdir = match env_ocamlfind_destdir with Some x -> x | None -> try Sys.getenv "OCAMLFIND_DESTDIR" with Not_found -> "" in let env_metadir = match env_ocamlfind_metadir with Some x -> x | None -> try Sys.getenv "OCAMLFIND_METADIR" with Not_found -> "" in let env_search_path = Fl_split.path (match env_ocamlpath with Some x -> x | None -> try Sys.getenv "OCAMLPATH" with Not_found -> "" ) in let env_stdlib = match env_camllib with Some x -> x | None -> ( try Sys.getenv "OCAMLLIB" with Not_found -> (try Sys.getenv "CAMLLIB" with Not_found -> "" ) ) in let env_ldconf = match env_ldconf with Some x -> x | None -> try Sys.getenv "OCAMLFIND_LDCONF" with Not_found -> "" in let ignore_dups_in_list = match env_ocamlfind_ignore_dups_in, env_ocamlfind_ignore_dups_in_list with | Some x0, Some l -> x0 :: l | None, Some l -> l | Some x0, None -> [x0] | None, None -> try Fl_split.path (Sys.getenv "OCAMLFIND_IGNORE_DUPS_IN") with Not_found -> [] in let ocamlc, ocamlopt, ocamlcp, ocamloptp, ocamlmklib, ocamlmktop, ocamldep, ocamlbrowser, ocamldoc, search_path, destdir, metadir, stdlib, ldconf = (try List.assoc "ocamlc" env_commands with Not_found -> sys_ocamlc), (try List.assoc "ocamlopt" env_commands with Not_found -> sys_ocamlopt), (try List.assoc "ocamlcp" env_commands with Not_found -> sys_ocamlcp), (try List.assoc "ocamloptp" env_commands with Not_found -> sys_ocamloptp), (try List.assoc "ocamlmklib" env_commands with Not_found -> sys_ocamlmklib), (try List.assoc "ocamlmktop" env_commands with Not_found -> sys_ocamlmktop), (try List.assoc "ocamldep" env_commands with Not_found -> sys_ocamldep), (try List.assoc "ocamlbrowser" env_commands with Not_found -> sys_ocamlbrowser), (try List.assoc "ocamldoc" env_commands with Not_found -> sys_ocamldoc), (env_search_path @ sys_search_path), (if env_destdir = "" then sys_destdir else env_destdir), (if env_metadir = "" then sys_metadir else env_metadir), (if env_stdlib = "" then sys_stdlib else env_stdlib), (if env_ldconf = "" then sys_ldconf else env_ldconf) in init_manually ~ocamlc_command: ocamlc ~ocamlopt_command: ocamlopt ~ocamlcp_command: ocamlcp ~ocamloptp_command: ocamloptp ~ocamlmklib_command: ocamlmklib ~ocamlmktop_command: ocamlmktop ~ocamldep_command: ocamldep ~ocamlbrowser_command: ocamlbrowser ~ocamldoc_command: ocamldoc ~ignore_dups_in_list ~stdlib: stdlib ~ldconf: ldconf ~config: config_file ~install_dir: destdir ~meta_dir: metadir ~search_path: search_path () ;; let lazy_init() = if not !init_called then init() let config_file() = lazy_init(); !conf_config_file;; let default_location() = lazy_init(); !conf_default_location;; let meta_directory() = lazy_init(); if !conf_meta_directory = "none" then "" else !conf_meta_directory;; let search_path() = lazy_init(); !conf_search_path;; let command which = lazy_init(); try List.assoc which !conf_command with Not_found -> assert false ;; let ocaml_stdlib() = lazy_init(); !conf_stdlib;; let ocaml_ldconf() = lazy_init(); !conf_ldconf;; let ignore_dups_in() = lazy_init(); !conf_ignore_dups_in;; let package_directory pkg = lazy_init(); (Fl_package_base.query pkg).Fl_package_base.package_dir ;; let package_meta_file pkg = lazy_init(); (Fl_package_base.query pkg).Fl_package_base.package_meta ;; let package_property_2 predlist pkg propname = lazy_init(); let l = Fl_package_base.query pkg in Fl_metascanner.lookup_2 propname predlist l.Fl_package_base.package_defs ;; let package_property predlist pkg propname = lazy_init(); let l = Fl_package_base.query pkg in Fl_metascanner.lookup propname predlist l.Fl_package_base.package_defs ;; let package_ancestors preds pkg = lazy_init(); Fl_package_base.requires ~preds pkg ;; let package_deep_ancestors preds pkglist = lazy_init(); Fl_package_base.requires_deeply ~preds pkglist ;; let resolve_path ?base ?(explicit=false) p = lazy_init(); if p = "" then "" else ( match p.[0] with '^' | '+' -> let stdlibdir = Fl_split.norm_dir (ocaml_stdlib()) in Filename.concat stdlibdir (String.sub p 1 (String.length p - 1)) | '@' -> (* Search slash *) ( try let k = String.index p '/' in (* or Not_found *) let pkg = String.sub p 1 (k-1) in let p' = String.sub p (k+1) (String.length p - k - 1) in let pkgdir = package_directory pkg in Filename.concat pkgdir p' with Not_found -> let pkg = String.sub p 1 (String.length p - 1) in package_directory pkg ) | _ -> ( match base with None -> p | Some b -> if Filename.is_relative p && (not explicit || not (Filename.is_implicit p)) then Filename.concat b p else p ) ) ;; let list_packages ?(tab = 20) ?(descr = false) ch = lazy_init(); let packages = Fl_package_base.list_packages() in let packages_sorted = List.sort compare packages in List.iter (fun p -> let v_string = try let v = package_property [] p "version" in "(version: " ^ v ^ ")" with Not_found -> "(version: n/a)" in let descr_string = try package_property [] p "description" with Not_found -> "(no description)" in let spaces1 = String.make (max 1 (tab-String.length p)) ' ' in let spaces2 = String.make tab ' ' in if descr then ( output_string ch (p ^ spaces1 ^ descr_string ^ "\n"); output_string ch (spaces2 ^ v_string ^ "\n") ) else output_string ch (p ^ spaces1 ^ v_string ^ "\n"); ) packages_sorted ;; let list_packages' ?prefix () = lazy_init(); Fl_package_base.list_packages ?prefix () type rectype = | Record_core | Record_load let rec_core = ref StrSet.empty let rec_load = ref StrSet.empty let rec_preds = ref [] let record_package (rt:rectype) (p:string) = match rt with | Record_core -> rec_core := StrSet.add p !rec_core | Record_load -> rec_load := StrSet.add p !rec_load let recorded_packages rt = match rt with | Record_core -> StrSet.elements !rec_core | Record_load -> StrSet.elements (StrSet.diff !rec_load !rec_core) let reset_recordings() = rec_load := StrSet.empty let type_of_recorded_package p = if StrSet.mem p !rec_core then Record_core else if StrSet.mem p !rec_load then Record_load else raise Not_found let is_recorded_package p = try ignore(type_of_recorded_package p); true with Not_found -> false let rm_preds = [ "create_toploop"; "toploop"; "executable"; "plugin"; "autolink"; "preprocessor"; "syntax" ] let rm_preds_set = List.fold_right StrSet.add rm_preds StrSet.empty let record_package_predicates preds = let preds' = List.filter (fun p -> not(StrSet.mem p rm_preds_set)) preds in rec_preds := preds' let recorded_predicates() = !rec_preds not-ocamlfind-0.14/local-packages/ocamlfind/src/findlib/findlib.mli0000644000175000017500000002632414770304423024345 0ustar stephsteph(* $Id$ * ---------------------------------------------------------------------- * *) (** The primary findlib interface * * The Findlib module is the primary interface of the findlib library. It * contains functions to look up packages, to interpret META * files, and to determine the ancestors of packages. * * This module must be initialized before it can be used: Call either * [init] or [init_manually] for this. *) exception No_such_package of string * string (** First arg is the package name not found, second arg contains additional * info for the user *) exception Package_loop of string (** A package is required by itself. The arg is the name of the * package *) type formal_pred = [ `Pred of string (** Positive occurrence of a formal predicate var *) | `NegPred of string (** Negative occurrence of a formal predicate var *) ] (** A formal predicate as it occurs in a package definition *) val init : ?env_ocamlpath: string -> ?env_ocamlfind_destdir: string -> ?env_ocamlfind_metadir: string -> ?env_ocamlfind_commands: string -> ?env_ocamlfind_ignore_dups_in: string -> ?env_ocamlfind_ignore_dups_in_list: string list -> ?env_camllib: string -> ?env_ldconf: string -> ?config: string -> ?toolchain: string -> unit -> unit (** Initializes the library from the configuration file and the environment. * By default the * function reads the file specified at compile time, but you can also * pass a different file name in the [config] argument. * Furthermore, the environment variables OCAMLPATH, OCAMLFIND_DESTDIR, * OCAMLFIND_COMMANDS, OCAMLFIND_IGNORE_DUPS_IN, and CAMLLIB are interpreted. * By default, the function takes * the values found in the environment, but you can pass different values * using the [env_*] arguments. By setting these values to empty strings * they are no longer considered. * The result of the initialization is determined as follows: * - The default installation directory is the env variable OCAMLFIND_DESTDIR * (if present and non-empty), and otherwise the variable [destdir] of the * configuration file. * - The installation directory for META files is read from the env * variable OCAMLFIND_METADIR (if present and non-empty), and otherwise * from the variable [metadir] of the configuration file, and otherwise * no such directory is used. * The special value ["none"] turns this feature off. * - The search path is the concatenation of the env variable OCAMLPATH * and the variable [path] of the config file * - The executables of (ocamlc|ocamlopt|ocamlcp|ocamlmklib|ocamlmktop) are * determined as follows: if the env variable OCAMLFIND_COMMANDS is set * and non-empty, its contents specify the executables. Otherwise, if the * config file variables [ocamlc], [ocamlopt], [ocamlcp], [ocamlmklib] and * [ocamlmktop] are set, their contents specify the executables. Otherwise, * the obvious default values are chosen: ["ocamlc"] for [ocamlc], * ["ocamlopt"] for [ocamlopt], and so on. * - The directory of the standard library is the value of the environment * variable CAMLLIB (or OCAMLLIB), or if unset or empty, the value of * the configuration variable [stdlib], or if unset the built-in location * - The [ld.conf] file (configuring the dynamic loader) is the value of * the environment variable OCAMLFIND_LDCONF, or if unset or empty, the * value of the configuration variable [ldconf], or if unset the * built-in location. * - The ocamlfind tool doesn't emit warnings about double cmi files * for the directories listed in OCAMLFIND_IGNORE_DUPS_IN. Since * findlib-1.8 this variable is interpreted as colon-separated path. * (Before, only one directory could be given.) If the variable is not * set there are no exceptions, and the warnings are always printed. * Note that both the parameters [env_ocamlfind_ignore_dups_in] (a * single directory) and [env_ocamlfind_ignore_dups_in_list] (a list * of directories) override the default. *) val init_manually : ?ocamlc_command: string -> (* default: "ocamlc" *) ?ocamlopt_command: string -> (* default: "ocamlopt" *) ?ocamlcp_command: string -> (* default: "ocamlcp" *) ?ocamloptp_command: string -> (* default: "ocamloptp" *) ?ocamlmklib_command: string -> (* default: "ocamlmklib" *) ?ocamlmktop_command: string -> (* default: "ocamlmktop" *) ?ocamldep_command: string -> (* default: "ocamldep" *) ?ocamlbrowser_command: string -> (* default: "ocamlbrowser" *) ?ocamldoc_command: string -> (* default: "ocamldoc" *) ?ignore_dups_in:string -> (* default: None *) ?ignore_dups_in_list:string list -> (* default: [] *) ?stdlib: string -> (* default: taken from Findlib_config *) ?ldconf: string -> ?config: string -> install_dir: string -> meta_dir: string -> search_path: string list -> unit -> unit (** This is an alternate way to initialize the library directly. * Environment variables and configuration files are ignored. The * parameter [config] just sets the file name reported by the * [config_file] function below. *) val config_file : unit -> string (** The location of the configuration file *) val default_location : unit -> string (** Get the default installation directory for packages *) val meta_directory : unit -> string (** Get the META installation directory for packages. * Returns [""] if no such directory is configured. *) val search_path : unit -> string list (** Get the search path for packages *) val command : [ `ocamlc | `ocamlopt | `ocamlcp | `ocamloptp | `ocamlmklib | `ocamlmktop | `ocamldep | `ocamlbrowser | `ocamldoc ] -> string (** Get the name/path of the executable *) val ocaml_stdlib : unit -> string (** Get the directory of the standard library *) val ocaml_ldconf : unit -> string (** Get the file name of [ld.conf] *) val package_directory : string -> string (** Get the absolute path of the directory where the given package is * stored. * * Raises [No_such_package] if the package cannot be found. *) val package_meta_file : string -> string (** Get the absolute path of the META file of the given package *) val ignore_dups_in : unit -> string list (** If [Some d], duplicate packages below [d] are ignored, and do not * produce warnings. (Only affects the generation of warnings.) * * Since findlib-1.8 this configuration is a list. Before, it was a * [string option]. *) val package_property : string list -> string -> string -> string (** [package_property predlist pkg propname]: * Looks up the property [propname] of package [pkg] under the assumption * that the predicates in [predlist] are true. * * Raises [No_such_package] if the package, and [Not_found] if the property * cannot be found. * * EXAMPLES: * - [package_property [] "p" "requires":] * get the value of the [requires] clause of package [p] * - [package_property [ "mt"; "byte" ] "p" "archive":] * get the value of the [archive] property of package [p] for multi- * threaded bytecode applications. *) val package_property_2 : string list -> string -> string -> string * formal_pred list (** [package_property_2 predlist pkg propname]: This returns two values [(v, preds)]. The first one, [v], is computed as in [package_property]. The other list, [preds], contains the predicates that actually had to be set or not set in order to select the particular variable definition. *) val package_ancestors : string list -> string -> string list (** [package_ancestors predlist pkg:] * Determines the direct ancestors of package [pkg] under the assumption * that the predicates in [predlist] are true, i.e. the names of the * packages required by [pkg]. * The returned list is unsorted. * * Raises [No_such_package] if the package [pkg] or one of its ancestors * could not be found. *) val package_deep_ancestors : string list -> string list -> string list (** [package_deep_ancestors predlist pkglist:] * determines the list of direct or indirect ancestors of the packages * named in [pkglist] under the assumption that the predicates in [predlist] * are true. * * The returned list is topologically sorted: The first element is the * deepest ancestor; the last element is one of [pkglist]. * * Raises [No_such_package] if one of the packages in [pkglist] or one of * the ancestors cannot be found. Raises [Package_loop] if there is a * cyclic dependency. *) val resolve_path : ?base:string -> ?explicit:bool -> string -> string (** Resolves findlib notation in filename paths. The notation * [ +name/path ] can be used to refer to the subdirectory [name] * of the standard library directory; the continuation [ /path ] is * optional. The notation [ \@name/path ] can be used to refer to * the directory of the package [name]; the continuation [ /path ] * is optional. For these two notations, absolute paths are returned. * * @param base When the function is applied on a relative path, the * [base] path is prepended. Otherwise, the path is returned as * it is. * @param explicit Changes the meaning of [base] so that only paths * count as relative that include at least one slash. *) val list_packages : ?tab:int -> ?descr:bool -> out_channel -> unit (** Prints the list of available packages to the [out_channel]. * * @param tab The tabulator width, by default 20 * @param descr Whether package descriptions are printed. Default: false *) val list_packages' : ?prefix:string -> unit -> string list (** Returns the (unsorted) list of all packages. * * @param prefix Limit to the packages that starts with it. Default: unlimited *) (** Managing dynamically loaded packages *) (** This is a registry of packages that are available in-core. This is both used for toploops and for plugins. *) type rectype = | Record_core (** The package is part of the executable core *) | Record_load (** The package has been dynamically loaded *) val record_package : rectype -> string -> unit (** Record this package *) val record_package_predicates : string list -> unit (** Record the predicates to be used for package loading. Certain predicates are automatically filtered out if inappropriate. A call of [record_package_predicates] replaces the set of predicates that was installed beforehand. *) val recorded_packages : rectype -> string list (** The list of packages recorded with [record_package] *) val is_recorded_package : string -> bool (** Whether there is a recording for this package *) val type_of_recorded_package : string -> rectype (** Returns the type, or raises [Not_found] *) val recorded_predicates : unit -> string list (** The most recent version of the recorded predicate list *) val reset_recordings : unit -> unit (** Removes all [Record_load] packages from the list of recordings. This forces that the packages are loaded again. *) not-ocamlfind-0.14/local-packages/ocamlfind/src/findlib/findlib_config.mlp0000644000175000017500000000605414770304423025677 0ustar stephsteph(* $Id$ * ---------------------------------------------------------------------- * *) open Fl_compat let ( / ) = Filename.concat let exists path = match Sys.file_exists path with | true -> Some path | false -> None let findlib_conf_of_path path = match exists (path / "etc" / "findlib.conf") with | Some etc_path -> etc_path | None -> path / "lib" / "findlib.conf" let install_dir_from_binary path = let exe_dir = Filename.dirname path in let install_dir = Filename.dirname exe_dir in let config_path = findlib_conf_of_path install_dir in match Sys.file_exists config_path with | true -> Some install_dir | false -> None ;; let find_in_path name = match Sys.getenv_opt "PATH" with | None -> None | Some search_in -> ( let paths = String.split_on_char Fl_split.path_separator search_in in match List.find_map (fun path -> path / name |> exists) paths with | None -> None | Some location -> install_dir_from_binary location) ;; let install_dir_from_ld_library_path paths = String.split_on_char Fl_split.path_separator paths |> List.find_map (fun path -> let parent = Filename.dirname path in let parent' = Filename.dirname parent in match Sys.file_exists (findlib_conf_of_path parent') with | true -> Some parent' | false -> None) ;; let install_dir_from_ocaml_toplevel_path = install_dir_from_binary let install_dir_from_opam_switch_prefix path = match Sys.file_exists (findlib_conf_of_path path) with | false -> None | true -> Some path let default = "@CONFIGFILE@" let fallback = Option.value ~default let rec try_vars = function | [] -> None | (var, mapper)::xs -> ( match Sys.getenv_opt var with | None -> try_vars xs | Some content -> ( match mapper content with | None -> try_vars xs | Some _ as found -> found)) (* exposed condfigure-time setting *) let uses_relative_paths = @RELATIVE_PATHS@ (* the location where we assume to be installed in *) let location = lazy ( try_vars [ ("OPAM_SWITCH_PREFIX", install_dir_from_opam_switch_prefix); ("CAML_LD_LIBRARY_PATH", install_dir_from_ld_library_path); ("OCAML_TOPLEVEL_PATH", install_dir_from_ocaml_toplevel_path); ]) let findlib_conf = lazy ( match Lazy.force location with | None -> default | Some location -> location |> findlib_conf_of_path |> exists |> fallback) let config_file = lazy ( match uses_relative_paths with | false -> default | true -> Lazy.force findlib_conf) let ocaml_has_meta_files = let ocaml_major = String.sub Sys.ocaml_version 0 (String.index Sys.ocaml_version '.') in int_of_string ocaml_major >= 5;; let ocaml_stdlib = "@STDLIB@";; let ocaml_ldconf = ocaml_stdlib / "ld.conf";; let ocaml_has_autolinking = @AUTOLINK@;; let libexec_name = "stublibs";; let system = "@SYSTEM@";; (* - "mingw", "mingw64", "win32", "cygwin", "linux_elf", ... *) let dll_suffix = match Sys.os_type with | "Unix" | "BeOS" -> ".so" | "Win32" | "Cygwin" -> ".dll" | "MacOS" -> "" (* don't know *) | _ -> failwith "Unknown Sys.os_type" ;; not-ocamlfind-0.14/local-packages/ocamlfind/src/findlib/fl_args.ml0000644000175000017500000000524314770304423024177 0ustar stephsteph(* $Id$ *) (* Rewrite a list of arguments args (from Sys.args) so that contracted options like -L are transformed to -L , and become parseable by Arg. *) let make_ht (l:string list) = let ht = Hashtbl.create 10 in List.iter (fun x -> Hashtbl.add ht x ()) l; ht let is_prefix s1 s2 = let l1 = String.length s1 in let l2 = String.length s2 in l2 >= l1 && String.sub s2 0 l1 = s1 let rewrite_contracted_args spec contracted_opts args = let args = Array.to_list args in let switches = List.map (fun (name,kind,text) -> name) (List.filter (fun (name,kind,text) -> match kind with | Arg.Unit _ | Arg.Set _ | Arg.Clear _ -> true | Arg.Tuple _ -> failwith "Fl_args.rewrite_for_contracted_args: Arg.Tuple unsupported" | _ -> false ) spec ) in let unary_opts = List.map (fun (name,kind,text) -> name) (List.filter (fun (name,kind,text) -> match kind with | Arg.String _ | Arg.Set_string _ | Arg.Int _ | Arg.Set_int _ | Arg.Float _ | Arg.Set_float _ -> true | _ -> false ) spec ) in let rest_opts = List.map (fun (name,kind,text) -> name) (List.filter (fun (name,kind,text) -> match kind with | Arg.Rest _ -> true | _ -> false ) spec ) in let sw_ht = make_ht switches in let unary_ht = make_ht unary_opts in let rest_ht = make_ht rest_opts in let rec rewrite (args:string list) = match args with | arg :: args_rest when Hashtbl.mem sw_ht arg -> arg :: rewrite args_rest | arg :: args_rest when Hashtbl.mem rest_ht arg -> args | arg1 :: arg2 :: args_rest when Hashtbl.mem unary_ht arg1 -> arg1 :: arg2 :: rewrite args_rest | arg :: args_rest -> ( try let args1 = expand arg contracted_opts in let args2 = rewrite args_rest in args1 @ args2 with | Not_found -> arg :: rewrite args_rest ) | [] -> [] and expand arg olo = match olo with | olo1 :: olo_rest -> if is_prefix olo1 arg then let p = String.length olo1 in let l = String.length arg in [ olo1; String.sub arg p (l-p) ] else expand arg olo_rest | [] -> raise Not_found in Array.of_list (rewrite args) not-ocamlfind-0.14/local-packages/ocamlfind/src/findlib/fl_compat.ml0000644000175000017500000000246614770304423024532 0ustar stephstephlet ( |> ) x f = f x module String = struct let split_on_char sep s = let r = ref [] in let j = ref (String.length s) in for i = String.length s - 1 downto 0 do if String.unsafe_get s i = sep then begin r := String.sub s (i + 1) (!j - i - 1) :: !r; j := i end done; String.sub s 0 !j :: !r let starts_with ~prefix s = let len_s = String.length s and len_pre = String.length prefix in let rec aux i = if i = len_pre then true else if String.unsafe_get s i <> String.unsafe_get prefix i then false else aux (i + 1) in len_s >= len_pre && aux 0 include String end module List = struct let rec find_map f = function | [] -> None | x :: l -> begin match f x with | Some _ as result -> result | None -> find_map f l end let rec filter_map f = function | [] -> [] | x :: l -> ( match f x with | None -> filter_map f l | Some v -> v :: filter_map f l) include List end module Option = struct let value o ~default = match o with Some v -> v | None -> default (* can't include Option because it was only introduced in 4.08 *) (* include Option *) end module Sys = struct let getenv_opt s = try Some (Sys.getenv s) with Not_found -> None include Sys end not-ocamlfind-0.14/local-packages/ocamlfind/src/findlib/fl_dynload.ml0000644000175000017500000000352314770304423024674 0ustar stephsteph(* $Id$ *) (* Utilities for loading dynamically packages *) open Printf let load_pkg ~debug ~loadfile pkg = if not (Findlib.is_recorded_package pkg) then ( if debug then eprintf "[DEBUG] Fl_dynload: about to load: %s\n%!" pkg; (* Determine the package directory: *) let d = Findlib.package_directory pkg in (* First try the new "plugin" variable: *) let preds = Findlib.recorded_predicates() in let archive = try Findlib.package_property preds pkg "plugin" with | Not_found -> (* Legacy: use "archive" but require that the predicate "plugin" is mentioned in the definition *) try let v, fpreds = Findlib.package_property_2 ("plugin"::preds) pkg "archive" in let need_plugin = List.mem "native" preds in if need_plugin && not (List.mem (`Pred "plugin") fpreds) then "" else v with Not_found -> "" in (* Split the plugin/archive property and resolve the files: *) let files = Fl_split.in_words archive in if debug then eprintf "[DEBUG] Fl_dynload: files=%S\n%!" archive; List.iter (fun file -> if debug then eprintf "[DEBUG] Fl_dynload: loading %S\n%!" file; let file = Findlib.resolve_path ~base:d file in loadfile file ) files; Findlib.record_package Findlib.Record_load pkg ) else if debug then eprintf "[DEBUG] Fl_dynload: not loading: %s\n%!" pkg let load_packages ?(debug=false) ?(loadfile=Dynlink.loadfile) pkgs = let preds = Findlib.recorded_predicates() in let eff_pkglist = Findlib.package_deep_ancestors preds pkgs in List.iter (load_pkg ~debug ~loadfile) eff_pkglist not-ocamlfind-0.14/local-packages/ocamlfind/src/findlib/fl_dynload.mli0000644000175000017500000000322414770304423025043 0ustar stephsteph(* $Id$ *) (** Utilities for loading dynamically packages *) val load_packages : ?debug:bool -> ?loadfile:(string -> unit) -> string list -> unit (** Load the given packages and all their dependencies dynamically. Packages already loaded or already in-core are not loaded again. The predicates are taken from {!Findlib.recorded_predicates}, which are normally the predicates from the link-time of the executable. In order to initialize this module correctly, you need to link the executable in a special way. This is done by including "findlib.dynload" in the [ocamlfind] command, e.g. {[ ocamlfind ocamlopt -o program -package findlib.dynload -linkpkg m.ml ]} It is not sufficient to just link [findlib_dynload.cm(x)a] into the executable. The above command adds special initialization code that (a) records the predicates and (b) records the packages already present in the executable. Also [-linkall] is implicitly added. The dynamic package loader works both for bytecode and native code. The META files of the packages need to specify the cma or cmxs files in the following way: - First, the "plugin" variable is checked (instead of "archive"), e.g. {[ plugin(byte) = "my_plugin.cma" plugin(native) = "my_plugin.cmxs" ]} This is the preferred style. - Second, for bytecode only, the normal "archive" variable is also accepted if "plugin" is not present. (Because bytecode archives can normally be dynamically loaded without special preparation.) - Third, for native-code only, the "archive(plugin)" variable is also accepted. This is for legacy packages. *) not-ocamlfind-0.14/local-packages/ocamlfind/src/findlib/fl_lint.ml0000644000175000017500000000705114770304423024210 0ustar stephsteph(* $Id$ -*- tuareg -*- * ---------------------------------------------------------------------- * *) open Fl_metascanner module Have = struct module T = struct type mode = [`Byte | `Native | `Toploop | `Preprocessor | `Ppx_driver] type t = [ `Mode of [ `TooMany | `None] (** problem in the number of mode (byte,native,syntax,...) in the variable *) | `Archive of [`Plugin|`NoPlugin] * mode (** archive(plugin,...) or archive(...)) *) | `Plugin of [`Plugin|`NoPlugin] * mode (** plugin(...) *) | `Description | `Requires | `Version ] let compare = compare end include T module Set = Set.Make(T) module Map = Map.Make(T) end let scan_def acc def = let add have = Have.Map.add have def acc in let has_plugin_pred = List.mem (`Pred "plugin") def.def_preds in let plugin = if has_plugin_pred then `Plugin else `NoPlugin in let modes = [ "byte", `Byte; "native", `Native; "toploop", `Toploop; "preprocessor", `Preprocessor; "ppx_driver", `Ppx_driver ] in let modes = List.filter (fun (p,_) -> List.mem (`Pred p) def.def_preds) modes in let modes = List.map snd modes in match def.def_var, modes with (** For archive the modes are used in multiple ways, so we can't check exhaustiveness or presence. *) | "plugin", [] -> add (`Mode(`None)) | "plugin", _::_::_ -> add (`Mode(`TooMany)) | "archive", [mode] -> add (`Archive(plugin,mode)) | "plugin", [mode] -> add (`Plugin(plugin,mode)) | "description", _ -> add `Description | "requires", _ -> add `Requires | "version", _ -> add `Version | _ -> acc let warn_def ~warned pkg = let haves = List.fold_left scan_def Have.Map.empty pkg.pkg_defs in let mem x = Have.Map.mem x haves in let find x = Have.Map.find x haves in let warning fmt = warned := true; Printf.printf fmt in let if_ ?has ?(has_not=[]) msg = match has, has_not with | Some has, [] when mem has -> warning "%a%s\n\n" print_def (find has) msg; | Some has, has_not when mem has && not (List.exists mem has_not) -> warning "%a%s\n\n" print_def (find has) msg; | None, has_not when not (List.exists mem has_not) -> warning "%s\n\n" msg; | _ -> () in if_ ~has_not:[`Description] "You should add a description."; if_ ~has_not:[`Version] "You should add a version."; if_ ~has_not:[`Requires] "You should add the required libraries. You can silent this \ warning by using the empty string."; if_ ~has:(`Mode(`TooMany)) "This variable should have only one mode (\"byte\", \"native\")."; if_ ~has:(`Mode(`None)) "This variable should have at least the predicate \ \"byte\" or \"native\"."; let with_mode mode = if_ ~has:(`Plugin (`Plugin,mode)) "You must not add the predicate \"plugin\" to the variable \ \"plugin\"."; if_ ~has:(`Archive (`Plugin,mode)) ~has_not:[`Plugin (`NoPlugin,mode)] "This specification of dynamic loading is deprecated, you should add a \ \"plugin(...)\" variable."; if_ ~has:(`Archive (`NoPlugin,mode)) ~has_not:[`Plugin (`NoPlugin,mode);`Archive (`Plugin,mode)] "This variable indicates how to link statically, you should add a \ \"plugin(...)\" variable for linking dynamically."; in with_mode `Byte; with_mode `Native let warn pkg = let warned = ref false in let rec aux pkg = warn_def ~warned pkg; List.iter (fun (_,pkg) -> aux pkg) pkg.pkg_children; in aux pkg; !warned not-ocamlfind-0.14/local-packages/ocamlfind/src/findlib/fl_meta.mll0000644000175000017500000000204314770304423024340 0ustar stephsteph(* $Id$ * ---------------------------------------------------------------------- * *) { open Fl_metatoken } rule token = parse [ 'A'-'Z' 'a'-'z' '_' '0'-'9' '.' ]+ { Name (Lexing.lexeme lexbuf) } | '(' { LParen } | ')' { RParen } | "+=" { PlusEqual } | '=' { Equal } | '-' { Minus } | ',' { Comma } | '"' [^ '"' '\\' ]* ( ( "\\\\" | "\\\"" ) [^ '"' '\\' ]* )* '"' { let s1 = Lexing.lexeme lexbuf in let s2 = String.sub s1 1 (String.length s1 - 2) in let l2 = String.length s2 in let b = Buffer.create 80 in let rec fill i = if i Buffer.add_char b s2.[i+1]; fill (i+2) | c -> Buffer.add_char b c; fill (i+1) in fill 0; String (Buffer.contents b) } | [ ' ' '\t' '\r' ] { Space } | '\n' { Newline } | '#' [^ '\n']* '\n' { Newline } | '#' [^ '\n']* eof { Eof } | eof { Eof } | _ { Unknown } {} not-ocamlfind-0.14/local-packages/ocamlfind/src/findlib/fl_metascanner.ml0000644000175000017500000002337014770304423025544 0ustar stephsteph(* $Id$ -*- tuareg -*- * ---------------------------------------------------------------------- * *) open Fl_metatoken open Printf type formal_pred = [ | `Pred of string | `NegPred of string ] type flavour = [ | `BaseDef | `Appendix ] type pkg_definition = { def_var : string; def_flav : flavour; def_preds : formal_pred list; def_value : string } type pkg_expr = { pkg_defs : pkg_definition list; pkg_children : (string * pkg_expr) list } exception Error of string let string_of_preds pl = let print = function | `Pred n -> n | `NegPred n -> "-" ^ n in if pl = [] then "" else "(" ^ ((String.concat "," (List.map print pl)) ^ ")") let scan_lexing buf = (* transform an in_channel to a token stream; 'Space' tokens are left * out. *) let (line_ref, pos0_ref, eof_found) = ((ref 1), (ref 0), (ref false)) in fun () -> let rec next line pos0 = let t = Fl_meta.token buf in match t with | Space -> next line pos0 | Newline -> next (line + 1) (Lexing.lexeme_end buf) | Eof -> (eof_found := true; produce line pos0 Eof) | _ -> produce line pos0 t and produce line pos0 t = (line_ref := line; pos0_ref := pos0; let pos = (Lexing.lexeme_start buf) - pos0 in (line, pos, t)) in if !eof_found then produce !line_ref !pos0_ref Eof else next !line_ref !pos0_ref let scan ch = scan_lexing (Lexing.from_channel ch) let parse_lexing lexbuf = let rec mk_set l = match l with | x :: l' -> if List.mem x l' then mk_set l' else x :: (mk_set l') | [] -> [] in let error_msg msg line col = Printf.sprintf "%s at line %d position %d" msg line col in let next_token = scan_lexing lexbuf in let raise_err error_fun line col = raise (Error (error_fun line col)) in let get_tok test error_fun = let (line, col, tok) = next_token () in match test tok with | None -> raise_err error_fun line col | Some result -> result in let get_rule rule arg error_fmt line col = try rule arg with | Error _ -> raise_err error_fmt line col in let rec parse_all need_rparen = match next_token () with | (line, col, Name "package") -> let n = get_tok string_tok (error_msg "String literal expected after 'package'") in let () = get_tok (const_tok LParen) (error_msg "'(' expected after string") in let subpkg = get_rule parse_all true (error_msg "Error in subpackage definition") line col in let rest = parse_all need_rparen in { pkg_defs = rest.pkg_defs; pkg_children = (n, subpkg) :: rest.pkg_children; } | (line, col, Name n) -> let (args, flav, value) = get_rule parse_properties () (error_msg "Error in 'name = value' clause") line col in let rest = parse_all need_rparen in (* TODO: Check args *) let args' = List.sort compare (mk_set args) in let def = { def_var = n; def_flav = flav; def_preds = args'; def_value = value; } in { pkg_defs = def :: rest.pkg_defs; pkg_children = rest.pkg_children; } | (line, col, Eof) -> (if need_rparen then raise_err (Printf.sprintf "Unexpected end of file in line %d position %d") line col else (); { pkg_defs = []; pkg_children = []; }) | (line, col, RParen) -> (if not need_rparen then raise_err (Printf.sprintf "Unexpected end of file in line %d position %d") line col else (); { pkg_defs = []; pkg_children = []; }) | (line, col, _) -> raise_err (error_msg "Expected 'name = value' clause") line col and parse_properties () = match next_token () with | (line, col, LParen) -> let arg1 = parse_argument () in let args = parse_arguments () in let flav = parse_flavour () in let s = get_tok string_tok (error_msg "Expected string constant after '='") in ((arg1 :: args), flav, s) | (line, col, Equal) -> let s = get_tok string_tok (error_msg "'=' must be followed by a string constant") in ([], `BaseDef, s) | (line, col, PlusEqual) -> let s = get_tok string_tok (error_msg "'+=' must be followed by a string constant") in ([], `Appendix, s) | (line, col, _) -> raise_err (error_msg "Expected a '=' or a '(arguments,...)=' clause") line col and parse_arguments () = match next_token () with | (line, col, Comma) -> let arg = parse_argument () in let args = parse_arguments () in arg :: args | (_, _, RParen) -> [] | (line, col, _) -> raise_err (error_msg "Another predicate or a ')' expected") line col and parse_argument () = match next_token () with | (line, col, Name n) -> `Pred n | (line, col, Minus) -> let n = get_tok name_tok (error_msg "Name expected after '-'") in `NegPred n | (line, col, _) -> raise_err (error_msg "Name or -Name expected") line col and parse_flavour () = match next_token () with | (line, col, Equal) -> `BaseDef | (line, col, PlusEqual) -> `Appendix | (line, col, _) -> raise_err (error_msg "'+' or '+=' expected") line col in let rec check_defs p l = match l with | [] -> () | def :: l' -> (List.iter (fun def' -> if (def.def_var = def'.def_var) && ((def.def_preds = def'.def_preds) && ((def.def_flav = `BaseDef) && (def'.def_flav = `BaseDef))) then (let prefix = if p = "" then "" else "In subpackage " ^ (p ^ ": ") in let args = string_of_preds def.def_preds in raise (Error (prefix ^ ("Double definition of '" ^ (def.def_var ^ (args ^ "'")))))) else ()) l'; check_defs p l') in let rec check_pkg p pkg = (check_defs p pkg.pkg_defs; let l = ref [] in List.iter (fun (n, subpkg) -> let p' = if p = "" then n else p ^ ("." ^ n) in (if List.mem n !l then raise (Error ("Double definition for subpackage " ^ p')) else (); if String.contains n '.' then raise (Error ("Subpackage name must not contain '.': \"" ^ (n ^ "\""))) else (); check_pkg p' subpkg; l := n :: !l)) pkg.pkg_children) in try let pkg = parse_all false in (check_pkg "" pkg; pkg) with | Error "" -> raise (Error "Syntax Error") let parse ch = parse_lexing (Lexing.from_channel ch) let escape s = (* no Str available :-( *) let b = Buffer.create (String.length s) in (for k = 0 to (String.length s) - 1 do (match s.[k] with | '\\' -> Buffer.add_string b "\\\\" | '"' -> Buffer.add_string b "\\\"" | c -> Buffer.add_char b c) done; Buffer.contents b) let print_def f def = let format_pred = function | `Pred s -> s | `NegPred s -> "-" ^ s in fprintf f "%s%s %s \"%s\"\n" def.def_var (match def.def_preds with | [] -> "" | l -> "(" ^ ((String.concat "," (List.map format_pred l)) ^ ")")) (match def.def_flav with | `BaseDef -> "=" | `Appendix -> "+=") (escape def.def_value) let rec print f pkg = (List.iter (print_def f) pkg.pkg_defs; List.iter (fun (name, child) -> (fprintf f "\npackage \"%s\" (\n" (escape name); print f child; fprintf f ")\n")) pkg.pkg_children) let rec remove_dups l = (* FIXME: O(n^2) *) match l with x :: l' -> if List.mem x l' then remove_dups l' else x::remove_dups l' | [] -> [] let lookup_2 name predicate_list def = let fulfills actual_preds formal_preds = List.for_all (function | `Pred n -> List.mem n predicate_list | `NegPred n -> not (List.mem n predicate_list)) formal_preds in let rec search_base best_n best_value l = match l with | [] -> if best_n >= 0 then best_value else raise Not_found | def :: l' -> if (name = def.def_var) && ((def.def_flav = `BaseDef) && ((fulfills predicate_list def.def_preds) && ((List.length def.def_preds) > best_n))) then search_base (List.length def.def_preds) (def.def_value, def.def_preds) l' else search_base best_n best_value l' in let rec search_appdx l = match l with | [] -> [] | def :: l' -> if (name = def.def_var) && ((def.def_flav = `Appendix) && (fulfills predicate_list def.def_preds)) then (def.def_value, def.def_preds) :: (search_appdx l') else search_appdx l' in let value_a, preds_a = search_base (-1) ("",[]) def in let additions = search_appdx def in let values_b = List.map fst additions in let preds_b = List.flatten (List.map snd additions) in let value = String.concat " " (value_a :: values_b) in let preds = remove_dups (preds_a @ preds_b) in (value, preds) let lookup name predicate_list def = fst(lookup_2 name predicate_list def) let predicate_exists p defs = List.exists (fun def -> List.exists (function | `Pred n -> n = p | `NegPred n -> n = p) def.def_preds) defs not-ocamlfind-0.14/local-packages/ocamlfind/src/findlib/fl_metascanner.mli0000644000175000017500000000700314770304423025710 0ustar stephsteph(* $Id$ * ---------------------------------------------------------------------- * *) (** Parses META files *) open Fl_metatoken type formal_pred = [ `Pred of string (** Positive occurrence of a formal predicate var *) | `NegPred of string (** Negative occurrence of a formal predicate var *) ] type flavour = [ `BaseDef | `Appendix ] (** [`BaseDef] refers to META definitions using the "=" operator, * and [`Appendix] refers to definitions using the "+=" operator. *) type pkg_definition = { def_var : string; (** The name of the defined variable *) def_flav : flavour; (** The flavour of the definition *) def_preds : formal_pred list; (** The formal predicates of the def *) def_value : string; (** The value assigned to the variable *) } (** A [pkg_definition] is expressed by the syntax * {[ var(p1,p2,...) = "value" ]} (flavour `BaseDef), * or the syntax * {[ var(p1,p2,...) += "value" ]} (flavour `Appendix) * in the META file. The list of predicates may be omitted. Predicates * may be negated by using "-", e.g. "-x". *) type pkg_expr = { pkg_defs : pkg_definition list; pkg_children : (string * pkg_expr) list; } (** A value of type [pkg_expr] denotes the contents of a META file. * The component [pkg_defs] are the variable definitions. * The component [pkg_children] contains * the definitions of the subpackages. *) exception Error of string val parse : in_channel -> pkg_expr (** [parse ch:] * scans and parses the file connected with channel [ch]. The file must * have a syntax compatible with the META format. The return value * contains the found definitions for the package and all subpackages. * * [exception Error of string:] is * raised on syntax errors. The string explains the error. *) val parse_lexing : Lexing.lexbuf -> pkg_expr val print_def : out_channel -> pkg_definition -> unit (** [print_def ch def]: * Outputs the definition to a channel. *) val print : out_channel -> pkg_expr -> unit (** [print ch expr]: * Outputs the package expression to a channel. *) val lookup : string -> string list -> pkg_definition list -> string (** [lookup variable_name predicate_list def]: * * Returns the value of [variable_name] in [def] under the assumption * that the predicates in [predicate_list] hold, but no other predicates. * * The rules are as follows: In the step (A), only the [`BaseDef] * definitions are considered. The first base definition is determined where * all predicates are satisfied and that has the longest predicate list. * In the step (B) only the [`Appendix] definitions are considered. * All definitions are determined where all predicates are satisfied. * The final result is the concatenation of the single result of (A) * and all results of (B) (in the order they are defined). A space * character is inserted between two concatenated strings. * * When step (A) does not find any matching definition, the exception * [Not_found] is raised. *) val lookup_2 : string -> string list -> pkg_definition list -> string * formal_pred list (** Like [lookup], but also returns the list of predicates that had to be considered to select the particular variable definition. *) val predicate_exists : string -> pkg_definition list -> bool (** [predicate_exists variable_name def]: Whether [variable_name] is explicitly mentioned in [def]. *) not-ocamlfind-0.14/local-packages/ocamlfind/src/findlib/fl_metatoken.ml0000644000175000017500000000122014770304423025221 0ustar stephsteph(* $Id$ * ---------------------------------------------------------------------- * *) type token = Name of string | LParen | RParen | Equal | PlusEqual | Minus | Comma | String of string | Space | Newline | Eof | Unknown ;; let name_tok = function | Name s -> Some s | _ -> None let string_tok = function | String s -> Some s | _ -> None let const_tok constant tok = match constant with | Name _ | String _ -> failwith "expect: only for constant tokens" | LParen | RParen | Equal | PlusEqual | Minus | Comma | Space | Newline | Eof | Unknown -> if constant = tok then Some () else None not-ocamlfind-0.14/local-packages/ocamlfind/src/findlib/fl_package_base.ml0000644000175000017500000004452014770304423025631 0ustar stephsteph(* $Id$ * ---------------------------------------------------------------------- * *) open Fl_metascanner exception No_such_package of string * string (* (name, reason) *) type package = { package_name : string; package_dir : string; package_meta : string; package_defs : Fl_metascanner.pkg_definition list; package_priv : package_priv } and package_priv = { mutable missing_reqs : (string * string) list; (* If non-empty the package is broken. This may be set by add_all_relations, and should be checked before using the package later. Each element corresponds to No_such_package. *) } ;; module Fl_metaentry = struct type t = package type id_t = string let id m = m.package_name end ;; module Fl_metastore = Fl_topo.Make(Fl_metaentry) ;; module StringSet = Set.Make(String);; let has_prefix s pref = String.length s >= String.length pref && String.sub s 0 (String.length pref) = pref ;; let ocamlpath = ref [];; let ocamlstdlib = ref "";; let conf_ignore_dups_in = ref ([] : string list) let store = Fl_metastore.create();; (* We collect here only nodes, but no relations. First copy [store] * and put relations into the copy. *) let init path stdlib ignore_dups_in = ocamlpath := path; ocamlstdlib := stdlib; conf_ignore_dups_in := ignore_dups_in ;; let packages_in_meta_file ?(directory_required = false) ~name:package_name ~dir:package_dir ~meta_file () = (* Parses the META file whose name is [meta_file]. In [package_name], the * name of the main package must be passed. [package_dir] is the * directory associated with the package by default (i.e. before * it is overridden by the "directory" directive). * * directory_required: If true, a "directory" directive is necessary. * * Returns the [package] records found in this file. The "directory" * directive is already applied. *) let rec flatten_meta pkg_name_prefix pkg_dir (pkg_name_component,pkg_expr) = (* Turns the recursive [pkg_expr] into a flat list of [package]s. * [pkg_dir] is the default package directory. [pkg_name_prefix] is * the name prefix to prepend to the fully qualified package name, or * "". [pkg_name_component] is the local package name. *) (* Determine the final package directory: *) let d = (* The value of "directory", or "" if not applicable *) try lookup "directory" [] pkg_expr.pkg_defs with Not_found -> if pkg_name_prefix="" && directory_required then failwith ("The `directory' directive is required in this META definition"); "" in let d' = if d = "" then pkg_dir else match d.[0] with | '^' | '+' -> let rest = String.sub d 1 (String.length d - 1) in if rest = "" then !ocamlstdlib else Filename.concat !ocamlstdlib rest | _ -> if Filename.is_relative d then Filename.concat pkg_dir d else d in let p_name = if pkg_name_prefix = "" then pkg_name_component else pkg_name_prefix ^ "." ^ pkg_name_component in let p = { package_name = p_name; package_dir = d'; package_meta = meta_file; package_defs = pkg_expr.pkg_defs; package_priv = { missing_reqs = [] } } in (* Check for exists_if: *) let p_exists = try let def = List.find (fun def -> def.def_var = "exists_if") p.package_defs in let files = Fl_split.in_words def.def_value in List.exists (fun file -> Sys.file_exists (Filename.concat d' file)) files with Not_found -> true in if p_exists then p :: (List.flatten (List.map (flatten_meta p_name d') pkg_expr.pkg_children)) else [] in let ch = open_in meta_file in try let pkg_expr = Fl_metascanner.parse ch in let packages = flatten_meta "" package_dir (package_name, pkg_expr) in close_in ch; packages with Failure s -> close_in ch; failwith ("While parsing '" ^ meta_file ^ "': " ^ s) | Fl_metascanner.Error s -> close_in ch; failwith ("While parsing '" ^ meta_file ^ "': " ^ s) | any -> close_in ch; raise any ;; let query package_name = let package_name_comps = Fl_split.package_name package_name in if package_name_comps = [] then invalid_arg "Fl_package_base.query"; let main_name = List.hd package_name_comps in let process_file_and_lookup ?directory_required package_dir meta_file = let packages = packages_in_meta_file ?directory_required ~name:main_name ~dir:package_dir ~meta_file () in let p = ( try List.find (fun p -> p.package_name = package_name) packages with Not_found -> raise (No_such_package (package_name, "")) ) in List.iter (Fl_metastore.add store) packages; p in let rec run_ocamlpath path = match path with [] -> raise(No_such_package(package_name, "")) | dir :: path' -> let package_dir = Filename.concat dir main_name in let meta_file_1 = Filename.concat package_dir "META" in let meta_file_2 = Filename.concat dir ("META." ^ main_name) in if Sys.file_exists meta_file_1 then process_file_and_lookup package_dir meta_file_1 else if Sys.file_exists meta_file_2 then process_file_and_lookup ~directory_required:true dir meta_file_2 (* Note: It is allowed to have relative "directory" directives. * The base directory is [dir] in this case. *) else run_ocamlpath path' in try Fl_metastore.find store package_name with Not_found -> run_ocamlpath !ocamlpath ;; exception Package_loop of string (* A package is required by itself. The arg is the name of the * package *) let fixup_thread_needed_1 predlist = (* When the thread fixup is required to apply, 1st criterion *) List.mem "mt" predlist ;; let fixup_thread_needed_2 pkg = (* When the thread fixup is required to apply, 2nd criterion *) (pkg <> "unix" && pkg <> "threads" && not (has_prefix pkg "threads.")) ;; let fixup_thread_base predlist pkg = (* Add the package "threads" if required *) if fixup_thread_needed_1 predlist && fixup_thread_needed_2 pkg then [ "threads" ] else [] ;; let query_requirements ~preds:predlist package_name = (* Part of [requires] implementation: Load all required packages, but * do not add relations *) let m = query package_name in (* may raise No_such_package *) let r = try Fl_metascanner.lookup "requires" predlist m.package_defs with Not_found -> "" in let ancestors = Fl_split.in_words r @ fixup_thread_base predlist package_name in List.iter (fun p -> try let _ = query p in (* may raise No_such_package *) () with No_such_package(pname,_) -> raise(No_such_package(pname, "required by `" ^ package_name ^ "'")) ) ancestors; ancestors ;; let add_relations s ancestors package_name = (* Part of [requires] implementation: Adds the relations from [package_name] * to [ancestors]. Target store is [s]. *) List.iter (fun p -> try Fl_metastore.let_le s p package_name (* add relation *) with | Fl_topo.Inconsistent_ordering -> raise(Package_loop p) | Not_found -> (* A relation to a package not part of [s]. We ignore it here. *) () ) ancestors ;; let add_all_relations preds s = (* Adds all relations for the packages currently defined in [s]. Note that missing requirements are not reported immediately (we do not know here which part of the graph [s] is really accessed), and instead the error is added to the missing_reqs field, where it should be checked before used. *) let pkgs = ref [] in Fl_metastore.iter_up (fun p -> pkgs := p :: !pkgs) s; List.iter (fun p -> let pkg = p.package_name in try let pkg_ancestors = query_requirements ~preds pkg in add_relations s pkg_ancestors pkg with | No_such_package(n,reason) -> p.package_priv.missing_reqs <- (n,reason) :: p.package_priv.missing_reqs ) !pkgs ;; let fixup_thread_deps s = (* All packages (except "threads", "threads.*", and "unix") are made * dependent on "threads" *) let pkgs = ref [] in Fl_metastore.iter_up (fun p -> pkgs := p.package_name :: !pkgs) s; List.iter (fun pkg -> if fixup_thread_needed_2 pkg then ( try Fl_metastore.let_le s "threads" pkg (* add relation *) with Not_found -> (* Because "threads" does not exist! Normally this is an * error, because "threads" is also magically added by * query_requirements. However, there are situations * where it cannot be expected that required packages * are loaded, so ignore this case. *) () ) ) !pkgs ;; let requires ~preds package_name = (* returns names of packages required by [package_name], the fully qualified * name of the package. It is checked that the packages really exist. * [preds]: list of true predicates * May raise [No_such_package] or [Package_loop]. *) let ancestors = query_requirements ~preds package_name in let store' = Fl_metastore.copy store in (* work with a copy *) add_relations store' ancestors package_name; if List.mem "mt" preds then fixup_thread_deps store'; ancestors ;; let requires_deeply ~preds package_list = (* returns names of packages required by the packages in [package_list], * either directly or indirectly. * It is checked that the packages really exist. * The list of names is sorted topologically; first comes the deepest * ancestor. * [preds]: list of true predicates * - raises [Not_found] if there is no 'package' * - raises [Failure] if some of the ancestors do not exist *) let pkgset = ref StringSet.empty in let rec query_packages pkglist = match pkglist with pkg :: pkglist' -> if not(StringSet.mem pkg !pkgset) then begin let pkg_ancestors = query_requirements ~preds pkg in pkgset := StringSet.add pkg !pkgset; query_packages pkg_ancestors end; query_packages pkglist' | [] -> () in (* First query for all packages, such that they are loaded: *) query_packages package_list; (* Now make a copy of the store, and add the relations: *) let store' = Fl_metastore.copy store in add_all_relations preds store'; if List.mem "mt" preds then fixup_thread_deps store'; (* Finally, iterate through the graph. Note that the graph may * contain more members than required, so we have to test explicitly * whether the packages are contained in pkgset. *) let l = ref [] in Fl_metastore.iter_up_at (fun m -> if StringSet.mem m.package_name !pkgset then ( if m.package_priv.missing_reqs <> [] then ( let (n,reason) = List.hd m.package_priv.missing_reqs in raise(No_such_package(n,reason)) ); l := m.package_name :: !l ) ) store' package_list; List.rev !l ;; (**********************************************************************) (* The following two functions do not use !ocamlpath, because there may * be duplicates in it. *) let package_definitions ~search_path package_name = (* Return all META files defining this [package_name] that occur in the * directories mentioned in [search_path] *) let package_name_comps = Fl_split.package_name package_name in if package_name_comps = [] then invalid_arg "Fl_package_base.package_definitions"; let main_name = List.hd package_name_comps in let rec run_ocamlpath path = match path with [] -> [] | dir :: path' -> let package_dir = Filename.concat dir main_name in let meta_file_1 = Filename.concat package_dir "META" in let meta_file_2 = Filename.concat dir ("META." ^ main_name) in if Sys.file_exists meta_file_1 then meta_file_1 :: run_ocamlpath path' else if Sys.file_exists meta_file_2 then meta_file_2 :: run_ocamlpath path' else run_ocamlpath path' in run_ocamlpath search_path ;; let in_report_search_path identify_dir d = (* Whether package dir d is to be considered for generating reports. d is sorted out when the ignore_dups_in option is set *) List.for_all (fun id -> try identify_dir d <> identify_dir id with _ -> Fl_split.norm_dir d <> Fl_split.norm_dir id ) !conf_ignore_dups_in ;; let package_conflict_report_1 identify_dir () = let remove_dups_from_path p = (* Removes directories which are physically the same from the path [p], * and returns the shortened path *) let dir_identity = Hashtbl.create 20 in let rec remove p = match p with d :: p' -> begin try let id = identify_dir d in (* may raise exceptions *) if Hashtbl.mem dir_identity id then remove p' else begin Hashtbl.add dir_identity id (); d :: (remove p') end with error -> (* Don't know anything, so the "directory" remains in the path *) d :: (remove p') end | [] -> [] in remove p in (* If we have ignore_dups_in this directory is removed from our search path first *) let search_path0 = List.filter (in_report_search_path identify_dir) !ocamlpath in (* Now eliminate all duplicates *) let search_path = remove_dups_from_path search_path0 in Fl_metastore.iter_up (fun pkg -> (* Check only main packages: *) let package_name_comps = Fl_split.package_name pkg.package_name in match package_name_comps with [_] -> (* pkg is a main package *) ( let c = package_definitions ~search_path pkg.package_name in match c with [] | [_] -> () | _ -> Printf.eprintf "findlib: [WARNING] Package %s has multiple definitions in %s\n" pkg.package_name (String.concat ", " c) ) | _ -> () ) store; flush stderr ;; let package_conflict_report ?identify_dir () = match identify_dir with None -> package_conflict_report_1 (fun s -> s) () | Some f -> package_conflict_report_1 f () ;; let check_prefix ?prefix f = match prefix with | None -> true | Some prefix -> let len = String.length prefix in String.length f >= len && String.sub f 0 len = prefix let load_base ?prefix () = (* Ensures that the cache is completely filled with every package * of the system that match prefix *) let list_directory d = try Array.to_list(Sys.readdir d) with Sys_error msg -> prerr_endline ("findlib: [WARNING] cannot read directory " ^ msg); [] in let process_file ?directory_required main_name package_dir meta_file = try let _ = Fl_metastore.find store main_name in (* Note: If the main package is already loaded into the graph, we * do not even look at the subpackages! *) () with Not_found -> let packages = try packages_in_meta_file ?directory_required ~name:main_name ~dir:package_dir ~meta_file () with Failure s -> prerr_endline ("findlib: [WARNING] " ^ s); [] in List.iter (Fl_metastore.add store) packages; (* Nothing evil can happen! *) in let rec run_ocamlpath path = match path with [] -> () | dir :: path' -> let files = list_directory dir in List.iter (fun f -> if check_prefix ?prefix f then (* If f/META exists: Add package f *) let package_dir = Filename.concat dir f in let meta_file_1 = Filename.concat package_dir "META" in if Sys.file_exists meta_file_1 then process_file f package_dir meta_file_1 else (* If f is META.pkgname: Add package pkgname *) (* We skip over filenames ending in '~' *) if String.length f >= 6 && String.sub f 0 5 = "META." && String.sub f (String.length f - 1) 1 <> "~" then begin let name = String.sub f 5 (String.length f - 5) in let meta_file_2 = Filename.concat dir f in process_file ~directory_required:true name dir meta_file_2 end; ) files; run_ocamlpath path' in run_ocamlpath !ocamlpath ;; let list_packages ?prefix () = load_base ?prefix (); let l = ref [] in Fl_metastore.iter_up (fun m -> if check_prefix ?prefix m.package_name then l := m.package_name :: !l ) store; !l ;; let package_users ~preds pl = (* Check that all packages in [pl] really exist, or raise No_such_package: *) List.iter (fun p -> let _ = query p in ()) pl; load_base(); let store' = Fl_metastore.copy store in add_all_relations preds store'; if List.mem "mt" preds then fixup_thread_deps store'; let l = ref [] in Fl_metastore.iter_down_at (fun m -> if m.package_priv.missing_reqs <> [] then ( let (n,reason) = List.hd m.package_priv.missing_reqs in raise(No_such_package(n,reason)) ); l := m.package_name :: !l ) store' pl; !l ;; let module_conflict_report_1 identify_dir incpath = (* Find any *.cmi files occurring twice in incpath. *) let dir_of_module = Hashtbl.create 100 in let dirs = ref [] in let examine_dir d = try let d = Fl_split.norm_dir d in let d_id = identify_dir d in (* Is d new? *) if not (List.mem d_id !dirs) then begin dirs := d_id :: !dirs; (* Yes: Get all files ending in .cmi *) try let d_all = Array.to_list(Sys.readdir d) in (* or Sys_error *) let d_cmi = List.filter (fun n -> Filename.check_suffix n ".cmi") d_all in (* Add the modules to dir_of_module: *) List.iter (fun m -> try let entry = Hashtbl.find dir_of_module m in (* or Not_found *) entry := d :: !entry with Not_found -> Hashtbl.add dir_of_module m (ref [d]) ) d_cmi with Sys_error msg -> prerr_endline ("findlib: [WARNING] cannot read directory " ^ msg) end with | _ -> () (* identify_dir fails *) in let print_report() = Hashtbl.iter (fun m dlist -> match !dlist with [] | [_] -> () | _ -> Printf.eprintf "findlib: [WARNING] Interface %s occurs in several directories: %s\n" m (String.concat ", " !dlist) ) dir_of_module in (* If we have ignore_dups_in this directory is removed from our search path first *) let incpath1 = List.filter (in_report_search_path identify_dir) incpath in List.iter examine_dir incpath1; print_report(); flush stderr ;; let module_conflict_report ?identify_dir incpath = match identify_dir with None -> module_conflict_report_1 (fun s -> s) incpath | Some f -> module_conflict_report_1 f incpath ;; not-ocamlfind-0.14/local-packages/ocamlfind/src/findlib/fl_package_base.mli0000644000175000017500000001535214770304423026003 0ustar stephsteph(* $Id$ * ---------------------------------------------------------------------- * *) (** Direct access to the package graph and package files *) type package = { package_name : string; (** The fully qualified package name, i.e. for subpackages the * names of the containing packages are prepended and the name * components are separated by '.' *) package_dir : string; (** The directory where to lookup package files *) package_meta : string; (** The path to the META file *) package_defs : Fl_metascanner.pkg_definition list; (** The definitions in the META file *) package_priv : package_priv; (** Private part of the definition *) } (** The definition of a package *) and package_priv val init : string list -> string -> string list -> unit (** This function must be called before [Fl_package_base] can be used. * The first string corresponds to the [OCAMLPATH] setting, the second * string is the location of the standard library. The second is the * list of directories with ignored duplicate cmi files. * * This function is called by {!Findlib.init} and {!Findlib.init_manually}, * so it is already sufficient to initialize the [Findlib] module. *) (** {1 The package graph} *) (** The functions in this section operate on a representation of the * package graph in memory. The graph is usually only partially available, * as only packages are loaded that are queried for. *) exception No_such_package of string * string (** First arg is the package name not found, second arg contains additional * info for the user. - This is the same exception as in [Findlib]. *) exception Package_loop of string (** A package is required by itself. The arg is the name of the * package. - This is the same exception as in [Findlib]. *) val query : string -> package (** Returns the [package] definition for the fully-qualified package name, * or raises [No_such_package]. It is allowed to query for subpackages. * * This function loads package definitions into the graph kept in memory. *) val requires : preds:string list -> string -> string list (** Analyzes the direct requirements of the package whose name is passed as * second argument under the assumption that the predicates [preds] * hold. The function returns the names of the required packages. * It is checked whether these packages exist. * * If there is the "mt" predicate, missing dependencies on "threads" * are silently added. * * The function may raise [No_such_package] or [Package_loop]. * * This function loads package definitions into the graph kept in memory. *) val requires_deeply : preds:string list -> string list -> string list (** Analyzes the direct or indirect requirements of the packages whose names * are passed as second argument under the assumption that the predicates * [preds] hold. The function returns the names of the required packages. * It is checked whether these packages exist. * * If there is the "mt" predicate, missing dependencies on "threads" * are silently added. * * The function may raise [No_such_package] or [Package_loop]. * * This function loads package definitions into the graph kept in memory. *) val package_conflict_report : ?identify_dir:(string -> 'a) -> unit -> unit (** Checks whether there are several META files for the same main * packages. Complaints are printed to stderr. * * Only packages in the loaded part of the package graph are checked (i.e. * packages for which there was a query). * * It is recommended to pass the ~identify_dir function whose task * it is to return a unique value for every existing directory. * For example, * {[ fun d -> * let s = Unix.stat d in * (s.Unix.st_dev, s.Unix.st_ino) * ]} * could be an implementation for this function. The default is * the identity (and not this nice implementation to avoid dependencies * on the Unix module). *) val module_conflict_report : ?identify_dir:(string -> 'a) -> string list -> unit (** Checks whether there are cmi files for the same modules. The * directories passed as first argument are checked. (Note: * Neither the '+' nor the '@' notation are recognized.) * Complaints about double cmi files are printed to stderr. * * @param identify_dir See [package_conflict_report]. *) val load_base : ?prefix:string -> unit -> unit (** Ensures that the complete package graph is loaded into memory. * This is a time-consuming operation. Warnings may be printed to * stderr. * * @param prefix Limit to the packages that starts with it. Default: unlimited *) val list_packages : ?prefix:string -> unit -> string list (** Ensures that the complete package graph is loaded into memory * (like [load_base]), and returns the (unsorted) list of all * packages. * * @param prefix Limit to the packages that starts with it. Default: unlimited *) val package_users : preds:string list -> string list -> string list (** Ensures that the complete package graph is loaded into memory * (like [load_base]), and determines the packages using one of * the packages passed as second argument. The [preds] are assumed * for the evaluation of the [requires] directives. * The returned list is sorted in ascending order. * * If there is the "mt" predicate, missing dependencies on "threads" * are silently added. * * Raises [No_such_package] if one of the passed packages cannot * be found. *) (** {1 Parsing META files} *) (** The functions in this section access directly files and directories. * The package graph is unknown. *) val packages_in_meta_file : ?directory_required:bool -> name:string -> dir:string -> meta_file:string -> unit -> package list (** Parses the META file whose name is [meta_file]. In [name], the * name of the main package must be passed. [dir] is the * directory associated with the package by default (i.e. before * it is overridden by the "directory" directive). * * Returns the package records found in this file. The "directory" * directive is already applied. * * @param directory_required If true, it is checked whether there is a * "directory" directive in the main package. If this directive is missing, * the function will fail. *) val package_definitions : search_path:string list -> string -> string list (** Return all META files defining this package that occur in the * directories mentioned in [search_path]. The package name must be * fully-qualified. For simplicity, however, only the name of the main * package is taken into account (so it is a good idea to call this * function only for main packages). *) not-ocamlfind-0.14/local-packages/ocamlfind/src/findlib/fl_split.ml0000644000175000017500000000705014770304423024374 0ustar stephsteph(* $Id$ * ---------------------------------------------------------------------- * *) let in_words s = (* splits s in words separated by commas and/or whitespace *) let l = String.length s in let rec split i j = if j < l then match s.[j] with (' '|'\t'|'\n'|'\r'|',') -> if i split i (j+1) else if i if i split i (j+1) else if i if i split i (j+1) else if i ':' | "Cygwin" -> ';' (* You might want to change this *) | "Win32" -> ';' | "MacOS" -> failwith "Findlib: I do not know what is the correct path separator for MacOS. If you can help me, write a mail to gerd@gerd-stolpmann.de" | _ -> failwith "Findlib: unknown operating system" ;; let path str = (* split "str" into parts separated by "path_separator" *) let l = String.length str in let rec split_up j k = if k < l then begin let c = str.[k] in if c = path_separator then begin if k - j > 0 then String.sub str j (k-j) :: split_up (k+1) (k+1) else split_up (k+1) (k+1) end else split_up j (k+1) end else if k - j > 0 then [ String.sub str j (k-j) ] else [] in split_up 0 0 ;; let norm_dir s = (* Converts the file name of the directory [d] to the normal form. * For Unix, the '/' characters at the end are removed, and multiple * '/' are deleted. * For Windows, all '/' characters are converted to '\'. Two * backslashes at the beginning are tolerated. *) let b = Buffer.create 80 in let l = String.length s in let norm_dir_unix() = Buffer.add_char b s.[0]; for k = 1 to l - 1 do let c = s.[k] in if not ((c = '/' && s.[k-1] = '/') || (c = '/' && k = l-1)) then Buffer.add_char b c done in let is_slash = function | '/' | '\\' -> true | _ -> false in let norm_dir_win() = if l >= 1 then if s.[0] = '/' then Buffer.add_char b '\\' else Buffer.add_char b s.[0]; if l >= 2 then if s.[1] = '/' then Buffer.add_char b '\\' else Buffer.add_char b s.[1]; for k = 2 to l - 1 do let c = s.[k] in if is_slash c then ( if not (is_slash s.[k-1] || k = l-1) then Buffer.add_char b '\\' ) else Buffer.add_char b c done in match Sys.os_type with "Unix" | "BeOS" | "Cygwin" -> norm_dir_unix(); Buffer.contents b | "Win32" -> norm_dir_win(); Buffer.contents b | _ -> failwith "This os_type is not supported" ;; not-ocamlfind-0.14/local-packages/ocamlfind/src/findlib/fl_topo.ml0000644000175000017500000001756214770304423024233 0ustar stephsteph(* $Id$ * ---------------------------------------------------------------------- * *) (* TODO: * - Use a hashtable in 'find' * - implement le_than with an 'iter' like method *) (**********************************************************************) module type IdentifiedType = sig type t type id_t val id : t -> id_t end exception Inconsistent_ordering module type S = sig type key type el_t type t val create : unit -> t val add : t -> el_t -> unit val let_le : t -> key -> key -> unit val find : t -> key -> el_t val le_than : t -> key -> key -> bool val key : el_t -> key val iter_up : (el_t -> unit) -> t -> unit val iter_down : (el_t -> unit) -> t -> unit val iter_up_at : (el_t -> unit) -> t -> key list -> unit val iter_down_at : (el_t -> unit) -> t -> key list -> unit val clear : t -> unit val replace : t -> key -> el_t -> unit val delete : t -> key -> unit val copy : t -> t end (**********************************************************************) module Make(H: IdentifiedType) = struct type key = H.id_t type el_t = H.t type 'a node = { mutable content : 'a; mutable smaller : 'a node list; mutable bigger : 'a node list; mutable mark : bool; (* used in 'iter' *) (* mutable ppmark : bool *) (* used in 'private_property' *) } type t = { mutable cnt : el_t node list; mutable lock : bool } let copy ord = (* This operation is quite expensive when the graph has already * relations. In findlib, this case is avoided, and is here only * implemented for completeness. *) let ord' = { cnt = List.map (fun n -> { n with smaller = []; bigger = []; mark = false }) ord.cnt; lock = false } in let combined_list = List.combine ord.cnt ord'.cnt in let lookup_node n = (* Find the new node corresponding to old node n *) try List.assq n combined_list with Not_found -> assert false in List.iter2 (fun n n' -> (* n: old node, n': new node *) let smaller = List.map lookup_node n.smaller in let bigger = List.map lookup_node n.bigger in n'.smaller <- smaller; n'.bigger <- bigger; ) ord.cnt ord'.cnt; ord' let rec delete_all p l = match l with x::l' -> if p x then delete_all p l' else x :: delete_all p l' | [] -> [] (******************************************************************) let create () = { cnt = []; lock = false } let clear ordering = ordering.cnt <- []; ordering.lock <- false (******************************************************************) let add ordering x = (* Is there already a node with the same key? *) let k = H.id x in if List.exists (fun y -> H.id y.content = k) ordering.cnt then raise Inconsistent_ordering; (* Ok, add the node to the list *) let nx = { content = x; smaller = []; bigger = []; mark = false } in ordering.cnt <- nx :: ordering.cnt (******************************************************************) let find_node ordering kx = let rec search l = match l with [] -> raise Not_found | y :: l' -> if H.id y.content = kx then y else search l' in search ordering.cnt let find ordering kx = (find_node ordering kx).content (******************************************************************) let replace ordering kx x' = let x = find_node ordering kx in x.content <- x' (******************************************************************) let delete ordering kx = let x = find_node ordering kx in ordering.cnt <- delete_all (fun a -> a == x) ordering.cnt; List.iter (fun x -> x.smaller <- delete_all (fun a -> a == x) x.smaller; x.bigger <- delete_all (fun a -> a == x) x.bigger) ordering.cnt (******************************************************************) let le_than ordering kx ky = (* Find x, y: *) let x = find_node ordering kx in let y = find_node ordering ky in let rec search x1 = if x1 == y then true else List.exists search x1.bigger in search x (******************************************************************) let let_le ordering kx ky = (* Find x, y: *) let x = find_node ordering kx in let y = find_node ordering ky in (* If already done just return (this is an idempotent function) *) if not (List.memq x y.smaller) then begin (* let x <= y. This is only allowed if not (y <= x) *) if le_than ordering ky kx then raise Inconsistent_ordering; (* Ok, add the relation *) x.bigger <- y :: x.bigger; y.smaller <- x :: y.smaller end (******************************************************************) let key x = H.id x (******************************************************************) let iter upwards f ordering = let in_direction n = if upwards then n.bigger else n.smaller in let against_direction n = if upwards then n.smaller else n.bigger in (* the following is written as if for iter_up. *) let rec find_biggest ordlist = (* find biggest, non-marked node *) match ordlist with [] -> raise Not_found | nx :: ordlist' -> if not nx.mark && in_direction nx = [] then nx else find_biggest ordlist' in let rec run_up n = (* iterate over all nodes <= x and return their number *) let rec run_up_list l = match l with [] -> 0 | x :: l' -> run_up x + run_up_list l' in if n.mark then (* have already visited this node *) 0 else let u = run_up_list (against_direction n) in n.mark <- true; f n.content; u + 1 in (* Lock *) if ordering.lock then failwith "iter_up: recursive application not allowed"; ordering.lock <- true; (* clear all marks *) List.iter (fun nx -> nx.mark <- false) ordering.cnt; (* Catch exceptions *) try (* while there is a biggest node... *) let c = ref 0 in (* counter *) while !c < List.length ordering.cnt do (* Find a biggest node *) let n_biggest = find_biggest ordering.cnt in (* run through the graph *) c := !c + run_up n_biggest done; (* unlock *) ordering.lock <- false with any -> (* unlock, too *) ordering.lock <- false; raise any let iter_up = iter true let iter_down = iter false (******************************************************************) let iter_at upwards f ordering startpoints = (* let in_direction n = if upwards then n.bigger else n.smaller in *) let against_direction n = if upwards then n.smaller else n.bigger in (* the following is written as if for iter_up. *) let rec run_up n = (* iterate over all nodes <= x and return their number *) let rec run_up_list l = match l with [] -> 0 | x :: l' -> run_up x + run_up_list l' in if n.mark then (* have already visited this node *) 0 else let u = run_up_list (against_direction n) in n.mark <- true; f n.content; u + 1 in (* Lock *) if ordering.lock then failwith "iter_up: recursive application not allowed"; ordering.lock <- true; (* clear all marks *) List.iter (fun nx -> nx.mark <- false) ordering.cnt; (* Catch exceptions *) try List.iter (fun start -> let _ = run_up (find_node ordering start) in ()) startpoints; (* unlock *) ordering.lock <- false with any -> (* unlock, too *) ordering.lock <- false; raise any let iter_up_at = iter_at true let iter_down_at = iter_at false (******************************************************************) end not-ocamlfind-0.14/local-packages/ocamlfind/src/findlib/fl_topo.mli0000644000175000017500000000200514770304423024366 0ustar stephsteph(* $Id$ * ---------------------------------------------------------------------- * *) (* The type topo.t is a partially ordered relation. You can add an element * by giving all descendents ... *) module type IdentifiedType = sig type t type id_t val id : t -> id_t end exception Inconsistent_ordering module type S = sig type key type el_t type t val create : unit -> t val add : t -> el_t -> unit val let_le : t -> key -> key -> unit val find : t -> key -> el_t val le_than : t -> key -> key -> bool val key : el_t -> key val iter_up : (el_t -> unit) -> t -> unit val iter_down : (el_t -> unit) -> t -> unit val iter_up_at : (el_t -> unit) -> t -> key list -> unit val iter_down_at : (el_t -> unit) -> t -> key list -> unit val clear : t -> unit val replace : t -> key -> el_t -> unit val delete : t -> key -> unit val copy : t -> t end module Make(H: IdentifiedType): (S with type el_t = H.t and type key = H.id_t) not-ocamlfind-0.14/local-packages/ocamlfind/src/findlib/frontend.ml0000644000175000017500000024046714770304423024412 0ustar stephsteph(* $Id$ * ---------------------------------------------------------------------- * *) open Findlib;; exception Usage;; exception Silent_error;; type mode = M_use | M_query | M_install | M_remove | M_compiler of string | M_dep | M_printconf | M_list | M_browser | M_call of (string*string) | M_doc | M_lint | M_printppx ;; type psubst = Const of string | Percent of string * modifier | Lookup of string * modifier and modifier = | Plain | Plus ;; let sys_error code arg = if arg = "" then Sys_error (Unix.error_message code) else Sys_error (arg ^ ": " ^ Unix.error_message code) let slashify s = match Findlib_config.system with | "mingw" | "mingw64" | "cygwin" -> let b = Buffer.create 80 in String.iter (function | '\\' -> Buffer.add_char b '/' | c -> Buffer.add_char b c ) s; Buffer.contents b | _ -> s let out_path ?(prefix="") s = match Findlib_config.system with | "mingw" | "mingw64" | "cygwin" -> let u = slashify s in prefix ^ (if String.contains u ' ' then (* Desperate attempt to fix the space problem in paths. Note that we invoke commands via Unix.open_process, and this function already quotes the arguments on win32. However, for -ccopt arguments, one quoting level seems to be lost, and we have to add another level to compensate. E.g. for the list of args [ -ccopt; -L/my programs/include -L/somewhere ] we get after out_path [ -ccopt; "-I/my programs/include -L/somewhere" ] which actually translates to -ccopt "\"-I/my programs/include\" \"-L/somewhere\"" on the command line, i.e. a double-quoted argument. *) "\"" ^ u ^ "\"" else u ) | _ -> prefix ^ slashify s let percent_subst ?base spec lookup s = (* spec = [ "%c", [ "ctext1"; "ctext2"; ... ]; * "%d", [ "dtext1"; "dtext2"; ... ] ] * All occurrences of %c in the string s are replaced as specified in spec. * spec is an association list with the %-notation as keys * and lists of strings as values. The result is a list of strings containing * every combination of substituted values. * * Support for the %(name) syntax: In this case, the name is taken as * key for the [lookup] function, which either returns the string value * or raises Not_found. * * "+" modifier: A "+" after "%" causes that Findlib.resolve_path is * called for the substitution string (e.g. %+c, %+(name)). * * Example: * spec = [ "%a", [ "file1" ] ] * lookup = function "archive" -> "file2" | _ -> raise Not_found * Here, %a is substituted by file1, and %(archive) is substituted by * file2. * * ?base: The base parameter for Findlib.resolve_path. *) let l = String.length s in let fail() = failwith "bad format string" in let parenthesized_name j = try if j+1>=l then raise Not_found; let k = String.index_from s (j+1) ')' in let name = String.sub s (j+1) (k-j-1) in (name, k+1) with Not_found -> fail() in let rec preprocess i j = if j if j+1 prev :: Const "%" :: preprocess (j+2) (j+2) | '(' -> let name, j_next = parenthesized_name (j+1) in prev :: Lookup(name,Plain) :: preprocess j_next j_next | '+' -> if j+2 fail() | '(' -> let name, j_next = parenthesized_name (j+2) in prev :: Lookup(name,Plus) :: preprocess j_next j_next | _ -> let name = "%" ^ String.make 1 c in prev :: Percent(name,Plus) :: preprocess (j+3) (j+3) end else fail() | _ -> let name = "%" ^ String.make 1 c in prev :: Percent(name,Plain) :: preprocess (j+2) (j+2) end else fail() | _ -> preprocess i (j+1) end else if i u | Plus -> plus_subst u in let rec subst prefix l = match l with [] -> [prefix] | Const s :: l' -> subst (prefix ^ s) l' | Percent(name,modi) :: l' -> let replacements0 = try List.assoc name spec with Not_found -> failwith "bad format string" in let replacements = List.map (any_subst modi) replacements0 in List.flatten (List.map (fun replacement -> subst (prefix ^ replacement) l') replacements) | Lookup(name,modi) :: l' -> let replacement0 = try lookup name with Not_found -> "" in let replacement = any_subst modi replacement0 in subst (prefix ^ replacement) l' in subst "" (preprocess 0 0) ;; let rec remove_dups l = match l with x :: l' -> if List.mem x l' then remove_dups l' else x::remove_dups l' | [] -> [] ;; let arg n = if n < Array.length Sys.argv then Sys.argv.(n) else raise Not_found ;; let escape_if_needed s = if String.contains s ' ' then "\"" ^ String.escaped s ^ "\"" else s ;; let use_package prefix pkgnames = (* may raise No_such_package *) let pdirs = List.map (fun pname -> "-I " ^ out_path(package_directory pname) ) pkgnames in print_endline (prefix ^ String.concat " " pdirs) ;; let read_ldconf filename = let lines = ref [] in let f = open_in filename in try while true do let line = input_line f in if line <> "" then lines := line :: !lines done; assert false with End_of_file -> close_in f; List.rev !lines | other -> close_in f; raise other ;; let write_ldconf filename lines new_lines = let f = open_out filename in try List.iter (fun line -> output_string f (line ^ "\n")) (lines @ new_lines); close_out f; prerr_endline("Updated " ^ filename); with Sys_error e -> prerr_endline ("ocamlfind: [WARNING] Cannot write " ^ filename); prerr_endline ("Reason: " ^ e); prerr_endline ("This file contains the directories with DLLs."); if new_lines <> [] then begin prerr_endline ("It is recommended to add the following line(s) to this file:"); List.iter prerr_endline new_lines end ;; let is_dll p = let sfx = Findlib_config.dll_suffix in sfx <> "" && Filename.check_suffix p sfx ;; let identify_dir d = match Sys.os_type with | "Win32" -> failwith "identify_dir" (* not available *) | _ -> let s = Unix.stat d in (s.Unix.st_dev, s.Unix.st_ino) ;; let conflict_report incpath pkglist = (* Check whether there are several definitions for packages * in the current path. We remove duplicate directories first. * Note that all other checks are not sensitive to duplicate directories. *) Fl_package_base.package_conflict_report ~identify_dir (); (* Second check whether there are module conflicts *) let pkgpath = List.map Findlib.package_directory pkglist in Fl_package_base.module_conflict_report ~identify_dir (pkgpath @ incpath); (* Finally check whether there are multiple DLLs: *) (* Note: Only the directories mentioned in ld.conf are checked, but not the * directories in [incpath], and not the directories in CAML_LD_LIBRARY_PATH. * The idea of this check is to ensure a proper installation, and not to * complain about the user's special configuration. *) let ldconf = ocaml_ldconf() in if ldconf <> "ignore" then begin let dll_dirs = remove_dups (read_ldconf ldconf) in let dll_pairs = List.flatten (List.map (fun dll_dir -> let files = try Array.to_list (Sys.readdir dll_dir) with _ -> prerr_endline ("ocamlfind: [WARNING] Cannot read directory " ^ dll_dir ^ " which is mentioned in ld.conf"); [] in List.map (fun file -> (file, dll_dir)) (List.filter is_dll files) ) dll_dirs ) in let dll_hash = Hashtbl.create 50 in List.iter (fun (file, dll_dir) -> Hashtbl.add dll_hash file dll_dir) dll_pairs; Hashtbl.iter (fun file dll_dir -> let locations = Hashtbl.find_all dll_hash file in if List.length locations > 1 then begin prerr_endline ("ocamlfind: [WARNING] The DLL " ^ file ^ " occurs in multiple directories: " ^ dll_dir) end ) dll_hash end ;; let check_package_list l = (* may raise No_such_package *) List.iter (fun pkg -> let _ = package_directory pkg in () ) l ;; type verbosity = | Normal | Verbose | Only_show let run_command ?filter verbose cmd args = let printable_cmd = cmd ^ " " ^ String.concat " " (List.map escape_if_needed args) in ( match verbose with | Normal -> () | Verbose -> print_endline ("+ " ^ printable_cmd); if filter <> None then print_string (" (output of this command is filtered by ocamlfind)\n") | Only_show -> print_endline printable_cmd ); flush stdout; if verbose <> Only_show then ( let filter_input, cmd_output = match filter with None -> Unix.stdin (* dummy *), Unix.stdout | Some f -> Unix.pipe() in (* Signals: On SIGINT, we wait until the subprocess finishes, and * die then. This allows us to call interactive commands as subprocesses. *) let old_sigint = Sys.signal Sys.sigint Sys.Signal_ignore in let need_exe = List.mem Findlib_config.system [ "win32"; "win64"; "mingw"; "mingw64" ] in let fixed_cmd = if need_exe then ( if Filename.check_suffix cmd ".exe" then cmd else cmd ^ ".exe" ) else cmd in let pid = Unix.create_process fixed_cmd (Array.of_list (cmd :: args)) Unix.stdin cmd_output Unix.stderr in begin match filter with Some filter_fun -> begin Unix.close cmd_output; let ch = Unix.in_channel_of_descr filter_input in try while true do let line = input_line ch in match filter_fun line with None -> () (* Suppress line *) | Some line' -> print_endline line' done; assert false with End_of_file -> close_in ch; flush stdout end | None -> () end; let (_,status) = Unix.waitpid [] pid in Sys.set_signal Sys.sigint old_sigint; begin match status with Unix.WEXITED 0 -> () | Unix.WEXITED n -> if verbose = Verbose then print_string (cmd ^ " returned with exit code " ^ string_of_int n ^ "\n"); exit n | Unix.WSIGNALED _ -> print_string (cmd ^ " got signal and exited\n"); exit 2 | Unix.WSTOPPED _ -> failwith "Your operating system does not work correctly" end ) ;; (**************** preprocessor ******************************************) let select_pp_packages syntax_preds packages = if syntax_preds = [] then (* No syntax predicates, no preprocessor! *) [] else List.filter (fun pkg -> let al = try package_property syntax_preds pkg "archive" with Not_found -> "" in let w = Fl_split.in_words al in w <> [] ) packages let process_pp_spec syntax_preds packages pp_opts = (* Returns: pp_command *) (* may raise No_such_package *) (* [packages]: all packages given on the command line. May include * packages for compilation and for preprocessing. * * The difficulty is now that the preprocessor packages may have * requirements that are non-preprocessor packages. To get exactly * the preprocessor packages and its requirements, we do: * * 1. Determine the subset of [packages] that are preprocessor * packages by checking whether they have an "archive" for * [syntax_preds], i.e. the preprocessor packages mentioned * on the command line = [cl_pp_packages]. * * 2. Add their requirements = [pp_packages] * * Because the packages are now mixed, we must evaluate for * [syntax_preds] + "byte". *) (* One packages must now have the variable "preprocessor", usually camlp4 *) let cl_pp_packages = select_pp_packages syntax_preds packages in let pp_packages = package_deep_ancestors syntax_preds cl_pp_packages in let preprocessor_cmds = List.flatten (List.map (fun pname -> try [ pname, package_property syntax_preds pname "preprocessor" ] with Not_found -> [] ) pp_packages ) in let preprocessor_cmd = if syntax_preds <> [] then match preprocessor_cmds with [] -> failwith("Using -syntax, but no package is selected specifying \ a preprocessor as required for -syntax") | [_, cmd] -> Some cmd | _ -> failwith("Several packages are selected that specify \ preprocessors: " ^ String.concat ", " (List.map (fun (n,v) -> "package " ^ n ^ " defines `" ^ v ^ "'") preprocessor_cmds ) ) else None in let pp_i_options = List.flatten (List.map (fun pkg -> let pkgdir = package_directory pkg in [ "-I"; slashify pkgdir ] ) pp_packages) in let pp_archives = if preprocessor_cmd = None then [] else List.flatten (List.map (fun pkg -> let al = try package_property ("byte" :: syntax_preds) pkg "archive" with Not_found -> "" in Fl_split.in_words al ) pp_packages) in match preprocessor_cmd with None -> [] | Some cmd -> ["-pp"; cmd ^ " " ^ String.concat " " (List.map Filename.quote pp_i_options) ^ " " ^ String.concat " " (List.map Filename.quote pp_archives) ^ " " ^ String.concat " " (List.map Filename.quote pp_opts)] ;; (**************** ppx extensions ****************************************) let process_ppx_spec predicates packages ppx_opts = (* Returns: ppx_commands *) (* may raise No_such_package *) let ppx_packages = package_deep_ancestors predicates packages in let ppx_opts = List.map (fun opt -> match Fl_split.in_words opt with | pkg :: ((_ :: _) as opts) -> let exists = try ignore(package_directory pkg); true with No_such_package _ -> false in if not exists then failwith ("The package named in -ppxopt does not exist: " ^ pkg); pkg, opts | _ -> failwith "-ppxopt must include package name, e.g. -ppxopt \"foo,-name bar\"" ) ppx_opts in let meta_ppx_opts = List.concat (List.map (fun pname -> try let opts = package_property predicates pname "ppxopt" in (* Split by whitespace to get (package,options) combinations. Then, split by commas to get individual options. *) List.map (fun opts -> match Fl_split.in_words opts with | pkg :: ((_ :: _) as opts) -> let exists = try ignore(package_directory pkg); true with No_such_package _ -> false in if not exists then failwith ("The package named in ppxopt variable does not exist: " ^ pkg ^ " (from " ^ pname ^ ")"); let base = package_directory pname in pkg, List.map (resolve_path ~base ~explicit:true) opts | _ -> failwith ("ppxopt variable must include package name, e.g. " ^ "ppxopt=\"foo,-name bar\" (from " ^ pname ^ ")") ) (Fl_split.in_words_ws opts) with Not_found -> [] ) ppx_packages ) in List.flatten (List.map (fun pname -> let base = package_directory pname in let options = try List.concat (List.map (fun (_, opts) -> opts) (List.filter (fun (pname', _) -> pname' = pname) (meta_ppx_opts @ ppx_opts))) with Not_found -> [] in try let preprocessor = resolve_path ~base ~explicit:true (package_property predicates pname "ppx") in ["-ppx"; String.concat " " (preprocessor :: options)] with Not_found -> [] ) ppx_packages) (**************** Generic argument processing *************************) let merge_native_arguments native_spec f_unit f_string f_special_list = List.map (fun (switch_name, switch_has_arg, help_text) -> let f = try List.assoc switch_name f_special_list with Not_found -> if switch_has_arg then f_string switch_name else f_unit switch_name in (switch_name, f, help_text) ) native_spec ;; let parse_args ?(current = Arg.current) ?(args = Sys.argv) ?(align = true) spec anon usage = try Arg.parse_argv ~current args (if align then Arg.align spec else spec) anon usage with | Arg.Help text -> print_string text; exit 0 | Arg.Bad text -> prerr_string text; exit 2 (************************* format expansion *************************) let expand predicates eff_packages format = (* may raise No_such_package *) (* format: * %p package name * %d package directory * %m META file * %D description * %v version * %a archive file(s) * %A archive files as single string * %o link option(s) * %O link options as single string *) List.flatten (List.map (fun pkg -> let dir = package_directory pkg in (* May raise No_such_package *) let spec = [ "%p", [pkg]; "%d", [out_path dir]; "%m", [out_path (package_meta_file pkg)]; "%D", [try package_property predicates pkg "description" with Not_found -> "[n/a]"]; "%v", [try package_property predicates pkg "version" with Not_found -> "[unspecified]"]; "%a", Fl_split.in_words (try package_property predicates pkg "archive" with Not_found -> ""); "%A", [String.concat " " (Fl_split.in_words (try package_property predicates pkg "archive" with Not_found -> ""))]; "%o", Fl_split.in_words_ws (try package_property predicates pkg "linkopts" with Not_found -> ""); "%O", [String.concat " " (Fl_split.in_words_ws (try package_property predicates pkg "linkopts" with Not_found -> ""))]; ] in let lookup = package_property predicates pkg in percent_subst ~base:dir spec lookup format) eff_packages) ;; let help_format() = print_endline "Formats for -format strings: %p package name %d package directory %m META file %D description %v version %a archive file(s) %+a archive file(s), converted to absolute paths %A archive files as single string %+A archive files as single string, converted to absolute paths %o link option(s) %O link options as single string %(name) the value of the property %+(name) the value of the property , converted to absolute paths (like )"; flush stdout (************************** QUERY SUBCOMMAND ***************************) let query_package () = let long_format = "package: %p\ndescription: %D\nversion: %v\narchive(s): %A\nlinkopts: %O\nlocation: %d\n" in let i_format = "-I %d" in let l_format = if Findlib_config.system = "win32" || Findlib_config.system = "win64" then (* Microsoft toolchain *) "-ccopt \"/link /libpath:%d\"" else "-ccopt -L%d" in let a_format = "%+a" in let o_format = "%o" in let p_format = "%p" in let predicates = ref [] in let format = ref "%d" in let separator = ref "\n" in let prefix = ref "" in let suffix = ref "\n" in let recursive = ref false in let descendants = ref false in let pp = ref false in let qe = ref false in let qo = ref false in let packages = ref [] in let append_predicate s = let pl = Fl_split.in_words s in predicates := !predicates @ pl in parse_args [ "-predicates", Arg.String append_predicate, " specifies comma-separated list of assumed predicates"; "-format", Arg.String (fun s -> format := s), " specifies the output format"; "-separator", Arg.String (fun s -> separator := s), " specifies the string that separates multiple answers"; "-prefix", Arg.String (fun s -> prefix := s), "

a string printed before the first answer"; "-suffix", Arg.String (fun s -> suffix := s), " a string printed after the last answer"; "-recursive", Arg.Set recursive, " select direct and indirect ancestors/descendants, too"; "-r", Arg.Set recursive, " same as -recursive"; "-descendants", Arg.Unit (fun () -> descendants := true; recursive := true), " query descendants instead of ancestors; implies -recursive"; "-d", Arg.Unit (fun () -> descendants := true; recursive := true), " same as -descendants"; "-pp", Arg.Unit (fun () -> pp := true; recursive := true), " get preprocessor pkgs (predicates are taken as syntax preds)"; "-long-format", Arg.Unit (fun () -> format := long_format), " specifies long output format"; "-l", Arg.Unit (fun () -> format := long_format), " same as -long-format"; "-i-format", Arg.Unit (fun () -> format := i_format), " prints -I options for ocamlc"; "-l-format", Arg.Unit (fun () -> format := l_format), " prints -ccopt -L options for ocamlc"; "-a-format", Arg.Unit (fun () -> format := a_format), " prints names of archives to be linked in for ocamlc"; "-o-format", Arg.Unit (fun () -> format := o_format), " prints link options for ocamlc"; "-p-format", Arg.Unit (fun () -> format := p_format), " prints package names"; "-help-format", Arg.Unit help_format, " lists the supported formats for -format"; "-qe", Arg.Set qe, " do not print most errors, just set the exit code"; "-qo", Arg.Set qo, " do not print regular output"; ] (fun p -> packages := !packages @ Fl_split.in_words p) "usage: ocamlfind query [ -predicates

| -format | -long-format | -i-format | -l-format | -a-format | -o-format | -p-format | -prefix

| -suffix | -separator | -descendants | -recursive ] package ..."; ignore(config_file()); (* ensure findlib is initialized *) try let predicates1 = if !pp then "preprocessor" :: "syntax" :: !predicates else !predicates in let packages1 = if !pp then let predicates2 = List.filter (fun p -> p <> "byte" && p <> "native") predicates1 in select_pp_packages predicates2 !packages else !packages in let eff_packages = if !recursive then begin if !descendants then Fl_package_base.package_users ~preds:predicates1 packages1 else package_deep_ancestors predicates1 packages1 end else packages1 in let answers = expand predicates1 eff_packages !format in if not !qo then ( print_string !prefix; print_string (String.concat !separator answers); print_string !suffix; ) with ( Findlib.No_such_package _ | Failure _ | Sys_error _ ) when !qe -> raise Silent_error ;; (**************** OCAMLC/OCAMLMKTOP/OCAMLOPT subcommands ****************) type pass_file_t = Pass of string | Impl of string (* Forces module implementation: -impl *) | Intf of string (* Forces module interface: -intf *) | Cclib of string (* Option for the C linker: -cclib *) ;; let contracted_ocamlmklib_options = [ "-l"; "-L"; "-R"; "-F"; "-Wl,-rpath,"; "-Wl,-R" ] (* The ocamlmklib options where the argument is directly attached to the switch (e.g. -L instead of -L ) *) let ocamlc which () = (* let destdir = ref (default_location()) in *) let switches = ref [] in let pass_options = ref [] in let pass_files = ref [] in let incpath = ref [] in let only_show = ref false in let dll_pkgs = ref [] in let dll_pkgs_all = ref false in let linkpkg = ref false in let packages = ref [] in let predicates = ref [] in let dontlink = ref [] in let syntax_preds = ref [] in let pp_opts = ref [] in let ppx_opts = ref [] in let pp_specified = ref false in let type_of_threads = try package_property [] "threads" "type_of_threads" with Not_found -> "ignore" in let threads_default = match type_of_threads with "posix" -> `POSIX_threads | "vm" -> `VM_threads | _ -> `None in let threads = ref `None in let support_threads() = if threads_default = `None then failwith "threading is not supported on this platform" in let add_switch name = Arg.Unit (fun () -> switches := name :: !switches; pass_options := !pass_options @ [name]) in let add_spec_fn name s = pass_options := !pass_options @ [name; s] in let add_spec name = Arg.String (add_spec_fn name) in let add_contracted_spec_fn name s = pass_options := !pass_options @ [name ^ s] in let add_contracted_spec name = Arg.String (add_contracted_spec_fn name) in let add_pkg = Arg.String (fun s -> packages := !packages @ (Fl_split.in_words s)) in let add_pred = Arg.String (fun s -> predicates := !predicates @ (Fl_split.in_words s)) in let add_dontlink = Arg.String (fun s -> dontlink := !dontlink @ (Fl_split.in_words s)) in let add_syntax_pred = Arg.String (fun s -> syntax_preds := !syntax_preds @ (Fl_split.in_words s)) in let add_pp_opt = Arg.String (fun s -> pp_opts := !pp_opts @ [s]) in let add_dll_pkg = Arg.String (fun s -> dll_pkgs := !dll_pkgs @ (Fl_split.in_words s)) in let ignore_error = ref false in let native_spec_opt = match which with | "ocamlc" -> Ocaml_args.ocamlc_spec | "ocamlcp" -> Ocaml_args.ocamlcp_spec | "ocamlmklib" -> Ocaml_args.ocamlmklib_spec | "ocamlmktop" -> Ocaml_args.ocamlmktop_spec | "ocamlopt" -> Ocaml_args.ocamlopt_spec | "ocamloptp" -> Ocaml_args.ocamloptp_spec | _ -> None in let native_spec = match native_spec_opt with | None -> failwith ("Not supported in your configuration: " ^ which) | Some s -> s in let arg_spec = List.flatten [ [ "-package", add_pkg, " Refer to package when compiling"; "-linkpkg", Arg.Set linkpkg, " Link the packages in"; "-predicates", add_pred, "

Add predicate

when resolving package properties"; "-dontlink", add_dontlink, " Do not link in package and its ancestors"; "-syntax", add_syntax_pred, "

Use preprocessor with predicate

"; "-ppopt", add_pp_opt, " Append option to preprocessor invocation"; "-ppxopt", Arg.String (fun s -> ppx_opts := !ppx_opts @ [s]), ", Append options to ppx invocation for package "; "-dllpath-pkg", add_dll_pkg, " Add -dllpath for this package"; "-dllpath-all", Arg.Set dll_pkgs_all, " Add -dllpath for all linked packages"; "-ignore-error", Arg.Set ignore_error, " Ignore the 'error' directive in META files"; "-passopt", Arg.String (fun s -> pass_options := !pass_options @ [s]), " Pass option directly to ocamlc/opt/mklib/mktop"; "-passrest", Arg.Rest (fun s -> pass_options := !pass_options @ [s]), " Pass all remaining options directly"; "-only-show", Arg.Set only_show, " Only show the constructed command, but do not exec it\nSTANDARD OPTIONS:"; ]; merge_native_arguments native_spec add_switch add_spec ( [ "-cclib", Arg.String (fun s -> pass_files := !pass_files @ [ Cclib s ]); "-I", (Arg.String (fun s -> let s = resolve_path s in if Sys.file_exists s then incpath := s :: !incpath; (* reverted below *) add_spec_fn "-I" (slashify s) )); "-impl", Arg.String (fun s -> pass_files := !pass_files @ [ Impl(slashify s) ]); "-intf", Arg.String (fun s -> pass_files := !pass_files @ [ Intf(slashify s) ]); "-pp", Arg.String (fun s -> pp_specified := true; add_spec_fn "-pp" s); "-thread", Arg.Unit (fun _ -> support_threads(); threads := threads_default); "-vmthread", Arg.Unit (fun _ -> support_threads(); threads := `VM_threads); "-", Arg.String (fun s -> pass_files := !pass_files @ [ Pass s ]); ] @ if which = "ocamlmklib" then List.map (fun opt -> (opt, add_contracted_spec opt) ) contracted_ocamlmklib_options else [] ) ] in let (current,args) = if which = "ocamlmklib" then (* Special processing for -L, -R etc. *) let c = !(Arg.current) in let l = Array.length Sys.argv in let args1 = Array.sub Sys.argv (c+1) (l-c-1) in let args2 = Array.append [| Sys.argv.(0) |] (Fl_args.rewrite_contracted_args arg_spec contracted_ocamlmklib_options args1 ) in (ref 0, args2) else (Arg.current, Sys.argv) in parse_args ~current ~args arg_spec (fun s -> pass_files := !pass_files @ [ Pass s]) ("usage: ocamlfind " ^ which ^ " [options] file ..."); (* ---- Start requirements analysis ---- *) begin match which with "ocamlc" -> predicates := "byte" :: !predicates; | "ocamlcp" -> predicates := "byte" :: !predicates; | "ocamlmklib" -> predicates := "byte" :: "native" :: !predicates; | "ocamlmktop" -> predicates := "byte" :: "create_toploop" :: !predicates; | "ocamlopt" -> predicates := "native" :: !predicates; | "ocamloptp" -> predicates := "native" :: !predicates; | _ -> failwith "unsupported backend" end; incpath := List.rev !incpath; ( match !threads with `None -> () | `VM_threads -> if which = "ocamlopt" then failwith "ocamlopt does not support multi-threaded programs for your configuration"; pass_options := !pass_options @ [ "-vmthread" ]; predicates := "mt" :: "mt_vm" :: !predicates; | `POSIX_threads -> if not Findlib_config.ocaml_has_meta_files then pass_options := !pass_options @ [ "-thread" ]; predicates := "mt" :: "mt_posix" :: !predicates; ); if List.mem "-p" !switches then predicates := "gprof" :: !predicates; if Findlib_config.ocaml_has_autolinking && not (List.mem "-noautolink" !switches) then predicates := "autolink" :: !predicates; if !syntax_preds <> [] then begin predicates := "syntax" :: !predicates; syntax_preds := "preprocessor" :: "syntax" :: !syntax_preds; end; let verbose = if List.mem "-verbose" !switches then Verbose else if !only_show then Only_show else Normal in if !pp_specified && !syntax_preds <> [] then prerr_endline("ocamlfind: [WARNING] -pp overrides the effect of -syntax partly"); (* check packages: *) check_package_list !packages; check_package_list !dontlink; let eff_packages = package_deep_ancestors !predicates !packages in let eff_dontlink = package_deep_ancestors !predicates !dontlink in let eff_link = List.flatten (List.map (fun pkg -> if List.mem pkg eff_dontlink then [] else [pkg]) eff_packages) in let eff_packages_dl = remove_dups (List.map package_directory eff_packages) in let eff_link_dl = remove_dups (List.map package_directory eff_link) in (* Conflict report: *) conflict_report (!incpath @ ["."; Findlib.ocaml_stdlib() ]) eff_packages; (* ---- End of requirements analysis ---- *) (* Add the pkg_ predicates: *) predicates := List.map (fun pkg -> "pkg_" ^ pkg) eff_packages @ !predicates; (* Check on [warning] directives: *) List.iter (fun pkg -> try let warning = package_property !predicates pkg "warning" in prerr_endline("ocamlfind: [WARNING] Package `" ^ pkg ^ "': " ^ warning) with Not_found -> () ) eff_packages; (* Check on [error] directives: *) List.iter (fun pkg -> try let error = package_property !predicates pkg "error" in if !ignore_error then prerr_endline("ocamlfind: [WARNING] Package `" ^ pkg ^ "' signals error: " ^ error) else failwith ("Error from package `" ^ pkg ^ "': " ^ error) with Not_found -> () ) eff_packages; if verbose = Verbose then begin if !syntax_preds <> [] then print_string ("Effective set of preprocessor predicates: " ^ String.concat "," !syntax_preds ^ "\n"); print_string ("Effective set of compiler predicates: " ^ String.concat "," !predicates ^ "\n"); end; let stdlibdir = Fl_split.norm_dir (Findlib.ocaml_stdlib()) in let threads_dir = Filename.concat stdlibdir "threads" in let vmthreads_dir = Filename.concat stdlibdir "vmthreads" in let create_toploop = List.mem "create_toploop" !predicates && List.mem "findlib" eff_link in let have_dynload = List.mem "findlib.dynload" eff_link in let initl_file_needed = create_toploop || have_dynload in let initl_file_name = if initl_file_needed then Filename.temp_file "findlib_initl" ".ml" else "" in (* initl_file_name: the initialization code inserted at the end of * the cma/cmo list (initl = init last) *) if initl_file_needed then begin (* Generate initializer for "findlib_top.cma" *) let initl = open_out_gen [Open_wronly; Open_trunc; Open_text] 0o777 initl_file_name in try List.iter (fun pkg -> Printf.fprintf initl "let () = Findlib.record_package Findlib.Record_core %S;;\n" pkg ) eff_packages; output_string initl ("let () = Findlib.record_package_predicates [" ^ String.concat ";" (List.map (fun pred -> "\"" ^ String.escaped pred ^ "\"") !predicates ) ^ "];;\n"); close_out initl; with any -> close_out initl; Sys.remove initl_file_name; raise any end; if initl_file_needed && verbose <> Only_show then at_exit (fun () -> let tr f x = try f x with _ -> () in tr Sys.remove initl_file_name; tr Sys.remove (Filename.chop_extension initl_file_name ^ ".cmi"); tr Sys.remove (Filename.chop_extension initl_file_name ^ ".cmo"); ); let exclude_list = if Findlib_config.ocaml_has_meta_files then [ stdlibdir ] else [ stdlibdir; threads_dir; vmthreads_dir ] in (* Don't generate -I options for these directories because there is * also some magic in ocamlc/ocamlopt that would not work otherwise *) let i_options = List.flatten (List.map (fun pkgdir -> let npkgdir = Fl_split.norm_dir pkgdir in if List.mem npkgdir exclude_list then [] else [ "-I"; slashify pkgdir; (* "-ccopt"; out_path ~prefix:"-I" pkgdir; -- see comment *) ]) eff_packages_dl) in (* We no longer emit -ccopt options, because ocamlc/ocamlopt already do that for each -I if the C compiler needs to be invoked (so far I tracked it, ocamlc/ocamlopt have always done this, even back in 1996). *) let l_options = [] in (* Also, no longer -ccopt -L options. Current ocamlc/ocamlopt do that for each -I option passed to them anyway, so we can omit that here. See ocaml change (quite old, but I was not aware of it): http://camlcvs.inria.fr/cgi-bin/cvsweb/ocaml/asmcomp/asmlink.ml.diff?r1=1.38;r2=1.39 *) (* let l_options = List.flatten (List.map (fun pkgdir -> let npkgdir = Fl_split.norm_dir pkgdir in if List.mem npkgdir exclude_list then [] else if Findlib_config.system = "win32" || Findlib_config.system = "win64" then (* Microsoft toolchain *) [ "-ccopt"; out_path ~prefix:"/link /libpath:" pkgdir ] else [ "-ccopt"; out_path ~prefix:"-L" pkgdir; ]) eff_link_dl) in *) let archives = List.flatten (List.map (fun pkg -> let al = try package_property !predicates pkg "archive" with Not_found -> "" in let al_ext = if have_dynload && pkg = "findlib.dynload" then [ initl_file_name ] else [] in let pkg_dir = if not Findlib_config.ocaml_has_meta_files && pkg = "threads" then (* MAGIC for pre-5.x days *) match !threads with `None -> stdlibdir | `VM_threads -> vmthreads_dir | `POSIX_threads -> threads_dir else package_directory pkg in let pkg_dir = slashify pkg_dir in List.map (fun arch -> resolve_path ~base:pkg_dir arch) (Fl_split.in_words al @ al_ext) ) eff_link) @ (if create_toploop then [ initl_file_name ] else [] ) in let linkopts = List.flatten (List.map (fun pkg -> let ol = try package_property !predicates pkg "linkopts" with Not_found -> "" in Fl_split.in_words_ws ol) (List.rev eff_link)) in let pp_command = if !pp_specified then [] else process_pp_spec !syntax_preds !packages !pp_opts in let ppx_commands = process_ppx_spec !predicates !packages !ppx_opts in let pass_files' = List.flatten (List.map (function Pass s -> if s <> "" && s.[0] = '-' then [ "-"; String.sub s 1 (String.length s - 1) ] else [ resolve_path s ] | Impl s -> [ "-impl"; resolve_path s ] | Intf s -> [ "-intf"; resolve_path s ] | Cclib s -> [ "-cclib"; s ] ) !pass_files) in let dll_dirs = remove_dups ((List.map package_directory !dll_pkgs) @ (if !dll_pkgs_all then eff_link_dl else [])) in let dll_options = List.flatten (List.map (fun pkg -> ["-dllpath"; slashify pkg] ) dll_dirs) in let mklib_options = ["-ocamlc"; Findlib.command `ocamlc; "-ocamlopt"; Findlib.command `ocamlopt] in let arguments = (if which = "ocamlmklib" then mklib_options else []) @ !pass_options @ (* other options from the command line *) i_options @ (* Generated -I options from package analysis *) pp_command @ (* Optional preprocessor command *) ppx_commands @ (* Optional ppx extension commands *) (if !linkpkg then l_options else []) @ (* Generated -ccopt -L options *) (if !linkpkg then archives else []) @ (* Gen file names to link *) pass_files' @ (* File names from cmd line *) (if !linkpkg then linkopts else []) @ (* Generated link options *) dll_options (* Generated -dllpath options *) in let actual_command = match which with "ocamlc" -> Findlib.command `ocamlc | "ocamlopt" -> Findlib.command `ocamlopt | "ocamlcp" -> Findlib.command `ocamlcp | "ocamlmklib" -> Findlib.command `ocamlmklib | "ocamlmktop" -> Findlib.command `ocamlmktop | "ocamloptp" -> Findlib.command `ocamloptp | _ -> assert false in run_command verbose actual_command arguments ;; (************************************************************************) let ocamldoc() = let packages = ref [] in let predicates = ref [] in let syntax_preds = ref [] in let pp_opts = ref [] in let ppx_opts = ref [] in let pp_specified = ref false in let verbose = ref Normal in let options = ref [] in let native_spec = match Ocaml_args.ocamldoc_spec with | None -> failwith "Not supported in your configuration: ocamldoc" | Some s -> s in parse_args ~align:false ( Arg.align [ "-package", Arg.String (fun s -> packages := !packages @ Fl_split.in_words s), " Add this package to the search path"; "-predicates", Arg.String (fun s -> predicates := !predicates @ Fl_split.in_words s), "

Add predicate

when calculating dependencies"; "-syntax", Arg.String (fun s -> syntax_preds := !syntax_preds @ Fl_split.in_words s), "

Use preprocessor with predicate

"; "-ppopt", Arg.String (fun s -> pp_opts := !pp_opts @ [s]), " Append option to preprocessor invocation"; "-ppxopt", Arg.String (fun s -> ppx_opts := !ppx_opts @ [s]), ", Append options to ppx invocation for package "; "-thread", Arg.Unit (fun () -> predicates := "mt" :: "mt_posix" :: !predicates), " Assume kernel multi-threading when doing dependency analyses"; "-vmthread", Arg.Unit (fun () -> predicates := "mt" :: "mt_vm" :: !predicates), " Assume bytecode multi-threading when doing dependency analyses"; "-passopt", Arg.String (fun s -> options := !options @ [s]), " Pass this option directly to ocamldoc"; "-passrest", Arg.Rest (fun s -> options := !options @ [s]), " Pass all remaining options directly to ocamldoc"; "-only-show", Arg.Unit (fun () -> verbose := Only_show), " Only show the constructed command but do not exec it"; "-verbose", Arg.Unit (fun () -> verbose := Verbose), " Be verbose\nSTANDARD OPTIONS:"; ] @ ( merge_native_arguments native_spec (fun s -> Arg.Unit (fun () -> options := !options @ [s])) (fun s -> Arg.String (fun arg -> options := !options @ [s; arg])) [ "-v", Arg.Unit (fun () -> verbose := Verbose); "-pp", Arg.String (fun s -> pp_specified := true; options := !options @ ["-pp"; s]); ] ) ) (fun s -> options := !options @ [s]) "usage: ocamlfind ocamldoc ..."; check_package_list !packages; if !syntax_preds <> [] then ( predicates := "syntax" :: !predicates; syntax_preds := "preprocessor" :: "syntax" :: !syntax_preds; ); if !verbose = Verbose then begin if !syntax_preds <> [] then print_string ("Effective set of preprocessor predicates: " ^ String.concat "," !syntax_preds ^ "\n"); print_string ("Effective set of compiler predicates: " ^ String.concat "," !predicates ^ "\n"); end; if !pp_specified && !syntax_preds <> [] then prerr_endline("Warning: -pp overrides the effect of -syntax partly"); let pp_command = if !pp_specified then [] else process_pp_spec !syntax_preds !packages !pp_opts in let ppx_commands = process_ppx_spec !predicates !packages !ppx_opts in let eff_packages = package_deep_ancestors !predicates !packages in (* Check on [error] directives (turned into warnings): *) List.iter (fun pkg -> try let error = package_property !predicates pkg "error" in prerr_endline("ocamlfind: [WARNING] Package `" ^ pkg ^ "' signals error: " ^ error) with Not_found -> () ) eff_packages; let eff_packages_dl = remove_dups (List.map package_directory eff_packages) in let arguments = (List.flatten (List.map (fun d -> [ "-I"; slashify d ]) eff_packages_dl)) @ pp_command @ ppx_commands @ !options in let actual_command = Findlib.command `ocamldoc in run_command !verbose actual_command arguments ;; (************************************************************************) (* From ocamldep source code: *) let depends_on_char, continuation_char = match Sys.os_type with | "Unix" | "BeOS" | "Win32" | "Cygwin" -> ':', '\\' | "MacOS" -> '\196', '\182' | _ -> assert false ;; let suppress_targets suffix = (* If [line] begins with "target: dependencies ...", and [target] is a * file name ending in [suffix], this line is suppressed, and all * follow-up lines. *) let do_suppress = ref false in fun line -> let target = try let k = String.index_from line 0 depends_on_char in (* or Not_found *) let target_string = String.sub line 0 k in if String.contains target_string ' ' then raise Not_found; Some target_string with Not_found -> None in begin match target with Some target_string -> do_suppress := Filename.check_suffix target_string suffix; | None -> () end; if !do_suppress then None else Some line ;; let ocamldep () = let switches = ref [] in let pass_options = ref [] in let pass_files = ref [] in let packages = ref [] in let predicates = ref [] in let syntax_preds = ref [] in let pp_opts = ref [] in let ppx_opts = ref [] in let pp_specified = ref false in let verbose = ref Normal in let native_filter = ref false in let bytecode_filter = ref false in let add_switch name = Arg.Unit (fun () -> switches := name :: !switches; pass_options := !pass_options @ [name]) in let add_spec_fn name s = pass_options := !pass_options @ [name; s] in let add_spec name = Arg.String (add_spec_fn name) in let add_pred = Arg.String (fun s -> predicates := !predicates @ (Fl_split.in_words s)) in let add_syntax_pred = Arg.String (fun s -> syntax_preds := !syntax_preds @ (Fl_split.in_words s)) in let add_pp_opt = Arg.String (fun s -> pp_opts := !pp_opts @ [s]) in let add_pkg = Arg.String (fun s -> packages := !packages @ (Fl_split.in_words s)) in let native_spec = match Ocaml_args.ocamldep_spec with | None -> failwith "Not supported in your configuration: ocamldep" | Some s -> s in parse_args ( [ "-syntax", add_syntax_pred, "

Use preprocessor with predicate

"; "-package", add_pkg, "

Add preprocessor package

"; "-predicates", add_pred, "

Add predicate

when calculating dependencies"; "-ppopt", add_pp_opt, " Append option to preprocessor invocation"; "-ppxopt", Arg.String (fun s -> ppx_opts := !ppx_opts @ [s]), ", Append options to ppx invocation for package "; "-passopt", Arg.String (fun s -> pass_options := !pass_options @ [s]), " Pass option directly to ocamlc/opt/mktop"; "-passrest", Arg.Rest (fun s -> pass_options := !pass_options @ [s]), " Pass all remaining options directly"; "-native-filter", Arg.Set native_filter, " Output only dependencies for native code (implies -native)"; "-bytecode-filter", Arg.Set bytecode_filter, " Output only dependencies for bytecode"; "-only-show", Arg.Unit (fun () -> verbose := Only_show), " Only show the constructed command but do not exec it"; "-verbose", Arg.Unit (fun () -> verbose := Verbose), " Print calls to external commands\nSTANDARD OPTIONS:"; ] @ ( merge_native_arguments native_spec add_switch add_spec [ "-I", Arg.String (fun s -> add_spec_fn "-I" (slashify (resolve_path s))); "-pp", Arg.String (fun s -> pp_specified := true; add_spec_fn "-pp" s); ] ) ) (fun s -> pass_files := !pass_files @ [ s]) ("usage: ocamlfind ocamldep [options] file ..."); check_package_list !packages; if !native_filter && !bytecode_filter then failwith "The options -native-filter and -bytecode-filter are incompatible"; if !native_filter && not (List.mem "-native" !switches) then pass_options := "-native" :: !pass_options; if !syntax_preds <> [] then syntax_preds := "preprocessor" :: "syntax" :: !syntax_preds; if !verbose = Verbose && !syntax_preds <> [] then print_string ("Effective set of preprocessor predicates: " ^ String.concat "," !syntax_preds ^ "\n"); if !pp_specified && !syntax_preds <> [] then prerr_endline("Warning: -pp overrides the effect of -syntax partly"); let pp_command = if !pp_specified then [] else process_pp_spec !syntax_preds !packages !pp_opts in let ppx_commands = process_ppx_spec !predicates !packages !ppx_opts in let arguments = !pass_options @ pp_command @ ppx_commands @ !pass_files in let actual_command = Findlib.command `ocamldep in let filter = if !native_filter then (* Suppress when target is ".cmo": *) Some (suppress_targets ".cmo") else if !bytecode_filter then (* Suppress when target is ".cmx": *) Some (suppress_targets ".cmx") else None in run_command ?filter !verbose actual_command arguments ;; (************************************************************************) let ocamlbrowser () = (* let switches = ref [] in *) let pass_options = ref [] in let add_all = ref false in let packages = ref [] in (* let add_switch name = Arg.Unit (fun () -> switches := name :: !switches; pass_options := !pass_options @ [name]) in *) let add_spec_fn name s = pass_options := !pass_options @ [name; s] in (* let add_spec name = Arg.String (add_spec_fn name) in *) let add_pkg = Arg.String (fun s -> packages := !packages @ (Fl_split.in_words s)) in parse_args [ "-I", Arg.String (fun s -> add_spec_fn "-I" (slashify(resolve_path s))), "

Add to the list of include directories"; "-all", Arg.Set add_all, " Add all packages to include path"; "-package", add_pkg, "

Add package

to include path"; "-passopt", Arg.String (fun s -> pass_options := !pass_options @ [s]), " Pass option directly to ocamlbrowser"; "-passrest", Arg.Rest (fun s -> pass_options := !pass_options @ [s]), " Pass all remaining options directly"; ] (fun s -> raise (Arg.Bad ("Unexpected argument: " ^ s))) ("usage: ocamlfind ocamlbrowser [options] file ..."); if !add_all then packages := Fl_package_base.list_packages(); check_package_list !packages; let arguments = !pass_options @ (List.flatten (List.map (fun pkg -> let dir = Findlib.package_directory pkg in [ "-I"; slashify dir ] ) !packages ) ) in let actual_command = Findlib.command `ocamlbrowser in run_command Normal actual_command arguments ;; (************************************************************************) let copy_file ?(rename = (fun name -> name)) ?(append = "") src dstdir = (* A system-independent function to copy the file src to dstdir *) let outname = rename (Filename.basename src) in let ch_in = open_in_bin src in (* Determine the permissions of the file: the permissions of the * user bits are extended to all groups (user, group, world bits), * and the umask is applied to the result. * Furthermore, the mtime of the file is preserved. This seems to be * important for BSD-style archives (otherwise the system is confused * and wants that ranlib is run again). For simplicity, the atime is * set to the mtime, too. *) let s = Unix.stat src in let perm = s.Unix.st_perm in let user_perm = (perm land 0o700) lsr 6 in let perm' = user_perm lor (user_perm lsl 3) lor (user_perm lsl 6) in try let outpath = Filename.concat dstdir outname in if Sys.file_exists outpath then prerr_endline ("ocamlfind: [WARNING] Overwriting file " ^ outpath); let ch_out = open_out_gen [Open_wronly; Open_creat; Open_trunc; Open_binary] perm' outpath in try let buflen = 4096 in let buf = Bytes.create buflen in let pos = ref 0 in let len = ref (input ch_in buf 0 buflen) in while !len > 0 do output ch_out buf !pos !len; len := input ch_in buf !pos buflen; done; output_string ch_out append; close_out ch_out; close_in ch_in; Unix.utimes outpath s.Unix.st_mtime s.Unix.st_mtime; prerr_endline("Installed " ^ outpath); with exc -> close_out ch_out; raise exc with exc -> close_in ch_in; raise exc ;; let install_create_directory pkgname dstdir = try Unix.mkdir dstdir 0o777 with Unix.Unix_error(Unix.EEXIST,_,_) -> () | Unix.Unix_error(Unix.ENOENT,_,_) | Unix.Unix_error(Unix.ENOTDIR,_,_) -> failwith ("Bad configuration: Cannot mkdir " ^ dstdir ^ " because a path component does not exist or is not a directory") | Unix.Unix_error(e,_,_) -> failwith ("Cannot mkdir " ^ dstdir ^ ": " ^ Unix.error_message e) ;; let create_owner_file pkg file = let outpath = file ^ ".owner" in let f = open_out outpath in try output_string f (pkg ^ "\n"); close_out f; prerr_endline("Installed " ^ outpath); with exc -> close_out f; raise exc ;; let trim_cr s = let len = String.length s in if len > 0 && String.get s (len-1) = '\r' then String.sub s 0 (len-1) else s let find_owned_files pkg dir = let files = Array.to_list(Sys.readdir dir) in List.filter (fun file -> let owner_file = if Filename.check_suffix file ".owner" then file else file ^ ".owner" in (List.mem owner_file files) && ( try let fd = Unix.openfile (Filename.concat dir owner_file) [Unix.O_RDONLY] 0 in let f = Unix.in_channel_of_descr fd in try let line = trim_cr (input_line f) in let is_my_file = (line = pkg) in close_in f; is_my_file with | End_of_file -> close_in f; false | exc -> close_in f; raise exc with | Unix.Unix_error(Unix.ENOENT,_,_) -> (* the owner file might have been removed by a package removal that is being done in parallel *) false | Unix.Unix_error(code, _, arg) -> raise(sys_error code arg) ) ) files ;; exception Missing_archives of Fl_metascanner.pkg_expr let rec patch_archives pkgdir pkg = (* First remove all missing files from archive variables: *) let defs' = List.map (fun def -> if def.Fl_metascanner.def_var = "archive" then ( let files = Fl_split.in_words def.Fl_metascanner.def_value in let files' = List.filter (fun file -> let p = Findlib.resolve_path ~base:pkgdir file in Sys.file_exists p) files in { def with Fl_metascanner.def_value = String.concat " " files' } ) else def ) pkg.Fl_metascanner.pkg_defs in (* Remove empty archive variables: *) let defs'' = List.filter (fun def -> def.Fl_metascanner.def_var <> "archive" || Fl_split.in_words def.Fl_metascanner.def_value <> [] ) defs' in (* Return the package or raise Not_found if all archives vanished: *) let children = (* Recursive patch, remove all Not_found packages: *) List.flatten (List.map (fun (name, child) -> try [ name, patch_archives pkgdir child ] with Missing_archives _ -> [] ) pkg.Fl_metascanner.pkg_children) in let pkg' = { Fl_metascanner.pkg_defs = defs''; pkg_children = children } in if List.exists (fun def -> def.Fl_metascanner.def_var = "archive") defs'' then pkg' else raise (Missing_archives pkg') ;; let rec patch_pkg pkgdir pkg patches = match patches with | [] -> pkg | (`Version v) :: patches' -> let def = { Fl_metascanner.def_var = "version"; def_flav = `BaseDef; def_preds = []; def_value = v } in let defs = List.filter (fun d -> d.Fl_metascanner.def_var <> "version") pkg.Fl_metascanner.pkg_defs in let pkg' = { pkg with Fl_metascanner.pkg_defs = def :: defs } in patch_pkg pkgdir pkg' patches' | (`Rmpkg n) :: patches' -> let children = List.filter (fun (name,_) -> name <> n) pkg.Fl_metascanner.pkg_children in let pkg' = { pkg with Fl_metascanner.pkg_children = children } in patch_pkg pkgdir pkg' patches' | `Archives :: patches' -> let pkg' = try patch_archives pkgdir pkg with Missing_archives p -> p in patch_pkg pkgdir pkg' patches' ;; exception Skip_file;; type which = Auto | Dll | No_dll;; let meta_pkg meta_name = let f = open_in meta_name in try let pkg = Fl_metascanner.parse f in close_in f; pkg with | Failure s | Fl_metascanner.Error s -> close_in f; failwith ("Cannot parse '" ^ meta_name ^ "': " ^ s) let char_lowercase_ascii c = (* Char.lowercase_ascii and String.lowercase_ascii first available in OCaml-4.03, but we want to support earlier versions too *) if (c >= 'A' && c <= 'Z') then Char.unsafe_chr(Char.code c + 32) else c let string_lowercase_ascii s = let n = String.length s in let b = Bytes.create n in for i = 0 to n - 1 do Bytes.unsafe_set b i (char_lowercase_ascii (String.unsafe_get s i)) done; Bytes.to_string b let install_package () = let destdir = ref (default_location()) in let metadir = ref (meta_directory()) in let ldconf = ref (ocaml_ldconf()) in let don't_add_directory_directive = ref false in let pkgname = ref "" in let auto_files = ref [] in let dll_files = ref [] in let nodll_files = ref [] in let which = ref Auto in let add_files = ref false in let optional = ref false in let patches = ref [] in let keywords = [ "-destdir", (Arg.String (fun s -> destdir := s)), (" Set the destination directory (default: " ^ !destdir ^ ")"); "-metadir", (Arg.String (fun s -> metadir := s)), (" Install the META file into this directory (default: "^ (if !metadir = "" then "none" else !metadir) ^ ")"); "-ldconf", (Arg.String (fun s -> ldconf := s)), (" Update this ld.conf file (default: " ^ !ldconf ^ ")"); "-dont-add-directory-directive", (Arg.Set don't_add_directory_directive), " never append directory='...' to META"; "-dll", Arg.Unit (fun () -> which := Dll), " The following files are DLLs"; "-nodll", Arg.Unit (fun () -> which := No_dll), " The following files are not DLLs"; "-add", Arg.Unit (fun () -> add_files := true), " Add files to the package"; "-optional", Arg.Set optional, " The following files are optional"; "-patch-version", Arg.String (fun s -> patches := !patches @ [`Version s]), " Set the package version to "; "-patch-rmpkg", Arg.String (fun s -> patches := !patches @ [`Rmpkg s]), " Remove the subpackage "; "-patch-archives", Arg.Unit (fun () -> patches := !patches @ [`Archives]), " Remove non-existing archives"; ] in let errmsg = "usage: ocamlfind install [options] ..." in parse_args keywords (fun s -> if !pkgname = "" then pkgname := s else if not !optional || Sys.file_exists s then match !which with Auto -> auto_files := s :: !auto_files | Dll -> dll_files := s :: !dll_files | No_dll -> nodll_files := s :: !nodll_files ) errmsg; if !pkgname = "" then (Arg.usage keywords errmsg; exit 1); if not (Fl_split.is_valid_package_name !pkgname) then failwith "Package names must not contain the character '.'!"; let pkgdir = Filename.concat !destdir !pkgname in let dlldir = Filename.concat !destdir Findlib_config.libexec_name in let has_metadir = !metadir <> "" in let meta_dot_pkg = "META." ^ !pkgname in (* The list of all files to install: *) let full_list = !auto_files @ !dll_files @ !nodll_files in (* Check whether there are DLLs: *) let (l1,l2) = List.partition is_dll !auto_files in let dll_list = l1 @ !dll_files in let nodll_list = l2 @ !nodll_files in let have_libexec = Sys.file_exists dlldir in let pkgdir_list = if have_libexec then nodll_list else full_list in let pkgdir_eff_list = (* The files that will be placed into pkgdir: *) List.map (fun f -> if f = meta_dot_pkg then "META" else f) (List.filter (fun f -> not has_metadir || (f <> "META" && f <> meta_dot_pkg)) pkgdir_list) in (* Check whether META exists: (And check syntax) *) let meta_name = try List.find (fun p -> let b = Filename.basename p in b = "META" || b = meta_dot_pkg) nodll_list with | Not_found -> if !add_files then ( let m1 = Filename.concat !metadir meta_dot_pkg in let m2 = Filename.concat pkgdir "META" in if Sys.file_exists m1 then m1 else if Sys.file_exists m2 then m2 else failwith "Cannot find META in package dir" ) else failwith "The META file is missing" in let meta_pkg = meta_pkg meta_name in if not !add_files then ( (* Check for frequent reasons why installation can go wrong *) if Sys.file_exists (Filename.concat !metadir meta_dot_pkg) then failwith ("Package " ^ !pkgname ^ " is already installed\n - (file " ^ Filename.concat !metadir meta_dot_pkg ^ " already exists)"); if Sys.file_exists (Filename.concat pkgdir "META") then failwith ("Package " ^ !pkgname ^ " is already installed\n - (file " ^ pkgdir ^ "/META already exists)"); ); List.iter (fun f -> let f' = Filename.concat pkgdir f in if Sys.file_exists f' then failwith ("Conflict with file: " ^ f')) pkgdir_eff_list; if have_libexec then begin List.iter (fun dll -> let b = Filename.basename dll in if Sys.file_exists (Filename.concat dlldir b) then failwith ("Conflict with another package: Library " ^ b ^ " is already installed"); ) dll_list end; (* Create the package directory: *) install_create_directory !pkgname pkgdir; (* Now copy the files into the package directory (except META): *) List.iter (fun p -> try copy_file ~rename: (fun f -> if f = "META" || f = meta_dot_pkg then raise Skip_file else f) p pkgdir with Skip_file -> () ) pkgdir_list; (* Copy the DLLs into the libexec directory if necessary *) if have_libexec then begin List.iter (fun p -> copy_file p dlldir; create_owner_file !pkgname (Filename.concat dlldir (Filename.basename p)) ) dll_list end; (* Extend ld.conf if necessary: *) if dll_list <> [] && !ldconf <> "ignore" && not have_libexec then begin if Sys.file_exists !ldconf then begin let lines = read_ldconf !ldconf in write_ldconf !ldconf lines [ pkgdir ] end else prerr_endline("ocamlfind: [WARNING] You have installed DLLs but there is no ld.conf") end; if dll_list <> [] && have_libexec && !ldconf <> "ignore" then begin (* Check whether libexec is mentioned in ldconf *) (* FIXME: We have to be careful with case-insensitive filesystems. Currently, we only check for Win32, but also OS X may have ci filesystems. So some better check would be nice. *) let lines = read_ldconf !ldconf in let dlldir_norm = Fl_split.norm_dir dlldir in let dlldir_norm_lc = string_lowercase_ascii dlldir_norm in let ci_filesys = (Sys.os_type = "Win32") in let check_dir d = let d' = Fl_split.norm_dir d in (d' = dlldir_norm) || (ci_filesys && string_lowercase_ascii d' = dlldir_norm_lc) in if not (List.exists check_dir lines) then prerr_endline("ocamlfind: [WARNING] You have installed DLLs but the directory " ^ dlldir_norm ^ " is not mentioned in ld.conf"); end; (* Finally, write the META file: *) let write_meta append_directory dir name = (* If there are patches, write the patched META, else copy the file: *) if !patches = [] then copy_file ~rename:(fun _ -> name) ?append:(if append_directory then Some("\ndirectory=\"" ^ pkgdir ^ "\" # auto-added by ocamlfind\n") else None) meta_name dir else ( let p = Filename.concat dir name in let patched_pkg = patch_pkg pkgdir meta_pkg !patches in let out = open_out p in Fl_metascanner.print out patched_pkg; if append_directory then output_string out ("\ndirectory=\"" ^ pkgdir ^ "\" # auto-added by ocamlfind\n"); close_out out; prerr_endline ("Installed " ^ p); ) in if not !add_files then ( if has_metadir then write_meta true !metadir meta_dot_pkg else write_meta false pkgdir "META"; ); (* Check if there is a postinstall script: *) let postinstall = Filename.concat !destdir "postinstall" in if Sys.file_exists postinstall then run_command Verbose postinstall [ slashify !destdir; !pkgname ] ;; let reserved_names = [ Findlib_config.libexec_name; "postinstall"; "postremove" ];; let remove_package () = let destdir = ref (default_location()) in let destdir_set = ref false in let metadir = ref (meta_directory()) in let ldconf = ref (ocaml_ldconf()) in let pkgname = ref "" in let keywords = [ "-destdir", (Arg.String (fun s -> destdir := s; destdir_set := true)), (" Set the destination directory (default: " ^ !destdir ^ ")"); "-metadir", (Arg.String (fun s -> metadir := s)), (" Remove the META file from this directory (default: " ^ (if !metadir = "" then "none" else !metadir) ^ ")"); "-ldconf", (Arg.String (fun s -> ldconf := s)), (" Update this ld.conf file (default: " ^ !ldconf ^ ")"); ] in let errmsg = "usage: ocamlfind remove [options] " in parse_args keywords (fun s -> if !pkgname = "" then pkgname := s else raise (Arg.Bad "too many arguments") ) errmsg; if !pkgname = "" then (Arg.usage keywords errmsg; exit 1); if List.mem !pkgname reserved_names then failwith ("You are not allowed to remove this thing by ocamlfind!"); if not (Fl_split.is_valid_package_name !pkgname) then failwith "Package names must not contain the character '.'!"; let meta_dot_pkg = "META." ^ !pkgname in let has_metadir = !metadir <> "" in let pkgdir = Filename.concat !destdir !pkgname in let dlldir = Filename.concat !destdir Findlib_config.libexec_name in let have_libexec = Sys.file_exists dlldir in (* Warn if there is another package with the same name: *) let other_pkgdir = try Findlib.package_directory !pkgname with No_such_package _ -> "" in if other_pkgdir <> "" && not !destdir_set then begin (* Is pkgdir = other_pkgdir? - We check physical identity: *) try let s_other_pkgdir = Unix.stat other_pkgdir in try let s_pkgdir = Unix.stat pkgdir in if (s_pkgdir.Unix.st_dev <> s_other_pkgdir.Unix.st_dev) || (s_pkgdir.Unix.st_ino <> s_other_pkgdir.Unix.st_ino) then prerr_endline("ocamlfind: [WARNING] You are removing the package from " ^ pkgdir ^ " but the currently visible package is at " ^ other_pkgdir ^ "; you may want to specify the -destdir option"); with Unix.Unix_error(Unix.ENOENT,_,_) -> prerr_endline("ocamlfind: [WARNING] You are trying to remove the package from " ^ pkgdir ^ " but the currently visible package is at " ^ other_pkgdir ^ "; you may want to specify the -destdir option"); with Unix.Unix_error(_,_,_) -> () (* ignore, it's only a warning *) end; (* First remove the META file. If it is already gone, assume that a parallel running removal removed it already. *) (* If there is a metadir, remove the META file from it: *) let meta_removal_ok = if has_metadir then ( let f = Filename.concat !metadir meta_dot_pkg in try Unix.unlink f; prerr_endline ("Removed " ^ f); true with | Unix.Unix_error(Unix.ENOENT,_,_) -> prerr_endline ("ocamlfind: [WARNING] No such file: " ^ f); false | Unix.Unix_error(code, _, arg) -> raise(sys_error code arg) ) else let f = Filename.concat pkgdir "META" in try Unix.unlink f; prerr_endline ("Removed " ^ f); true with | Unix.Unix_error(Unix.ENOENT,_,_) -> prerr_endline ("ocamlfind: [WARNING] No such file: " ^ f); false | Unix.Unix_error(code, _, arg) -> raise(sys_error code arg) in if meta_removal_ok then ( (* Remove files from libexec directory: *) if have_libexec then begin let dll_files = find_owned_files !pkgname dlldir in List.iter (fun file -> let absfile = Filename.concat dlldir file in Sys.remove absfile; prerr_endline ("Removed " ^ absfile) ) dll_files end; (* Remove the files from the package directory: *) if Sys.file_exists pkgdir then begin let files = Sys.readdir pkgdir in Array.iter (fun f -> Sys.remove (Filename.concat pkgdir f)) files; Unix.rmdir pkgdir; prerr_endline ("Removed " ^ pkgdir) end else prerr_endline("ocamlfind: [WARNING] No such directory: " ^ pkgdir); (* Modify ld.conf *) if !ldconf <> "ignore" then begin if Sys.file_exists !ldconf then begin let lines = read_ldconf !ldconf in let d = Fl_split.norm_dir pkgdir in let exists = List.exists (fun p -> Fl_split.norm_dir p = d) lines in if exists then begin let lines' = List.filter (fun p -> Fl_split.norm_dir p <> d) lines in write_ldconf !ldconf lines' [] end end end; (* Check if there is a postremove script: *) let postremove = Filename.concat !destdir "postremove" in if Sys.file_exists postremove then run_command Verbose postremove [ slashify !destdir; !pkgname ] ) ;; let list_packages() = let descr = ref false in let keywords = [ "-describe", Arg.Set descr, " Output package descriptions"; ] in let errmsg = "usage: ocamlfind list [options]" in parse_args keywords (fun _ -> Arg.usage keywords errmsg; exit 1) errmsg; Findlib.list_packages ~descr:!descr stdout; Fl_package_base.package_conflict_report ~identify_dir () ;; let print_configuration() = let dir s = if Sys.file_exists s then s else s ^ " (not found)" in let var = ref None in let errmsg = "usage: ocamlfind printconf (conf|path|destdir|metadir|metapath|stdlib|ldconf)" in parse_args [] (fun s -> if !var <> None then raise(Arg.Bad "Unexpected argument"); match s with ("conf" | "path" | "destdir" | "metadir" | "metapath" | "stdlib" | "ldconf") -> var := Some s | _ -> raise(Arg.Bad "Bad argument"); ) errmsg; match !var with None -> print_endline "Effective configuration:"; Printf.printf "Configuration file:\n %s\n" (dir (Findlib.config_file())); Printf.printf "Search path:\n"; List.iter (fun p -> Printf.printf " %s\n" (dir p)) (Findlib.search_path()); Printf.printf "Packages will be installed in/removed from:\n %s\n" (dir (Findlib.default_location())); Printf.printf "META files will be installed in/removed from:\n %s\n" (let md = Findlib.meta_directory() in if md = "" then "the corresponding package directories" else dir md ); Printf.printf "The standard library is assumed to reside in:\n %s\n" (Findlib.ocaml_stdlib()); Printf.printf "The ld.conf file can be found here:\n %s\n" (Findlib.ocaml_ldconf()); flush stdout | Some "conf" -> print_endline (Findlib.config_file()) | Some "path" -> List.iter print_endline (Findlib.search_path()) | Some "destdir" -> print_endline (Findlib.default_location()) | Some "metadir" -> print_endline (Findlib.meta_directory()) | Some "metapath" -> let mdir = Findlib.meta_directory() in let ddir = Findlib.default_location() in print_endline (if mdir <> "" then mdir ^ "/META.%s" else ddir ^ "/%s/META") | Some "stdlib" -> print_endline (Findlib.ocaml_stdlib()) | Some "ldconf" -> print_endline (Findlib.ocaml_ldconf()) | _ -> assert false ;; let ocamlcall pkg cmd = let dir = package_directory pkg in let path = Filename.concat dir cmd in begin try Unix.access path [ Unix.X_OK ] with Unix.Unix_error (Unix.ENOENT, _, _) -> failwith ("Cannot find command: " ^ path) | Unix.Unix_error (Unix.EACCES, _, _) -> failwith ("Cannot execute: " ^ path) | other -> Unix.handle_unix_error (fun () -> raise other) () end; let args = Array.to_list (Array.sub Sys.argv 2 (Array.length Sys.argv -2)) in run_command Normal path args ;; (** lint META file *) let lint () = let meta_files = Queue.create () in parse_args ~align:false ( Arg.align [ ]) (fun s -> if Sys.file_exists s then Queue.add s meta_files else raise(Arg.Bad (Printf.sprintf "%s: file doesn't exists" s))) "usage: ocamlfind lint ..."; let error = Queue.fold (fun error file -> let pkg = meta_pkg file in let error = Fl_lint.warn pkg || error in error ) false meta_files in exit (if error then 1 else 0) ;; (** print ppx options *) let print_ppx () = let packages = ref [] in let predicates = ref [] in let ppx_opts = ref [] in let add_pred = Arg.String (fun s -> predicates := !predicates @ (Fl_split.in_words s)) in let add_ppx_opt = Arg.String (fun s -> ppx_opts := !ppx_opts @ [s]) in parse_args [ "-predicates", add_pred, " specifies comma-separated list of assumed predicates"; "-ppxopt", add_ppx_opt, ", Append options to ppx invocation for package "; ] (fun p -> packages := !packages @ [p]) "usage: ocamlfind printppx [options] package ..."; let ppx_commands = process_ppx_spec !predicates !packages !ppx_opts in print_endline (String.concat " " (List.map escape_if_needed ppx_commands)) ;; let rec select_mode () = let k = !Arg.current in let m_string = try arg (k+1) with Not_found -> raise Usage in let m = match m_string with ("use"|"-use") -> incr Arg.current; M_use | ("query"|"-query") -> incr Arg.current; M_query | ("install"|"-install") -> incr Arg.current; M_install | ("remove"|"-remove") -> incr Arg.current; M_remove | ("ocamlc"|"-ocamlc"|"c") -> incr Arg.current; M_compiler "ocamlc" | ("ocamlcp"|"-ocamlcp"|"cp") -> incr Arg.current; M_compiler "ocamlcp" | ("ocamloptp"|"-ocamloptp"|"optp") -> incr Arg.current; M_compiler "ocamloptp" | ("ocamlmklib"|"-ocamlmklib"|"mklib") -> incr Arg.current; M_compiler "ocamlmklib" | ("ocamlmktop"|"-ocamlmktop"|"mktop") -> incr Arg.current; M_compiler "ocamlmktop" | ("ocamlopt"|"-ocamlopt"|"opt") -> incr Arg.current; M_compiler "ocamlopt" | ("ocamldep"|"-ocamldep"|"dep") -> incr Arg.current; M_dep | ("ocamlbrowser"|"-ocamlbrowser"|"browser") -> incr Arg.current; M_browser | ("ocamldoc"|"-ocamldoc"|"doc") -> incr Arg.current; M_doc | ("printconf"|"-printconf") -> incr Arg.current; M_printconf | ("list"|"-list") -> incr Arg.current; M_list | ("lint"|"-lint") -> incr Arg.current; M_lint | ("printppx"|"-printppx") -> incr Arg.current; M_printppx | "-toolchain" -> let t = try arg (k+2) with Not_found -> raise Usage in Findlib.init ~toolchain:t (); Arg.current := k+2; select_mode() | s when String.contains m_string '/' -> incr Arg.current; let k = String.index m_string '/' in let pkg = String.sub m_string 0 k in let cmd = String.sub m_string (k+1) (String.length m_string - k - 1) in M_call(pkg,cmd) | _ -> raise Usage in m ;; let main() = try let m = select_mode() in let l = Array.length Sys.argv in let k = !Arg.current in let rest = Array.sub Sys.argv (k+1) (l-k-1) in match m with M_use -> if rest = [| |] then raise Usage; if rest.(0) = "-p" then begin if l<4 then raise Usage; use_package rest.(1) (List.tl(List.tl(Array.to_list rest))) end else use_package "" (Array.to_list rest) | M_query -> query_package () | M_install -> install_package() | M_remove -> remove_package () | M_printconf -> print_configuration () | M_list -> list_packages() | M_dep -> ocamldep() | M_browser -> ocamlbrowser() | M_doc -> ocamldoc() | M_call(pkg,cmd) -> ocamlcall pkg cmd | M_compiler which -> ocamlc which () | M_lint -> lint() | M_printppx -> print_ppx() with Usage -> prerr_endline "Usage: ocamlfind query [-help | other options] ..."; prerr_endline " or: ocamlfind ocamlc [-help | other options] ..."; prerr_endline " or: ocamlfind ocamlcp [-help | other options] ..."; prerr_endline " or: ocamlfind ocamlmklib [-help | other options] ..."; prerr_endline " or: ocamlfind ocamlmktop [-help | other options] ..."; if Ocaml_args.ocamlopt_spec <> None then prerr_endline " or: ocamlfind ocamlopt [-help | other options] ..."; if Ocaml_args.ocamloptp_spec <> None then prerr_endline " or: ocamlfind ocamloptp [-help | other options] ..."; prerr_endline " or: ocamlfind ocamldep [-help | other options] ..."; prerr_endline " or: ocamlfind ocamlbrowser [-help | other options]"; prerr_endline " or: ocamlfind ocamldoc [-help | other options] ..."; prerr_endline " or: ocamlfind install [-help | other options] ..."; prerr_endline " or: ocamlfind remove [-help | other options] "; prerr_endline " or: ocamlfind printppx [-help | other options] ..."; prerr_endline " or: ocamlfind printconf [-help] [variable]"; prerr_endline " or: ocamlfind lint [-help] "; prerr_endline " or: ocamlfind list"; prerr_endline " or: ocamlfind pkg/cmd arg ..."; prerr_endline "Select toolchain with:"; prerr_endline " ocamlfind -toolchain "; prerr_endline "Abbreviations:"; prerr_endline " e.g. ocamlfind opt instead of ocamlfind ocamlopt"; exit 2 | Failure f -> prerr_endline ("ocamlfind: " ^ f); exit 2 | Sys_error f -> prerr_endline ("ocamlfind: " ^ f); exit 2 | Findlib.No_such_package(pkg,info) -> prerr_endline ("ocamlfind: Package `" ^ pkg ^ "' not found" ^ (if info <> "" then " - " ^ info else "")); exit 2 | Findlib.Package_loop pkg -> prerr_endline ("ocamlfind: Package `" ^ pkg ^ "' requires itself"); exit 2 | Silent_error -> exit 2 ;; try Sys.catch_break true; main() with any -> prerr_endline ("Uncaught exception: " ^ Printexc.to_string any); let raise_again = try ignore(Sys.getenv "OCAMLFIND_DEBUG"); true with Not_found -> false in if raise_again then raise any; exit 3 ;; not-ocamlfind-0.14/local-packages/ocamlfind/src/findlib/num_top.ml0000644000175000017500000000151114770304423024235 0ustar stephsteph(* $Id$ * ---------------------------------------------------------------------- * *) let print_outcome = false let error_fmt = Format.err_formatter let printers = [ "Num_top_printers.nat_printer"; "Num_top_printers.big_int_printer"; "Num_top_printers.ratio_printer"; "Num_top_printers.num_printer"; ] let eval_phrase s = let lexbuf = Lexing.from_string s in let phrase = !Toploop.parse_toplevel_phrase lexbuf in Toploop.execute_phrase print_outcome error_fmt phrase let install_all () = List.fold_left (fun outcome phrase -> outcome && eval_phrase (Printf.sprintf "#install_printer %s;;" phrase)) true printers let _ = if not (install_all ()) then begin Format.fprintf error_fmt "Something weird happened while installing Num library printers"; Format.pp_print_flush error_fmt () end not-ocamlfind-0.14/local-packages/ocamlfind/src/findlib/num_top.mli0000644000175000017500000000055314770304423024413 0ustar stephsteph(* $Id$ * ---------------------------------------------------------------------- * *) (** Load this module in the toplevel to install printers for the following types defined in the "num" library: - Nat.nat - Big_int.big_int - Ratio.ratio - Num.num No functions exported. Copyright (C) 2003 Stefano Zacchiroli *) not-ocamlfind-0.14/local-packages/ocamlfind/src/findlib/num_top_printers.ml0000644000175000017500000000065614770304423026174 0ustar stephsteph(* $Id$ * ---------------------------------------------------------------------- * *) let nat_printer fmt v = Format.fprintf fmt "" (Nat.string_of_nat v) let big_int_printer fmt v = Format.fprintf fmt "" (Big_int.string_of_big_int v) let ratio_printer fmt v = Format.fprintf fmt "" (Ratio.string_of_ratio v) let num_printer fmt v = Format.fprintf fmt "" (Num.string_of_num v) not-ocamlfind-0.14/local-packages/ocamlfind/src/findlib/num_top_printers.mli0000644000175000017500000000105714770304423026341 0ustar stephsteph(* $Id$ * ---------------------------------------------------------------------- * *) (** Printers for types defined in the "num" library. Meant to be used as printers in the ocaml toplevel. See num_top.mli. Copyright (C) 2003 Stefano Zacchiroli Released under the same terms as findlib. *) val nat_printer : Format.formatter -> Nat.nat -> unit val big_int_printer : Format.formatter -> Big_int.big_int -> unit val ratio_printer : Format.formatter -> Ratio.ratio -> unit val num_printer: Format.formatter -> Num.num -> unit not-ocamlfind-0.14/local-packages/ocamlfind/src/findlib/test_parser.ml0000644000175000017500000000523014770304423025111 0ustar stephstephlet with_open_in file func = let chan = open_in file in let result = try func chan with exn -> close_in chan; raise exn in close_in chan; result ;; type test_mode = Compare_both | Only of (old_or_new * int) and old_or_new = Old | New let read_file file = let buf = Buffer.create 100 in with_open_in file (fun ch -> try while true do Buffer.add_string buf (input_line ch) done with End_of_file -> ()); Buffer.contents buf let test mode file = match mode with | Compare_both -> let ast1 = with_open_in file Fl_metascanner.parse in let ast2 = with_open_in file Fl_metascanner.parse2 in Printf.printf "%s tested %s\n" file (if ast1 = ast2 then "OK" else "FAIL") | Only (old_or_new, niter) -> let content = read_file file in for i = 1 to niter do let parse = match old_or_new with | Old -> Fl_metascanner.parse_lexing | New -> Fl_metascanner.parse2_lexing in ignore (parse (Lexing.from_string content)) done let rec explore mode path = if Sys.is_directory path then let traverse file = explore mode (Filename.concat path file) in Array.iter traverse (Sys.readdir path) else if Filename.basename path = "META" then test mode path let () = let test_mode, targets = (* command-line option handling *) let only_old = ref false in let only_new = ref false in let niter = ref 1 in let targets = ref [] in let usage = "test_parser ....\n \ recursively traverse paths and compare the two parsers \ on each file named META" in let options = [ ("--niter", Arg.Set_int niter, "iterate the parser for performance comparison (only in --only-old or --only-new modes)"); ("--only-old", Arg.Set only_old, "only test the old parser"); ("--only-new", Arg.Set only_new, "only test the new parser"); ] in let action path = targets := path :: !targets in Arg.parse options action usage; let quit_with_usage () = Arg.usage options usage; exit 1 in let test_mode = match !only_old, !only_new with | false, false -> Compare_both | false, true -> Only (New, !niter) | true, false -> Only (Old, !niter) | true, true -> prerr_endline "--only-only and --new-only cannot be \ both set at the same time"; quit_with_usage (); in if !targets = [] then quit_with_usage (); test_mode, !targets in let traverse path = if Sys.file_exists path then explore test_mode path else Printf.eprintf "Error: path %s does not exist and was ignored.\n" path in List.iter traverse targets not-ocamlfind-0.14/local-packages/ocamlfind/src/findlib/topfind.in0000644000175000017500000001046114770304423024221 0ustar stephsteph(* $Id$ -*- tuareg -*- *) (* For Ocaml-3.03 and up, so you can do: #use "topfind" and get a * working findlib toploop. *) (* To access Toploop in OCaml >= 4.00. This directory will be later removed from path if possible *) #directory "+compiler-libs";; let exists path = match Sys.file_exists path with | true -> Some path | false -> None in let ( / ) = Filename.concat in let findlib_conf_of_path path = match exists (path / "etc" / "findlib.conf") with | Some etc_path -> etc_path | None -> path / "lib" / "findlib.conf" in let install_dir_from_opam_switch_prefix path = match Sys.file_exists (findlib_conf_of_path path) with | false -> None | true -> Some path in let install_dir_from_ocaml_toplevel_path path = let exe_dir = Filename.dirname path in let install_dir = Filename.dirname exe_dir in let config_path = findlib_conf_of_path install_dir in match Sys.file_exists config_path with | true -> Some install_dir | false -> None in let fl_split_path_separator = match Sys.os_type with | "Unix" | "BeOS" -> ':' | "Cygwin" -> ';' (* You might want to change this *) | "Win32" -> ';' | "MacOS" -> failwith "Findlib: I do not know what is the correct path separator for MacOS. If you can help me, write a mail to gerd@gerd-stolpmann.de" | _ -> failwith "Findlib: unknown operating system" in let string_split_on_char sep s = let r = ref [] in let j = ref (String.length s) in for i = String.length s - 1 downto 0 do if String.unsafe_get s i = sep then begin r := String.sub s (i + 1) (!j - i - 1) :: !r; j := i end done; String.sub s 0 !j :: !r in let rec list_find_map f = function | [] -> None | x :: l -> begin match f x with | Some _ as result -> result | None -> list_find_map f l end in let install_dir_from_ld_library_path paths = let v = string_split_on_char fl_split_path_separator paths in list_find_map (fun path -> let parent = Filename.dirname path in let parent' = Filename.dirname parent in match Sys.file_exists (findlib_conf_of_path parent') with | true -> Some parent' | false -> None) v in let getenv_opt v = try Some (Sys.getenv v) with Not_found -> None in let rec try_vars = function | [] -> None | (var, mapper)::xs -> ( match getenv_opt var with | None -> try_vars xs | Some content -> ( match mapper content with | None -> try_vars xs | Some _ as found -> found)) in let location = match try_vars [ ("OPAM_SWITCH_PREFIX", install_dir_from_opam_switch_prefix); ("CAML_LD_LIBRARY_PATH", install_dir_from_ld_library_path); ("OCAML_TOPLEVEL_PATH", install_dir_from_ocaml_toplevel_path); ] with | Some location -> location | None -> "@SITELIB@" in let findlib_directory = match @RELATIVE_PATHS@ with | true -> location / "lib" / "findlib" | false -> "@SITELIB@/findlib" in let () = Topdirs.dir_directory findlib_directory in (* OCaml-4.00 requires to use dir_directory before we load anything *) let exec_test s = let l = Lexing.from_string s in let ph = !Toploop.parse_toplevel_phrase l in let fmt = Format.make_formatter (fun _ _ _ -> ()) (fun _ -> ()) in try Toploop.execute_phrase false fmt ph with _ -> false in (* one of the few observable differences... *) let is_native = (Gc.get ()).Gc.stack_limit = 0 in let suffix = if is_native then "cmxs" else "cma" in (* First test whether findlib_top is already loaded. If not, load it now. * The test works by executing the toplevel phrase "Topfind.reset" and * checking whether this causes an error. *) if not (exec_test "Topfind.reset;;") then ( Topdirs.dir_load Format.err_formatter (findlib_directory / ("findlib." ^ suffix)); Topdirs.dir_load Format.err_formatter (findlib_directory / ("findlib_top." ^ suffix))) ;; (* phrase has to end here otherwise Topfind is not accessible *) (* REMOVE_DIRECTORY_BEGIN *) (* OCaml < 4.00 do not have this so only include this code if it was detected *) let () = Topdirs.dir_remove_directory "+compiler-libs" in (* REMOVE_DIRECTORY_END *) (* The following is always executed. It is harmless if findlib was already * initialized *) let is_native = (Gc.get ()).Gc.stack_limit = 0 in let pred = if is_native then "native" else "byte" in Topfind.add_predicates [ pred; "toploop" ]; Topfind.don't_load ["findlib"]; Topfind.announce ();; not-ocamlfind-0.14/local-packages/ocamlfind/src/findlib/topfind.ml.in0000644000175000017500000002250114770304423024626 0ustar stephsteph(* $Id$ * ---------------------------------------------------------------------- * *) let predicates = ref ("toploop" :: Findlib.recorded_predicates());; (* We also want things like "syntax" here which are not allowed in Findlib, hence we maintain our own list *) let ocaml_stdlib = lazy (Findlib.ocaml_stdlib ());; let directories = ref [ ] ;; (* Note: Sys.interactive is always _true_ during toploop startup. * When a script is executed, it is set to false just before the * script starts. This is important for ocamlmktop-generated toploops: * For initialization code linked into the toploop, Sys.interactive * is _true_. It is set to false just before the script starts. *) let real_toploop = !Sys.interactive;; let log = ref (if real_toploop then prerr_endline else ignore) let rec remove_dups l = match l with x :: l' -> if List.mem x l' then remove_dups l' else x::remove_dups l' | [] -> [] ;; let add_predicates pl = predicates := remove_dups (pl @ !predicates); Findlib.record_package_predicates !predicates;; let syntax s = add_predicates [ "syntax"; s ];; let standard_syntax () = syntax "camlp4o";; let revised_syntax () = syntax "camlp4r";; let add_dir d = let d = Fl_split.norm_dir d in let ocaml_stdlib = Lazy.force ocaml_stdlib in if d <> ocaml_stdlib && not (List.mem d !directories) then begin Topdirs.dir_directory d; directories := d :: !directories; !log (d ^ ": added to search path") end ;; let exec_string s = let l = Lexing.from_string s in let ph = !Toploop.parse_toplevel_phrase l in (* PPXOPT_BEGIN *) let ph = Toploop.preprocess_phrase Format.err_formatter ph in (* PPXOPT_END *) let fmt = Format.make_formatter (fun _ _ _ -> ()) (fun _ -> ()) in try Toploop.execute_phrase false fmt ph with _ -> false ;; let load pkglist = List.iter (fun pkg -> let _stdlibdir = Findlib.ocaml_stdlib() in let loaded = Findlib.is_recorded_package pkg && Findlib.type_of_recorded_package pkg = Findlib.Record_load in let incore = Findlib.is_recorded_package pkg && Findlib.type_of_recorded_package pkg = Findlib.Record_core in if not loaded then begin (* Determine the package directory: *) let d = Findlib.package_directory pkg in add_dir d; (* Leave pkg out if mentioned in !forbidden *) if not incore then begin (* Determine the 'archive' property: *) let archive = try Findlib.package_property !predicates pkg "archive" with Not_found -> "" in (* Split the 'archive' property and load the files: *) let archives = Fl_split.in_words archive in List.iter (fun arch -> let arch' = Findlib.resolve_path ~base:d arch in !log (arch' ^ ": loaded"); Topdirs.dir_load Format.std_formatter arch') archives; (* Determine the 'ppx' property: *) let ppx = try Some(Findlib.resolve_path ~base:d ~explicit:true (Findlib.package_property !predicates pkg "ppx") ) with Not_found -> None and ppxopts = try List.map (fun opt -> match Fl_split.in_words opt with | pkg :: opts -> pkg, List.map (Findlib.resolve_path ~base:d ~explicit:true) opts | _ -> assert false) (Fl_split.in_words_ws (Findlib.package_property !predicates pkg "ppxopt")) with Not_found -> [] in (* Feed the 'ppx' property into the toplevel. To remain compatible with pre-4.01 OCaml, construct and execute a phrase instead of directly altering Clflags. *) begin match ppx with | Some ppx -> begin try match Hashtbl.find Toploop.directive_table "ppx" with | Toploop.Directive_string fn -> fn ppx; !log (ppx ^ ": activated") | _ -> assert false with Not_found -> failwith "Package defines a ppx preprocessor, but OCaml is too old. \ Use OCaml >= 4.02.0 for ppx support." end | None -> () end; (* Feed the 'ppxopt' property into the toplevel. *) match ppxopts with | [] -> () | _ -> (* PPXOPT_BEGIN *) List.iter (fun (pkg, opts) -> ignore (exec_string ("[@@@findlib.ppxopt " ^ (String.concat ", " (List.map (Printf.sprintf "%S") (pkg :: opts))) ^ "];;")); !log (pkg ^ ": " ^ (String.concat " " opts) ^ ": option added")) ppxopts (* (* PPXOPT_END *) failwith "Package defines a ppx preprocessor option, but OCaml is too old. \ Use OCaml >=4.02.1 for ppxopt support." (* PPXOPT_BEGIN *) *) (* PPXOPT_END *) end; (* The package is loaded: *) Findlib.record_package Findlib.Record_load pkg end) pkglist ;; let load_deeply pkglist = (* Get the sorted list of ancestors *) let eff_pkglist = Findlib.package_deep_ancestors !predicates pkglist in List.iter (fun pkg -> try let error = Findlib.package_property !predicates pkg "error" in failwith ("Error from package `" ^ pkg ^ "': " ^ error) with Not_found -> ()) eff_pkglist ; (* Load the packages in turn: *) load eff_pkglist ;; let check_existence pkglist = List.iter (fun pkg -> let _ = Findlib.package_directory pkg in () ) pkglist ;; let don't_load pkglist = check_existence pkglist; List.iter (Findlib.record_package Findlib.Record_core) pkglist ;; let don't_load_deeply pkglist = (* Check if packages exist: *) check_existence pkglist; (* Get the sorted list of ancestors *) let eff_pkglist = Findlib.package_deep_ancestors !predicates pkglist in (* Add this to the list of core packages: *) List.iter (Findlib.record_package Findlib.Record_core) eff_pkglist ;; let reset() = Findlib.reset_recordings() ;; let have_mt_support() = Findlib.package_property [] "threads" "type_of_threads" = "posix" ;; let load_mt_support() = (* Load only if package "threads" is not yet loaded. *) if not(Findlib.is_recorded_package "threads") then ( (* This works only for POSIX threads. *) if have_mt_support() then ( add_predicates ["mt"; "mt_posix"]; add_dir (Filename.concat (Findlib.ocaml_stdlib()) "threads"); load_deeply ["unix"]; load_deeply ["threads"]; ) else ( failwith "It is not possible to load support for vmthreads dynamically. Use\n 'ocamlfind ocamlmktop -o vmtop -package threads,findlib -linkpkg -vmthread'\n to create a toploop with integrated vmthreads library." ) ) ;; let list_packages() = Findlib.list_packages stdout; flush stdout ;; let protect f arg = try let _ = f arg in () with Failure s -> print_endline s | Fl_package_base.No_such_package(pkg, reason) -> print_endline ("No such package: " ^ pkg ^ (if reason <> "" then " - " ^ reason else "")) | Fl_package_base.Package_loop pkg -> print_endline ("Package requires itself: " ^ pkg) ;; (* Add "#require" directive: *) Hashtbl.add Toploop.directive_table "require" (Toploop.Directive_string (fun s -> protect load_deeply (Fl_split.in_words s) )) ;; (* Add "#predicates" directive: *) Hashtbl.add Toploop.directive_table "predicates" (Toploop.Directive_string (fun s -> protect add_predicates (Fl_split.in_words s) )) ;; (* Add "#camlp4o" directive: *) Hashtbl.add Toploop.directive_table "camlp4o" (Toploop.Directive_none (fun () -> protect (fun () -> standard_syntax(); load_deeply ["camlp4"]) () )) ;; (* Add "#camlp4r" directive: *) Hashtbl.add Toploop.directive_table "camlp4r" (Toploop.Directive_none (fun () -> protect (fun () -> revised_syntax(); load_deeply ["camlp4"]) () )) ;; (* Add "#list" directive: *) Hashtbl.add Toploop.directive_table "list" (Toploop.Directive_none (fun () -> protect list_packages () )) ;; (* Add "#thread" directive: *) Hashtbl.add Toploop.directive_table "thread" (Toploop.Directive_none (fun () -> protect load_mt_support () )) ;; let announce() = if real_toploop then begin (* Assume we are in a toploop and not a script *) let msg_thread = " #thread;; to enable threads\n" in print_endline ("Findlib has been successfully loaded. Additional directives:\n" ^ " #require \"package\";; to load a package\n" ^ " #list;; to list the available packages\n" ^ " #camlp4o;; to load camlp4 (standard syntax)\n" ^ " #camlp4r;; to load camlp4 (revised syntax)\n" ^ " #predicates \"p,q,...\";; to set these predicates\n" ^ " Topfind.reset();; to force that packages will be reloaded\n" ^ (if have_mt_support() then msg_thread else "")) end ;; not-ocamlfind-0.14/local-packages/ocamlfind/src/findlib/topfind.mli0000644000175000017500000001001314770304423024365 0ustar stephsteph(* $Id$ * ---------------------------------------------------------------------- * *) (** Load packages from toploops and scripts * * The [Topfind] module is part of the [findlib] package. The module * depends on the presence of a toploop. When building a toploop, it is * automatically linked in if "findlib" is linked in, e.g. * {[ * ocamlfind ocamlmktop ...options... -package findlib -linkpkg * ]} * * When the platform supports DLLs, another possibility to get a toploop * with findlib directives is to load the file "topfind" (normally installed * in the standard library directory): * {[ * $ ocaml * Objective Caml version 3.04 * # #use "topfind";; * 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) * Topfind.reset();; to force that packages will be reloaded * ~ : unit = () * # _ * ]} * * This works even in scripts (but the startup message is suppressed in this * case). * * The module is not thread-safe; if used in a multi-threaded script, all * packgage loading must have happened before the first thread forks. * * The Topfind module contains some functions simplifying package loading * in scripts. Most important, there is a new directive [#require] for * the same purpose (see below). * * The [Topfind] module needs some initialization, in particular the * [predicates] variable needs to be * set, and the packages already compiled into the toploop needs to be * declared by the [don't_load] * function. If the toploop has been built by [ocamlfind], * the necessary initialization is * automatically compiled in. *) (** {1 Directives} * * This module also defines the following directives for the toploop: * * - [#require ""] * loads the package (and if necessary the prerequisites of the package) * - [#camlp4o] * loads camlp4 and selects standard syntax * - [#camlp4r] * loads camlp4 and selects revised syntax * - [#list] * lists the available packages (calls external command "ocamlfind") * - [#thread] * enables multi-threading if possible * - [#predicates "p1,p2,..."] * adds these predicates *) (** {1 Functions and variables} *) val predicates : string list ref (** The list of predicates used for package loading *) val add_predicates : string list -> unit (** Adds predicates to the list of predicates *) val syntax : string -> unit (** Emulates the [-syntax] option *) val standard_syntax : unit -> unit (** Adds predicates that select the standard syntax. Same as * [syntax "camlp4o"] *) val revised_syntax : unit -> unit (** Adds predicates that select the revised syntax. Same as * [syntax "camlp4r"] *) val don't_load : string list -> unit (** The packages named in pkglist are added to the list of packages which * are already loaded. *) val don't_load_deeply : string list -> unit (** The packages named in pkglist and all direct and indirect ancestors * are added to the list of packages which are already loaded. *) val load : string list -> unit (** The packages from the passed package list are loaded, from left to * right, but packages that have already been loaded are left out. *) val load_deeply : string list -> unit (** The packages from the passed package list and all direct or indirect * ancestors are loaded in topological order. Packages that have already * been loaded are left out. *) val reset : unit -> unit (** All entries in the list of loaded packages that have been added by * [load] or [load_deeply] functions are removed from this list. This * means that if you execute the same [load] or [load_deeply] functions * again, the packages will be reloaded. *) val announce : unit -> unit (** Output the startup message *) val log : (string -> unit) ref (** Function used to log messages from this module. *) not-ocamlfind-0.14/local-packages/ocamlfind/tools/0002755000175000017500000000000014770304423021170 5ustar stephstephnot-ocamlfind-0.14/local-packages/ocamlfind/tools/cmd_from_same_dir0000755000175000017500000000110414770304423024541 0ustar stephsteph#! /bin/sh # Check whether ocamlc and ocamlc.opt are installed in the same # directory (or whatever command names are passed as $1). get_path () { IFS=":" for d in $PATH; do if test -x "$d/$1"; then IFS="$oldifs" echo "$d/$1" return fi done IFS="$oldifs" #--- The following is not portable enough: # if test -x `type -p ls`; then # # type -p works! # type -p $1 # else # # use 'which' instead # p=`which $1` # test -x "$p" && echo $p # fi } p1="$(get_path "$1").opt" p2="$(get_path "$1.opt")" [ "X$p1" = "X$p2" ] not-ocamlfind-0.14/local-packages/ocamlfind/tools/collect_files0000755000175000017500000000044714770304423023730 0ustar stephsteph#! /bin/sh # # $Id$ # ---------------------------------------------------------------------- # # usage: collect_files file ... # # Prints the names of the files passed as arguments which actually # exist and are regular files. for x in "$@"; do if [ -f "$x" ]; then echo "$x" fi done not-ocamlfind-0.14/local-packages/ocamlfind/tools/extract_args/0002755000175000017500000000000014770304423023656 5ustar stephstephnot-ocamlfind-0.14/local-packages/ocamlfind/tools/extract_args/Makefile0000644000175000017500000000035014770304423025312 0ustar stephstephall: extract_args extract_args.ml: extract_args.mll ocamllex -o extract_args.ml extract_args.mll extract_args: extract_args.ml ocamlc -o extract_args extract_args.ml clean: rm -f *.cmo *.cmi *.cma extract_args extract_args.ml not-ocamlfind-0.14/local-packages/ocamlfind/tools/extract_args/extract_args.mll0000644000175000017500000000632014770304423027051 0ustar stephsteph(* $Id$ *) (* Runs ocamlc -help and extract the command-line signature *) { open Printf } let whitespace = [ ' ' '\t' ] rule get_switch = parse | whitespace* ('-' [ '-' 'a'-'z' 'A'-'Z' '0'-'9' '_' ',' ]+ as switch_name) whitespace? (_* as help_text) eof {Some (switch_name, help_text)} | whitespace* '-' whitespace+ (_* as help_text) eof {Some ("-", help_text)} | _? {None} and has_argument = parse | whitespace* [ '<' '[' '{' ] {true} | _? {false} { let read_lines file = let f = open_in file in let lines = ref [] in try while true do lines := input_line f :: !lines done; assert false with | End_of_file -> close_in f; List.rev !lines | error -> close_in f; raise error ;; let get_help cmd = let temp_file = Filename.temp_file "findlib" ".txt" in let help_out = try let code = Sys.command (sprintf "%s -help >%s 2>&1" cmd (Filename.quote temp_file)) in if code <> 0 then raise Not_found; (* Assume command does not exist! *) let lines = read_lines temp_file in Sys.remove temp_file; lines with error -> Sys.remove temp_file; raise error in help_out ;; let get_switch s = get_switch (Lexing.from_string s) let has_argument s = has_argument (Lexing.from_string s) let rec extract_signature lines = match lines with | [] -> [] | line :: lines' -> match get_switch line with | Some (switch_name, help_text) -> let has_arg = has_argument help_text in let help_lines, lines'' = extract_help_continuation lines' in let help_text' = String.concat "\n" (help_text :: help_lines) in let r = (switch_name, has_arg, help_text') in r :: extract_signature lines'' | None -> extract_signature lines' and extract_help_continuation lines = match lines with | [] -> ( [], [] ) | line :: lines' -> if get_switch line <> None then ( [], lines ) else let help_lines, lines'' = extract_help_continuation lines' in (line :: help_lines, lines'') ;; let rm_help_switch switches = List.filter (fun (name, _, _) -> name <> "-help" && name <> "--help") switches ;; let output_some_signature f name switches = fprintf f "let %s_spec = Some [\n" name; List.iter (fun (switch_name, has_arg, help_text) -> fprintf f " \"%s\",\n" (String.escaped switch_name); fprintf f " %b,\n" has_arg; fprintf f " \"%s\";\n\n" (String.escaped help_text) ) switches; fprintf f "];;\n\n" ;; let output_none f name = fprintf f "let %s_spec = None;;\n\n" name ;; let main() = let f = ref stdout in let progs = ref [] in Arg.parse [ "-o", Arg.String (fun s -> f := open_out s), " Save generated module to this file"; ] (fun arg -> progs := arg :: !progs) "usage: extract_args ..."; progs := List.rev !progs; List.iter (fun prog -> try let help_lines = get_help prog in (* or Not_found *) let switches = rm_help_switch (extract_signature help_lines) in output_some_signature !f prog switches with Not_found -> output_none !f prog ) !progs; close_out !f ;; main();; } not-ocamlfind-0.14/local-packages/ocamlfind/tools/file_exists0000755000175000017500000000010414770304423023425 0ustar stephsteph#! /bin/sh # Approximation of: test -e $1 test -d "$1" -o -f "$1" not-ocamlfind-0.14/local-packages/ocamlfind/tools/patch0000755000175000017500000000154014770304423022213 0ustar stephsteph#! /bin/sh # Usage: patch @VARIABLE@ value [extra-args-for-cygpath] # Environment variable USE_CYGPATH is honoured. varname="$1" varvalue="$2" if [ "${USE_CYGPATH}" = "1" ]; then #varvalue="$(echo "$varvalue" | sed -e 's;/;\\;g')" varvalue="$(cygpath -w -l $3 "$varvalue")" varvalue="$(echo "$varvalue" | sed -e 's;\\;\\\\\\\\;g;s/;/\\;/g')" # e.g. c:\file is transformed to c:\\\\file else case `uname` in MINGW*) varvalue="$(echo "$varvalue" | sed -e 's;\\;\\\\\\\\;g')" # Convert the first letter drive to DOS style (naive). # This is necessary because OCaml uses DOS paths even if # run under MSYS. varvalue="$(echo "$varvalue" | sed -e 's;^/\([a-z]\)/;\1:/;g')" ;; esac fi sed -e 's;'"$varname"';'"$varvalue"';g' # e.g. c:\\\\file is parsed by sed as c:\\file which is correct for the # ocaml string not-ocamlfind-0.14/local-packages/ocamlfind/tools/safe_camlp40000755000175000017500000000201714770304423023272 0ustar stephsteph#! /bin/sh # Call camlp4 with fallback method if dynamic loading is not supported dl_string="dynamic loading not supported on this platform" fn_string="The external function .* is not available" tmp_stderr="tmp.safe_camlp4_stderr.$$" tmp_camlp4="tmp.safe_camlp4_camlp4.$$" trap "rm -f $tmp_stderr $tmp_camlp4" 0 print_stderr=1 code=0 camlp4 "$@" 2>$tmp_stderr || { code=$? grep "$dl_string" $tmp_stderr >/dev/null 2>&1; t1=$? grep "$fn_string" $tmp_stderr >/dev/null 2>&1; t2=$? if [ $t1 -eq 0 -o $t2 -eq 0 ]; then # Fallback: print_stderr=0 cp4_mods="" cp4_args="" i=0 for arg in "$@"; do if [ $i -gt 0 ]; then cp4_mods="$cp4_mods -I $arg" cp4_args="$cp4_args -I $arg" i=0 else case "$arg" in *.cma|*.cmo) cp4_mods="$cp4_mods $arg" ;; -I) i=1 ;; *) cp4_args="$cp4_args $arg" ;; esac fi done mkcamlp4 -o $tmp_camlp4 $cp4_mods || exit ./$tmp_camlp4 $cp4_args || exit code=0 fi } if [ $print_stderr -gt 0 ]; then cat $tmp_stderr >&2 fi exit $code not-ocamlfind-0.14/main.ml0000644000175000017500000000044314770304423014503 0ustar stephsteph try Sys.catch_break true; Frontend.main() with any -> prerr_endline ("Uncaught exception: " ^ Printexc.to_string any); let raise_again = try ignore(Sys.getenv "OCAMLFIND_DEBUG"); true with Not_found -> false in if raise_again then raise any; exit 3 ;; not-ocamlfind-0.14/opam0000644000175000017500000000201314770304423014077 0ustar stephstephversion: "0.14" opam-version: "2.0" synopsis: "A small frontend for ocamlfind that adds a few useful commands" license: "MIT" x-maintenance-intent: [ "(latest)" ] maintainer: "Chet Murthy " (* Gerd wrote most of this code; I just modified it (and probably introduced bugs. This is to silence opam *) authors: "Chet Murthy " homepage: "https://github.com/chetmurthy/not-ocamlfind" bug-reports: "Chet Murthy " depends: [ "ocamlfind" {>= "1.8.0"} "camlp-streams" "conf-m4" {build} "fmt" {>= "0.8.8"} "rresult" {>= "0.6.0"} "ocamlgraph" {>= "2.0.0"} "conf-which" ] depexts: [ [ "xdot" ] {os-family = "debian"} ] build: [ ["./configure" "-bindir" bin "-sitelib" lib "-mandir" man "-config" "%{lib}%/findlib.conf" "-no-custom" "-no-topfind" {preinstalled}] [make "all"] ] install: [make "install"] conflicts: [ "frama-clang" { = "0.0.14" } ] dev-repo: "git+https://github.com/chetmurthy/not-ocamlfind" url { src: "" checksum: [ "sha512=" ] } not-ocamlfind-0.14/papr_official.ml0000644000175000017500000000670014770304423016357 0ustar stephsteph let rec sep_last = function [] -> failwith "sep_last" | [hd] -> hd, [] | hd :: tl -> let (l, tl) = sep_last tl in l, hd :: tl let input_magic ic magic = let maglen = String.length magic in let b = Bytes.create maglen in really_input ic b 0 maglen; Bytes.to_string b let input_implem ic = if Config.ast_impl_magic_number <> input_magic ic Config.ast_impl_magic_number then failwith "input_implem: bad magic number" else let _ = input_value ic in (input_value ic : Parsetree.structure) let input_interf ic = if Config.ast_intf_magic_number <> input_magic ic Config.ast_intf_magic_number then failwith "input_interf: bad magic number" else let _ = input_value ic in (input_value ic : Parsetree.signature) let output_magic oc magic = output_string oc magic let output_interf fname oc (pt : Parsetree.signature) = output_string oc Config.ast_intf_magic_number; output_value oc fname; output_value oc pt; flush oc let output_implem fname oc (pt : Parsetree.structure) = output_string oc Config.ast_impl_magic_number; output_value oc fname; output_value oc pt; flush oc let parse_interf fname ic = let lb = Lexing.from_channel ic in Location.init lb fname; Parse.interface lb let parse_implem fname ic = let lb = Lexing.from_channel ic in Location.init lb fname; Parse.implementation lb let print_interf oc v = let ofmt = Format.formatter_of_out_channel oc in Pprintast.signature ofmt v; Format.pp_print_flush ofmt () let print_implem oc v = let ofmt = Format.formatter_of_out_channel oc in Pprintast.structure ofmt v; Format.pp_print_flush ofmt () let binary_input = ref false let binary_output = ref false let files = ref [] let filetype = ref None let set_impl s = filetype := Some "-impl" let set_intf s = filetype := Some "-intf" let passthru paf prf ic oc = (ic |> paf) |> prf oc let papr_official () = Arg. (parse ["-binary-input", Set binary_input, " binary input"; "-binary-output", Set binary_output, " binary output"; "-impl", Unit set_impl, " implementation"; "-intf", Unit set_intf, " interface"] (fun s -> files := s :: !files) "papr_official: usage"); let open_or opener ifminus = function "-" -> ifminus, "" | f -> opener f, f in let ((ic, ifile), (oc, _)) = match List.rev !files with [] -> (stdin, ""), (stdout, "") | [ifile] -> open_or open_in stdin ifile, (stdout, "") | [ifile; ofile] -> open_or open_in stdin ifile, open_or open_out stdout ofile | _ -> failwith "too many filenames provided" in begin match !filetype, !binary_input, !binary_output with Some "-impl", true, true -> failwith "cannot have both binary input and output" | Some "-impl", true, false -> passthru input_implem print_implem ic oc | Some "-impl", false, true -> passthru (parse_implem ifile) (output_implem ifile) ic oc | Some "-impl", false, false -> passthru (parse_implem ifile) print_implem ic oc | Some "-intf", true, true -> failwith "cannot have both binary input and output" | Some "-intf", true, false -> passthru input_interf print_interf ic oc | Some "-intf", false, true -> passthru (parse_interf ifile) (output_interf ifile) ic oc | Some "-intf", false, false -> passthru (parse_interf ifile) print_interf ic oc | _ -> failwith "unrecognized filetype" end; close_out oc; close_in ic let _ = papr_official () (* ;;; Local Variables: *** ;;; mode:tuareg *** ;;; End: *** *)