From 4cb044433c177868d7e35957f76ce29fa9aaeb47 Mon Sep 17 00:00:00 2001 From: Alberto Sartori Date: Tue, 21 Feb 2023 17:01:02 +0100 Subject: rules: CC/auto: add "config_file" rule to generate a c/c++ header... ...starting from a template (aka configuration file), and using the variables defined via a ["CC/auto", "config"] target. For example, to use a CMake configuration file, the targets could be defined as follows ... , "foo-header-blueprint": { "type": ["@", "rules", "CC/auto", "config_file"] , "input": ["config.hpp.in"] , "output": ["config.hpp"] , "stage": ["foo"] , "magic_string": ["cmakedefine"] , "@only": ["true"] } , "foo-header": { "type": "configure" , "target": "foo-header-blueprint" , "config": { "type": "let*" , "bindings": [ [ "defines" , [ ["var", "\"string value\""] , ["FOO_MAJOR_VERSION", "3"] , ["use_this_feature", true] ] ] ] , "body": {"type": "env", "vars": ["defines"]} } } ... The file config.hpp.in may look as follows #ifndef config_cmake #define config_cmake #cmakedefine var #cmakedefine use_this_feature #cmakedefine01 use_this_feature #cmakedefine unused #define FOO_VERSION @FOO_MAJOR_VERSION@ #define DONT_TOUCH_THIS ${FOO_MAJOR_VERSION} #endif and the generated configuration file foo/config.hpp is #ifndef config_cmake #define config_cmake #define var "string value" #define use_this_feature #define use_this_feature 1 /* #undef unused */ #define FOO_VERSION 3 #define DONT_TOUCH_THIS ${FOO_MAJOR_VERSION} #endif --- CC/auto/RULES | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) (limited to 'CC/auto/RULES') diff --git a/CC/auto/RULES b/CC/auto/RULES index 4f38504..7d27ff6 100644 --- a/CC/auto/RULES +++ b/CC/auto/RULES @@ -952,4 +952,150 @@ } } } +, "config_file": + { "doc": + [ "Generate a C/C++ config header from a given template" + , "" + , "Generate a C/C++ configuration header using defines specified via the" + , "target configuration. In the usual case, a target using this rule is" + , "configured by depending on it from a target that uses the built-in" + , "\"configure\" rule." + ] + , "field_doc": + { "output": + [ "Name of the header file to generate (incl. file name ext). Components are joined with /." + ] + , "input": ["The input configuration file, used as template."] + , "magic_string": + [ "The magic string (e.g., \"cmakedefine\") which identifies in which line" + , "we have to \"#define\" or \"#undef\" variables according to what is" + , "defined in the config field \"defines\"." + ] + , "@only": ["If set, only replace @VAR@ and not ${VAR}"] + } + , "config_doc": + { "defines": + [ "Set a define to a specific value unless its value is \"null\". Must" + , "contain a list of pairs. The first element of each pair is the define" + , "name and the second argument is the value to set. Strings must be" + , "properly escaped. Defines generated from this field are added last," + , "so that they can refer to defines from other \"defines*\" values." + ] + } + , "string_fields": ["magic_string", "@only", "output"] + , "target_fields": ["input"] + , "config_vars": ["defines"] + , "imports": + { "first": "first_list_entry" + , "last": "last_list_entry" + , "stage_singleton_field": ["", "stage_singleton_field"] + } + , "implicit": {"runner": ["config_runner.py"]} + , "expression": + { "type": "let*" + , "bindings": + [ [ "runner" + , { "type": "let*" + , "bindings": [["fieldname", "runner"], ["location", "runner"]] + , "body": + {"type": "CALL_EXPRESSION", "name": "stage_singleton_field"} + } + ] + , [ "dict-defines" + , { "type": "map_union" + , "$1": + { "type": "foreach" + , "range": {"type": "var", "name": "defines", "default": []} + , "var": "pair" + , "body": + { "type": "let*" + , "bindings": + [ ["list", {"type": "var", "name": "pair"}] + , ["key", {"type": "CALL_EXPRESSION", "name": "first"}] + , ["val", {"type": "CALL_EXPRESSION", "name": "last"}] + ] + , "body": + { "type": "singleton_map" + , "key": {"type": "var", "name": "key"} + , "value": {"type": "var", "name": "val"} + } + } + } + } + ] + , [ "magic_string" + , { "type": "assert_non_empty" + , "msg": "A non-empty string has to be provided for magic_string" + , "$1": + {"type": "join", "$1": {"type": "FIELD", "name": "magic_string"}} + } + ] + , [ "@only" + , { "type": "if" + , "cond": {"type": "FIELD", "name": "@only"} + , "then": "true" + , "else": "false" + } + ] + , [ "param-blob" + , { "type": "singleton_map" + , "key": "param-file" + , "value": + { "type": "BLOB" + , "data": + { "type": "json_encode" + , "$1": {"type": "var", "name": "dict-defines"} + } + } + } + ] + , [ "input-blob" + , { "type": "let*" + , "bindings": [["fieldname", "input"], ["location", "input-file"]] + , "body": + {"type": "CALL_EXPRESSION", "name": "stage_singleton_field"} + } + ] + , [ "outfile" + , { "type": "ACTION" + , "inputs": + { "type": "map_union" + , "$1": + [ {"type": "var", "name": "param-blob"} + , {"type": "var", "name": "input-blob"} + , {"type": "var", "name": "runner"} + ] + } + , "cmd": + [ "./runner" + , "input-file" + , "param-file" + , {"type": "var", "name": "magic_string"} + , {"type": "var", "name": "@only"} + ] + , "outs": ["out"] + } + ] + , [ "outfile" + , { "type": "singleton_map" + , "key": + { "type": "join" + , "separator": "/" + , "$1": {"type": "FIELD", "name": "output"} + } + , "value": + { "type": "lookup" + , "key": "out" + , "map": {"type": "var", "name": "outfile"} + } + } + ] + ] + , "body": + { "type": "RESULT" + , "artifacts": {"type": "var", "name": "outfile"} + , "runfiles": {"type": "var", "name": "outfile"} + } + } + } } -- cgit v1.2.3