summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKlaus Aehlig <klaus.aehlig@huawei.com>2022-02-22 17:03:21 +0100
committerKlaus Aehlig <klaus.aehlig@huawei.com>2022-02-22 17:03:21 +0100
commit86c4f55b6f578bfae74ab35151c1e4425b7e1fd1 (patch)
treea0eb1319d6449726f345b7c2f237c3fbffa71096
downloadrules-cc-86c4f55b6f578bfae74ab35151c1e4425b7e1fd1.tar.gz
Initial self-hosting commit
This is the initial version of our tool that is able to build itself. In can be bootstrapped by ./bin/bootstrap.py Co-authored-by: Oliver Reiche <oliver.reiche@huawei.com> Co-authored-by: Victor Moreno <victor.moreno1@huawei.com>
-rw-r--r--CC/EXPRESSIONS504
-rw-r--r--CC/RULES538
-rw-r--r--CC/proto/EXPRESSIONS301
-rw-r--r--CC/proto/RULES72
-rw-r--r--CC/test/RULES265
-rw-r--r--CC/test/test_runner.sh36
-rw-r--r--EXPRESSIONS89
-rw-r--r--data/RULES42
-rw-r--r--proto/RULES105
-rw-r--r--transitions/EXPRESSIONS13
10 files changed, 1965 insertions, 0 deletions
diff --git a/CC/EXPRESSIONS b/CC/EXPRESSIONS
new file mode 100644
index 0000000..f1e6592
--- /dev/null
+++ b/CC/EXPRESSIONS
@@ -0,0 +1,504 @@
+{ "default-CC":
+ { "expression":
+ { "type": "join"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ { "type": "foreach"
+ , "var": "x"
+ , "range": {"type": "FIELD", "name": "defaults"}
+ , "body":
+ { "type": "DEP_PROVIDES"
+ , "provider": "CC"
+ , "dep": {"type": "var", "name": "x"}
+ }
+ }
+ }
+ }
+ }
+, "default-CXX":
+ { "expression":
+ { "type": "join"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ { "type": "foreach"
+ , "var": "x"
+ , "range": {"type": "FIELD", "name": "defaults"}
+ , "body":
+ { "type": "DEP_PROVIDES"
+ , "provider": "CXX"
+ , "dep": {"type": "var", "name": "x"}
+ }
+ }
+ }
+ }
+ }
+, "default-CFLAGS":
+ { "expression":
+ { "type": "++"
+ , "$1":
+ { "type": "foreach"
+ , "var": "x"
+ , "range": {"type": "FIELD", "name": "defaults"}
+ , "body":
+ { "type": "DEP_PROVIDES"
+ , "provider": "CFLAGS"
+ , "dep": {"type": "var", "name": "x"}
+ }
+ }
+ }
+ }
+, "default-CXXFLAGS":
+ { "expression":
+ { "type": "++"
+ , "$1":
+ { "type": "foreach"
+ , "var": "x"
+ , "range": {"type": "FIELD", "name": "defaults"}
+ , "body":
+ { "type": "DEP_PROVIDES"
+ , "provider": "CXXFLAGS"
+ , "dep": {"type": "var", "name": "x"}
+ }
+ }
+ }
+ }
+, "default-ENV":
+ { "expression":
+ { "type": "foreach"
+ , "var": "x"
+ , "range": {"type": "FIELD", "name": "defaults"}
+ , "body":
+ { "type": "DEP_PROVIDES"
+ , "provider": "ENV"
+ , "dep": {"type": "var", "name": "x"}
+ }
+ }
+ }
+, "configure transition":
+ { "expression":
+ { "type": "let*"
+ , "bindings":
+ [ [ "OS"
+ , { "type": "assert_non_empty"
+ , "msg": "Missing field \"os\" for \"configure\"."
+ , "$1": {"type": "join", "$1": {"type": "FIELD", "name": "os"}}
+ }
+ ]
+ , [ "ARCH"
+ , { "type": "assert_non_empty"
+ , "msg": "Missing field \"arch\" for \"configure\"."
+ , "$1": {"type": "join", "$1": {"type": "FIELD", "name": "arch"}}
+ }
+ ]
+ , ["HOST_ARCH", {"type": "var", "name": "ARCH"}]
+ , [ "TARGET_ARCH"
+ , {"type": "join", "$1": {"type": "FIELD", "name": "target_arch"}}
+ ]
+ , [ "TARGET_ARCH"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "TARGET_ARCH"}
+ , "then": {"type": "var", "name": "TARGET_ARCH"}
+ , "else": {"type": "var", "name": "ARCH"}
+ }
+ ]
+ ]
+ , "body":
+ { "type": "map_union"
+ , "$1":
+ [ { "type": "singleton_map"
+ , "key": "OS"
+ , "value": {"type": "var", "name": "OS"}
+ }
+ , { "type": "singleton_map"
+ , "key": "ARCH"
+ , "value": {"type": "var", "name": "TARGET_ARCH"}
+ }
+ , { "type": "singleton_map"
+ , "key": "HOST_ARCH"
+ , "value": {"type": "var", "name": "HOST_ARCH"}
+ }
+ , { "type": "singleton_map"
+ , "key": "TARGET_ARCH"
+ , "value": {"type": "var", "name": "TARGET_ARCH"}
+ }
+ ]
+ }
+ }
+ }
+, "compile-deps":
+ { "expression":
+ { "type": "disjoint_map_union"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ { "type": "foreach"
+ , "var": "dep"
+ , "range": {"type": "FIELD", "name": "deps"}
+ , "body":
+ { "type": "DEP_PROVIDES"
+ , "dep": {"type": "var", "name": "dep"}
+ , "provider": "compile-deps"
+ , "default": {"type": "empty_map"}
+ }
+ }
+ , { "type": "foreach"
+ , "var": "dep"
+ , "range": {"type": "FIELD", "name": "deps"}
+ , "body":
+ {"type": "DEP_RUNFILES", "dep": {"type": "var", "name": "dep"}}
+ }
+ , { "type": "foreach"
+ , "var": "dep"
+ , "range": {"type": "FIELD", "name": "proto-deps"}
+ , "body":
+ { "type": "DEP_PROVIDES"
+ , "dep": {"type": "var", "name": "dep"}
+ , "provider": "compile-deps"
+ , "default": {"type": "empty_map"}
+ }
+ }
+ , { "type": "foreach"
+ , "var": "dep"
+ , "range": {"type": "FIELD", "name": "proto-deps"}
+ , "body":
+ {"type": "DEP_RUNFILES", "dep": {"type": "var", "name": "dep"}}
+ }
+ ]
+ }
+ }
+ }
+, "link-deps":
+ { "expression":
+ { "type": "disjoint_map_union"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ { "type": "foreach"
+ , "var": "dep"
+ , "range": {"type": "FIELD", "name": "deps"}
+ , "body":
+ { "type": "DEP_PROVIDES"
+ , "dep": {"type": "var", "name": "dep"}
+ , "provider": "link-deps"
+ , "default": {"type": "empty_map"}
+ }
+ }
+ , { "type": "foreach"
+ , "var": "dep"
+ , "range": {"type": "FIELD", "name": "deps"}
+ , "body":
+ {"type": "DEP_ARTIFACTS", "dep": {"type": "var", "name": "dep"}}
+ }
+ , { "type": "foreach"
+ , "var": "dep"
+ , "range": {"type": "FIELD", "name": "proto-deps"}
+ , "body":
+ { "type": "DEP_PROVIDES"
+ , "dep": {"type": "var", "name": "dep"}
+ , "provider": "link-deps"
+ , "default": {"type": "empty_map"}
+ }
+ }
+ , { "type": "foreach"
+ , "var": "dep"
+ , "range": {"type": "FIELD", "name": "proto-deps"}
+ , "body":
+ {"type": "DEP_ARTIFACTS", "dep": {"type": "var", "name": "dep"}}
+ }
+ ]
+ }
+ }
+ }
+, "objects":
+ { "vars": ["CXX", "CXXFLAGS", "ENV", "srcs", "compile-deps", "local hdrs"]
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ [ "include tree"
+ , { "type": "singleton_map"
+ , "key": "include"
+ , "value":
+ {"type": "TREE", "$1": {"type": "var", "name": "compile-deps"}}
+ }
+ ]
+ , [ "all hdrs"
+ , { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "include tree"}
+ , { "type": "to_subdir"
+ , "subdir": "work"
+ , "$1": {"type": "var", "name": "local hdrs"}
+ }
+ ]
+ }
+ ]
+ ]
+ , "body":
+ { "type": "map_union"
+ , "$1":
+ { "type": "foreach_map"
+ , "var_key": "src_name"
+ , "var_val": "src_val"
+ , "range": {"type": "var", "name": "srcs"}
+ , "body":
+ { "type": "let*"
+ , "bindings":
+ [ [ "work src_name"
+ , { "type": "join"
+ , "separator": "/"
+ , "$1": ["work", {"type": "var", "name": "src_name"}]
+ }
+ ]
+ , [ "inputs"
+ , { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "all hdrs"}
+ , { "type": "singleton_map"
+ , "key": {"type": "var", "name": "work src_name"}
+ , "value": {"type": "var", "name": "src_val"}
+ }
+ ]
+ }
+ ]
+ , [ "out"
+ , { "type": "change_ending"
+ , "$1": {"type": "var", "name": "src_name"}
+ , "ending": ".o"
+ }
+ ]
+ , [ "work out"
+ , { "type": "join"
+ , "separator": "/"
+ , "$1": ["work", {"type": "var", "name": "out"}]
+ }
+ ]
+ , [ "action output"
+ , { "type": "ACTION"
+ , "outs": [{"type": "var", "name": "work out"}]
+ , "inputs": {"type": "var", "name": "inputs"}
+ , "cmd":
+ { "type": "++"
+ , "$1":
+ [ [{"type": "var", "name": "CXX"}]
+ , {"type": "var", "name": "CXXFLAGS"}
+ , ["-I", "work", "-isystem", "include"]
+ , ["-c", {"type": "var", "name": "work src_name"}]
+ , ["-o", {"type": "var", "name": "work out"}]
+ ]
+ }
+ }
+ ]
+ , [ "staged output artifact"
+ , { "type": "map_union"
+ , "$1":
+ { "type": "foreach_map"
+ , "range": {"type": "var", "name": "action output"}
+ , "var_val": "object"
+ , "body":
+ { "type": "singleton_map"
+ , "key": {"type": "var", "name": "out"}
+ , "value": {"type": "var", "name": "object"}
+ }
+ }
+ }
+ ]
+ ]
+ , "body": {"type": "var", "name": "staged output artifact"}
+ }
+ }
+ }
+ }
+ }
+, "lib result":
+ { "vars":
+ [ "CXX"
+ , "CXXFLAGS"
+ , "CC"
+ , "CFLAGS"
+ , "ENV"
+ , "AR"
+ , "srcs"
+ , "hdrs"
+ , "private-hdrs"
+ , "link external"
+ , "extra-provides"
+ ]
+ , "imports":
+ { "artifacts": ["./", "..", "field_artifacts"]
+ , "compile-deps": "compile-deps"
+ , "link-deps": "link-deps"
+ , "objects": "objects"
+ , "default-CC": "default-CC"
+ , "default-CXX": "default-CXX"
+ , "default-CFLAGS": "default-CFLAGS"
+ , "default-CXXFLAGS": "default-CXXFLAGS"
+ , "default-ENV": "default-ENV"
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ [ "stage"
+ , { "type": "join"
+ , "separator": "/"
+ , "$1": {"type": "FIELD", "name": "stage"}
+ }
+ ]
+ , [ "CXX"
+ , { "type": "if"
+ , "cond": {"type": "FIELD", "name": "pure C"}
+ , "then":
+ { "type": "var"
+ , "name": "CC"
+ , "default": {"type": "CALL_EXPRESSION", "name": "default-CC"}
+ }
+ , "else":
+ { "type": "var"
+ , "name": "CXX"
+ , "default": {"type": "CALL_EXPRESSION", "name": "default-CXX"}
+ }
+ }
+ ]
+ , [ "CXXFLAGS"
+ , { "type": "if"
+ , "cond": {"type": "FIELD", "name": "pure C"}
+ , "then":
+ { "type": "var"
+ , "name": "CFLAGS"
+ , "default": {"type": "CALL_EXPRESSION", "name": "default-CFLAGS"}
+ }
+ , "else":
+ { "type": "var"
+ , "name": "CXXFLAGS"
+ , "default":
+ {"type": "CALL_EXPRESSION", "name": "default-CXXFLAGS"}
+ }
+ }
+ ]
+ , [ "ENV"
+ , { "type": "map_union"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "default-ENV"}
+ , [ { "type": "var"
+ , "name": "ENV"
+ , "default": {"type": "empty_map"}
+ }
+ ]
+ ]
+ }
+ }
+ ]
+ , ["compile-deps", {"type": "CALL_EXPRESSION", "name": "compile-deps"}]
+ , ["link-deps", {"type": "CALL_EXPRESSION", "name": "link-deps"}]
+ , [ "local hdrs"
+ , { "type": "disjoint_map_union"
+ , "$1":
+ [ {"type": "var", "name": "hdrs"}
+ , {"type": "var", "name": "private-hdrs"}
+ ]
+ }
+ ]
+ , ["objects", {"type": "CALL_EXPRESSION", "name": "objects"}]
+ , [ "base name"
+ , {"type": "join", "$1": {"type": "FIELD", "name": "name"}}
+ ]
+ , [ "libname"
+ , { "type": "join"
+ , "$1": ["lib", {"type": "var", "name": "base name"}, ".a"]
+ }
+ ]
+ , [ "lib"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "objects"}
+ , "else": {"type": "empty_map"}
+ , "then":
+ { "type": "ACTION"
+ , "outs": [{"type": "var", "name": "libname"}]
+ , "inputs": {"type": "var", "name": "objects"}
+ , "cmd":
+ { "type": "++"
+ , "$1":
+ [ [ {"type": "var", "name": "AR", "default": "ar"}
+ , "cqs"
+ , {"type": "var", "name": "libname"}
+ ]
+ , {"type": "keys", "$1": {"type": "var", "name": "objects"}}
+ ]
+ }
+ }
+ }
+ ]
+ , [ "lib"
+ , { "type": "to_subdir"
+ , "subdir": {"type": "var", "name": "stage"}
+ , "$1": {"type": "var", "name": "lib"}
+ }
+ ]
+ , [ "link-args"
+ , { "type": "nub_right"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "keys", "$1": {"type": "var", "name": "lib"}}
+ , { "type": "++"
+ , "$1":
+ { "type": "foreach"
+ , "var": "dep"
+ , "range": {"type": "FIELD", "name": "deps"}
+ , "body":
+ { "type": "DEP_PROVIDES"
+ , "dep": {"type": "var", "name": "dep"}
+ , "provider": "link-args"
+ }
+ }
+ }
+ , { "type": "++"
+ , "$1":
+ { "type": "foreach"
+ , "var": "dep"
+ , "range": {"type": "FIELD", "name": "proto-deps"}
+ , "body":
+ { "type": "DEP_PROVIDES"
+ , "dep": {"type": "var", "name": "dep"}
+ , "provider": "link-args"
+ }
+ }
+ }
+ , {"type": "var", "name": "link external", "default": []}
+ ]
+ }
+ }
+ ]
+ ]
+ , "body":
+ { "type": "RESULT"
+ , "artifacts": {"type": "var", "name": "lib"}
+ , "runfiles": {"type": "var", "name": "hdrs"}
+ , "provides":
+ { "type": "map_union"
+ , "$1":
+ [ { "type": "singleton_map"
+ , "key": "compile-deps"
+ , "value": {"type": "var", "name": "compile-deps"}
+ }
+ , { "type": "singleton_map"
+ , "key": "link-deps"
+ , "value": {"type": "var", "name": "link-deps"}
+ }
+ , { "type": "singleton_map"
+ , "key": "link-args"
+ , "value": {"type": "var", "name": "link-args"}
+ }
+ , { "type": "var"
+ , "name": "extra-provides"
+ , "default": {"type": "empty_map"}
+ }
+ ]
+ }
+ }
+ }
+ }
+}
diff --git a/CC/RULES b/CC/RULES
new file mode 100644
index 0000000..93d5afc
--- /dev/null
+++ b/CC/RULES
@@ -0,0 +1,538 @@
+{ "defaults":
+ { "doc":
+ [ "A rule to provide defaults."
+ , "All CC targets take their defaults for CXX, CC, flags, etc from"
+ , "the target [\"CC\", \"defaults\"]. This is probably the only sensibe"
+ , "use of this rule. As targets form a different root, the defaults"
+ , "can be provided without changing this directory."
+ ]
+ , "string_fields": ["CC", "CXX", "CFLAGS", "CXXFLAGS", "PATH", "AR"]
+ , "expression":
+ { "type": "RESULT"
+ , "provides":
+ { "type": "map_union"
+ , "$1":
+ [ { "type": "singleton_map"
+ , "key": "CC"
+ , "value": {"type": "FIELD", "name": "CC"}
+ }
+ , { "type": "singleton_map"
+ , "key": "CXX"
+ , "value": {"type": "FIELD", "name": "CXX"}
+ }
+ , { "type": "singleton_map"
+ , "key": "CFLAGS"
+ , "value": {"type": "FIELD", "name": "CFLAGS"}
+ }
+ , { "type": "singleton_map"
+ , "key": "CXXFLAGS"
+ , "value": {"type": "FIELD", "name": "CXXFLAGS"}
+ }
+ , { "type": "singleton_map"
+ , "key": "AR"
+ , "value": {"type": "FIELD", "name": "AR"}
+ }
+ , { "type": "singleton_map"
+ , "key": "ENV"
+ , "value":
+ { "type": "singleton_map"
+ , "key": "PATH"
+ , "value":
+ { "type": "join"
+ , "separator": ":"
+ , "$1": {"type": "FIELD", "name": "PATH"}
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+, "configure":
+ { "doc":
+ [ "A rule to provide a static platform configuration for a target."
+ , "The artifacts and runfiles of the specified target will be propagated."
+ , "The target defined by this rule does not propagate any provides data."
+ ]
+ , "config_fields": ["os", "arch", "target_arch"]
+ , "target_fields": ["target"]
+ , "field_doc":
+ { "os": ["The operation system used for building."]
+ , "arch": ["The architecture used for building."]
+ , "target_arch":
+ [ "Non-mandatory target architecture to build for. If omitted, target"
+ , "architecture is derived from \"arch\"."
+ ]
+ , "target":
+ [ "The target to configure. Multiple targets are supported, but their"
+ , "artifacts and runfiles should not conflict."
+ ]
+ }
+ , "imports":
+ { "transition": "configure transition"
+ , "artifacts": ["./", "..", "field_artifacts"]
+ , "runfiles": ["./", "..", "field_runfiles"]
+ }
+ , "config_transitions":
+ {"target": [{"type": "CALL_EXPRESSION", "name": "transition"}]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "target"]
+ , ["transition", {"type": "CALL_EXPRESSION", "name": "transition"}]
+ ]
+ , "body":
+ { "type": "RESULT"
+ , "artifacts": {"type": "CALL_EXPRESSION", "name": "artifacts"}
+ , "runfiles": {"type": "CALL_EXPRESSION", "name": "runfiles"}
+ }
+ }
+ }
+, "header directory":
+ { "doc":
+ [ "A directory of header files."
+ , ""
+ , "Define a directory of header files that belong together and are staged"
+ , "in such a way that no other target (used together with this target) will"
+ , "have to put files in this directory. The typical use case is a library"
+ , "libfoo that expects all headers to be included as #include \"foo/bar.h\"."
+ , "In this case, one would define a header direcotry for \"foo\"."
+ , ""
+ , "Technically, a tree is created from the given files and staged to the"
+ , "specified location. Since trees are opaque, the directory name becomes"
+ , "essentially owned by target. In this way, staging conflicts can be"
+ , "avoided by detecting them early and not only once a file with the same"
+ , "name is added to the staging location. Also, as only a tree identifier"
+ , "has to be passed around, such a directory can be handled more"
+ , "efficiently by the tool."
+ ]
+ , "target_fields": ["hdrs"]
+ , "string_fields": ["stage", "public stage"]
+ , "field_doc":
+ { "hdrs": ["The header files to be put into the header directory."]
+ , "stage":
+ [ "The location of the header directory."
+ , "Path segments are joined with \"/\"."
+ ]
+ , "public stage":
+ [ "If non-empty, no closure for the header directory's stage is created, "
+ , "so can be combined with other header directories having the same "
+ , "public staging directory."
+ ]
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ [ "hdrs"
+ , { "type": "disjoint_map_union"
+ , "$1":
+ { "type": "foreach"
+ , "var": "x"
+ , "range": {"type": "FIELD", "name": "hdrs"}
+ , "body":
+ {"type": "DEP_RUNFILES", "dep": {"type": "var", "name": "x"}}
+ }
+ }
+ ]
+ , [ "stage"
+ , { "type": "join"
+ , "separator": "/"
+ , "$1": {"type": "FIELD", "name": "stage"}
+ }
+ ]
+ , [ "dir"
+ , { "type": "if"
+ , "cond": {"type": "FIELD", "name": "public stage"}
+ , "then":
+ { "type": "to_subdir"
+ , "subdir": {"type": "var", "name": "stage"}
+ , "$1": {"type": "var", "name": "hdrs"}
+ }
+ , "else":
+ { "type": "singleton_map"
+ , "key": {"type": "var", "name": "stage"}
+ , "value": {"type": "TREE", "$1": {"type": "var", "name": "hdrs"}}
+ }
+ }
+ ]
+ ]
+ , "body":
+ { "type": "RESULT"
+ , "artifacts": {"type": "var", "name": "dir"}
+ , "runfiles": {"type": "var", "name": "dir"}
+ }
+ }
+ }
+, "library":
+ { "doc": ["A C++ libaray"]
+ , "target_fields": ["srcs", "hdrs", "private-hdrs", "deps", "proto"]
+ , "string_fields":
+ ["name", "stage", "pure C", "local defines", "link external"]
+ , "config_vars": ["CXX", "CC", "CXXFLAGS", "CFLAGS", "ENV", "AR"]
+ , "implicit": {"defaults": ["defaults"]}
+ , "field_doc":
+ { "name":
+ ["The name of the library (without leading \"lib\" or trailing \".a\""]
+ , "srcs": ["The source files of the library."]
+ , "hdrs": ["Any public header files of the library."]
+ , "private-hdrs":
+ [ "Any header files that only need to be present when compiling the"
+ , "source files, but are not needed for any consumer of the library"
+ ]
+ , "stage":
+ [ "The logical location of all header and source files, as well as the"
+ , "resulting library file. Individual directory components are joined"
+ , "with \"/\"."
+ ]
+ , "pure C":
+ [ "If non-empty, compile as C sources rathter than C++ sources."
+ , "In particular, CC is used to compile rather than CXX"
+ ]
+ , "local defines":
+ [ "List of defines set for source files local to this target."
+ , "Each list entry will be prepended by \"-D\"."
+ ]
+ , "link external":
+ ["Additional linker flags for linking external libraries."]
+ , "deps": ["Any other libraries this library depends upon."]
+ }
+ , "config_doc":
+ { "CXX": ["The name of the C++ compiler to be used."]
+ , "CC":
+ ["The name of the C compiler to be used (when compiling pure C code)"]
+ , "AR": ["The archive tool to used for creating the library"]
+ , "ENV": ["The environment for any action generated."]
+ , "CXXFLAGS":
+ [ "The flags for CXX to be used instead of the default ones."
+ , "For libraries that should be built in a non-standard way; usually"
+ , "adapting the default target [\"CC\", \"defaults\"] is the better"
+ , "choice"
+ ]
+ , "CFLAGS":
+ [ "The flags for CC to be used instead of the default ones."
+ , "For libraries that should be built in a non-standard way; usually"
+ , "adapting the default target [\"CC\", \"defaults\"] is the better"
+ , "choice"
+ ]
+ }
+ , "anonymous":
+ { "proto-deps":
+ { "target": "proto"
+ , "provider": "proto"
+ , "rule_map":
+ { "library": ["./", "proto", "library"]
+ , "service library": ["./", "proto", "service library"]
+ }
+ }
+ }
+ , "imports":
+ { "artifacts": ["./", "..", "field_artifacts"]
+ , "default-CXXFLAGS": "default-CXXFLAGS"
+ , "default-CFLAGS": "default-CFLAGS"
+ , "result": "lib result"
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ [ "local defines"
+ , { "type": "foreach"
+ , "var": "def"
+ , "range": {"type": "FIELD", "name": "local defines"}
+ , "body":
+ {"type": "join", "$1": ["-D", {"type": "var", "name": "def"}]}
+ }
+ ]
+ , [ "CFLAGS"
+ , { "type": "++"
+ , "$1":
+ [ { "type": "var"
+ , "name": "CFLAGS"
+ , "default":
+ {"type": "CALL_EXPRESSION", "name": "default-CFLAGS"}
+ }
+ , {"type": "var", "name": "local defines"}
+ ]
+ }
+ ]
+ , [ "CXXFLAGS"
+ , { "type": "++"
+ , "$1":
+ [ { "type": "var"
+ , "name": "CXXFLAGS"
+ , "default":
+ {"type": "CALL_EXPRESSION", "name": "default-CXXFLAGS"}
+ }
+ , {"type": "var", "name": "local defines"}
+ ]
+ }
+ ]
+ , [ "stage"
+ , { "type": "join"
+ , "separator": "/"
+ , "$1": {"type": "FIELD", "name": "stage"}
+ }
+ ]
+ , [ "srcs"
+ , { "type": "to_subdir"
+ , "subdir": {"type": "var", "name": "stage"}
+ , "$1":
+ { "type": "let*"
+ , "bindings": [["fieldname", "srcs"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "artifacts"}
+ }
+ }
+ ]
+ , [ "hdrs"
+ , { "type": "to_subdir"
+ , "subdir": {"type": "var", "name": "stage"}
+ , "$1":
+ { "type": "let*"
+ , "bindings": [["fieldname", "hdrs"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "artifacts"}
+ }
+ }
+ ]
+ , [ "private-hdrs"
+ , { "type": "to_subdir"
+ , "subdir": {"type": "var", "name": "stage"}
+ , "$1":
+ { "type": "let*"
+ , "bindings": [["fieldname", "private-hdrs"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "artifacts"}
+ }
+ }
+ ]
+ , ["link external", {"type": "FIELD", "name": "link external"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "result"}
+ }
+ }
+, "binary":
+ { "doc": ["A binary written in C++"]
+ , "target_fields": ["srcs", "private-hdrs", "deps", "proto"]
+ , "string_fields":
+ ["name", "stage", "pure C", "local defines", "link external"]
+ , "config_vars": ["CXX", "CC", "CXXFLAGS", "CFLAGS", "ENV"]
+ , "implicit": {"defaults": ["defaults"]}
+ , "field_doc":
+ { "name": ["The name of the binary"]
+ , "srcs": ["The source files of the library."]
+ , "private-hdrs":
+ [ "Any header files that need to be present when compiling the"
+ , "source files."
+ ]
+ , "stage":
+ [ "The logical location of all header and source files, as well as the"
+ , "resulting binary file. Individual directory components are joined"
+ , "with \"/\"."
+ ]
+ , "pure C":
+ [ "If non-empty, compile as C sources rathter than C++ sources."
+ , "In particular, CC is used to compile rather than CXX"
+ ]
+ , "local defines":
+ [ "List of defines set for source files local to this target."
+ , "Each list entry will be prepended by \"-D\"."
+ ]
+ , "link external":
+ ["Additional linker flags for linking external libraries."]
+ , "deps": ["Any other libraries this binary depends upon."]
+ }
+ , "config_doc":
+ { "CXX": ["The name of the C++ compiler to be used."]
+ , "CC":
+ ["The name of the C compiler to be used (when compiling pure C code)"]
+ , "ENV": ["The environment for any action generated."]
+ , "CXXFLAGS":
+ [ "The flags for CXX to be used instead of the default ones"
+ , "taken from the [\"CC\", \"defaults\"] target"
+ ]
+ , "CFLAGS":
+ [ "The flags for CXX to be used instead of the default ones"
+ , "taken from the [\"CC\", \"defaults\"] target"
+ ]
+ }
+ , "anonymous":
+ { "proto-deps":
+ { "target": "proto"
+ , "provider": "proto"
+ , "rule_map":
+ { "library": ["./", "proto", "library"]
+ , "service library": ["./", "proto", "service library"]
+ }
+ }
+ }
+ , "imports":
+ { "artifacts": ["./", "..", "field_artifacts"]
+ , "compile-deps": "compile-deps"
+ , "link-deps": "link-deps"
+ , "objects": "objects"
+ , "default-CC": "default-CC"
+ , "default-CXX": "default-CXX"
+ , "default-CFLAGS": "default-CFLAGS"
+ , "default-CXXFLAGS": "default-CXXFLAGS"
+ , "default-ENV": "default-ENV"
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ [ "local defines"
+ , { "type": "foreach"
+ , "var": "def"
+ , "range": {"type": "FIELD", "name": "local defines"}
+ , "body":
+ {"type": "join", "$1": ["-D", {"type": "var", "name": "def"}]}
+ }
+ ]
+ , [ "stage"
+ , { "type": "join"
+ , "separator": "/"
+ , "$1": {"type": "FIELD", "name": "stage"}
+ }
+ ]
+ , [ "srcs"
+ , { "type": "to_subdir"
+ , "subdir": {"type": "var", "name": "stage"}
+ , "$1":
+ { "type": "let*"
+ , "bindings": [["fieldname", "srcs"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "artifacts"}
+ }
+ }
+ ]
+ , [ "local hdrs"
+ , { "type": "to_subdir"
+ , "subdir": {"type": "var", "name": "stage"}
+ , "$1":
+ { "type": "let*"
+ , "bindings": [["fieldname", "private-hdrs"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "artifacts"}
+ }
+ }
+ ]
+ , [ "CXX"
+ , { "type": "if"
+ , "cond": {"type": "FIELD", "name": "pure C"}
+ , "then":
+ { "type": "var"
+ , "name": "CC"
+ , "default": {"type": "CALL_EXPRESSION", "name": "default-CC"}
+ }
+ , "else":
+ { "type": "var"
+ , "name": "CXX"
+ , "default": {"type": "CALL_EXPRESSION", "name": "default-CXX"}
+ }
+ }
+ ]
+ , [ "CXXFLAGS"
+ , { "type": "if"
+ , "cond": {"type": "FIELD", "name": "pure C"}
+ , "then":
+ { "type": "var"
+ , "name": "CFLAGS"
+ , "default": {"type": "CALL_EXPRESSION", "name": "default-CFLAGS"}
+ }
+ , "else":
+ { "type": "var"
+ , "name": "CXXFLAGS"
+ , "default":
+ {"type": "CALL_EXPRESSION", "name": "default-CXXFLAGS"}
+ }
+ }
+ ]
+ , [ "CXXFLAGS"
+ , { "type": "++"
+ , "$1":
+ [ {"type": "var", "name": "CXXFLAGS"}
+ , {"type": "var", "name": "local defines"}
+ ]
+ }
+ ]
+ , [ "ENV"
+ , { "type": "map_union"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "default-ENV"}
+ , [ { "type": "var"
+ , "name": "ENV"
+ , "default": {"type": "empty_map"}
+ }
+ ]
+ ]
+ }
+ }
+ ]
+ , ["compile-deps", {"type": "CALL_EXPRESSION", "name": "compile-deps"}]
+ , ["link-deps", {"type": "CALL_EXPRESSION", "name": "link-deps"}]
+ , ["objects", {"type": "CALL_EXPRESSION", "name": "objects"}]
+ , [ "base name"
+ , {"type": "join", "$1": {"type": "FIELD", "name": "name"}}
+ ]
+ , [ "binary name"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "stage"}
+ , "else": {"type": "var", "name": "base name"}
+ , "then":
+ { "type": "join"
+ , "separator": "/"
+ , "$1":
+ [ {"type": "var", "name": "stage"}
+ , {"type": "var", "name": "base name"}
+ ]
+ }
+ }
+ ]
+ , [ "link-args"
+ , { "type": "nub_right"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "keys", "$1": {"type": "var", "name": "objects"}}
+ , { "type": "++"
+ , "$1":
+ { "type": "foreach"
+ , "var": "dep"
+ , "range": {"type": "FIELD", "name": "deps"}
+ , "body":
+ { "type": "DEP_PROVIDES"
+ , "dep": {"type": "var", "name": "dep"}
+ , "provider": "link-args"
+ }
+ }
+ }
+ , {"type": "FIELD", "name": "link external"}
+ ]
+ }
+ }
+ ]
+ , [ "binary"
+ , { "type": "ACTION"
+ , "outs": [{"type": "var", "name": "binary name"}]
+ , "inputs":
+ { "type": "disjoint_map_union"
+ , "$1":
+ [ {"type": "var", "name": "objects"}
+ , {"type": "var", "name": "link-deps"}
+ ]
+ }
+ , "cmd":
+ { "type": "++"
+ , "$1":
+ [ [ {"type": "var", "name": "CXX"}
+ , "-o"
+ , {"type": "var", "name": "binary name"}
+ ]
+ , {"type": "var", "name": "link-args"}
+ ]
+ }
+ , "env": {"type": "var", "name": "ENV"}
+ }
+ ]
+ ]
+ , "body":
+ {"type": "RESULT", "artifacts": {"type": "var", "name": "binary"}}
+ }
+ }
+}
diff --git a/CC/proto/EXPRESSIONS b/CC/proto/EXPRESSIONS
new file mode 100644
index 0000000..a98c51c
--- /dev/null
+++ b/CC/proto/EXPRESSIONS
@@ -0,0 +1,301 @@
+{ "protoc-deps":
+ { "expression":
+ { "type": "disjoint_map_union"
+ , "$1":
+ { "type": "foreach"
+ , "var": "dep"
+ , "range": {"type": "FIELD", "name": "deps"}
+ , "body":
+ { "type": "DEP_PROVIDES"
+ , "dep": {"type": "var", "name": "dep"}
+ , "provider": "protoc-deps"
+ , "default": {"type": "empty_map"}
+ }
+ }
+ }
+ }
+, "protoc-compile":
+ { "vars": ["transition", "service support"]
+ , "imports":
+ { "stage": ["", "stage_singleton_field"]
+ , "result": ["./", "..", "lib result"]
+ , "field_runfiles": ["", "field_runfiles"]
+ , "protoc-deps": "protoc-deps"
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ [ "protoc"
+ , { "type": "let*"
+ , "bindings": [["fieldname", "protoc"], ["location", "protoc"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "stage"}
+ }
+ ]
+ , [ "grpc_cpp_plugin"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "service support"}
+ , "then":
+ { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "grpc_cpp_plugin"]
+ , ["location", "grpc_cpp_plugin"]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "stage"}
+ }
+ , "else": {"type": "empty_map"}
+ }
+ ]
+ , ["protoc-deps", {"type": "CALL_EXPRESSION", "name": "protoc-deps"}]
+ , [ "proto deps"
+ , { "type": "to_subdir"
+ , "subdir": "work"
+ , "$1":
+ { "type": "disjoint_map_union"
+ , "$1":
+ { "type": "foreach"
+ , "var": "x"
+ , "range": {"type": "FIELD", "name": "well_known_protos"}
+ , "body":
+ {"type": "DEP_ARTIFACTS", "dep": {"type": "var", "name": "x"}}
+ }
+ }
+ }
+ ]
+ , [ "proto srcs"
+ , { "type": "disjoint_map_union"
+ , "msg": "Sources may not conflict"
+ , "$1":
+ { "type": "foreach"
+ , "var": "x"
+ , "range": {"type": "FIELD", "name": "srcs"}
+ , "body":
+ {"type": "DEP_ARTIFACTS", "dep": {"type": "var", "name": "x"}}
+ }
+ }
+ ]
+ , [ "all proto srcs"
+ , { "type": "disjoint_map_union"
+ , "msg": "Conflict with proto files of dependencies"
+ , "$1":
+ [ {"type": "var", "name": "protoc-deps"}
+ , {"type": "var", "name": "proto srcs"}
+ ]
+ }
+ ]
+ , [ "staged srcs"
+ , { "type": "to_subdir"
+ , "subdir": "work"
+ , "$1": {"type": "var", "name": "proto srcs"}
+ }
+ ]
+ , [ "staged all proto srcs"
+ , { "type": "to_subdir"
+ , "subdir": "work"
+ , "$1": {"type": "var", "name": "all proto srcs"}
+ }
+ ]
+ , [ "outs"
+ , { "type": "++"
+ , "$1":
+ { "type": "foreach"
+ , "var": "f"
+ , "range":
+ {"type": "keys", "$1": {"type": "var", "name": "staged srcs"}}
+ , "body":
+ { "type": "++"
+ , "$1":
+ [ [ { "type": "change_ending"
+ , "$1": {"type": "var", "name": "f"}
+ , "ending": ".pb.h"
+ }
+ , { "type": "change_ending"
+ , "$1": {"type": "var", "name": "f"}
+ , "ending": ".pb.cc"
+ }
+ ]
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "service support"}
+ , "then":
+ [ { "type": "change_ending"
+ , "$1": {"type": "var", "name": "f"}
+ , "ending": ".grpc.pb.h"
+ }
+ , { "type": "change_ending"
+ , "$1": {"type": "var", "name": "f"}
+ , "ending": ".grpc.pb.cc"
+ }
+ ]
+ , "else": []
+ }
+ ]
+ }
+ }
+ }
+ ]
+ , [ "cmd"
+ , { "type": "++"
+ , "$1":
+ [ ["./protoc", "--proto_path=work", "--cpp_out=work"]
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "service support"}
+ , "then":
+ [ "--grpc_out=work"
+ , "--plugin=protoc-gen-grpc=./grpc_cpp_plugin"
+ ]
+ , "else": []
+ }
+ , {"type": "keys", "$1": {"type": "var", "name": "staged srcs"}}
+ ]
+ }
+ ]
+ , [ "generated"
+ , { "type": "ACTION"
+ , "inputs":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "staged all proto srcs"}
+ , {"type": "var", "name": "protoc"}
+ , {"type": "var", "name": "grpc_cpp_plugin"}
+ , {"type": "var", "name": "proto deps"}
+ ]
+ }
+ , "outs": {"type": "var", "name": "outs"}
+ , "cmd": {"type": "var", "name": "cmd"}
+ }
+ ]
+ , [ "srcs"
+ , { "type": "map_union"
+ , "$1":
+ { "type": "foreach"
+ , "var": "name"
+ , "range":
+ {"type": "keys", "$1": {"type": "var", "name": "proto srcs"}}
+ , "body":
+ { "type": "map_union"
+ , "$1":
+ [ { "type": "singleton_map"
+ , "key":
+ { "type": "change_ending"
+ , "$1": {"type": "var", "name": "name"}
+ , "ending": ".pb.cc"
+ }
+ , "value":
+ { "type": "lookup"
+ , "map": {"type": "var", "name": "generated"}
+ , "key":
+ { "type": "join"
+ , "$1":
+ [ "work/"
+ , { "type": "change_ending"
+ , "$1": {"type": "var", "name": "name"}
+ , "ending": ".pb.cc"
+ }
+ ]
+ }
+ }
+ }
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "service support"}
+ , "then":
+ { "type": "singleton_map"
+ , "key":
+ { "type": "change_ending"
+ , "$1": {"type": "var", "name": "name"}
+ , "ending": ".grpc.pb.cc"
+ }
+ , "value":
+ { "type": "lookup"
+ , "map": {"type": "var", "name": "generated"}
+ , "key":
+ { "type": "join"
+ , "$1":
+ [ "work/"
+ , { "type": "change_ending"
+ , "$1": {"type": "var", "name": "name"}
+ , "ending": ".grpc.pb.cc"
+ }
+ ]
+ }
+ }
+ }
+ , "else": {"type": "empty_map"}
+ }
+ ]
+ }
+ }
+ }
+ ]
+ , [ "hdrs"
+ , { "type": "map_union"
+ , "$1":
+ { "type": "foreach"
+ , "var": "name"
+ , "range":
+ {"type": "keys", "$1": {"type": "var", "name": "proto srcs"}}
+ , "body":
+ { "type": "map_union"
+ , "$1":
+ [ { "type": "singleton_map"
+ , "key":
+ { "type": "change_ending"
+ , "$1": {"type": "var", "name": "name"}
+ , "ending": ".pb.h"
+ }
+ , "value":
+ { "type": "lookup"
+ , "map": {"type": "var", "name": "generated"}
+ , "key":
+ { "type": "join"
+ , "$1":
+ [ "work/"
+ , { "type": "change_ending"
+ , "$1": {"type": "var", "name": "name"}
+ , "ending": ".pb.h"
+ }
+ ]
+ }
+ }
+ }
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "service support"}
+ , "then":
+ { "type": "singleton_map"
+ , "key":
+ { "type": "change_ending"
+ , "$1": {"type": "var", "name": "name"}
+ , "ending": ".grpc.pb.h"
+ }
+ , "value":
+ { "type": "lookup"
+ , "map": {"type": "var", "name": "generated"}
+ , "key":
+ { "type": "join"
+ , "$1":
+ [ "work/"
+ , { "type": "change_ending"
+ , "$1": {"type": "var", "name": "name"}
+ , "ending": ".grpc.pb.h"
+ }
+ ]
+ }
+ }
+ }
+ , "else": {"type": "empty_map"}
+ }
+ ]
+ }
+ }
+ }
+ ]
+ , ["private-hdrs", {"type": "empty_map"}]
+ , [ "extra-provides"
+ , { "type": "singleton_map"
+ , "key": "protoc-deps"
+ , "value": {"type": "var", "name": "all proto srcs"}
+ }
+ ]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "result"}
+ }
+ }
+}
diff --git a/CC/proto/RULES b/CC/proto/RULES
new file mode 100644
index 0000000..04082c1
--- /dev/null
+++ b/CC/proto/RULES
@@ -0,0 +1,72 @@
+{ "library":
+ { "doc":
+ [ "A library C++ library, generated from proto files."
+ , ""
+ , "This rule usually is used to bind anonymous targets generated from"
+ , "proto libraries."
+ ]
+ , "string_fields": ["name", "stage"]
+ , "target_fields": ["srcs", "deps"]
+ , "config_vars":
+ ["OS", "ARCH", "HOST_ARCH", "CXX", "CC", "CXXFLAGS", "CFLAGS", "ENV", "AR"]
+ , "implicit":
+ { "protoc": [["@", "protoc", "", "protoc"]]
+ , "defaults": [["./", "..", "defaults"]]
+ , "proto-deps": [["@", "protoc", "", "C++ runtime"]]
+ , "well_known_protos": [["@", "protoc", "", "well_known_protos"]]
+ , "pure C": []
+ }
+ , "imports":
+ { "protoc-compile": "protoc-compile"
+ , "host transition": ["transitions", "for host"]
+ }
+ , "config_transitions":
+ {"protoc": [{"type": "CALL_EXPRESSION", "name": "host transition"}]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [["transition", {"type": "CALL_EXPRESSION", "name": "host transition"}]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "protoc-compile"}
+ }
+ }
+, "service library":
+ { "doc":
+ [ "A service library C++ library, generated from proto files."
+ , ""
+ , "Calls protoc with gRPC plugin to additionally generate gRPC services"
+ , "from proto libraries."
+ ]
+ , "string_fields": ["name", "stage"]
+ , "target_fields": ["srcs", "deps"]
+ , "config_vars":
+ ["OS", "ARCH", "HOST_ARCH", "CXX", "CC", "CXXFLAGS", "CFLAGS", "ENV", "AR"]
+ , "implicit":
+ { "protoc": [["@", "protoc", "", "protoc"]]
+ , "grpc_cpp_plugin": [["@", "grpc", "src/compiler", "grpc_cpp_plugin"]]
+ , "defaults": [["./", "..", "defaults"]]
+ , "proto-deps":
+ [ ["@", "grpc", "", "grpc++_codegen_proto"]
+ , ["@", "protoc", "", "C++ runtime"]
+ ]
+ , "well_known_protos": [["@", "protoc", "", "well_known_protos"]]
+ , "pure C": []
+ }
+ , "imports":
+ { "protoc-compile": "protoc-compile"
+ , "host transition": ["transitions", "for host"]
+ }
+ , "config_transitions":
+ { "protoc": [{"type": "CALL_EXPRESSION", "name": "host transition"}]
+ , "grpc_cpp_plugin":
+ [{"type": "CALL_EXPRESSION", "name": "host transition"}]
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["service support", true]
+ , ["transition", {"type": "CALL_EXPRESSION", "name": "host transition"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "protoc-compile"}
+ }
+ }
+}
diff --git a/CC/test/RULES b/CC/test/RULES
new file mode 100644
index 0000000..de5a485
--- /dev/null
+++ b/CC/test/RULES
@@ -0,0 +1,265 @@
+{ "test":
+ { "doc":
+ [ "A test written in C++"
+ , "FIXME: the test binary and data must be built for host"
+ ]
+ , "tainted": ["test"]
+ , "target_fields": ["srcs", "private-hdrs", "deps", "data"]
+ , "string_fields": ["name", "stage"]
+ , "config_vars": ["CXX", "CC", "CXXFLAGS", "CFLAGS", "ENV"]
+ , "implicit":
+ { "defaults": [["./", "..", "defaults"]]
+ , "proto-deps": []
+ , "runner": ["test_runner.sh"]
+ }
+ , "field_doc":
+ { "name":
+ [ "The name of the test"
+ , ""
+ , "Used to name the test binary as well as for staging the test result"
+ ]
+ , "srcs": ["The sources of the test binary"]
+ , "private-hdrs":
+ [ "Any additional header files that need to be present when compiling"
+ , "the test binary."
+ ]
+ , "stage":
+ [ "The logical location of all header and source files."
+ , "Individual directory components are joined with \"/\"."
+ ]
+ , "data": ["Any files the test binary needs access to when running"]
+ }
+ , "config_doc":
+ { "CXX": ["The name of the C++ compiler to be used."]
+ , "ENV": ["The environment for any action generated."]
+ , "CXXFLAGS":
+ [ "The flags for CXX to be used instead of the default ones"
+ , "taken from the [\"CC\", \"defaults\"] target"
+ ]
+ }
+ , "imports":
+ { "artifacts": ["./", "../..", "field_artifacts"]
+ , "compile-deps": ["./", "..", "compile-deps"]
+ , "link-deps": ["./", "..", "link-deps"]
+ , "objects": ["./", "..", "objects"]
+ , "default-CXX": ["./", "..", "default-CXX"]
+ , "default-CXXFLAGS": ["./", "..", "default-CXXFLAGS"]
+ , "default-ENV": ["./", "..", "default-ENV"]
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ [ "stage"
+ , { "type": "join"
+ , "separator": "/"
+ , "$1": {"type": "FIELD", "name": "stage"}
+ }
+ ]
+ , [ "srcs"
+ , { "type": "to_subdir"
+ , "subdir": {"type": "var", "name": "stage"}
+ , "$1":
+ { "type": "let*"
+ , "bindings": [["fieldname", "srcs"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "artifacts"}
+ }
+ }
+ ]
+ , [ "local hdrs"
+ , { "type": "to_subdir"
+ , "subdir": {"type": "var", "name": "stage"}
+ , "$1":
+ { "type": "let*"
+ , "bindings": [["fieldname", "private-hdrs"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "artifacts"}
+ }
+ }
+ ]
+ , [ "CXX"
+ , { "type": "var"
+ , "name": "CXX"
+ , "default": {"type": "CALL_EXPRESSION", "name": "default-CXX"}
+ }
+ ]
+ , [ "CXXFLAGS"
+ , { "type": "var"
+ , "name": "CXXFLAGS"
+ , "default": {"type": "CALL_EXPRESSION", "name": "default-CXXFLAGS"}
+ }
+ ]
+ , [ "ENV"
+ , { "type": "map_union"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "default-ENV"}
+ , [ { "type": "var"
+ , "name": "ENV"
+ , "default": {"type": "empty_map"}
+ }
+ ]
+ ]
+ }
+ }
+ ]
+ , ["compile-deps", {"type": "CALL_EXPRESSION", "name": "compile-deps"}]
+ , ["link-deps", {"type": "CALL_EXPRESSION", "name": "link-deps"}]
+ , ["objects", {"type": "CALL_EXPRESSION", "name": "objects"}]
+ , [ "base name"
+ , { "type": "assert_non_empty"
+ , "msg": "A non-empy name has to be provided"
+ , "$1": {"type": "join", "$1": {"type": "FIELD", "name": "name"}}
+ }
+ ]
+ , [ "binary name"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "stage"}
+ , "else": {"type": "var", "name": "base name"}
+ , "then":
+ { "type": "join"
+ , "separator": "/"
+ , "$1":
+ [ {"type": "var", "name": "stage"}
+ , {"type": "var", "name": "base name"}
+ ]
+ }
+ }
+ ]
+ , [ "link-args"
+ , { "type": "nub_right"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "keys", "$1": {"type": "var", "name": "objects"}}
+ , { "type": "++"
+ , "$1":
+ { "type": "foreach"
+ , "var": "dep"
+ , "range": {"type": "FIELD", "name": "deps"}
+ , "body":
+ { "type": "DEP_PROVIDES"
+ , "dep": {"type": "var", "name": "dep"}
+ , "provider": "link-args"
+ }
+ }
+ }
+ ]
+ }
+ }
+ ]
+ , [ "binary"
+ , { "type": "ACTION"
+ , "outs": [{"type": "var", "name": "binary name"}]
+ , "inputs":
+ { "type": "disjoint_map_union"
+ , "$1":
+ [ {"type": "var", "name": "objects"}
+ , {"type": "var", "name": "link-deps"}
+ ]
+ }
+ , "cmd":
+ { "type": "++"
+ , "$1":
+ [ [ {"type": "var", "name": "CXX"}
+ , "-o"
+ , {"type": "var", "name": "binary name"}
+ ]
+ , {"type": "var", "name": "link-args"}
+ ]
+ }
+ , "env": {"type": "var", "name": "ENV"}
+ }
+ ]
+ , [ "staged test binary"
+ , { "type": "map_union"
+ , "$1":
+ { "type": "foreach_map"
+ , "range": {"type": "var", "name": "binary"}
+ , "var_val": "binary"
+ , "body":
+ { "type": "singleton_map"
+ , "key": "test"
+ , "value": {"type": "var", "name": "binary"}
+ }
+ }
+ }
+ ]
+ , [ "runner"
+ , { "type": "map_union"
+ , "$1":
+ { "type": "foreach"
+ , "var": "runner"
+ , "range": {"type": "FIELD", "name": "runner"}
+ , "body":
+ { "type": "map_union"
+ , "$1":
+ { "type": "foreach"
+ , "var": "runner"
+ , "range":
+ { "type": "values"
+ , "$1":
+ { "type": "DEP_ARTIFACTS"
+ , "dep": {"type": "var", "name": "runner"}
+ }
+ }
+ , "body":
+ { "type": "singleton_map"
+ , "key": "runner.sh"
+ , "value": {"type": "var", "name": "runner"}
+ }
+ }
+ }
+ }
+ }
+ ]
+ , [ "data"
+ , { "type": "disjoint_map_union"
+ , "msg": "Data runfiles may not conflict"
+ , "$1":
+ { "type": "foreach"
+ , "var": "dep"
+ , "range": {"type": "FIELD", "name": "data"}
+ , "body":
+ {"type": "DEP_RUNFILES", "dep": {"type": "var", "name": "dep"}}
+ }
+ }
+ ]
+ , [ "test-results"
+ , { "type": "ACTION"
+ , "outs": ["result", "stdout", "stderr", "time-start", "time-stop"]
+ , "inputs":
+ { "type": "map_union"
+ , "$1":
+ [ { "type": "to_subdir"
+ , "subdir": "work"
+ , "$1": {"type": "var", "name": "data"}
+ }
+ , {"type": "var", "name": "runner"}
+ , {"type": "var", "name": "staged test binary"}
+ ]
+ }
+ , "cmd": ["sh", "./runner.sh"]
+ , "may_fail": ["test"]
+ , "fail_message":
+ { "type": "join"
+ , "$1":
+ ["CC test ", {"type": "var", "name": "binary name"}, " failed"]
+ }
+ }
+ ]
+ , [ "runfiles"
+ , { "type": "singleton_map"
+ , "key": {"type": "var", "name": "base name"}
+ , "value":
+ {"type": "TREE", "$1": {"type": "var", "name": "test-results"}}
+ }
+ ]
+ ]
+ , "body":
+ { "type": "RESULT"
+ , "artifacts": {"type": "var", "name": "test-results"}
+ , "runfiles": {"type": "var", "name": "runfiles"}
+ }
+ }
+ }
+}
diff --git a/CC/test/test_runner.sh b/CC/test/test_runner.sh
new file mode 100644
index 0000000..ed9f48a
--- /dev/null
+++ b/CC/test/test_runner.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+# ensure all required outputs are present
+touch stdout
+touch stderr
+RESULT=UNKNOWN
+echo "${RESULT}" > result
+echo UNKNOWN > time-start
+echo UNKNOWN > time-stop
+
+mkdir scratch
+export TEST_TMPDIR=$(realpath scratch)
+# Change to the working directory; note: the test might not
+# have test data, so we have to ensure the presence of the work
+# directory.
+
+mkdir -p work
+cd work
+
+date +%s > ../time-start
+# TODO:
+# - proper wrapping with timeout
+# - test arguments to select specific test cases
+if ../test > ../stdout 2> ../stderr
+then
+ RESULT=PASS
+else
+ RESULT=FAIL
+fi
+date +%s > ../time-stop
+echo "${RESULT}" > result
+
+if [ "${RESULT}" '!=' PASS ]
+then
+ exit 1;
+fi
diff --git a/EXPRESSIONS b/EXPRESSIONS
new file mode 100644
index 0000000..9b35b0a
--- /dev/null
+++ b/EXPRESSIONS
@@ -0,0 +1,89 @@
+{ "field_artifacts":
+ { "vars": ["fieldname", "transition"]
+ , "expression":
+ { "type": "map_union"
+ , "$1":
+ { "type": "foreach"
+ , "var": "x"
+ , "range":
+ {"type": "FIELD", "name": {"type": "var", "name": "fieldname"}}
+ , "body":
+ { "type": "DEP_ARTIFACTS"
+ , "dep": {"type": "var", "name": "x"}
+ , "transition":
+ { "type": "var"
+ , "name": "transition"
+ , "default": {"type": "empty_map"}
+ }
+ }
+ }
+ }
+ }
+, "field_runfiles":
+ { "vars": ["fieldname", "transition"]
+ , "expression":
+ { "type": "map_union"
+ , "$1":
+ { "type": "foreach"
+ , "var": "x"
+ , "range":
+ {"type": "FIELD", "name": {"type": "var", "name": "fieldname"}}
+ , "body":
+ { "type": "DEP_RUNFILES"
+ , "dep": {"type": "var", "name": "x"}
+ , "transition":
+ { "type": "var"
+ , "name": "transition"
+ , "default": {"type": "empty_map"}
+ }
+ }
+ }
+ }
+ }
+, "action_env":
+ { "vars": ["ENV"]
+ , "expression":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "singleton_map", "key": "PATH", "value": "/bin:/usr/bin"}
+ , {"type": "var", "name": "ENV", "default": {"type": "empty_map"}}
+ ]
+ }
+ }
+, "stage_singleton_field":
+ { "vars": ["fieldname", "transition", "location"]
+ , "expression":
+ { "type": "disjoint_map_union"
+ , "$1":
+ { "type": "foreach"
+ , "var": "src"
+ , "range":
+ {"type": "FIELD", "name": {"type": "var", "name": "fieldname"}}
+ , "body":
+ { "type": "disjoint_map_union"
+ , "$1":
+ { "type": "foreach"
+ , "var": "artifact"
+ , "range":
+ { "type": "values"
+ , "$1":
+ { "type": "DEP_ARTIFACTS"
+ , "dep": {"type": "var", "name": "src"}
+ , "transition":
+ { "type": "var"
+ , "name": "transition"
+ , "default": {"type": "empty_map"}
+ }
+ }
+ }
+ , "body":
+ { "type": "singleton_map"
+ , "key": {"type": "var", "name": "location"}
+ , "value": {"type": "var", "name": "artifact"}
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/data/RULES b/data/RULES
new file mode 100644
index 0000000..34bc624
--- /dev/null
+++ b/data/RULES
@@ -0,0 +1,42 @@
+{ "staged":
+ { "doc": ["Stage data to a logical subdirectory."]
+ , "target_fields": ["srcs"]
+ , "string_fields": ["stage"]
+ , "field_doc":
+ { "srcs": ["The (run)files to be staged"]
+ , "stage":
+ [ "The logical directory to stage the files to."
+ , "Individual directory components are joined with \"/\"."
+ ]
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ [ "stage"
+ , { "type": "join"
+ , "separator": "/"
+ , "$1": {"type": "FIELD", "name": "stage"}
+ }
+ ]
+ , [ "srcs"
+ , { "type": "disjoint_map_union"
+ , "$1":
+ { "type": "foreach"
+ , "var": "x"
+ , "range": {"type": "FIELD", "name": "srcs"}
+ , "body":
+ {"type": "DEP_RUNFILES", "dep": {"type": "var", "name": "x"}}
+ }
+ }
+ ]
+ , [ "staged"
+ , { "type": "to_subdir"
+ , "subdir": {"type": "var", "name": "stage"}
+ , "$1": {"type": "var", "name": "srcs"}
+ }
+ ]
+ ]
+ , "body": {"type": "RESULT", "runfiles": {"type": "var", "name": "staged"}}
+ }
+ }
+}
diff --git a/proto/RULES b/proto/RULES
new file mode 100644
index 0000000..b6ce000
--- /dev/null
+++ b/proto/RULES
@@ -0,0 +1,105 @@
+{ "library":
+ { "target_fields": ["srcs", "deps"]
+ , "string_fields": ["stage", "name", "service"]
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ [ "stage"
+ , { "type": "join"
+ , "separator": "/"
+ , "$1": {"type": "FIELD", "name": "stage"}
+ }
+ ]
+ , [ "name"
+ , { "type": "assert_non_empty"
+ , "msg": "Have to provide a name, unique in the stage"
+ , "$1": {"type": "join", "$1": {"type": "FIELD", "name": "name"}}
+ }
+ ]
+ , [ "srcs"
+ , [ { "type": "VALUE_NODE"
+ , "$1":
+ { "type": "RESULT"
+ , "artifacts":
+ { "type": "to_subdir"
+ , "subdir": {"type": "var", "name": "stage"}
+ , "$1":
+ { "type": "disjoint_map_union"
+ , "msg": "Sources have to be conflict free"
+ , "$1":
+ { "type": "foreach"
+ , "var": "x"
+ , "range": {"type": "FIELD", "name": "srcs"}
+ , "body":
+ { "type": "DEP_ARTIFACTS"
+ , "dep": {"type": "var", "name": "x"}
+ }
+ }
+ }
+ }
+ }
+ }
+ ]
+ ]
+ , [ "deps"
+ , { "type": "++"
+ , "$1":
+ { "type": "foreach"
+ , "var": "x"
+ , "range": {"type": "FIELD", "name": "deps"}
+ , "body":
+ { "type": "DEP_PROVIDES"
+ , "dep": {"type": "var", "name": "x"}
+ , "provider": "proto"
+ }
+ }
+ }
+ ]
+ , [ "node"
+ , { "type": "ABSTRACT_NODE"
+ , "node_type":
+ { "type": "if"
+ , "cond": {"type": "FIELD", "name": "service"}
+ , "then": "service library"
+ , "else": "library"
+ }
+ , "target_fields":
+ { "type": "map_union"
+ , "$1":
+ [ { "type": "singleton_map"
+ , "key": "srcs"
+ , "value": {"type": "var", "name": "srcs"}
+ }
+ , { "type": "singleton_map"
+ , "key": "deps"
+ , "value": {"type": "var", "name": "deps"}
+ }
+ ]
+ }
+ , "string_fields":
+ { "type": "map_union"
+ , "$1":
+ [ { "type": "singleton_map"
+ , "key": "name"
+ , "value": [{"type": "var", "name": "name"}]
+ }
+ , { "type": "singleton_map"
+ , "key": "stage"
+ , "value": [{"type": "var", "name": "stage"}]
+ }
+ ]
+ }
+ }
+ ]
+ ]
+ , "body":
+ { "type": "RESULT"
+ , "provides":
+ { "type": "singleton_map"
+ , "key": "proto"
+ , "value": [{"type": "var", "name": "node"}]
+ }
+ }
+ }
+ }
+}
diff --git a/transitions/EXPRESSIONS b/transitions/EXPRESSIONS
new file mode 100644
index 0000000..8ea7550
--- /dev/null
+++ b/transitions/EXPRESSIONS
@@ -0,0 +1,13 @@
+{ "for host":
+ { "vars": ["ARCH", "HOST_ARCH"]
+ , "expression":
+ { "type": "singleton_map"
+ , "key": "TARGET_ARCH"
+ , "value":
+ { "type": "var"
+ , "name": "HOST_ARCH"
+ , "default": {"type": "var", "name": "ARCH"}
+ }
+ }
+ }
+}