Functions or other ways to reuse code in gni templates

9 views
Skip to first unread message

Łukasz Anforowicz

unread,
Jul 13, 2022, 1:01:16 PM7/13/22
to gn-dev, danakj
Hello gn-dev@,

I've been trying to create GNI template that uses `metadata` to gather a cmdline argument for an external tool (for more details, please see the CL here, or the Crubit discussion here).  The metadata file desirably ends up containing lines that look more or less like this:

{"t": "target1_name", "h": ["/home/lukasza/.../full/path/.../target1_header1.h", "/home/lukasza/.../full/path/.../target1_header2.h"]}

My problem is related to the desire to ensure that the lines above are valid JSON snippets - this requires escaping some characters in target names and in header paths (e.g. replacing quotes in target names and paths with a backslash character + similarly escaping backslashes).

The above leads to the following questions:
  • Q1: Does GN offer a generic escaping utility (other than the `string_replace` function)?
  • Q2: Can my GNI file declare a function that I can reuse (I'd rather call `escapeLukaszaValues` twice than duplicate the escaping code twice)?
  • Q3: Maybe I can structure metadata gathering differently and move "escaping" into the python action that reads the metadata file?  This seems difficult given that there can be *multiple* headers per target.

Thanks,

Lukasz

Tomasz Śniatowski

unread,
Jul 13, 2022, 2:08:04 PM7/13/22
to Łukasz Anforowicz, gn-dev, danakj
Hi!

I had a quick look out of curiosity. Manually gluing up json bits strikes me as somewhat fragile and inflexible. I would instead lean into producing a digestible json file using gn conversions, even if that requires some mild post-processing -- but I'd expect escaping should be handled by gn. So sort-of Q3.

It might be possible to use output_conversion = "json" in the generated_file, and make metadata contain nested dictionaries. I'm not clear if this last bit is allowed by the docs, strictly speaking, but using:

group("dep") {
  metadata = {
    foo = [
      {
        h1 = [
          "a\"",
          "b\\b",
          "c\\n\\\"c",
        ]
        h2 = [ "dddd" ]
      }
    ]
  }
}

generated_file("file") {
  output_conversion = "json"
  deps = [ ":dep" ]
  outputs = [ "file.json" ]
  data_keys = [ "foo" ]
}

gets me a json file looking like this:

[
  {
    "h1": [
      "a\"",
      "b\b",
      "c\n\\\"c"
    ],
    "h2": [
      "dddd"
    ]
  }
]

which is promising. h1 and h2 must be valid gn identifiers in this example but this can be reworked with further nesting so they're string values, and so on.
--
Tomasz Śniatowski


--
To unsubscribe from this group and stop receiving emails from it, send an email to gn-dev+un...@chromium.org.

Łukasz Anforowicz

unread,
Jul 13, 2022, 2:42:22 PM7/13/22
to Tomasz Śniatowski, gn-dev, danakj
Thanks!  This is exactly what I was looking for - I missed that there is `output_conversion = "json"` option.

David Turner

unread,
Jul 13, 2022, 2:59:40 PM7/13/22
to Łukasz Anforowicz, gn-dev, danakj
Hello Łukasz,



Le mer. 13 juil. 2022 à 19:01, Łukasz Anforowicz <luk...@chromium.org> a écrit :
Hello gn-dev@,

I've been trying to create GNI template that uses `metadata` to gather a cmdline argument for an external tool (for more details, please see the CL here, or the Crubit discussion here).  The metadata file desirably ends up containing lines that look more or less like this:

{"t": "target1_name", "h": ["/home/lukasza/.../full/path/.../target1_header1.h", "/home/lukasza/.../full/path/.../target1_header2.h"]}

My problem is related to the desire to ensure that the lines above are valid JSON snippets - this requires escaping some characters in target names and in header paths (e.g. replacing quotes in target names and paths with a backslash character + similarly escaping backslashes).

The above leads to the following questions:
There is none as far as I know. 
  • Q2: Can my GNI file declare a function that I can reuse (I'd rather call `escapeLukaszaValues` twice than duplicate the escaping code twice)?
 No, GN does not supports user-defined functions, and there are no plans to add them.
  • Q3: Maybe I can structure metadata gathering differently and move "escaping" into the python action that reads the metadata file?  This seems difficult given that there can be *multiple* headers per target.

One way to do what you describe is to introduce, for each metadata file, an extra target that processes it and produces a valid JSON file, which would then be fed to your tool.
Alternatively, you could have one script that takes several metadata files as input, and generates a single JSON output. That's essentially what we do with a variety of metadata files in the Fuchsia build (though very often our tools would just consume the input as in and do their own expansion internally).

Hope this helps,

- Digit

 
Reply all
Reply to author
Forward
0 new messages