2016-11-13 12:25:45 +00:00
|
|
|
open Import
|
2016-12-02 13:54:32 +00:00
|
|
|
open Future
|
|
|
|
|
2017-02-20 15:51:03 +00:00
|
|
|
let internal = function
|
2016-11-13 12:25:45 +00:00
|
|
|
| [_; "findlib-packages"] ->
|
2016-12-02 13:54:32 +00:00
|
|
|
Future.Scheduler.go
|
|
|
|
(Lazy.force Context.default >>= fun ctx ->
|
|
|
|
let findlib = Findlib.create ctx in
|
|
|
|
let pkgs = Findlib.all_packages findlib in
|
|
|
|
let max_len =
|
|
|
|
List.map pkgs ~f:String.length
|
|
|
|
|> List.fold_left ~init:0 ~f:max
|
|
|
|
in
|
|
|
|
List.iter pkgs ~f:(fun pkg ->
|
|
|
|
let ver =
|
2016-12-15 13:00:30 +00:00
|
|
|
match (Findlib.find_exn findlib pkg).version with
|
2016-12-02 13:54:32 +00:00
|
|
|
| "" -> "n/a"
|
|
|
|
| v -> v
|
|
|
|
in
|
|
|
|
Printf.printf "%-*s (version: %s)\n" max_len pkg ver);
|
|
|
|
return ())
|
2016-11-13 12:25:45 +00:00
|
|
|
| _ ->
|
|
|
|
()
|
|
|
|
|
2016-12-15 13:00:30 +00:00
|
|
|
let setup ?filter_out_optional_stanzas_with_missing_deps () =
|
2016-12-31 15:12:39 +00:00
|
|
|
let { Jbuild_load. file_tree; tree; stanzas; packages } = Jbuild_load.load () in
|
2016-12-02 13:54:32 +00:00
|
|
|
Lazy.force Context.default >>= fun ctx ->
|
2016-12-15 13:00:30 +00:00
|
|
|
let rules =
|
2016-12-31 15:12:39 +00:00
|
|
|
Gen_rules.gen ~context:ctx ~file_tree ~tree ~stanzas ~packages
|
2016-12-15 13:00:30 +00:00
|
|
|
?filter_out_optional_stanzas_with_missing_deps ()
|
|
|
|
in
|
2016-12-31 15:12:39 +00:00
|
|
|
let bs = Build_system.create ~file_tree ~rules in
|
2016-12-15 11:20:46 +00:00
|
|
|
return (bs, stanzas, ctx)
|
2016-12-02 13:54:32 +00:00
|
|
|
|
|
|
|
let external_lib_deps ~packages =
|
|
|
|
Future.Scheduler.go
|
2016-12-15 13:00:30 +00:00
|
|
|
(setup () ~filter_out_optional_stanzas_with_missing_deps:false
|
|
|
|
>>| fun (bs, stanzas, _) ->
|
2016-12-15 11:20:46 +00:00
|
|
|
Path.Map.map
|
|
|
|
(Build_system.all_lib_deps bs
|
|
|
|
(List.map packages ~f:(fun pkg ->
|
|
|
|
Path.(relative root) (pkg ^ ".install"))))
|
2016-12-15 13:00:30 +00:00
|
|
|
~f:(fun deps ->
|
|
|
|
let internals = Jbuild_types.Stanza.lib_names stanzas in
|
|
|
|
String_map.filter deps ~f:(fun name _ -> not (String_set.mem name internals))))
|
2016-12-02 13:54:32 +00:00
|
|
|
|
2017-02-20 15:51:03 +00:00
|
|
|
let external_lib_deps_cmd packages =
|
2016-12-15 11:20:46 +00:00
|
|
|
let deps =
|
2016-12-15 13:00:30 +00:00
|
|
|
Path.Map.fold (external_lib_deps ~packages) ~init:String_map.empty
|
|
|
|
~f:(fun ~key:_ ~data:deps acc -> Build.merge_lib_deps deps acc)
|
2016-12-15 11:20:46 +00:00
|
|
|
in
|
2016-12-15 13:00:30 +00:00
|
|
|
String_map.iter deps ~f:(fun ~key:n ~data ->
|
|
|
|
match (data : Build.lib_dep_kind) with
|
|
|
|
| Required -> Printf.printf "%s\n" n
|
|
|
|
| Optional -> Printf.printf "%s (optional)\n" n)
|
2016-12-02 13:54:32 +00:00
|
|
|
|
2017-02-20 15:51:03 +00:00
|
|
|
let build_package pkg =
|
|
|
|
Future.Scheduler.go
|
|
|
|
(setup () >>= fun (bs, _, _) ->
|
|
|
|
Build_system.do_build_exn bs [Path.(relative root) (pkg ^ ".install")])
|
|
|
|
|
|
|
|
module Cli = struct
|
|
|
|
open Cmdliner
|
|
|
|
|
|
|
|
let internal =
|
|
|
|
let doc = "internal" in
|
|
|
|
let name_ = Arg.info [] in
|
|
|
|
( Term.(const internal $ Arg.(non_empty & pos_all string [] name_))
|
|
|
|
, Term.info "internal" ~doc)
|
|
|
|
|
|
|
|
type common =
|
|
|
|
{ concurrency: int
|
|
|
|
; debug_rules: bool
|
|
|
|
; debug_dep_path: bool
|
|
|
|
; debug_findlib: bool
|
|
|
|
}
|
|
|
|
|
|
|
|
let set_common c =
|
|
|
|
Clflags.concurrency := c.concurrency;
|
|
|
|
Clflags.debug_rules := c.debug_rules;
|
|
|
|
Clflags.debug_dep_path := c.debug_dep_path;
|
|
|
|
Clflags.debug_findlib := c.debug_findlib
|
|
|
|
|
|
|
|
let copts_sect = "COMMON OPTIONS"
|
|
|
|
let help_secs =
|
|
|
|
[ `S copts_sect
|
|
|
|
; `P "These options are common to all commands."
|
|
|
|
; `S "MORE HELP"
|
|
|
|
; `P "Use `$(mname) $(i,COMMAND) --help' for help on a single command."
|
|
|
|
;`Noblank
|
|
|
|
; `S "BUGS"
|
|
|
|
; `P "Check bug reports at https://github.com/janestreet/jbuilder/issues"
|
|
|
|
]
|
|
|
|
|
|
|
|
let common =
|
|
|
|
let make concurrency debug_rules debug_dep_path debug_findlib =
|
|
|
|
{ concurrency ; debug_rules ; debug_dep_path ; debug_findlib } in
|
|
|
|
let docs = copts_sect in
|
|
|
|
let concurrency =
|
|
|
|
Arg.(value & opt int !Clflags.concurrency & info ["j"] ~docs) in
|
|
|
|
let drules = Arg.(value & flag & info ["drules"] ~docs) in
|
|
|
|
let ddep_path = Arg.(value & flag & info ["ddep-path"] ~docs) in
|
|
|
|
let dfindlib = Arg.(value & flag & info ["dfindlib"] ~docs) in
|
|
|
|
Term.(const make $ concurrency $ drules $ ddep_path $ dfindlib)
|
|
|
|
|
|
|
|
let build_package =
|
|
|
|
let doc = "build-package" in
|
|
|
|
let name_ = Arg.info [] in
|
|
|
|
let go common pkg =
|
|
|
|
set_common common;
|
|
|
|
build_package pkg in
|
|
|
|
( Term.(const go
|
|
|
|
$ common
|
|
|
|
$ Arg.(required & pos 0 (some string) None name_))
|
|
|
|
, Term.info "build-package" ~doc ~man:help_secs)
|
|
|
|
|
|
|
|
let external_lib_deps =
|
|
|
|
let doc = "external-lib-deps" in
|
|
|
|
let name_ = Arg.info [] in
|
|
|
|
let go common packages =
|
|
|
|
set_common common;
|
|
|
|
external_lib_deps_cmd packages in
|
|
|
|
( Term.(const go
|
|
|
|
$ common
|
|
|
|
$ Arg.(non_empty & pos_all string [] name_))
|
|
|
|
, Term.info "external-lib-deps" ~doc ~man:help_secs)
|
|
|
|
|
|
|
|
let build_targets =
|
|
|
|
let doc = "build" in
|
|
|
|
let name_ = Arg.info [] in
|
|
|
|
let go common targets =
|
|
|
|
set_common common;
|
2016-12-02 13:54:32 +00:00
|
|
|
Future.Scheduler.go
|
2016-12-15 11:20:46 +00:00
|
|
|
(setup () >>= fun (bs, _, ctx) ->
|
2016-12-02 13:54:32 +00:00
|
|
|
let targets = List.map targets ~f:(Path.relative ctx.build_dir) in
|
2017-02-20 15:51:03 +00:00
|
|
|
Build_system.do_build_exn bs targets) in
|
|
|
|
( Term.(const go
|
|
|
|
$ common
|
|
|
|
$ Arg.(non_empty & pos_all string [] name_))
|
|
|
|
, Term.info "build" ~doc ~man:help_secs)
|
|
|
|
|
|
|
|
let all =
|
|
|
|
[ internal ; build_package ; external_lib_deps ; build_targets ]
|
|
|
|
|
|
|
|
let main () =
|
|
|
|
match Term.eval_choice build_targets all with
|
|
|
|
| `Error _ -> exit 1
|
|
|
|
| _ -> exit 0
|
|
|
|
end
|
|
|
|
|
|
|
|
let main = Cli.main
|
2016-11-13 12:32:12 +00:00
|
|
|
|
2016-12-02 13:54:32 +00:00
|
|
|
let report_error ?(map_fname=fun x->x) ppf exn ~backtrace =
|
|
|
|
match exn with
|
2016-11-13 12:32:12 +00:00
|
|
|
| Loc.Error ({ start; stop }, msg) ->
|
|
|
|
let start_c = start.pos_cnum - start.pos_bol in
|
|
|
|
let stop_c = stop.pos_cnum - start.pos_bol in
|
2016-12-02 13:54:32 +00:00
|
|
|
Format.fprintf ppf
|
2016-11-13 12:32:12 +00:00
|
|
|
"File \"%s\", line %d, characters %d-%d:\n\
|
2016-12-02 13:54:32 +00:00
|
|
|
Error: %s\n"
|
|
|
|
(map_fname start.pos_fname) start.pos_lnum start_c stop_c msg
|
|
|
|
| Fatal_error msg ->
|
|
|
|
Format.fprintf ppf "%s\n" (String.capitalize msg)
|
|
|
|
| Findlib.Package_not_found pkg ->
|
2016-12-15 11:20:46 +00:00
|
|
|
Format.fprintf ppf "Findlib package %S not found.\n" pkg
|
2016-12-02 13:54:32 +00:00
|
|
|
| Code_error msg ->
|
|
|
|
let bt = Printexc.raw_backtrace_to_string backtrace in
|
|
|
|
Format.fprintf ppf "Internal error, please report upstream.\n\
|
|
|
|
Description: %s\n\
|
|
|
|
Backtrace:\n\
|
|
|
|
%s" msg bt
|
|
|
|
| _ ->
|
|
|
|
let s = Printexc.to_string exn in
|
|
|
|
let bt = Printexc.raw_backtrace_to_string backtrace in
|
|
|
|
if String.is_prefix s ~prefix:"File \"" then
|
|
|
|
Format.fprintf ppf "%s\nBacktrace:\n%s" s bt
|
|
|
|
else
|
|
|
|
Format.fprintf ppf "Error: exception %s\nBacktrace:\n%s" s bt
|
2016-11-13 12:32:12 +00:00
|
|
|
|
2016-12-02 13:54:32 +00:00
|
|
|
let report_error ?map_fname ppf exn =
|
|
|
|
match exn with
|
|
|
|
| Build_system.Build_error.E err ->
|
|
|
|
let module E = Build_system.Build_error in
|
|
|
|
report_error ?map_fname ppf (E.exn err) ~backtrace:(E.backtrace err);
|
|
|
|
if !Clflags.debug_dep_path then
|
|
|
|
Format.fprintf ppf "Dependency path:\n %s\n"
|
|
|
|
(String.concat ~sep:"\n--> "
|
|
|
|
(List.map (E.dependency_path err) ~f:Path.to_string))
|
|
|
|
| exn ->
|
|
|
|
let backtrace = Printexc.get_raw_backtrace () in
|
|
|
|
report_error ?map_fname ppf exn ~backtrace
|
|
|
|
|
|
|
|
let main () =
|
|
|
|
try
|
|
|
|
main ()
|
|
|
|
with exn ->
|
|
|
|
Format.eprintf "%a@?" (report_error ?map_fname:None) exn;
|
|
|
|
exit 1
|