2016-11-13 12:25:45 +00:00
|
|
|
open Import
|
2016-12-02 13:54:32 +00:00
|
|
|
open Future
|
|
|
|
|
2017-02-23 14:58:18 +00:00
|
|
|
type setup =
|
|
|
|
{ build_system : Build_system.t
|
2017-06-05 12:42:13 +00:00
|
|
|
; stanzas : (Path.t * Jbuild.Scope.t * Jbuild.Stanzas.t) list String_map.t
|
2017-02-25 02:38:41 +00:00
|
|
|
; contexts : Context.t list
|
2017-02-24 18:21:22 +00:00
|
|
|
; packages : Package.t String_map.t
|
2017-09-29 15:06:29 +00:00
|
|
|
; file_tree : File_tree.t
|
2017-02-23 14:58:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
let package_install_file { packages; _ } pkg =
|
|
|
|
match String_map.find pkg packages with
|
|
|
|
| None -> Error ()
|
2017-12-21 11:54:00 +00:00
|
|
|
| Some p ->
|
|
|
|
Ok (Path.relative p.path (Utils.install_file ~package:p.name ~findlib_toolchain:None))
|
2017-02-23 14:58:18 +00:00
|
|
|
|
2018-01-19 08:50:06 +00:00
|
|
|
let setup ?(log=Log.no_log)
|
2017-11-28 11:03:22 +00:00
|
|
|
?filter_out_optional_stanzas_with_missing_deps
|
2017-03-01 13:25:18 +00:00
|
|
|
?workspace ?(workspace_file="jbuild-workspace")
|
2017-03-22 08:19:26 +00:00
|
|
|
?(use_findlib=true)
|
2017-03-29 15:51:48 +00:00
|
|
|
?only_packages
|
|
|
|
?extra_ignored_subtrees
|
2017-12-21 11:54:00 +00:00
|
|
|
?x
|
2018-01-25 19:07:46 +00:00
|
|
|
?ignore_promoted_rules
|
2017-03-29 15:51:48 +00:00
|
|
|
() =
|
2018-01-25 19:07:46 +00:00
|
|
|
let conf = Jbuild_load.load ?extra_ignored_subtrees ?ignore_promoted_rules () in
|
2017-03-02 18:21:19 +00:00
|
|
|
Option.iter only_packages ~f:(fun set ->
|
|
|
|
String_set.iter set ~f:(fun pkg ->
|
|
|
|
if not (String_map.mem pkg conf.packages) then
|
|
|
|
die "@{<error>Error@}: I don't know about package %s \
|
2017-04-04 15:56:14 +00:00
|
|
|
(passed through --only-packages/--release)%s"
|
2017-03-02 18:21:19 +00:00
|
|
|
pkg (hint pkg (String_map.keys conf.packages))));
|
2017-02-25 02:38:41 +00:00
|
|
|
let workspace =
|
|
|
|
match workspace with
|
|
|
|
| Some w -> w
|
|
|
|
| None ->
|
2017-02-27 15:04:49 +00:00
|
|
|
if Sys.file_exists workspace_file then
|
2017-12-21 11:54:00 +00:00
|
|
|
Workspace.load ?x workspace_file
|
2017-02-25 02:38:41 +00:00
|
|
|
else
|
2017-12-21 11:54:00 +00:00
|
|
|
{ merlin_context = Some "default"
|
|
|
|
; contexts = [Default [
|
|
|
|
match x with
|
|
|
|
| None -> Native
|
|
|
|
| Some x -> Named x
|
|
|
|
]]
|
|
|
|
}
|
2017-02-25 02:38:41 +00:00
|
|
|
in
|
2017-12-21 11:54:00 +00:00
|
|
|
|
|
|
|
Future.all (
|
|
|
|
List.map workspace.contexts ~f:(fun ctx_def ->
|
|
|
|
let name = Workspace.Context.name ctx_def in
|
|
|
|
Context.create ctx_def ~merlin:(workspace.merlin_context = Some name) ~use_findlib)
|
|
|
|
)
|
2017-02-25 00:28:10 +00:00
|
|
|
>>= fun contexts ->
|
2017-12-21 11:54:00 +00:00
|
|
|
let contexts = List.concat contexts in
|
|
|
|
List.iter contexts ~f:(fun (ctx : Context.t) ->
|
2017-03-10 12:32:27 +00:00
|
|
|
Log.infof log "@[<1>Jbuilder context:@,%a@]@." Sexp.pp (Context.sexp_of_t ctx));
|
2018-01-19 08:50:06 +00:00
|
|
|
let build_system =
|
|
|
|
Build_system.create ~contexts ~file_tree:conf.file_tree
|
|
|
|
in
|
2017-12-21 11:54:00 +00:00
|
|
|
Gen_rules.gen conf
|
2018-01-19 08:50:06 +00:00
|
|
|
~build_system
|
2017-12-21 11:54:00 +00:00
|
|
|
~contexts
|
2017-03-02 18:21:19 +00:00
|
|
|
?only_packages
|
2017-02-26 19:49:54 +00:00
|
|
|
?filter_out_optional_stanzas_with_missing_deps
|
2018-01-19 08:50:06 +00:00
|
|
|
>>= fun stanzas ->
|
2017-02-23 14:58:18 +00:00
|
|
|
return { build_system
|
2017-03-01 19:19:43 +00:00
|
|
|
; stanzas
|
2017-02-25 02:38:41 +00:00
|
|
|
; contexts
|
2017-02-25 18:21:23 +00:00
|
|
|
; packages = conf.packages
|
2017-09-29 15:06:29 +00:00
|
|
|
; file_tree = conf.file_tree
|
2017-02-23 14:58:18 +00:00
|
|
|
}
|
2016-12-02 13:54:32 +00:00
|
|
|
|
2017-02-24 13:08:37 +00:00
|
|
|
let external_lib_deps ?log ~packages () =
|
2017-02-23 11:45:03 +00:00
|
|
|
Future.Scheduler.go ?log
|
2016-12-15 13:00:30 +00:00
|
|
|
(setup () ~filter_out_optional_stanzas_with_missing_deps:false
|
2017-03-01 19:19:43 +00:00
|
|
|
>>| fun setup ->
|
2017-02-23 14:58:18 +00:00
|
|
|
let install_files =
|
|
|
|
List.map packages ~f:(fun pkg ->
|
|
|
|
match package_install_file setup pkg with
|
|
|
|
| Ok path -> path
|
|
|
|
| Error () -> die "Unknown package %S" pkg)
|
|
|
|
in
|
2017-03-01 19:19:43 +00:00
|
|
|
match String_map.find "default" setup.stanzas with
|
|
|
|
| None -> die "You need to set a default context to use external-lib-deps"
|
|
|
|
| Some stanzas ->
|
2017-06-02 13:32:05 +00:00
|
|
|
let internals = Jbuild.Stanzas.lib_names stanzas in
|
2017-03-01 19:19:43 +00:00
|
|
|
Path.Map.map
|
2017-09-29 15:06:29 +00:00
|
|
|
(Build_system.all_lib_deps setup.build_system
|
|
|
|
~request:(Build.paths install_files))
|
2017-03-01 19:19:43 +00:00
|
|
|
~f:(String_map.filter ~f:(fun name _ ->
|
2017-02-26 19:49:54 +00:00
|
|
|
not (String_set.mem name internals))))
|
2016-12-02 13:54:32 +00:00
|
|
|
|
2017-05-29 13:17:59 +00:00
|
|
|
(* Return [true] if the backtrace was printed *)
|
2016-12-02 13:54:32 +00:00
|
|
|
let report_error ?(map_fname=fun x->x) ppf exn ~backtrace =
|
|
|
|
match exn with
|
2017-05-18 15:50:53 +00:00
|
|
|
| Loc.Error (loc, msg) ->
|
|
|
|
let loc =
|
|
|
|
{ loc with
|
|
|
|
start = { loc.start with pos_fname = map_fname loc.start.pos_fname }
|
|
|
|
}
|
|
|
|
in
|
2017-05-29 13:17:59 +00:00
|
|
|
Format.fprintf ppf "%a@{<error>Error@}: %s\n" Loc.print loc msg;
|
|
|
|
false
|
2018-01-09 09:55:01 +00:00
|
|
|
| Usexp.Parser.Error e ->
|
|
|
|
let pos = Usexp.Parser.Error.position e in
|
|
|
|
let msg = Usexp.Parser.Error.message e in
|
|
|
|
let pos = { pos with pos_fname = map_fname pos.pos_fname } in
|
|
|
|
let loc = { Loc. start = pos; stop = pos } in
|
|
|
|
Format.fprintf ppf "%a@{<error>Error@}: %s\n" Loc.print loc msg;
|
|
|
|
false
|
2017-05-29 13:17:59 +00:00
|
|
|
| Fatal_error "" -> false
|
2016-12-02 13:54:32 +00:00
|
|
|
| Fatal_error msg ->
|
2017-05-29 13:17:59 +00:00
|
|
|
Format.fprintf ppf "%s\n" (String.capitalize_ascii msg);
|
|
|
|
false
|
2018-01-25 14:00:52 +00:00
|
|
|
| Findlib.Findlib (Findlib.Package_not_available { package; required_by; reason }) ->
|
2017-03-01 19:19:43 +00:00
|
|
|
Format.fprintf ppf
|
2017-05-17 12:52:40 +00:00
|
|
|
"@{<error>Error@}: External library %S %s.\n" package
|
|
|
|
(match reason with
|
|
|
|
| Not_found -> "not found"
|
|
|
|
| Hidden -> "is hidden"
|
|
|
|
| _ -> "is unavailable");
|
2017-03-14 15:57:22 +00:00
|
|
|
List.iter required_by ~f:(Format.fprintf ppf "-> required by %S\n");
|
2017-05-17 12:52:40 +00:00
|
|
|
begin match reason with
|
|
|
|
| Not_found -> ()
|
|
|
|
| Hidden ->
|
|
|
|
Format.fprintf ppf
|
|
|
|
"External library %S is hidden because its 'exist_if' \
|
|
|
|
clause is not satisfied.\n" package
|
|
|
|
| Dependencies_unavailable deps ->
|
|
|
|
Format.fprintf ppf
|
|
|
|
"External library %S is not available because it depends on the \
|
|
|
|
following libraries that are not available:\n" package;
|
|
|
|
let deps = Findlib.Package_not_available.top_closure deps in
|
|
|
|
let longest = List.longest_map deps ~f:(fun na -> na.package) in
|
|
|
|
List.iter deps ~f:(fun (na : Findlib.Package_not_available.t) ->
|
2017-05-17 13:54:50 +00:00
|
|
|
Format.fprintf ppf "- %-*s -> %a@\n" longest na.package
|
|
|
|
Findlib.Package_not_available.explain na.reason)
|
2017-05-17 12:52:40 +00:00
|
|
|
end;
|
2017-03-14 15:57:22 +00:00
|
|
|
Format.fprintf ppf
|
|
|
|
"Hint: try: %s\n"
|
2017-05-19 13:16:00 +00:00
|
|
|
(List.map !Clflags.external_lib_deps_hint ~f:quote_for_shell
|
2017-05-29 13:17:59 +00:00
|
|
|
|> String.concat ~sep:" ");
|
|
|
|
false
|
2018-01-25 14:00:52 +00:00
|
|
|
| Findlib.Findlib (Findlib.External_dep_conflicts_with_local_lib {
|
|
|
|
package; required_by; required_locally_in; defined_locally_in }) ->
|
2017-04-26 14:04:32 +00:00
|
|
|
Format.fprintf ppf
|
|
|
|
"@{<error>Error@}: Conflict between internal and external version of library %S:\n\
|
|
|
|
- it is defined locally in %s\n\
|
|
|
|
- it is required by external library %S\n\
|
2018-01-26 07:10:38 +00:00
|
|
|
%s\n\
|
2017-04-26 14:04:32 +00:00
|
|
|
This cannot work.\n"
|
|
|
|
package
|
2018-01-18 11:32:20 +00:00
|
|
|
(Utils.jbuild_name_in ~dir:(Path.drop_optional_build_context defined_locally_in))
|
2017-04-26 14:04:32 +00:00
|
|
|
required_by
|
2018-01-26 07:10:38 +00:00
|
|
|
(required_locally_in
|
|
|
|
|> List.map ~f:(sprintf " -> required by %S")
|
|
|
|
|> String.concat ~sep:"\n");
|
2017-05-29 13:17:59 +00:00
|
|
|
false
|
2016-12-02 13:54:32 +00:00
|
|
|
| Code_error msg ->
|
|
|
|
let bt = Printexc.raw_backtrace_to_string backtrace in
|
2017-03-10 11:22:01 +00:00
|
|
|
Format.fprintf ppf "@{<error>Internal error, please report upstream \
|
|
|
|
including the contents of _build/log.@}\n\
|
2016-12-02 13:54:32 +00:00
|
|
|
Description: %s\n\
|
|
|
|
Backtrace:\n\
|
2017-05-29 13:17:59 +00:00
|
|
|
%s" msg bt;
|
|
|
|
true
|
2017-03-01 11:27:58 +00:00
|
|
|
| Unix.Unix_error (err, func, fname) ->
|
|
|
|
Format.fprintf ppf "@{<error>Error@}: %s: %s: %s\n"
|
2017-05-29 13:17:59 +00:00
|
|
|
func fname (Unix.error_message err);
|
|
|
|
false
|
2016-12-02 13:54:32 +00:00
|
|
|
| _ ->
|
|
|
|
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
|
2017-05-29 13:17:59 +00:00
|
|
|
Format.fprintf ppf "@{<error>Error@}: exception %s\nBacktrace:\n%s" s bt;
|
|
|
|
true
|
2016-11-13 12:32:12 +00:00
|
|
|
|
2016-12-02 13:54:32 +00:00
|
|
|
let report_error ?map_fname ppf exn =
|
2017-05-29 13:17:59 +00:00
|
|
|
match
|
|
|
|
match exn with
|
|
|
|
| Build_system.Build_error.E err ->
|
|
|
|
let module E = Build_system.Build_error in
|
|
|
|
let backtrace = E.backtrace err in
|
|
|
|
let bt_printed =
|
|
|
|
report_error ?map_fname ppf (E.exn err) ~backtrace:(E.backtrace err)
|
|
|
|
in
|
|
|
|
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:Utils.describe_target));
|
|
|
|
Option.some_if (not bt_printed) backtrace
|
|
|
|
| exn ->
|
|
|
|
let backtrace = Printexc.get_raw_backtrace () in
|
|
|
|
let bt_printed =
|
|
|
|
report_error ?map_fname ppf exn ~backtrace
|
|
|
|
in
|
|
|
|
Option.some_if (not bt_printed) backtrace
|
|
|
|
with
|
|
|
|
| Some bt when !Clflags.debug_backtraces ->
|
|
|
|
Format.fprintf ppf "Backtrace:\n%s" (Printexc.raw_backtrace_to_string bt)
|
|
|
|
| _ -> ()
|
2016-12-02 13:54:32 +00:00
|
|
|
|
2017-03-29 15:51:48 +00:00
|
|
|
let ignored_during_bootstrap =
|
|
|
|
Path.Set.of_list
|
|
|
|
(List.map ~f:Path.of_string
|
|
|
|
[ "test"
|
|
|
|
; "example"
|
|
|
|
])
|
|
|
|
|
2017-02-21 15:09:58 +00:00
|
|
|
(* Called by the script generated by ../build.ml *)
|
|
|
|
let bootstrap () =
|
2017-02-24 12:20:07 +00:00
|
|
|
Ansi_color.setup_err_formatter_colors ();
|
2017-02-21 15:09:58 +00:00
|
|
|
let main () =
|
|
|
|
let anon s = raise (Arg.Bad (Printf.sprintf "don't know what to do with %s\n" s)) in
|
2017-05-07 19:48:10 +00:00
|
|
|
let subst () =
|
2017-05-08 15:53:12 +00:00
|
|
|
Future.Scheduler.go (Watermarks.subst () ~name:"jbuilder");
|
2017-05-07 19:53:40 +00:00
|
|
|
exit 0
|
2017-05-07 19:48:10 +00:00
|
|
|
in
|
2017-02-24 12:19:02 +00:00
|
|
|
Arg.parse
|
2017-03-01 11:27:58 +00:00
|
|
|
[ "-j" , Set_int Clflags.concurrency, "JOBS concurrency"
|
|
|
|
; "--dev" , Set Clflags.dev_mode , " set development mode"
|
2017-04-21 16:22:41 +00:00
|
|
|
; "--verbose" , Set Clflags.verbose , " print detailed information about commands being run"
|
2017-05-07 19:48:10 +00:00
|
|
|
; "--subst" , Unit subst , " substitute watermarks in source files"
|
2017-02-24 12:19:02 +00:00
|
|
|
]
|
|
|
|
anon "Usage: boot.exe [-j JOBS] [--dev]\nOptions are:";
|
2017-06-08 08:59:43 +00:00
|
|
|
Clflags.debug_dep_path := true;
|
2017-03-10 12:32:27 +00:00
|
|
|
let log = Log.create () in
|
|
|
|
Future.Scheduler.go ~log
|
2018-01-19 08:50:06 +00:00
|
|
|
(setup ~log ~workspace:{ merlin_context = Some "default"
|
|
|
|
; contexts = [Default [Native]] }
|
2017-03-29 15:51:48 +00:00
|
|
|
~use_findlib:false
|
|
|
|
~extra_ignored_subtrees:ignored_during_bootstrap
|
|
|
|
()
|
2017-02-26 20:53:32 +00:00
|
|
|
>>= fun { build_system = bs; _ } ->
|
2017-09-29 15:06:29 +00:00
|
|
|
Build_system.do_build_exn bs
|
2018-01-19 08:50:06 +00:00
|
|
|
~request:(Build.path (Path.of_string "_build/default/jbuilder.install")))
|
2017-02-21 15:09:58 +00:00
|
|
|
in
|
2016-12-02 13:54:32 +00:00
|
|
|
try
|
|
|
|
main ()
|
|
|
|
with exn ->
|
|
|
|
Format.eprintf "%a@?" (report_error ?map_fname:None) exn;
|
|
|
|
exit 1
|
2017-03-22 08:19:26 +00:00
|
|
|
|
2017-03-29 15:51:48 +00:00
|
|
|
let setup = setup ~use_findlib:true ~extra_ignored_subtrees:Path.Set.empty
|
2017-08-04 07:59:35 +00:00
|
|
|
|
|
|
|
let find_context_exn t ~name =
|
|
|
|
match List.find t.contexts ~f:(fun c -> c.name = name) with
|
|
|
|
| Some ctx -> ctx
|
|
|
|
| None ->
|
|
|
|
Format.eprintf "@{<Error>Error@}: Context %S not found!@." name;
|
|
|
|
die ""
|