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

[WIP/RFC] Make cmakeFlags more ergonomic #17886

Closed

Commits on Aug 5, 2018

  1. Configuration menu
    Copy the full SHA
    8dfd2c7 View commit details
    Browse the repository at this point in the history
  2. WIP cmake: make cmakeFlags more ergonomic

    There are three main parts to this change:
    - Support a new `setupHookFunc` in `mkDerivation`
    - Using attribute sets for `cmakeFlags` in Nix
    - Passing `cmakeFlags` to the builder more smartly
    
    == Introducing `setupHookFunc`
    
    The `setupHook` attribute allows a derivation to register arbitrary
    modifications to run in the context of downstream dependents' builds.
    
    To enable similar modifications to be made to the attributes passed
    to `mkDerivation`, teach `mkDerivation` a new trick: `setupHookFunc`.
    A derivation can set `setupHookFunc` to a Nix function
    which will be called for downstream dependencies
    (TODO using the same logic as the setupHook inclusion),
    and which takes the attribute set which was passed to `mkDerivation`
    and returns a new attribute set with any desired changes.
    
    These will stack (TODO: resolution order?) for composability,
    and having these live alongside the original derivation
    avoids cluttering `mkDerivation` with cmake-specific code
    (which was done in an earlier iteration).
    
    TODO: benchmark
    
    == Using Attribute Sets for `cmakeFlags`
    
    Almost all flags passed to `cmakeFlags` are setting CMake cache options
    with "-D<name>=<value>" or "-D<name>:<type>=<value>".
    Because the CMake cache is essentially a set of keys and values,
    model `cmakeFlags` as an attribute set in Nix as well.
    
    The cmake `setupHookFunc` will take a `cmakeFlags` set
    and convert each key/value pair to an appropriate "-D" option for cmake.
    String values are used as is, while integers are converted to strings
    and booleans are converted to `"ON"` and `"OFF"`.
    This presents the following benefits:
    - Removal of "-D" visual noise everywhere for ease of reading.
    - The `=` operater is literal, allowing extra whitespace for more ease
      of reading.
    - CMake options are now first class Nix values that can be operated on
      directly with the full strength of the Nix language.
      For example, boolean values can be used directly because the
      serialization logic is consolidated into the cmake `setupHookFunc`,
      getting rid of helpers like `edf`
      and making it easier to re-use feature flags like `pythonSupport`.
    - Sets automatically sort options, improving cache re-use.
    - An override which updates a CMake flag option will only incur
      (amortized) O(1) cost with a set, as opposed to O(n) cost with an
      (unsorted) list, which would require a full linear search.
      It's also shorter to write: just use `//`.
    
    A few other CMake flag types are supported:
    - Setting a value to null will cause its key to be unset via "-U<name>".
    - The `generator` key is mapped to the "-G<value>" option.
    - The `extraArgs` key is an escape hatch; any flags in this list of
      strings are not pre-processed, but concatenated to the generated list.
    
    Because `setupHookFunc`s are processed during `mkDerivation`,
    when overriding `cmakeFlags` `overrideAttrs` should be used instead of
    `overrideDerivation` so the cmake `setupHookFunc` has a chance to rerun.
    
    == Passing `cmakeFlags` to the builder more smartly
    
    Nix's regular conversion of lists to an environment variable
    simply concatenates the contents with spaces,
    which breaks if any of the flags themselves contain spaces.
    `cmakeFlagsArray` was added as a way to get around this limitation,
    but is unsatisfactory to use because items must be appended via bash
    in a preConfigure hook.
    
    Instead, pass the list to the builder in a smarter way:
    instead of relying on Nix's conversion to a string,
    perform our own conversion by escaping double quotes,
    double quoting each item, and passing the flags as a Bash array,
    which is hydrated via `eval`.
    
    This handles flags with spaces, newlines and other whitespace,
    as well as double quotes, faithfully.
    
    TODO: does it handle eg some_var="$out/blah"
    Make the list available during preConfigure as a bash array, so any
    dynamic modifications to the CMake flags can be done there.
    
    These changes make also `cmakeFlagsArray` redundant, so it has been
    removed and replaced in all cases with `cmakeFlags`.
    aneeshusa committed Aug 5, 2018
    Configuration menu
    Copy the full SHA
    e62f88b View commit details
    Browse the repository at this point in the history