.. post:: 2018-08-05 :tags: OCaml, Ppx, ppxlib, dune Extension Points - Ppxlib & Dune Update ======================================= In a :ref:`previous post`, I've described what are the latest technologies used to construct and package ppx rewriters. In just eight months a couple important changes have occurred that require ppx authors to react. In this post, I'd like to describe these changes and demonstrate how to update your ppx rewriters to keep up with them. Introduction of ppxlib_ ======================= There's been a welcome consolidation in the ppx ecosystem. First of all, important tools in the ppx ecosystem such ocaml-migrate-parsetree_, ppx_tools_versioned_, ppx_deriving_ have been moved to the ocaml-ppx_ organization. Second of all, Jane Street has consolidated the foundations of their ppx stack: ppx_core, ppx_driver, ppx_ast, ppx_traverse into a single library that they've kindly moved to ocaml-ppx and moved its development into the open, on github. The new library that encompasses this stack is called ppxlib_, and now I'll describe how to migrate the simple ppx_getenv2_ plugin from the previous post to ppxlib_. Luckily, the transition is going to be trivial and maintainly consists of renaming dependencies and modules. * The findlib package ``ppx_metaquot`` has been renamed to ``ppxlib.metaquot``, and ``ppx_core``, ``ppx_traverse``, ``ppx_driver``, are all replaced by ``ppxlib``. * All ppx libraries now live under the ``Ppxlib`` module. Driver related code has been to ``Ppxlib.Driver``. Here's a diff of the (minimal) changes required for ppx_getenv2_: :: -open Ppx_core +open Ppxlib let name = "getenv" @@ -14,4 +14,4 @@ let ext = Ast_pattern.(single_expr_payload (estring __)) expand -let () = Ppx_driver.register_transformation name ~extensions:[ext] +let () = Ppxlib.Driver.register_transformation name ~extensions:[ext] Changes in Dune =============== A couple of welcome changes in dune have also occurred to simplify using and testing ppx rewriters. Writing expectation tests for ppx rewriters is now simpler and doesn't require any external diff tools. We can now rely on dune's ``diff`` action to setup the rule: .. code-block:: lisp (rule (targets pp.result) (deps test.ml) (action (setenv PPX_GETENV2 foobar (run ./pp.exe --impl %{deps} -o %{targets})))) (alias (name runtest) (action (diff pp.expected pp.result))) and then use dune's promotion_ feature to update the expected results (``pp.expected`` in this case). The second change is a simplification with regard to drivers. Dune will now transparently select the "best" driver automatically. This is a welcome improvement because it's yet another implementation detail that doesn't concern the majority of users (and even authors). There exist only two ppx drivers today, the basic one from ocaml-migrate-parsetree_ and the full featured one from ppxlib_. Given that we're using ppxlib in ppx_getenv2 we get to use the best driver automatically. It is actually possible to implement your own driver, but I can't imagine too many useful applications for this and will not document this. Final Words =========== This isn't the last chapter of updates regarding keeping your ppx up to date. There are more changes in the horizon that will require ppx authors to keep their code up to date, such as ppx_view_ to give one example. If any of the changes described above were a bit too brief, the ppx_getenv2_ repo is fully up to date. The purpose of this project is to be a reference point for packaging ppx, and I intend to keep it up to date for this purpose. .. _ocaml-ppx: https://github.com/ocaml-ppx/ .. _ppxlib: https://github.com/ocaml-ppx/ppxlib/ .. _ocaml-migrate-parsetree: https://github.com/ocaml-ppx/ocaml-migrate-parsetree .. _ppx_deriving: https://github.com/ocaml-ppx/ppx_deriving .. _promotion: https://dune.readthedocs.io/en/latest/dune-files.html#diffing-and-promotion .. _ppx_view: https://github.com/ocaml-ppx/ppx_view .. _ppx_getenv2: https://github.com/rgrinberg/ppx_getenv2 .. _ppx_tools_versioned: https://github.com/ocaml-ppx/ppx_tools_versioned