Skip to content

Commit

Permalink
ctypes 0.3: run commands in stanza directory
Browse files Browse the repository at this point in the history
This creates version 0.3 of the ctypes field.

When used, commands are run in the directory where the corresponding
stanza is defined. This makes it possible to use relative directories.

Fixes ocaml#5325

Signed-off-by: Etienne Millon <me@emillon.org>
  • Loading branch information
emillon committed Feb 6, 2023
1 parent 55a26e2 commit 3218637
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 35 deletions.
10 changes: 8 additions & 2 deletions src/dune_rules/ctypes/ctypes_field.ml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ let name = "ctypes"

let syntax =
Dune_lang.Syntax.create ~name ~desc:"the ctypes extension"
[ ((0, 1), `Since (3, 0)); ((0, 2), `Since (3, 4)) ]
[ ((0, 1), `Since (3, 0))
; ((0, 2), `Since (3, 4))
; ((0, 3), `Since (3, 7)) (* TODO: actually target a later version *)
]

module Build_flags_resolver = struct
module Vendored = struct
Expand Down Expand Up @@ -140,6 +143,7 @@ type t =
; generated_types : Module_name.t
; generated_entry_point : Module_name.t
; deps : Dep_conf.t list
; version : Syntax.Version.t
}

type Stanza.t += T of t
Expand All @@ -157,7 +161,8 @@ let decode =
and+ generated_types = field_o "generated_types" Module_name.decode
and+ generated_entry_point =
field "generated_entry_point" Module_name.decode
and+ deps = field_o "deps" (repeat Dep_conf.decode) in
and+ deps = field_o "deps" (repeat Dep_conf.decode)
and+ version = Syntax.get_exn syntax in
let external_library_name =
External_lib_name.of_string external_library_name
in
Expand Down Expand Up @@ -187,6 +192,7 @@ let decode =
~default:(Module_name.of_string "Types_generated")
; generated_entry_point
; deps = Option.value ~default:[] deps
; version
})

let () =
Expand Down
1 change: 1 addition & 0 deletions src/dune_rules/ctypes/ctypes_field.mli
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ type t =
; generated_types : Module_name.t
; generated_entry_point : Module_name.t
; deps : Dep_conf.t list
; version : Syntax.Version.t
}

type Stanza.t += T of t
Expand Down
79 changes: 50 additions & 29 deletions src/dune_rules/ctypes/ctypes_rules.ml
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ let function_gen_gen ~expander
])

let build_c_program ~foreign_archives_deps ~sctx ~dir ~source_files ~scope
~cflags ~output ~deps =
~cflags ~output ~deps ~version =
let ctx = Super_context.context sctx in
let open Memo.O in
let* exe =
Expand Down Expand Up @@ -216,33 +216,54 @@ let build_c_program ~foreign_archives_deps ~sctx ~dir ~source_files ~scope
in
deps
in
let build =
let absolute_path_hack p =
(* These normal path builder things construct relative paths like
_build/default/your/project/file.c but before dune runs gcc it actually
cds into _build/default, which fails, so we turn them into absolutes to
hack around it. *)
Path.relative (Path.build dir) p |> Path.to_absolute_filename
in
let action =
let open Action_builder.O in
let* include_args = Resolve.Memo.read include_args in
let* base_args = with_user_and_std_flags in
deps
>>> Action_builder.map cflags ~f:(fun cflags_args ->
let source_files = List.map source_files ~f:absolute_path_hack in
let output = absolute_path_hack output in
let args =
base_args @ cflags_args @ include_args @ source_files
@ [ "-o"; output ]
in
Action.run exe args)
in
Action_builder.with_file_targets action
~file_targets:[ Path.Build.relative dir output ]
let action =
if version >= (0, 3) then
let args : _ Command.Args.t list =
[ Expand (fun ~dir:_ -> with_user_and_std_flags)
; Expand (fun ~dir:_ -> cflags)
; Expand (fun ~dir:_ -> Resolve.Memo.read include_args)
; Deps
(List.map
~f:(fun s -> Path.relative (Path.build dir) s)
source_files)
; A "-o"
; Target (Path.Build.relative dir output)
]
in
let open Action_builder.With_targets.O in
Action_builder.with_no_targets deps
>>> Command.run ~dir:(Path.build dir) exe args
else
let build =
let absolute_path_hack p =
(* These normal path builder things construct relative paths like
_build/default/your/project/file.c but before dune runs gcc it actually
cds into _build/default, which fails, so we turn them into absolutes to
hack around it. *)
Path.relative (Path.build dir) p |> Path.to_absolute_filename
in
let action =
let open Action_builder.O in
let* include_args = Resolve.Memo.read include_args in
let* base_args = with_user_and_std_flags in
deps
>>> Action_builder.map cflags ~f:(fun cflags_args ->
let source_files =
List.map source_files ~f:absolute_path_hack
in
let output = absolute_path_hack output in
let args =
base_args @ cflags_args @ include_args @ source_files
@ [ "-o"; output ]
in
Action.run exe args)
in
Action_builder.with_file_targets action
~file_targets:[ Path.Build.relative dir output ]
in
Action_builder.With_targets.map ~f:Action.Full.make build
in
Super_context.add_rule sctx ~dir
(Action_builder.With_targets.map ~f:Action.Full.make build)
Super_context.add_rule sctx ~dir action

let program_of_module_and_dir ~dir program =
let build_dir = Path.build dir in
Expand All @@ -261,7 +282,7 @@ let exe_link_only ~dir ~shared_cctx ~sandbox program ~deps =
Exe.link_many ~link_args ~programs:[ program ]
~linkages:[ Exe.Linkage.native ] ~promote:None shared_cctx ~sandbox

let gen_rules ~cctx ~(buildable : Buildable.t) ~loc ~scope ~dir ~sctx =
let gen_rules ~cctx ~(buildable : Buildable.t) ~loc ~scope ~dir ~sctx ~version =
let ctypes = Option.value_exn buildable.ctypes in
let external_library_name = ctypes.external_library_name in
let type_description_functor = ctypes.type_description.functor_ in
Expand Down Expand Up @@ -359,7 +380,7 @@ let gen_rules ~cctx ~(buildable : Buildable.t) ~loc ~scope ~dir ~sctx =
let* () =
build_c_program ~foreign_archives_deps ~sctx ~dir ~scope
~source_files:[ c_generated_types_cout_c ]
~output:c_generated_types_cout_exe ~deps ~cflags
~output:c_generated_types_cout_exe ~deps ~cflags ~version
in
Super_context.add_rule sctx ~loc:Loc.none ~dir
(let stdout_to =
Expand Down
1 change: 1 addition & 0 deletions src/dune_rules/ctypes/ctypes_rules.mli
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ val gen_rules :
-> scope:Scope.t
-> dir:Path.Build.t
-> sctx:Super_context.t
-> version:Syntax.Version.t
-> unit Memo.t

val ctypes_cclib_flags :
Expand Down
4 changes: 2 additions & 2 deletions src/dune_rules/exe_rules.ml
Original file line number Diff line number Diff line change
Expand Up @@ -191,15 +191,15 @@ let executables_rules ~sctx ~dir ~expander ~dir_contents ~scope ~compile_info
| None ->
Exe.build_and_link_many cctx ~programs ~linkages ~link_args ~o_files
~promote:exes.promote ~embed_in_plugin_libraries ~sandbox
| Some _ctypes ->
| Some { version; _ } ->
(* Ctypes stubgen builds utility .exe files that need to share modules
with this compilation context. To support that, we extract the one-time
run bits from [Exe.build_and_link_many] and run them here, then pass
that to the [Exe.link_many] call here as well as the Ctypes_rules. This
dance is done to avoid triggering duplicate rule exceptions. *)
let* () =
let loc = fst (List.hd exes.Executables.names) in
Ctypes_rules.gen_rules ~cctx ~buildable ~loc ~sctx ~scope ~dir
Ctypes_rules.gen_rules ~cctx ~buildable ~loc ~sctx ~scope ~dir ~version
in
let* () = Module_compilation.build_all cctx in
Exe.link_many ~programs ~linkages ~link_args ~o_files
Expand Down
4 changes: 2 additions & 2 deletions src/dune_rules/lib_rules.ml
Original file line number Diff line number Diff line change
Expand Up @@ -561,9 +561,9 @@ let rules (lib : Library.t) ~sctx ~dir_contents ~dir ~expander ~scope =
let* () =
match buildable.ctypes with
| None -> Memo.return ()
| Some _ctypes ->
| Some { version; _ } ->
Ctypes_rules.gen_rules ~loc:(fst lib.name) ~cctx ~buildable ~sctx ~scope
~dir
~dir ~version
in
library_rules lib ~local_lib ~cctx ~source_modules ~dir_contents
~compile_info
Expand Down
10 changes: 10 additions & 0 deletions test/blackbox-tests/test-cases/ctypes/directories.t
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,13 @@ We ensure that just `-I lib` or `-I .` are not enough on their own.
$ echo "(-I .)" > lib/extra_flags.sexp
$ dune build > /dev/null 2>&1
[1]

With 0.3, everything is relative to the directory.

$ cat > dune-project << EOF
> (lang dune 3.7)
> (using ctypes 0.3)
> EOF

$ echo "(-I .)" > lib/extra_flags.sexp
$ dune build

0 comments on commit 3218637

Please sign in to comment.