Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ctypes stanza #3905

Closed
wants to merge 78 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
716d790
start working on ctypes stanza
mbacarella Oct 30, 2020
40463b5
Merge branch 'master' of github.com:mbacarella/dune into ctypes-stanza
mbacarella Oct 30, 2020
ec9e8c1
pseudocode direction
mbacarella Nov 6, 2020
bbb3f93
naive first pass translation of hand-written dune file rules. with er…
mbacarella Dec 6, 2020
6f68c0c
have ctypes provide list of generated files to Dir_contents
mbacarella Dec 7, 2020
5ea1a03
lowercase
mbacarella Dec 7, 2020
f372ccd
save progress
mbacarella Dec 24, 2020
5743185
dont use Build.exec
mbacarella Dec 25, 2020
c68c1b6
no need for this variant anymore
mbacarella Dec 25, 2020
83947d8
saving work, almost almost compiles a ctypes module
mbacarella Jan 26, 2021
69a0f55
include parsing_context for :include directives
mbacarella Jan 29, 2021
a4d7fc3
minimal example works
mbacarella Jan 31, 2021
76a50c9
declare module names
mbacarella Feb 2, 2021
760b3ea
move from library to buildable stanza, so exe can use ctypes too
mbacarella Feb 4, 2021
1a0875f
finish ctypes stanza for executables
mbacarella Feb 4, 2021
8b8ca1f
inch towards a finalized ctypes config (for ctypes 0.1)
mbacarella Feb 13, 2021
ef88772
headers include or preamble
mbacarella Feb 14, 2021
545bf2e
get rid of extra cflags file. support vendoring
mbacarella Feb 14, 2021
227f520
user_error instead of failwith
mbacarella Feb 16, 2021
fdbbb13
ctypes_library is its own top-level stanza now
mbacarella Feb 21, 2021
d993a1d
decided to not do a top-level stanza after all
mbacarella Feb 22, 2021
1bd95b1
trying an approach with no intermediate libraries
mbacarella Mar 8, 2021
9d4662d
Add a test showing that Dune always pulls unused ml files
jeremiedimino Mar 8, 2021
7bd71b9
Narrow dependencies on .ml files for executables
jeremiedimino Mar 8, 2021
09fe7fd
resolve merge conflict with ctypes-stanza
mbacarella Mar 8, 2021
f0810fa
Merge remote-tracking branch 'jeremiedimino/dont-pull-all-ml-for-tran…
mbacarella Mar 8, 2021
365505e
(executables ... (ctypes ...)) almost works
mbacarella Mar 9, 2021
8a9c921
dont need the ctypes.foreign library
mbacarella Mar 10, 2021
827ec06
pull ctypes stubs into Buildable.foreign_stubs
mbacarella Mar 11, 2021
a75d8d6
implement ctypes for libraries too
mbacarella Mar 11, 2021
b1c9e40
add ctypes libraries to buildable if user uses ctypes
mbacarella Mar 12, 2021
93f69cd
use ctypes link flags in libraries
mbacarella Mar 12, 2021
ac3ad60
remove unneeded code
mbacarella Mar 13, 2021
326c279
build some blackbox tests
mbacarella Mar 25, 2021
22d7771
simplify stanza a bit
mbacarella Apr 1, 2021
c2f2521
start documenting ctypes stanza
mbacarella Apr 1, 2021
4702cb1
capital percent S
mbacarella Apr 16, 2021
64a581b
better error message
mbacarella Apr 16, 2021
44988cc
support building docs for libraries that depend on foreign_librarys
mbacarella Apr 23, 2021
968e238
dont install modules that are for stub generation
mbacarella Apr 23, 2021
12d58bf
simplifiy non_installable_modules
mbacarella Apr 24, 2021
823151f
whitespace
mbacarella Apr 24, 2021
cac6945
revert recent changes to install rules
mbacarella Apr 24, 2021
00d9efc
exclude ctypes code-gen programs from being added to archives
mbacarella Apr 24, 2021
33b73de
ctypes doc fix
mbacarella Apr 24, 2021
efcb33a
support repeated function_description stanzas
mbacarella Apr 28, 2021
4f535b8
list ctypes in CHANGES.md
mbacarella Apr 29, 2021
99aca83
fix descriptions
mbacarella May 19, 2021
90dfeed
merge main into ctypes-stanza
mbacarella May 20, 2021
e25db44
fix accidentally calling build_all twice
mbacarella May 20, 2021
233efad
fix comment
mbacarella May 20, 2021
746744d
re-add PR request number to CHANGES.md entry
mbacarella May 27, 2021
8f3227b
extension appears in dune 3.0 lang
mbacarella May 27, 2021
550e56f
Small doc tweak
rgrinberg Jul 20, 2021
8ed91d0
Move Dune_file.Ctypes to own module
rgrinberg Jul 20, 2021
60d1303
did not actually need to add this sub_systems field here
mbacarella Jul 20, 2021
35f66b1
ctypes build tests dune-project 2.8 -> 3.0
mbacarella Jul 20, 2021
3a8d53d
quick description of each unit test
mbacarella Jul 20, 2021
84ab501
remove whitespace-only changes from PR
mbacarella Jul 20, 2021
2da56ab
make fmt
mbacarella Jul 20, 2021
1655d9b
more ctypes unit tests (pkg-config probed args)
mbacarella Jul 21, 2021
0be0ea6
more docs on using ctypes, with quick example ocaml code
mbacarella Jul 22, 2021
a9a88e6
more unit test coverage
mbacarella Jul 22, 2021
4f341ec
unneeded file
mbacarella Jul 22, 2021
b175c71
coverage for preamble headers
mbacarella Jul 22, 2021
9e165d6
one more test
mbacarella Jul 22, 2021
d3519d3
Merge branch 'main' into ctypes-stanza
mbacarella Aug 2, 2021
0c46b09
resolve merge conflict
mbacarella Oct 14, 2021
b658441
Merge branch 'main' into ctypes-stanza
mbacarella Oct 15, 2021
5f57410
resolve merge conflict markers in doc
mbacarella Oct 15, 2021
3e48615
Merge branch 'ctypes-stanza' of github.com:mbacarella/dune into ctype…
mbacarella Oct 15, 2021
52ed839
fix(ctypes): busted merge conflict
rgrinberg Oct 17, 2021
8fa4100
test(ctypes): require ctypes as test dependency
rgrinberg Oct 17, 2021
627967e
test(ctypes): remove binaries
rgrinberg Oct 17, 2021
605350f
Merge branch 'main' into ctypes-stanza
rgrinberg Oct 17, 2021
18ca12c
chore(nix): add ctypes to test dependencies
rgrinberg Oct 17, 2021
9781f16
chore: add ctypes to test deps in makefile
rgrinberg Oct 17, 2021
cda682e
chore: enable ctypes tests on linux only
rgrinberg Oct 17, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 0 additions & 33 deletions src/dune_rules/ctypes.ml

