2017-02-21 15:09:58 +00:00
|
|
|
open Jbuilder
|
|
|
|
open Import
|
|
|
|
open Jbuilder_cmdliner.Cmdliner
|
|
|
|
|
|
|
|
module Main = Jbuilder.Main
|
|
|
|
|
2017-02-23 16:44:17 +00:00
|
|
|
(* Things in src/ don't depend on cmdliner to speed up the bootstrap, so we set this
|
|
|
|
reference here *)
|
|
|
|
let () = suggest_function := Jbuilder_cmdliner.Cmdliner_suggest.value
|
|
|
|
|
2017-02-21 15:09:58 +00:00
|
|
|
let (>>=) = Future.(>>=)
|
|
|
|
|
2017-02-23 11:45:03 +00:00
|
|
|
let create_log = Main.create_log
|
|
|
|
|
2017-02-21 15:09:58 +00:00
|
|
|
(* TODO: rewrite this when command trees are supported.
|
|
|
|
|
|
|
|
https://github.com/dbuenzli/cmdliner/issues/24 *)
|
|
|
|
let internal = function
|
|
|
|
| [_; "findlib-packages"] ->
|
2017-02-23 11:45:03 +00:00
|
|
|
Future.Scheduler.go ~log:(create_log ())
|
2017-02-21 15:09:58 +00:00
|
|
|
(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 =
|
|
|
|
match (Findlib.find_exn findlib pkg).version with
|
|
|
|
| "" -> "n/a"
|
|
|
|
| v -> v
|
|
|
|
in
|
|
|
|
Printf.printf "%-*s (version: %s)\n" max_len pkg ver);
|
|
|
|
Future.return ())
|
|
|
|
| _ ->
|
|
|
|
()
|
|
|
|
|
|
|
|
let internal =
|
2017-02-23 10:32:23 +00:00
|
|
|
let doc = "internal use only" in
|
2017-02-21 15:09:58 +00:00
|
|
|
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
|
2017-02-24 12:19:02 +00:00
|
|
|
; dev_mode: bool
|
2017-02-21 15:09:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
let set_common c =
|
|
|
|
Clflags.concurrency := c.concurrency;
|
|
|
|
Clflags.debug_rules := c.debug_rules;
|
|
|
|
Clflags.debug_dep_path := c.debug_dep_path;
|
2017-02-24 12:19:02 +00:00
|
|
|
Clflags.debug_findlib := c.debug_findlib;
|
|
|
|
Clflags.dev_mode := c.dev_mode
|
2017-02-21 15:09:58 +00:00
|
|
|
|
|
|
|
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."
|
|
|
|
; `S "BUGS"
|
|
|
|
; `P "Check bug reports at https://github.com/janestreet/jbuilder/issues"
|
|
|
|
]
|
|
|
|
|
|
|
|
let common =
|
2017-02-24 12:19:02 +00:00
|
|
|
let make concurrency debug_rules debug_dep_path debug_findlib dev_mode =
|
|
|
|
{ concurrency
|
|
|
|
; debug_rules
|
|
|
|
; debug_dep_path
|
|
|
|
; debug_findlib
|
|
|
|
; dev_mode
|
|
|
|
}
|
|
|
|
in
|
2017-02-21 15:09:58 +00:00
|
|
|
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
|
2017-02-24 12:19:02 +00:00
|
|
|
let dev = Arg.(value & flag & info ["dev"] ~docs) in
|
|
|
|
Term.(const make $ concurrency $ drules $ ddep_path $ dfindlib $ dev)
|
2017-02-21 15:09:58 +00:00
|
|
|
|
|
|
|
let build_package pkg =
|
2017-02-23 11:45:03 +00:00
|
|
|
Future.Scheduler.go ~log:(create_log ())
|
2017-02-23 14:58:18 +00:00
|
|
|
(Main.setup () >>= fun setup ->
|
|
|
|
match Main.package_install_file setup pkg with
|
|
|
|
| Ok path ->
|
|
|
|
Build_system.do_build_exn setup.build_system
|
|
|
|
[path]
|
|
|
|
| Error () ->
|
2017-02-23 16:44:17 +00:00
|
|
|
die "Unknown package %s!%s" pkg (hint pkg (String_map.keys setup.packages))
|
2017-02-23 14:58:18 +00:00
|
|
|
)
|
2017-02-21 15:09:58 +00:00
|
|
|
|
|
|
|
let build_package =
|
2017-02-23 10:32:23 +00:00
|
|
|
let doc = "build a package in release mode" in
|
2017-02-23 10:23:15 +00:00
|
|
|
let name_ = Arg.info [] ~docv:"PACKAGE-NAME" in
|
2017-02-21 15:09:58 +00:00
|
|
|
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 packages =
|
2017-02-23 11:45:03 +00:00
|
|
|
let log = create_log () in
|
2017-02-21 15:09:58 +00:00
|
|
|
let deps =
|
2017-02-23 11:45:03 +00:00
|
|
|
Path.Map.fold (Main.external_lib_deps ~log ~packages) ~init:String_map.empty
|
2017-02-21 15:09:58 +00:00
|
|
|
~f:(fun ~key:_ ~data:deps acc -> Build.merge_lib_deps deps acc)
|
|
|
|
in
|
|
|
|
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)
|
|
|
|
|
|
|
|
let external_lib_deps =
|
2017-02-23 10:32:23 +00:00
|
|
|
let doc = "print out external library dependencies" in
|
2017-02-23 10:23:15 +00:00
|
|
|
let name_ = Arg.info [] ~docv:"PACKAGE-NAME" in
|
2017-02-21 15:09:58 +00:00
|
|
|
let go common packages =
|
|
|
|
set_common common;
|
|
|
|
external_lib_deps packages
|
|
|
|
in
|
|
|
|
( Term.(const go
|
|
|
|
$ common
|
|
|
|
$ Arg.(non_empty & pos_all string [] name_))
|
|
|
|
, Term.info "external-lib-deps" ~doc ~man:help_secs)
|
|
|
|
|
2017-02-23 14:58:18 +00:00
|
|
|
let resolve_targets (setup : Main.setup)user_targets =
|
2017-02-23 10:03:35 +00:00
|
|
|
match user_targets with
|
|
|
|
| [] -> []
|
|
|
|
| _ ->
|
|
|
|
let user_targets = List.map user_targets ~f:(Path.relative Path.root) in
|
|
|
|
let real_targets =
|
|
|
|
List.map user_targets ~f:(fun path ->
|
|
|
|
if Path.is_in_build_dir path then
|
|
|
|
path
|
|
|
|
else if Path.is_local path &&
|
2017-02-23 14:58:18 +00:00
|
|
|
not (Build_system.is_target setup.build_system path) &&
|
2017-02-23 10:03:35 +00:00
|
|
|
not (Path.exists path) then
|
2017-02-23 14:58:18 +00:00
|
|
|
Path.append setup.context.build_dir path
|
2017-02-23 10:03:35 +00:00
|
|
|
else
|
|
|
|
path)
|
|
|
|
in
|
|
|
|
Printf.printf "Building the following targets:\n";
|
|
|
|
List.iter real_targets ~f:(fun target ->
|
|
|
|
Printf.printf "- %s\n" (Path.to_string target));
|
|
|
|
flush stdout;
|
|
|
|
real_targets
|
|
|
|
|
2017-02-23 10:32:23 +00:00
|
|
|
let build_targets ~name =
|
|
|
|
let doc = "build targets" in
|
2017-02-23 10:23:15 +00:00
|
|
|
let name_ = Arg.info [] ~docv:"TARGET" in
|
2017-02-21 15:09:58 +00:00
|
|
|
let go common targets =
|
|
|
|
set_common common;
|
2017-02-23 11:45:03 +00:00
|
|
|
Future.Scheduler.go ~log:(create_log ())
|
2017-02-23 14:58:18 +00:00
|
|
|
(Main.setup () >>= fun setup ->
|
|
|
|
let targets = resolve_targets setup targets in
|
|
|
|
Build_system.do_build_exn setup.build_system targets) in
|
2017-02-21 15:09:58 +00:00
|
|
|
( Term.(const go
|
|
|
|
$ common
|
|
|
|
$ Arg.(non_empty & pos_all string [] name_))
|
2017-02-23 10:32:23 +00:00
|
|
|
, Term.info name ~doc ~man:help_secs)
|
2017-02-21 15:09:58 +00:00
|
|
|
|
2017-02-23 13:17:25 +00:00
|
|
|
let runtest =
|
|
|
|
let doc = "run tests" in
|
|
|
|
let name_ = Arg.info [] ~docv:"DIR" in
|
|
|
|
let go common dirs =
|
|
|
|
set_common common;
|
|
|
|
Future.Scheduler.go ~log:(create_log ())
|
2017-02-23 14:58:18 +00:00
|
|
|
(Main.setup () >>= fun setup ->
|
2017-02-23 13:17:25 +00:00
|
|
|
let dirs =
|
|
|
|
match dirs with
|
|
|
|
| [] -> [Path.root]
|
|
|
|
| _ -> List.map dirs ~f:Path.(relative root)
|
|
|
|
in
|
|
|
|
let targets =
|
|
|
|
List.map dirs ~f:(fun dir ->
|
|
|
|
let dir =
|
|
|
|
if Path.is_in_build_dir dir then
|
|
|
|
dir
|
|
|
|
else
|
2017-02-23 14:58:18 +00:00
|
|
|
Path.append setup.context.build_dir dir
|
2017-02-23 13:17:25 +00:00
|
|
|
in
|
|
|
|
Alias.file (Alias.runtest ~dir))
|
|
|
|
in
|
2017-02-23 14:58:18 +00:00
|
|
|
Build_system.do_build_exn setup.build_system targets) in
|
2017-02-23 13:17:25 +00:00
|
|
|
( Term.(const go
|
|
|
|
$ common
|
|
|
|
$ Arg.(value & pos_all string [] name_))
|
|
|
|
, Term.info "runtest" ~doc ~man:help_secs)
|
|
|
|
|
2017-02-21 15:09:58 +00:00
|
|
|
let all =
|
2017-02-23 13:17:25 +00:00
|
|
|
[ internal
|
|
|
|
; build_package
|
|
|
|
; external_lib_deps
|
|
|
|
; build_targets ~name:"build"
|
|
|
|
; runtest
|
|
|
|
]
|
2017-02-21 15:09:58 +00:00
|
|
|
|
|
|
|
let () =
|
2017-02-24 11:28:30 +00:00
|
|
|
Ansi_color.setup_err_formatter_colors ();
|
2017-02-21 15:09:58 +00:00
|
|
|
try
|
2017-02-23 12:15:57 +00:00
|
|
|
match Term.eval_choice (build_targets ~name:"jbuilder") all ~catch:false with
|
2017-02-21 15:09:58 +00:00
|
|
|
| `Error _ -> exit 1
|
|
|
|
| _ -> exit 0
|
|
|
|
with exn ->
|
|
|
|
Format.eprintf "%a@?" (Main.report_error ?map_fname:None) exn;
|
|
|
|
exit 1
|