C build tool of the 21st century
1let parse_line line : string list =
2 let line = String.trim line in
3 let buf = Buffer.create 32 in
4 let in_quote = ref false in
5 let in_dquote = ref false in
6 let next acc =
7 in_quote := false;
8 in_dquote := false;
9 if Buffer.length buf = 0 then acc
10 else
11 let s = Buffer.contents buf in
12 let () = Buffer.clear buf in
13 s :: acc
14 in
15 let x =
16 String.fold_left
17 (fun acc -> function
18 | (' ' | '\t') when not (!in_quote && !in_dquote) -> next acc
19 | '"' when !in_dquote && not !in_quote -> next acc
20 | '\'' when !in_quote && not !in_dquote -> next acc
21 | '\'' when not !in_dquote ->
22 in_quote := true;
23 acc
24 | '"' when not !in_dquote ->
25 in_dquote := true;
26 acc
27 | c ->
28 Buffer.add_char buf c;
29 acc)
30 [] line
31 in
32 List.rev @@ next x
33
34let cflags ~env names =
35 if List.is_empty names then []
36 else
37 try
38 Eio.Process.parse_out env#process_mgr Eio.Buf_read.line
39 ([ "pkg-config"; "--cflags" ] @ names)
40 |> parse_line
41 with _ ->
42 Fmt.failwith "unable to find pkg-config package %a"
43 (Fmt.list ~sep:(Fmt.const Fmt.string ", ") Fmt.string)
44 names
45
46let ldflags ~env names =
47 if List.is_empty names then []
48 else
49 try
50 Eio.Process.parse_out env#process_mgr Eio.Buf_read.line
51 ([ "pkg-config"; "--libs" ] @ names)
52 |> parse_line
53 with _ ->
54 Fmt.failwith "unable to find pkg-config package %a"
55 (Fmt.list ~sep:(Fmt.const Fmt.string ", ") Fmt.string)
56 names
57
58let flags ~env names =
59 let compile = cflags ~env names in
60 let link = ldflags ~env names in
61 Flags.v ~compile ~link ()
62
63let generate ?(prefix = "/usr/local") ?(version = "0.0.0")
64 ?(include_dir = "include") ?(lib_dir = "lib") ?(requires = []) ~lib_name
65 name ~cflags ~ldflags =
66 Fmt.str
67 "prefix=%s\n\
68 includedir=${prefix}/%s/%s\n\
69 libdir=${prefix}/%s\n\n\
70 Name: %s\n\
71 Description: %s\n\
72 Version: %s\n\
73 Cflags: -I${includedir} %a\n\
74 Libs: -L${libdir} -l%s %a\n\
75 Requires: %a\n"
76 prefix include_dir lib_name lib_dir name name version
77 (Fmt.list ~sep:(Fmt.const Fmt.string " ") Fmt.string)
78 cflags lib_name
79 (Fmt.list ~sep:(Fmt.const Fmt.string " ") Fmt.string)
80 ldflags
81 (Fmt.list ~sep:(Fmt.const Fmt.string " ") Fmt.string)
82 requires