This file was deleted.

13 changes: 0 additions & 13 deletions src/dune_rules/ctypes.mli

This file was deleted.

117 changes: 117 additions & 0 deletions src/dune_rules/ctypes_rules.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
open! Dune_engine

(* This module simply expands a [(library ... (ctypes ...))] stanza into the
set of [library], [rule] and [action] stanzas and .ml files needed to
more conveniently build OCaml bindings for C libraries. Aside from perhaps
providing a '#include "header.h"' line, you should be able to wrap an
entire C library without writing a single line of C code.

The result of this stanza is a single library you can reference from your
projects to get at the underlying C types/data/functions that have been
exposed.

All you have to do is configure the stanza and provide two ocaml modules
- the types/data wrapping module
- the functions wrapping module

This module will then, behind the scenes
- generate a types/constants generator
- generate a functions generator
- set up a discovery program to query pkg-config for compile and link flags
- use the types/data and functions modules you filled in to tie everything
together into a neat library
*)

let gen_rule ~targets ~action () =
let open Dune_file in
{ Rule.targets; action }

let gen_library ?wrapped ?foreign_stubs ?c_library_flags ~name
~public_name ~modules ~libraries () =
let open Dune_file in
{ Library.name; public_name; modules; libraries; wrapped; foreign_stubs }

