How to keep static builds as is while adding ppx_expect support for dev/test builds?

Dear all, Cc @yurug @AltGr,

I have an issue related to dune, ppx_expect, and linking.

Context:

  • I’m working on learn-ocaml, to implement ppx_expect and ppx_inline_test support.
  • I added several unit tests in src/state/learnocaml_data.ml, in this PR.
  • So far, so good: the PR is ready and all our CI jobs (using GitHub Actions) are green;
    except the jobs for the Linux/macOS static builds.
  • Here is the error message (from this job):
    ...
    collect2: error: ld returned 1 exit status
    File "_none_", line 1:
    Error: Error while building custom runtime system
    
  • Locally, this can be reproduced by running ./scripts/static-build.sh

I suspect that removing

  (inline_tests)
  (preprocess (pps ppx_expect ppx_inline_test))

just for static builds would fix the issue? (do you think this is the case?)

Next, what I tried:

Replacing src/state/dune with:

...

(library
 (name learnocaml_data)
 (wrapped false)
 (modules Learnocaml_data)
 (libraries asak sha learnocaml_toplevel_history learnocaml_report learnocaml_repository)
  (enabled_if (= %{env:LINKING_MODE=dynamic} dynamic))
  (inline_tests)
  (preprocess (pps ppx_expect ppx_inline_test))
)

(library
 (name learnocaml_data)
 (wrapped false)
 (modules Learnocaml_data)
 (libraries asak sha learnocaml_toplevel_history learnocaml_report learnocaml_repository)
 (enabled_if (<> %{env:LINKING_MODE=dynamic} dynamic))
)

...

Unfortunately, I got:

File "src/state/dune", line 16, characters 19-44:
16 |   (enabled_if (= %{env:LINKING_MODE=dynamic} dynamic))
                        ^^^^^^^^^^^^^^^^^^^^^^^^^
Error: Only architecture, system, model, os_type, ccomp_type, profile,
ocaml_version and context_name variables are allowed in this 'enabled_if'
field. If you think that env should also be allowed, please file an issue
about it.

What solutions could workaround this? (ideally, feasible with the dune version we currently use: 2.9.0)

Thanks!

Did you try putting the tests in their own library, and then using the enabled_if stanza with some dune profile that only runs the tests in the right situations?

Not yet, thanks for the suggestion: that could work! I’ll try this.

FYI @mooreryan indeed, that worked as you suggested, thanks!

(The only drawback is that after “externalizing” ppx_inline_test in another module, we can only unit-test “public” functions of the other modules.)

1 Like

That’s true. I suppose whether it is a good or bad feature depends on your perspective.

However, one way around it is to use Private submodules as is done in the janestreet base/core. Here is the quote pulled from that style guide I linked to:

Private submodules contain functionality that is internal to the implementation, intended for use in closely-related code like expects tests and benchmarks of the module itself. Such code is often in another library and needs access to private internals of the main module.

2 Likes