File: install.ml

package info (click to toggle)
ocaml-obuild 0.2.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,456 kB
  • sloc: ml: 14,491; sh: 211; ansic: 34; makefile: 11
file content (152 lines) | stat: -rw-r--r-- 5,375 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
open Fugue
open Filepath
open Printf
open Project
open Types
open Target
open Helper
open Gconf

let list_target_files_pred target pred =
  let build_dir = Dist.get_build_exn (Dist.Target target.Target.target_name) in
  Build.sanity_check build_dir target;
  (* don't play with matches *)
  let matches = Filesystem.list_dir_pred pred build_dir in
  (build_dir, matches)

let list_lib_files lib build_dir =
  list_target_files_pred lib (fun f ->
      if fn_to_string f = "META" then
        true
      else
        match Filetype.of_filepath (build_dir </> f) with
        | Filetype.FileCMX
        | Filetype.FileCMI
        | Filetype.FileA
        | Filetype.FileCMXS
        | Filetype.FileCMXA
        | Filetype.FileCMA
        | Filetype.FileCMT
        | Filetype.FileCMTI -> true
        | _ -> false)

let list_exe_files lib build_dir =
  list_target_files_pred lib (fun f ->
      match Filetype.of_filepath (build_dir </> f) with
      | Filetype.FileEXE -> true
      | _ -> false)

let opam_install_file proj_file flags =
  let install_path = fp (proj_file.name ^ ".install") in
  Utils.generateFile install_path (fun add ->
      let all_targets = Project.get_all_installable_targets proj_file flags in
      let print_target_files target list_files_fun =
        let build_dir = Dist.get_build_exn (Dist.Target target.Target.target_name) in
        let _, files = list_files_fun target build_dir in
        List.iter
          (fun file ->
            let file_str = fn_to_string file in
            add (sprintf "  \"%s/%s\" {\"%s\"}\n" (fp_to_string build_dir) file_str file_str))
          files
      in
      add (sprintf "%s: [\n" "lib");
      List.iter
        (fun target ->
          match target.target_name with
          | Name.Lib _ -> print_target_files target list_lib_files
          | _ -> ())
        all_targets;
      add "]\n";
      add (sprintf "%s: [\n" "bin");
      List.iter
        (fun target ->
          match target.target_name with
          | Name.Exe _ -> print_target_files target list_exe_files
          | _ -> ())
        all_targets;
      add "]\n")

let lib_to_meta proj_file lib =
  let requires_of_lib lib =
    let deps = lib.Library.target.target_obits.target_builddeps in
    [ ([], List.map (fun d -> fst d) deps) ]
  in
  let set_meta_field_from_lib pkg lib =
    let linkopts_of_lib lib =
      match lib.Library.target.Target.target_cstubs with
      | Some _ ->
          (* The installed stubs library is named libstubs_<library_name>.a *)
          (* Use -cclib to wrap C linker flags for ocamlfind/ocamlopt compatibility *)
          let lib_name = Libname.to_string lib.Library.name in
          [(None, "-cclib -lstubs_" ^ lib_name)]
      | None -> []
    in
    {
      pkg with
      Meta.Pkg.requires = requires_of_lib lib;
      Meta.Pkg.description =
        (if lib.Library.description <> "" then lib.Library.description else proj_file.description);
      Meta.Pkg.linkopts = linkopts_of_lib lib;
      Meta.Pkg.archives =
        ([
           ([ Meta.Predicate.Byte ], fn_to_string (Libname.to_cmca ByteCode Normal lib.Library.name));
           ( [ Meta.Predicate.Byte; Meta.Predicate.Plugin ],
             fn_to_string (Libname.to_cmca ByteCode Normal lib.Library.name) );
           ([ Meta.Predicate.Native ], fn_to_string (Libname.to_cmca Native Normal lib.Library.name));
         ]
        @
        if Gconf.get_target_option_typed Gconf.Library_plugin then
          [
            ( [ Meta.Predicate.Native; Meta.Predicate.Plugin ],
              fn_to_string (Libname.to_cmxs Normal lib.Library.name) );
          ]
        else
          []);
    }
  in
  let subPkgs =
    List.map
      (fun sub ->
        let npkg = Meta.Pkg.make (list_last (Libname.to_string_nodes sub.Library.name)) in
        set_meta_field_from_lib npkg sub)
      lib.Library.subs
  in
  let pkg = set_meta_field_from_lib (Meta.Pkg.make "") lib in
  { pkg with Meta.Pkg.version = proj_file.version; Meta.Pkg.subs = subPkgs }

let write_lib_meta projFile lib =
  let dir = Dist.get_build_exn (Dist.Target lib.Library.target.target_name) in
  let metadir_path = dir </> fn "META" in
  let pkg = lib_to_meta projFile lib in
  Meta.Pkg.write metadir_path pkg

let copy_files files dest_dir dir_name =
  List.iter
    (fun (build_dir, build_files) ->
      List.iter
        (fun build_file ->
          Filesystem.copy_file (build_dir </> build_file) (dest_dir </> dir_name </> build_file))
        build_files)
    files

let install_lib proj_file lib dest_dir =
  write_lib_meta proj_file lib;
  let all_files =
    List.map
      (fun target ->
        let build_dir = Dist.get_build_exn (Dist.Target target.Target.target_name) in
        Build.sanity_check build_dir target;
        list_lib_files target build_dir)
      (Project.Library.to_targets lib)
  in
  let dir_name = fn (Libname.to_string lib.Project.Library.name) in
  log Report "installing library %s\n" (Libname.to_string lib.Project.Library.name);
  log Debug "installing files: %s\n"
    (Utils.showList "," fn_to_string (List.concat (List.map snd all_files)));
  copy_files all_files dest_dir dir_name

let install_libs proj_file destdir opam =
  if not opam then
    List.iter (fun lib -> install_lib proj_file lib destdir) proj_file.Project.libs
  else
    List.iter (fun lib -> write_lib_meta proj_file lib) proj_file.Project.libs