let gen_executable ~name ~modules ~libraries () =
let open Dune_file in
{ Executable.name; modules; libraries }

(* It may help to understand what this generator function is trying to do by
having a look at the hand-written version it's replacing.
XXX: link to mpg123 dune file *)
let really_expand lib ctypes =
let open Dune_file in
[ gen_executable
~name:"mpg123_discover"
~libraries:["dune.configurator"]
()
mbacarella marked this conversation as resolved.
Show resolved Hide resolved
; gen_rule
~targets:["c_flags.sexp"; "c_flags.txt"; "c_library_flags.sexp"]
~action:["run discover.exe"]
()
mbacarella marked this conversation as resolved.
Show resolved Hide resolved
; gen_library
~name:("mpg123_c_type_descriptions")
~public_name:("mpg123.c_type_descriptions")
~modules:"Mpg123_c_type_descriptions"
~libraries:["ctypes"]
()
; gen_executable
~name:"type_gen"
~modules:"Type_gen"
~libraries:["ctypes.stubs"; "ctypes.foreign"; "mpg123_c_type_descriptions"]
()
; gen_rule_stdout
~with_stdout_to:"c_generated_types.c"
~run:("./type_gen.exe")
()
; gen_rule
~targets:["c_generated_types.exe"]
~deps:[":c c_generated_types.c"]
mbacarella marked this conversation as resolved.
Show resolved Hide resolved
~action:["system blah blah"]
()
; gen_rule_stdout
~with_stdout_to:"mpg123_c_generated_types.ml"
~run:("./c_generated_types.exe")
mbacarella marked this conversation as resolved.
Show resolved Hide resolved
()
; gen_library
~name:"mpg123_c_function_descriptions"
~public_name:"mpg123.c_function_descriptions"
~modules:["Mpg123_c_generated_types"; "Mpg123_c_function_descriptions";
"Mpg123_c_types"]
~wrapped:false
~flags:":standard -w -27 -w -9"
~libraries:["ctypes"; "mpg123_c_type_descriptions"]
()
; gen_executable
~name:"function_gen"
~modules:"Function_gen"
~libraries:["ctypes.stubs"; "mpg123_c_function_descriptions"]
()
; gen_rule_stdout
~with_stdout_to:"c_generated_functions.c"
~run:"./function_gen.exe c mpg123_stub"
()
; gen_rule_stdout
~with_stdout_to:"mpg123_c_generated_functions.ml"
~run:"./function_gen.exe ml mpg123_stub"
()
; gen_library
~name:"mpg123_c"
~public_name:"mpg123.c"
~libraries:["ctypes"; "mpg123_c_function_descriptions"]
~modules:["Mpg123_c"; "Mpg123_c_generated_functions"]
~foreign_stubs:[
("language" , "c");
("names" , "c_generated_functions");
("flags" , ":include c_flags.sexp")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this need to be in a separate library? Can't it be a part of the user defined library? I think I forgot why we need this mpg123 vs. mpg123.c split.

Copy link
Collaborator Author

@mbacarella mbacarella Nov 6, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is actually what luv does, which I adapted. I didn't really question it but yeah, I'm not seeing why it can't simply set up in the library that contains the ctypes stanza.

]
~c_library_flags:":include c_library_flags.sexp"
()
]

let expand = function
| Dune_file.Library lib ->
begin match lib.Dune_file.Library.ctypes with
| Some ctypes -> really_expand lib ctypes
| None -> assert false
end
| _ -> assert false
44 changes: 39 additions & 5 deletions src/dune_rules/dune_file.ml
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,6 @@ module Buildable = struct
; flags : Ocaml_flags.Spec.t
; js_of_ocaml : Js_of_ocaml.t
; allow_overlapping_dependencies : bool
; ctypes : Ctypes.t list
}

