File: utils.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 (154 lines) | stat: -rw-r--r-- 4,647 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
153
154
open Fugue
open Filepath
open Types

let read_file_with f filename =
  let lines = ref [] in
  let chan = open_in filename in
  try
    while true do
      let z = f (input_line chan) in
      match z with
      | None -> ()
      | Some z' -> lines := z' :: !lines
    done;
    []
  with End_of_file ->
    close_in chan;
    List.rev !lines

let toKV line =
  match String_utils.split ~limit:2 ':' line with
  | [ k ] -> (String_utils.strip_spaces k, None)
  | [ k; v ] -> (String_utils.strip_spaces k, Some (String_utils.strip_spaces v))
  | _ -> assert false

let toKVeq line =
  match String_utils.split ~limit:2 '=' line with
  | [ k ] -> (String_utils.strip_spaces k, None)
  | [ k; v ] -> (String_utils.strip_spaces k, Some (String_utils.strip_spaces v))
  | _ -> assert false

let parseCSV value =
  List.filter
    (fun s -> String.length s > 0)
    (List.map String_utils.strip_spaces (String_utils.split ',' value))

let to_include_path_options paths =
  let ss = ref StringSet.empty in
  List.concat
  $ list_filter_map
      (fun p ->
        let ps = fp_to_string p in
        if ps = "" || StringSet.mem ps !ss || not (Filesystem.exists p) then
          None
        else (
          ss := StringSet.add ps !ss;
          Some [ "-I"; ps ]))
      paths

let showList sep f l = String.concat sep (List.map f l)
let isWindows = Sys.os_type = "Win32"

(* Platform-aware C library naming.
   OCaml's convention uses dll*.so even on macOS for stub libraries. *)
let shared_lib_name clib_name =
  if isWindows then clib_name ^ ".dll"
  else "dll" ^ clib_name ^ ".so"

let static_lib_name clib_name =
  if isWindows then clib_name ^ ".lib"
  else "lib" ^ clib_name ^ ".a"

let to_exe_name mode build name =
  let ext = extDP mode in
  let ext2 =
    match build with
    | ByteCode -> ".byte"
    | Native -> if Gconf.get_target_option_typed Gconf.Executable_as_obj then ".o" else ""
  in
  fn (name ^ ext ^ ext2 ^ if isWindows then ".exe" else "")

exception FileNotFoundInPaths of (filepath list * filename)
exception FilesNotFoundInPaths of (filepath list * filepath list)

let get_system_paths () =
  let sep = if isWindows then ';' else ':' in
  try List.map fp (String_utils.split sep (Sys.getenv "PATH"))
  with Not_found ->
    if isWindows then
      let sysroot =
        try Sys.getenv "SystemRoot"
        with Not_found -> "C:\\Windows"
      in
      List.map fp [ sysroot ^ "\\System32" ]
    else
      List.map fp [ "/usr/bin"; "/usr/local/bin" ]

let find_in_paths paths name =
  try List.find (fun p -> Filesystem.exists (p </> name)) paths
  with Not_found -> raise (FileNotFoundInPaths (paths, name))

let find_choice_in_paths paths names =
  try
    List.find
      (fun p ->
        try
          ignore (List.find (fun n -> Filesystem.exists (n p)) names);
          true
        with Not_found -> false)
      paths
  with Not_found ->
    let sample_path = match paths with p :: _ -> p | [] -> fp "." in
    raise (FilesNotFoundInPaths (paths, List.map (fun n -> n sample_path) names))

let exist_choice_in_paths paths names =
  try
    let _ = find_choice_in_paths paths names in
    true
  with FilesNotFoundInPaths _ -> false

let find_in_system_path name = find_in_paths (get_system_paths ()) name

let generateFile file f =
  let buffer = Buffer.create 1024 in
  f (Buffer.add_string buffer);
  Filesystem.write_file file (Buffer.contents buffer)

let get_cpu_count () =
  let read_command cmd =
    try
      let ic = Unix.open_process_in cmd in
      let line = input_line ic in
      let status = Unix.close_process_in ic in
      match status with
      | Unix.WEXITED 0 -> Some (int_of_string (String_utils.strip_spaces line))
      | _ -> None
    with _ -> None
  in

  let detected =
    match Sys.os_type with
    | "Unix" | "Cygwin" -> (
        (* Try different commands in order of preference *)
        match read_command "nproc 2>/dev/null" with
        (* Linux *)
        | Some n -> Some n
        | None -> (
            match read_command "sysctl -n hw.ncpu 2>/dev/null" with
            (* macOS, BSD *)
            | Some n -> Some n
            | None -> (
                match read_command "getconf _NPROCESSORS_ONLN 2>/dev/null" with
                (* POSIX *)
                | Some n -> Some n
                | None -> None)))
    | "Win32" -> (
        (* Windows: use NUMBER_OF_PROCESSORS environment variable *)
        try Some (int_of_string (Sys.getenv "NUMBER_OF_PROCESSORS")) with _ -> None)
    | _ -> None (* Unknown OS *)
  in

  match detected with
  | Some n when n > 0 && n <= 128 -> n (* Sanity check: reasonable CPU count *)
  | _ -> 2 (* Default fallback *)