let decode ~in_library ~allow_re_export =
Expand Down Expand Up @@ -233,9 +232,7 @@ module Buildable = struct
(multi_field "instrumentation"
( Dune_lang.Syntax.since Stanza.syntax (2, 7)
>>> fields (field "backend" (located Lib_name.decode)) ))
and+ ctypes =
(multi_field "ctypes" Ctypes.decode)
in
in
let preprocess =
let init =
let f libname = Preprocess.With_instrumentation.Ordinary libname in
Expand Down Expand Up @@ -288,7 +285,6 @@ module Buildable = struct
; flags
; js_of_ocaml
; allow_overlapping_dependencies
; ctypes
}

let has_foreign t =
Expand Down Expand Up @@ -479,6 +475,40 @@ module Mode_conf = struct
end
end

module Ctypes = struct
type t =
{ name : string
; pkg_config_name : string option
; c_headers : string option
; generated_modules : string list
}

let name = "ctypes"

type Stanza.t += T of t

let decode =
let open Dune_lang.Decoder in
fields
(let+ name = field "name" string
and+ pkg_config_name = field_o "pkg_config_name" string
and+ c_headers = field_o "c_headers" string
and+ generated_modules = field "generated_modules" (repeat string)
in
{ name; pkg_config_name; c_headers; generated_modules })

let syntax =
Dune_lang.Syntax.create ~name ~desc:"the ctypes extension"
(* XXX: insert the latest version of dune language *)
[ ((0, 1), `Since (2, 8))
]

let () =
let open Dune_lang.Decoder in
Dune_project.Extension.register_simple syntax
(return [ (name, decode >>| fun x -> [ T x ]) ])
end

module Library = struct
module Wrapped = struct
include Wrapped
Expand Down Expand Up @@ -539,6 +569,7 @@ module Library = struct
; special_builtin_support : Lib_info.Special_builtin_support.t option
; enabled_if : Blang.t
; instrumentation_backend : (Loc.t * Lib_name.t) option
; ctypes : Ctypes.t option
}

let decode =
Expand Down Expand Up @@ -617,6 +648,8 @@ module Library = struct
field_o "package"
( Dune_lang.Syntax.since Stanza.syntax (2, 8)
>>> located Stanza_common.Pkg.decode )
and+ ctypes =
(field_o "ctypes" Ctypes.decode)
in
let wrapped =
Wrapped.make ~wrapped ~implements ~special_builtin_support
Expand Down Expand Up @@ -705,6 +738,7 @@ module Library = struct
; special_builtin_support
; enabled_if
; instrumentation_backend
; ctypes
})

let package t =
Expand Down
14 changes: 13 additions & 1 deletion src/dune_rules/dune_file.mli
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ module Buildable : sig
; flags : Ocaml_flags.Spec.t
; js_of_ocaml : Js_of_ocaml.t
; allow_overlapping_dependencies : bool
; ctypes : Ctypes.t list
}

(** Check if the buildable has any foreign stubs or archives. *)
Expand Down Expand Up @@ -112,6 +111,18 @@ module Mode_conf : sig
end
end

module Ctypes : sig
type t =
{ name : string
; pkg_config_name : string option
; c_headers : string option
; generated_modules : string list
}

type Stanza.t += T of t
end


module Library : sig
type visibility =
| Public of Public_lib.t
Expand Down Expand Up @@ -148,6 +159,7 @@ module Library : sig
; special_builtin_support : Lib_info.Special_builtin_support.t option
; enabled_if : Blang.t
; instrumentation_backend : (Loc.t * Lib_name.t) option
; ctypes : Ctypes.t option
}

val sub_dir : t -> string option
Expand Down
6 changes: 6 additions & 0 deletions src/dune_rules/dune_load.ml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ module Dune_file = struct

let parse sexps ~dir ~file ~project =
let stanzas = Dune_file.Stanzas.parse ~file project sexps in
let stanzas = List.concat_map stanzas ~f:(fun stanza ->
match stanza with
| Dune_file.Stanzas.Library { ctypes = Some ctypes; _ } ->
Ctypes_rules.expand stanza
| _ -> [stanza])
in
let stanzas =
if !Clflags.ignore_promoted_rules then
List.filter stanzas ~f:(function
Expand Down