diff options
Diffstat (limited to 'rules')
-rw-r--r-- | rules/CC/EXPRESSIONS | 1240 | ||||
-rw-r--r-- | rules/CC/IDE/RULES | 96 | ||||
-rw-r--r-- | rules/CC/RULES | 536 | ||||
-rw-r--r-- | rules/CC/TARGETS | 11 | ||||
-rw-r--r-- | rules/CC/auto/EXPRESSIONS | 32 | ||||
-rw-r--r-- | rules/CC/auto/RULES | 955 | ||||
-rw-r--r-- | rules/CC/proto/EXPRESSIONS | 308 | ||||
-rw-r--r-- | rules/CC/proto/RULES | 93 | ||||
-rw-r--r-- | rules/CC/test/RULES | 330 | ||||
-rw-r--r-- | rules/CC/test/TARGETS | 1 | ||||
-rwxr-xr-x | rules/CC/test/test_runner.py | 69 | ||||
-rw-r--r-- | rules/EXPRESSIONS | 229 | ||||
-rw-r--r-- | rules/data/RULES | 109 | ||||
-rw-r--r-- | rules/patch/RULES | 139 | ||||
-rw-r--r-- | rules/proto/RULES | 99 | ||||
-rw-r--r-- | rules/shell/test/EXPRESSIONS | 206 | ||||
-rw-r--r-- | rules/shell/test/RULES | 186 | ||||
-rw-r--r-- | rules/shell/test/TARGETS | 1 | ||||
-rwxr-xr-x | rules/shell/test/test_runner.sh | 59 | ||||
-rwxr-xr-x | rules/shell/test/test_summary.py | 67 | ||||
-rw-r--r-- | rules/transitions/EXPRESSIONS | 29 |
21 files changed, 4795 insertions, 0 deletions
diff --git a/rules/CC/EXPRESSIONS b/rules/CC/EXPRESSIONS new file mode 100644 index 0000000..2998fa8 --- /dev/null +++ b/rules/CC/EXPRESSIONS @@ -0,0 +1,1240 @@ +{ "default-CC": + { "vars": ["defaults-transition"] + , "imports": {"list_provider": ["./", "..", "field_list_provider"]} + , "expression": + { "type": "join" + , "$1": + { "type": "let*" + , "bindings": + [ ["fieldname", "defaults"] + , ["provider", "CC"] + , [ "transition" + , {"type": "var", "name": "defaults-transition", "default": null} + ] + ] + , "body": {"type": "CALL_EXPRESSION", "name": "list_provider"} + } + } + } +, "default-CXX": + { "vars": ["defaults-transition"] + , "imports": {"list_provider": ["./", "..", "field_list_provider"]} + , "expression": + { "type": "join" + , "$1": + { "type": "let*" + , "bindings": + [ ["fieldname", "defaults"] + , ["provider", "CXX"] + , [ "transition" + , {"type": "var", "name": "defaults-transition", "default": null} + ] + ] + , "body": {"type": "CALL_EXPRESSION", "name": "list_provider"} + } + } + } +, "default-AR": + { "vars": ["defaults-transition"] + , "imports": {"list_provider": ["./", "..", "field_list_provider"]} + , "expression": + { "type": "join" + , "$1": + { "type": "let*" + , "bindings": + [ ["fieldname", "defaults"] + , ["provider", "AR"] + , [ "transition" + , {"type": "var", "name": "defaults-transition", "default": null} + ] + ] + , "body": {"type": "CALL_EXPRESSION", "name": "list_provider"} + } + } + } +, "default-CFLAGS": + { "vars": ["defaults-transition"] + , "imports": {"list_provider": ["./", "..", "field_list_provider"]} + , "expression": + { "type": "let*" + , "bindings": + [ ["fieldname", "defaults"] + , ["provider", "CFLAGS"] + , [ "transition" + , {"type": "var", "name": "defaults-transition", "default": null} + ] + ] + , "body": {"type": "CALL_EXPRESSION", "name": "list_provider"} + } + } +, "default-CXXFLAGS": + { "vars": ["defaults-transition"] + , "imports": {"list_provider": ["./", "..", "field_list_provider"]} + , "expression": + { "type": "let*" + , "bindings": + [ ["fieldname", "defaults"] + , ["provider", "CXXFLAGS"] + , [ "transition" + , {"type": "var", "name": "defaults-transition", "default": null} + ] + ] + , "body": {"type": "CALL_EXPRESSION", "name": "list_provider"} + } + } +, "default-LDFLAGS": + { "vars": ["defaults-transition"] + , "imports": {"list_provider": ["./", "..", "field_list_provider"]} + , "expression": + { "type": "let*" + , "bindings": + [ ["fieldname", "defaults"] + , ["provider", "LDFLAGS"] + , [ "transition" + , {"type": "var", "name": "defaults-transition", "default": null} + ] + ] + , "body": {"type": "CALL_EXPRESSION", "name": "list_provider"} + } + } +, "default-ENV": + { "vars": ["defaults-transition"] + , "imports": {"provider_list": ["./", "..", "field_provider_list"]} + , "expression": + { "type": "let*" + , "bindings": + [ ["fieldname", "defaults"] + , ["provider", "ENV"] + , [ "transition" + , {"type": "var", "name": "defaults-transition", "default": null} + ] + , ["default", {"type": "empty_map"}] + ] + , "body": {"type": "CALL_EXPRESSION", "name": "provider_list"} + } + } +, "defaults-base-provides": + { "doc": ["Query list-provider from 'base' targets (last wins)"] + , "vars": ["provider"] + , "vars_doc": + {"provider": ["The name of the list-provider in the provides map."]} + , "imports": {"provider_list": ["./", "..", "field_provider_list"]} + , "expression": + { "type": "let*" + , "bindings": [["fieldname", "base"]] + , "body": + { "type": "foldl" + , "var": "next" + , "accum_var": "curr" + , "range": {"type": "CALL_EXPRESSION", "name": "provider_list"} + , "body": + { "type": "if" + , "cond": {"type": "var", "name": "next"} + , "then": {"type": "var", "name": "next"} + , "else": {"type": "var", "name": "curr"} + } + } + } + } +, "compile-deps": + { "doc": ["Collect compile dependencies (headers) from given target_fields"] + , "vars": ["deps-fieldnames", "deps-transition"] + , "vars_doc": + { "deps-fieldnames": + ["List of target_field names to collect dependencies from."] + , "deps-transition": + ["The optional configuration transition for the targets."] + } + , "imports": + { "runfiles_list": ["./", "..", "field_runfiles_list"] + , "provider_list": ["./", "..", "field_provider_list"] + } + , "expression": + { "type": "disjoint_map_union" + , "$1": + { "type": "++" + , "$1": + { "type": "foreach" + , "var": "fieldname" + , "range": {"type": "var", "name": "deps-fieldnames"} + , "body": + { "type": "++" + , "$1": + { "type": "let*" + , "bindings": + [ ["provider", "compile-deps"] + , ["transition", {"type": "var", "name": "deps-transition"}] + , ["default", {"type": "empty_map"}] + ] + , "body": + [ {"type": "CALL_EXPRESSION", "name": "provider_list"} + , {"type": "CALL_EXPRESSION", "name": "runfiles_list"} + ] + } + } + } + } + } + } +, "compile-args-deps": + { "doc": ["Collect compile arguments from given target_fields"] + , "vars": ["deps-fieldnames", "deps-transition"] + , "vars_doc": + { "deps-fieldnames": + ["List of target_field names to collect arguments from."] + , "deps-transition": + ["The optional configuration transition for the targets."] + } + , "imports": {"list_provider": ["./", "..", "field_list_provider"]} + , "expression": + { "type": "++" + , "$1": + { "type": "foreach" + , "var": "fieldname" + , "range": {"type": "var", "name": "deps-fieldnames"} + , "body": + { "type": "let*" + , "bindings": + [ ["provider", "compile-args"] + , ["transition", {"type": "var", "name": "deps-transition"}] + ] + , "body": {"type": "CALL_EXPRESSION", "name": "list_provider"} + } + } + } + } +, "link-deps": + { "doc": ["Collect link dependencies (libraries) from given target_fields"] + , "vars": ["deps-fieldnames", "deps-transition"] + , "vars_doc": + { "deps-fieldnames": + ["List of target_field names to collect dependencies from."] + , "deps-transition": + ["The optional configuration transition for the targets."] + } + , "imports": + { "artifacts_list": ["./", "..", "field_artifacts_list"] + , "provider_list": ["./", "..", "field_provider_list"] + } + , "expression": + { "type": "disjoint_map_union" + , "$1": + { "type": "++" + , "$1": + { "type": "foreach" + , "var": "fieldname" + , "range": {"type": "var", "name": "deps-fieldnames"} + , "body": + { "type": "++" + , "$1": + { "type": "let*" + , "bindings": + [ ["provider", "link-deps"] + , ["default", {"type": "empty_map"}] + , ["transition", {"type": "var", "name": "deps-transition"}] + ] + , "body": + [ {"type": "CALL_EXPRESSION", "name": "provider_list"} + , {"type": "CALL_EXPRESSION", "name": "artifacts_list"} + ] + } + } + } + } + } + } +, "link-args-deps": + { "doc": ["Collect linker arguments from given target_fields"] + , "vars": ["deps-fieldnames", "deps-transition"] + , "vars_doc": + { "deps-fieldnames": + ["List of target_field names to collect arguments from."] + , "deps-transition": + ["The optional configuration transition for the targets."] + } + , "imports": {"list_provider": ["./", "..", "field_list_provider"]} + , "expression": + { "type": "++" + , "$1": + { "type": "foreach" + , "var": "fieldname" + , "range": {"type": "var", "name": "deps-fieldnames"} + , "body": + { "type": "let*" + , "bindings": + [ ["provider", "link-args"] + , ["transition", {"type": "var", "name": "deps-transition"}] + ] + , "body": {"type": "CALL_EXPRESSION", "name": "list_provider"} + } + } + } + } +, "run-libs-deps": + { "doc": ["Collect runtime libraries from given target_fields"] + , "vars": ["deps-fieldnames", "deps-transition"] + , "vars_doc": + { "deps-fieldnames": + ["List of target_field names to collect dependencies from."] + , "deps-transition": + ["The optional configuration transition for the targets."] + } + , "imports": {"provider_list": ["./", "..", "field_provider_list"]} + , "expression": + { "type": "to_subdir" + , "flat": true + , "$1": + { "type": "disjoint_map_union" + , "$1": + { "type": "++" + , "$1": + { "type": "foreach" + , "var": "fieldname" + , "range": {"type": "var", "name": "deps-fieldnames"} + , "body": + { "type": "let*" + , "bindings": + [ ["provider", "run-libs"] + , ["default", {"type": "empty_map"}] + , ["transition", {"type": "var", "name": "deps-transition"}] + ] + , "body": {"type": "CALL_EXPRESSION", "name": "provider_list"} + } + } + } + } + } + } +, "run-libs-args-deps": + { "doc": + ["Collect runtime libraries link arguments from given target_fields"] + , "vars": ["deps-fieldnames", "deps-transition"] + , "vars_doc": + { "deps-fieldnames": + ["List of target_field names to collect arguments from."] + , "deps-transition": + ["The optional configuration transition for the targets."] + } + , "imports": {"list_provider": ["./", "..", "field_list_provider"]} + , "expression": + { "type": "++" + , "$1": + { "type": "foreach" + , "var": "fieldname" + , "range": {"type": "var", "name": "deps-fieldnames"} + , "body": + { "type": "let*" + , "bindings": + [ ["provider", "run-libs-args"] + , ["transition", {"type": "var", "name": "deps-transition"}] + ] + , "body": {"type": "CALL_EXPRESSION", "name": "list_provider"} + } + } + } + } +, "objects": + { "vars": + [ "COMPILER" + , "COMPILE_FLAGS" + , "ENV" + , "srcs" + , "hdrs" + , "private-hdrs" + , "compile-deps" + ] + , "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": "disjoint_map_union" + , "$1": + [ {"type": "var", "name": "hdrs"} + , {"type": "var", "name": "private-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"} + , "env": + { "type": "var" + , "name": "ENV" + , "default": {"type": "empty_map"} + } + , "cmd": + { "type": "++" + , "$1": + [ [{"type": "var", "name": "COMPILER"}] + , {"type": "var", "name": "COMPILE_FLAGS"} + , ["-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"} + } + } + } + } + } +, "compiler-cc": + { "vars": ["CC", "defaults-transition"] + , "imports": {"default-CC": "default-CC"} + , "expression": + { "type": "var" + , "name": "CC" + , "default": {"type": "CALL_EXPRESSION", "name": "default-CC"} + } + } +, "compiler-cxx": + { "vars": ["CXX", "defaults-transition"] + , "imports": {"default-CXX": "default-CXX"} + , "expression": + { "type": "var" + , "name": "CXX" + , "default": {"type": "CALL_EXPRESSION", "name": "default-CXX"} + } + } +, "compiler": + { "vars": ["CC", "CXX", "pure C", "defaults-transition"] + , "imports": {"compiler-cc": "compiler-cc", "compiler-cxx": "compiler-cxx"} + , "expression": + { "type": "if" + , "cond": {"type": "var", "name": "pure C"} + , "then": {"type": "CALL_EXPRESSION", "name": "compiler-cc"} + , "else": {"type": "CALL_EXPRESSION", "name": "compiler-cxx"} + } + } +, "flags-cc": + { "vars": + [ "CFLAGS" + , "ADD_CFLAGS" + , "BUILD_POSITION_INDEPENDENT" + , "defaults-transition" + ] + , "imports": {"default-CFLAGS": "default-CFLAGS"} + , "expression": + { "type": "++" + , "$1": + [ { "type": "if" + , "cond": {"type": "var", "name": "BUILD_POSITION_INDEPENDENT"} + , "then": ["-fPIC"] + } + , { "type": "var" + , "name": "CFLAGS" + , "default": {"type": "CALL_EXPRESSION", "name": "default-CFLAGS"} + } + , {"type": "var", "name": "ADD_CFLAGS", "default": []} + ] + } + } +, "flags-cxx": + { "vars": + [ "CXXFLAGS" + , "ADD_CXXFLAGS" + , "BUILD_POSITION_INDEPENDENT" + , "defaults-transition" + ] + , "imports": {"default-CXXFLAGS": "default-CXXFLAGS"} + , "expression": + { "type": "++" + , "$1": + [ { "type": "if" + , "cond": {"type": "var", "name": "BUILD_POSITION_INDEPENDENT"} + , "then": ["-fPIC"] + } + , { "type": "var" + , "name": "CXXFLAGS" + , "default": {"type": "CALL_EXPRESSION", "name": "default-CXXFLAGS"} + } + , {"type": "var", "name": "ADD_CXXFLAGS", "default": []} + ] + } + } +, "flags": + { "vars": + [ "CFLAGS" + , "CXXFLAGS" + , "ADD_CFLAGS" + , "ADD_CXXFLAGS" + , "BUILD_POSITION_INDEPENDENT" + , "pure C" + , "defaults-transition" + ] + , "imports": {"flags-cc": "flags-cc", "flags-cxx": "flags-cxx"} + , "expression": + { "type": "if" + , "cond": {"type": "var", "name": "pure C"} + , "then": {"type": "CALL_EXPRESSION", "name": "flags-cc"} + , "else": {"type": "CALL_EXPRESSION", "name": "flags-cxx"} + } + } +, "lib artifact": + { "vars": + [ "CC" + , "CXX" + , "CFLAGS" + , "CXXFLAGS" + , "ADD_CFLAGS" + , "ADD_CXXFLAGS" + , "AR" + , "ENV" + , "BUILD_POSITION_INDEPENDENT" + , "name" + , "pure C" + , "srcs" + , "hdrs" + , "private-hdrs" + , "stage" + , "compile-deps" + , "compile-args" + , "defaults-transition" + ] + , "imports": + { "compiler": "compiler" + , "flags": "flags" + , "objects": "objects" + , "default-AR": "default-AR" + , "default-ENV": "default-ENV" + } + , "expression": + { "type": "let*" + , "bindings": + [ ["COMPILER", {"type": "CALL_EXPRESSION", "name": "compiler"}] + , [ "COMPILE_FLAGS" + , { "type": "++" + , "$1": + [ {"type": "CALL_EXPRESSION", "name": "flags"} + , {"type": "var", "name": "compile-args"} + ] + } + ] + , [ "AR" + , { "type": "var" + , "name": "AR" + , "default": {"type": "CALL_EXPRESSION", "name": "default-AR"} + } + ] + , [ "ENV" + , { "type": "map_union" + , "$1": + { "type": "++" + , "$1": + [ {"type": "CALL_EXPRESSION", "name": "default-ENV"} + , [ { "type": "var" + , "name": "ENV" + , "default": {"type": "empty_map"} + } + ] + ] + } + } + ] + , ["objects", {"type": "CALL_EXPRESSION", "name": "objects"}] + , [ "base name" + , { "type": "if" + , "cond": {"type": "var", "name": "objects"} + , "then": + { "type": "assert_non_empty" + , "msg": "A name has to be provided for non-header-only libraries" + , "$1": {"type": "var", "name": "name"} + } + , "else": {"type": "var", "name": "name"} + } + ] + , [ "libname" + , { "type": "join" + , "$1": ["lib", {"type": "var", "name": "base name"}, ".a"] + } + ] + , [ "libpath" + , { "type": "if" + , "cond": {"type": "var", "name": "stage"} + , "then": + { "type": "join" + , "separator": "/" + , "$1": + [ {"type": "var", "name": "stage"} + , {"type": "var", "name": "libname"} + ] + } + , "else": {"type": "var", "name": "libname"} + } + ] + , [ "lib" + , { "type": "if" + , "cond": {"type": "var", "name": "objects"} + , "else": {"type": "empty_map"} + , "then": + { "type": "ACTION" + , "outs": [{"type": "var", "name": "libpath"}] + , "inputs": {"type": "var", "name": "objects"} + , "env": + {"type": "var", "name": "ENV", "default": {"type": "empty_map"}} + , "cmd": + { "type": "++" + , "$1": + [ [ {"type": "var", "name": "AR", "default": "ar"} + , "cqs" + , {"type": "var", "name": "libpath"} + ] + , {"type": "keys", "$1": {"type": "var", "name": "objects"}} + ] + } + } + } + ] + ] + , "body": {"type": "var", "name": "lib"} + } + } +, "lib result": + { "vars": + [ "CC" + , "CXX" + , "CFLAGS" + , "CXXFLAGS" + , "ADD_CFLAGS" + , "ADD_CXXFLAGS" + , "AR" + , "ENV" + , "BUILD_POSITION_INDEPENDENT" + , "name" + , "pure C" + , "srcs" + , "hdrs" + , "private-hdrs" + , "cflags" + , "private-cflags" + , "private-ldflags" + , "stage" + , "extra-provides" + , "public-fieldnames" + , "private-fieldnames" + ] + , "imports": + { "compile-deps": "compile-deps" + , "compile-args-deps": "compile-args-deps" + , "link-deps": "link-deps" + , "link-args-deps": "link-args-deps" + , "run-libs-deps": "run-libs-deps" + , "run-libs-args-deps": "run-libs-args-deps" + , "lib artifact": "lib artifact" + } + , "expression": + { "type": "let*" + , "bindings": + [ ["deps-fieldnames", {"type": "var", "name": "private-fieldnames"}] + , ["compile-deps", {"type": "CALL_EXPRESSION", "name": "compile-deps"}] + , [ "compile-args" + , { "type": "nub_right" + , "$1": + { "type": "++" + , "$1": + [ {"type": "var", "name": "cflags"} + , {"type": "var", "name": "private-cflags"} + , {"type": "CALL_EXPRESSION", "name": "compile-args-deps"} + ] + } + } + ] + , ["link-deps", {"type": "CALL_EXPRESSION", "name": "link-deps"}] + , ["lib", {"type": "CALL_EXPRESSION", "name": "lib artifact"}] + , [ "link-args" + , { "type": "nub_right" + , "$1": + { "type": "++" + , "$1": + [ {"type": "keys", "$1": {"type": "var", "name": "lib"}} + , {"type": "var", "name": "private-ldflags", "default": []} + , {"type": "CALL_EXPRESSION", "name": "link-args-deps"} + ] + } + } + ] + , ["run-libs", {"type": "CALL_EXPRESSION", "name": "run-libs-deps"}] + , [ "run-libs-args" + , { "type": "nub_right" + , "$1": {"type": "CALL_EXPRESSION", "name": "run-libs-args-deps"} + } + ] + , ["deps-fieldnames", {"type": "var", "name": "public-fieldnames"}] + , ["compile-deps", {"type": "CALL_EXPRESSION", "name": "compile-deps"}] + , [ "compile-args" + , { "type": "nub_right" + , "$1": + { "type": "++" + , "$1": + [ {"type": "var", "name": "cflags"} + , {"type": "CALL_EXPRESSION", "name": "compile-args-deps"} + ] + } + } + ] + ] + , "body": + { "type": "RESULT" + , "artifacts": {"type": "var", "name": "lib"} + , "runfiles": {"type": "var", "name": "hdrs"} + , "provides": + { "type": "map_union" + , "$1": + [ { "type": "env" + , "vars": + [ "compile-deps" + , "compile-args" + , "link-deps" + , "link-args" + , "run-libs" + , "run-libs-args" + ] + } + , { "type": "var" + , "name": "extra-provides" + , "default": {"type": "empty_map"} + } + ] + } + } + } + } +, "shared artifact": + { "vars": + [ "CC" + , "CXX" + , "CFLAGS" + , "CXXFLAGS" + , "LDFLAGS" + , "ADD_CFLAGS" + , "ADD_CXXFLAGS" + , "ADD_LDFLAGS" + , "ENV" + , "name" + , "pure C" + , "srcs" + , "hdrs" + , "private-hdrs" + , "soversion" + , "compile-deps" + , "compile-args" + , "link-deps" + , "link-args" + , "run-libs" + , "run-libs-args" + , "defaults-transition" + ] + , "imports": + { "compiler": "compiler" + , "flags": "flags" + , "objects": "objects" + , "default-LDFLAGS": "default-LDFLAGS" + , "default-ENV": "default-ENV" + } + , "expression": + { "type": "let*" + , "bindings": + [ ["BUILD_POSITION_INDEPENDENT", true] + , ["COMPILER", {"type": "CALL_EXPRESSION", "name": "compiler"}] + , [ "COMPILE_FLAGS" + , { "type": "++" + , "$1": + [ {"type": "CALL_EXPRESSION", "name": "flags"} + , {"type": "var", "name": "compile-args"} + ] + } + ] + , [ "LDFLAGS" + , { "type": "++" + , "$1": + [ { "type": "var" + , "name": "LDFLAGS" + , "default": + {"type": "CALL_EXPRESSION", "name": "default-LDFLAGS"} + } + , {"type": "var", "name": "ADD_LDFLAGS", "default": []} + ] + } + ] + , [ "ENV" + , { "type": "map_union" + , "$1": + { "type": "++" + , "$1": + [ {"type": "CALL_EXPRESSION", "name": "default-ENV"} + , [ { "type": "var" + , "name": "ENV" + , "default": {"type": "empty_map"} + } + ] + ] + } + } + ] + , ["objects", {"type": "CALL_EXPRESSION", "name": "objects"}] + , [ "base name" + , { "type": "if" + , "cond": {"type": "var", "name": "objects"} + , "then": + { "type": "assert_non_empty" + , "msg": "A name has to be provided for non-header-only libraries" + , "$1": {"type": "var", "name": "name"} + } + , "else": {"type": "var", "name": "name"} + } + ] + , [ "libname" + , { "type": "join" + , "$1": ["lib", {"type": "var", "name": "base name"}, ".so"] + } + ] + , [ "libname" + , { "type": "join" + , "separator": "." + , "$1": + { "type": "++" + , "$1": + [ [{"type": "var", "name": "libname"}] + , {"type": "var", "name": "soversion"} + ] + } + } + ] + , [ "lib" + , { "type": "if" + , "cond": {"type": "var", "name": "objects"} + , "else": {"type": "empty_map"} + , "then": + { "type": "ACTION" + , "outs": [{"type": "var", "name": "libname"}] + , "inputs": + { "type": "map_union" + , "$1": + [ {"type": "var", "name": "objects"} + , {"type": "var", "name": "link-deps"} + , {"type": "var", "name": "run-libs"} + ] + } + , "env": + {"type": "var", "name": "ENV", "default": {"type": "empty_map"}} + , "cmd": + { "type": "++" + , "$1": + [ [ {"type": "var", "name": "COMPILER"} + , "-shared" + , "-Wl,-rpath,$ORIGIN" + , "-Wl,-rpath,$ORIGIN/../lib" + , { "type": "join" + , "$1": + ["-Wl,-soname,", {"type": "var", "name": "libname"}] + } + ] + , {"type": "var", "name": "COMPILE_FLAGS"} + , {"type": "var", "name": "LDFLAGS"} + , ["-o", {"type": "var", "name": "libname"}] + , {"type": "keys", "$1": {"type": "var", "name": "objects"}} + , {"type": "var", "name": "link-args"} + , {"type": "var", "name": "run-libs-args"} + ] + } + } + } + ] + ] + , "body": {"type": "var", "name": "lib"} + } + } +, "shared result": + { "vars": + [ "CC" + , "CXX" + , "CFLAGS" + , "CXXFLAGS" + , "LDFLAGS" + , "ADD_CXXFLAGS" + , "ADD_CFLAGS" + , "ADD_LDFLAGS" + , "ENV" + , "name" + , "pure C" + , "srcs" + , "hdrs" + , "private-hdrs" + , "cflags" + , "private-cflags" + , "private-ldflags" + , "soversion" + , "extra-provides" + , "deps-transition" + , "public-fieldnames" + , "private-fieldnames" + ] + , "imports": + { "compile-deps": "compile-deps" + , "compile-args-deps": "compile-args-deps" + , "link-deps": "link-deps" + , "link-args-deps": "link-args-deps" + , "run-libs-deps": "run-libs-deps" + , "run-libs-args-deps": "run-libs-args-deps" + , "shared artifact": "shared artifact" + } + , "expression": + { "type": "let*" + , "bindings": + [ ["deps-fieldnames", {"type": "var", "name": "private-fieldnames"}] + , ["compile-deps", {"type": "CALL_EXPRESSION", "name": "compile-deps"}] + , [ "compile-args" + , { "type": "nub_right" + , "$1": + { "type": "++" + , "$1": + [ {"type": "var", "name": "cflags"} + , {"type": "var", "name": "private-cflags"} + , {"type": "CALL_EXPRESSION", "name": "compile-args-deps"} + ] + } + } + ] + , ["link-deps", {"type": "CALL_EXPRESSION", "name": "link-deps"}] + , ["link-args", {"type": "CALL_EXPRESSION", "name": "link-args-deps"}] + , ["run-libs", {"type": "CALL_EXPRESSION", "name": "run-libs-deps"}] + , [ "run-libs-args" + , { "type": "nub_right" + , "$1": + { "type": "++" + , "$1": + [ {"type": "var", "name": "private-ldflags", "default": []} + , {"type": "CALL_EXPRESSION", "name": "run-libs-args-deps"} + ] + } + } + ] + , ["lib", {"type": "CALL_EXPRESSION", "name": "shared artifact"}] + , ["deps-fieldnames", {"type": "var", "name": "public-fieldnames"}] + , ["compile-deps", {"type": "CALL_EXPRESSION", "name": "compile-deps"}] + , [ "compile-args" + , { "type": "nub_right" + , "$1": + { "type": "++" + , "$1": + [ {"type": "var", "name": "cflags"} + , {"type": "CALL_EXPRESSION", "name": "compile-args-deps"} + ] + } + } + ] + , ["link-deps", {"type": "CALL_EXPRESSION", "name": "link-deps"}] + , ["link-args", {"type": "CALL_EXPRESSION", "name": "link-args-deps"}] + , [ "run-libs" + , { "type": "map_union" + , "$1": + [ {"type": "var", "name": "lib"} + , {"type": "var", "name": "run-libs"} + ] + } + ] + , [ "run-libs-args" + , {"type": "keys", "$1": {"type": "var", "name": "lib"}} + ] + ] + , "body": + { "type": "RESULT" + , "artifacts": {"type": "var", "name": "lib"} + , "runfiles": {"type": "var", "name": "hdrs"} + , "provides": + { "type": "map_union" + , "$1": + [ { "type": "env" + , "vars": + [ "compile-deps" + , "compile-args" + , "link-deps" + , "link-args" + , "run-libs" + , "run-libs-args" + ] + } + , { "type": "var" + , "name": "extra-provides" + , "default": {"type": "empty_map"} + } + ] + } + } + } + } +, "bin artifact": + { "doc": ["Produces the binary artifact."] + , "vars": + [ "CC" + , "CXX" + , "CFLAGS" + , "CXXFLAGS" + , "LDFLAGS" + , "ADD_CFLAGS" + , "ADD_CXXFLAGS" + , "ADD_LDFLAGS" + , "ENV" + , "BUILD_POSITION_INDEPENDENT" + , "name" + , "pure C" + , "srcs" + , "private-hdrs" + , "stage" + , "compile-deps" + , "compile-args" + , "link-deps" + , "link-args" + , "run-libs" + , "run-libs-args" + , "defaults-transition" + ] + , "imports": + { "compiler": "compiler" + , "flags": "flags" + , "objects": "objects" + , "default-ENV": "default-ENV" + , "default-LDFLAGS": "default-LDFLAGS" + } + , "expression": + { "type": "let*" + , "bindings": + [ ["COMPILER", {"type": "CALL_EXPRESSION", "name": "compiler"}] + , [ "COMPILE_FLAGS" + , { "type": "++" + , "$1": + [ {"type": "CALL_EXPRESSION", "name": "flags"} + , {"type": "var", "name": "compile-args"} + ] + } + ] + , [ "LDFLAGS" + , { "type": "++" + , "$1": + [ { "type": "var" + , "name": "LDFLAGS" + , "default": + {"type": "CALL_EXPRESSION", "name": "default-LDFLAGS"} + } + , {"type": "var", "name": "ADD_LDFLAGS", "default": []} + ] + } + ] + , [ "ENV" + , { "type": "map_union" + , "$1": + { "type": "++" + , "$1": + [ {"type": "CALL_EXPRESSION", "name": "default-ENV"} + , [ { "type": "var" + , "name": "ENV" + , "default": {"type": "empty_map"} + } + ] + ] + } + } + ] + , ["hdrs", {"type": "empty_map"}] + , ["objects", {"type": "CALL_EXPRESSION", "name": "objects"}] + , [ "link-args" + , { "type": "nub_right" + , "$1": + { "type": "++" + , "$1": + [ {"type": "keys", "$1": {"type": "var", "name": "objects"}} + , {"type": "var", "name": "link-args"} + ] + } + } + ] + , [ "binpath" + , { "type": "if" + , "cond": {"type": "var", "name": "stage"} + , "then": + { "type": "join" + , "separator": "/" + , "$1": + [ {"type": "var", "name": "stage"} + , {"type": "var", "name": "name"} + ] + } + , "else": {"type": "var", "name": "name"} + } + ] + , [ "binary" + , { "type": "ACTION" + , "outs": [{"type": "var", "name": "binpath"}] + , "inputs": + { "type": "disjoint_map_union" + , "$1": + [ {"type": "var", "name": "objects"} + , {"type": "var", "name": "link-deps"} + , {"type": "var", "name": "run-libs"} + ] + } + , "cmd": + { "type": "++" + , "$1": + [ [ {"type": "var", "name": "COMPILER"} + , "-Wl,-rpath,$ORIGIN" + , "-Wl,-rpath,$ORIGIN/../lib" + , "-o" + , {"type": "var", "name": "binpath"} + ] + , {"type": "var", "name": "COMPILE_FLAGS"} + , {"type": "var", "name": "LDFLAGS"} + , {"type": "var", "name": "link-args"} + , {"type": "var", "name": "run-libs-args"} + ] + } + , "env": {"type": "var", "name": "ENV"} + } + ] + ] + , "body": {"type": "var", "name": "binary"} + } + } +, "bin result": + { "doc": ["Produces the binary target result."] + , "vars": + [ "CC" + , "CXX" + , "CFLAGS" + , "CXXFLAGS" + , "LDFLAGS" + , "ADD_CFLAGS" + , "ADD_CXXFLAGS" + , "ADD_LDFLAGS" + , "ENV" + , "BUILD_POSITION_INDEPENDENT" + , "name" + , "pure C" + , "srcs" + , "private-hdrs" + , "private-cflags" + , "private-ldflags" + , "stage" + , "private-fieldnames" + ] + , "imports": + { "compile-deps": "compile-deps" + , "compile-args-deps": "compile-args-deps" + , "link-deps": "link-deps" + , "link-args-deps": "link-args-deps" + , "run-libs-deps": "run-libs-deps" + , "run-libs-args-deps": "run-libs-args-deps" + , "binary": "bin artifact" + } + , "expression": + { "type": "let*" + , "bindings": + [ ["deps-fieldnames", {"type": "var", "name": "private-fieldnames"}] + , ["compile-deps", {"type": "CALL_EXPRESSION", "name": "compile-deps"}] + , [ "compile-args" + , { "type": "++" + , "$1": + [ {"type": "CALL_EXPRESSION", "name": "compile-args-deps"} + , {"type": "var", "name": "private-cflags"} + ] + } + ] + , ["link-deps", {"type": "CALL_EXPRESSION", "name": "link-deps"}] + , [ "link-args" + , { "type": "nub_right" + , "$1": + { "type": "++" + , "$1": + [ {"type": "var", "name": "private-ldflags"} + , {"type": "CALL_EXPRESSION", "name": "link-args-deps"} + ] + } + } + ] + , ["run-libs", {"type": "CALL_EXPRESSION", "name": "run-libs-deps"}] + , [ "run-libs-args" + , {"type": "CALL_EXPRESSION", "name": "run-libs-args-deps"} + ] + ] + , "body": + { "type": "RESULT" + , "artifacts": {"type": "CALL_EXPRESSION", "name": "binary"} + , "provides": {"type": "env", "vars": ["run-libs"]} + } + } + } +} diff --git a/rules/CC/IDE/RULES b/rules/CC/IDE/RULES new file mode 100644 index 0000000..dc4b607 --- /dev/null +++ b/rules/CC/IDE/RULES @@ -0,0 +1,96 @@ +{ "headers": + { "doc": ["Transitive public headers of C++ target"] + , "target_fields": ["proto", "deps"] + , "string_fields": ["stage"] + , "field_doc": + { "proto": ["The proto source files for creating cc bindings."] + , "deps": ["The targets to obtain the headers from."] + , "stage": + [ "The logical location of the header files. Individual directory" + , "components are joined with \"/\"." + ] + } + , "anonymous": + { "proto-deps": + { "target": "proto" + , "provider": "proto" + , "rule_map": + { "library": ["./", "../proto", "library"] + , "service library": ["./", "../proto", "service library"] + } + } + } + , "imports": {"runfiles_list": ["./", "../..", "field_runfiles_list"]} + , "expression": + { "type": "let*" + , "bindings": + [ [ "stage" + , { "type": "join" + , "separator": "/" + , "$1": {"type": "FIELD", "name": "stage"} + } + ] + , [ "artifacts" + , { "type": "to_subdir" + , "subdir": {"type": "var", "name": "stage"} + , "$1": + { "type": "map_union" + , "$1": + { "type": "++" + , "$1": + [ { "type": "let*" + , "bindings": [["fieldname", "proto-deps"]] + , "body": + {"type": "CALL_EXPRESSION", "name": "runfiles_list"} + } + , { "type": "foreach" + , "var": "x" + , "range": {"type": "FIELD", "name": "proto-deps"} + , "body": + { "type": "DEP_PROVIDES" + , "provider": "compile-deps" + , "dep": {"type": "var", "name": "x"} + , "default": + { "type": "fail" + , "msg": + [ "Expected a library target, but got:" + , {"type": "var", "name": "x"} + ] + } + } + } + , { "type": "let*" + , "bindings": [["fieldname", "deps"]] + , "body": + {"type": "CALL_EXPRESSION", "name": "runfiles_list"} + } + , { "type": "foreach" + , "var": "x" + , "range": {"type": "FIELD", "name": "deps"} + , "body": + { "type": "DEP_PROVIDES" + , "provider": "compile-deps" + , "dep": {"type": "var", "name": "x"} + , "default": + { "type": "fail" + , "msg": + [ "Expected a library target, but got:" + , {"type": "var", "name": "x"} + ] + } + } + } + ] + } + } + } + ] + ] + , "body": + { "type": "RESULT" + , "artifacts": {"type": "var", "name": "artifacts"} + , "runfiles": {"type": "var", "name": "artifacts"} + } + } + } +} diff --git a/rules/CC/RULES b/rules/CC/RULES new file mode 100644 index 0000000..4d90adc --- /dev/null +++ b/rules/CC/RULES @@ -0,0 +1,536 @@ +{ "defaults": + { "doc": + [ "A rule to provide defaults." + , "All CC targets take their defaults for CC, CXX, 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." + ] + , "target_fields": ["base"] + , "string_fields": + [ "CC" + , "CXX" + , "CFLAGS" + , "CXXFLAGS" + , "LDFLAGS" + , "ADD_CFLAGS" + , "ADD_CXXFLAGS" + , "ADD_LDFLAGS" + , "AR" + , "PATH" + ] + , "imports": {"base-provides": "defaults-base-provides"} + , "expression": + { "type": "let*" + , "bindings": + [ ["CC", {"type": "FIELD", "name": "CC"}] + , ["CXX", {"type": "FIELD", "name": "CXX"}] + , ["CFLAGS", {"type": "FIELD", "name": "CFLAGS"}] + , ["CXXFLAGS", {"type": "FIELD", "name": "CXXFLAGS"}] + , ["LDFLAGS", {"type": "FIELD", "name": "LDFLAGS"}] + , ["AR", {"type": "FIELD", "name": "AR"}] + , ["PATH", {"type": "FIELD", "name": "PATH"}] + , ["provider", "CC"] + , [ "CC" + , { "type": "if" + , "cond": {"type": "var", "name": "CC"} + , "then": {"type": "var", "name": "CC"} + , "else": {"type": "CALL_EXPRESSION", "name": "base-provides"} + } + ] + , ["provider", "CXX"] + , [ "CXX" + , { "type": "if" + , "cond": {"type": "var", "name": "CXX"} + , "then": {"type": "var", "name": "CXX"} + , "else": {"type": "CALL_EXPRESSION", "name": "base-provides"} + } + ] + , ["provider", "CFLAGS"] + , [ "CFLAGS" + , { "type": "if" + , "cond": {"type": "var", "name": "CFLAGS"} + , "then": {"type": "var", "name": "CFLAGS"} + , "else": {"type": "CALL_EXPRESSION", "name": "base-provides"} + } + ] + , ["provider", "CXXFLAGS"] + , [ "CXXFLAGS" + , { "type": "if" + , "cond": {"type": "var", "name": "CXXFLAGS"} + , "then": {"type": "var", "name": "CXXFLAGS"} + , "else": {"type": "CALL_EXPRESSION", "name": "base-provides"} + } + ] + , ["provider", "AR"] + , [ "AR" + , { "type": "if" + , "cond": {"type": "var", "name": "AR"} + , "then": {"type": "var", "name": "AR"} + , "else": {"type": "CALL_EXPRESSION", "name": "base-provides"} + } + ] + , ["provider", "ENV"] + , [ "ENV" + , { "type": "if" + , "cond": {"type": "var", "name": "PATH"} + , "then": + { "type": "singleton_map" + , "key": "PATH" + , "value": + { "type": "join" + , "separator": ":" + , "$1": {"type": "var", "name": "PATH"} + } + } + , "else": {"type": "CALL_EXPRESSION", "name": "base-provides"} + } + ] + , [ "CFLAGS" + , { "type": "++" + , "$1": + [ {"type": "var", "name": "CFLAGS"} + , {"type": "FIELD", "name": "ADD_CFLAGS"} + ] + } + ] + , [ "CXXFLAGS" + , { "type": "++" + , "$1": + [ {"type": "var", "name": "CXXFLAGS"} + , {"type": "FIELD", "name": "ADD_CXXFLAGS"} + ] + } + ] + , [ "LDFLAGS" + , { "type": "++" + , "$1": + [ {"type": "var", "name": "LDFLAGS"} + , {"type": "FIELD", "name": "ADD_LDFLAGS"} + ] + } + ] + ] + , "body": + { "type": "RESULT" + , "provides": + { "type": "env" + , "vars": ["CC", "CXX", "CFLAGS", "CXXFLAGS", "LDFLAGS", "AR", "ENV"] + } + } + } + } +, "library": + { "doc": ["A C++ library"] + , "target_fields": + ["srcs", "hdrs", "private-hdrs", "deps", "private-deps", "proto"] + , "string_fields": + [ "name" + , "stage" + , "pure C" + , "defines" + , "private-defines" + , "cflags" + , "private-cflags" + , "private-ldflags" + , "soversion" + ] + , "config_fields": ["shared"] + , "config_vars": + [ "CC" + , "CXX" + , "CFLAGS" + , "CXXFLAGS" + , "LDFLAGS" + , "ADD_CFLAGS" + , "ADD_CXXFLAGS" + , "ADD_LDFLAGS" + , "AR" + , "ENV" + , "BUILD_POSITION_INDEPENDENT" + ] + , "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 (or their" + , "respective defaults)." + ] + , "defines": + [ "List of defines set for this target and its consumers." + , "Each list entry will be prepended by \"-D\"." + ] + , "private-defines": + [ "List of defines set for source files local to this target." + , "Each list entry will be prepended by \"-D\"." + ] + , "cflags": + ["List of compile flags set for this target and its consumers."] + , "private-cflags": + ["List of compile flags set for source files local to this target."] + , "private-ldflags": + [ "Additional linker flags for linking external libraries (not built" + , "by this tool, typically system libraries)." + ] + , "deps": ["Any other libraries this library depends upon."] + , "private-deps": + [ "Any other libraries this library depends upon but does not include" + , "in its public headers." + ] + , "proto": + [ "Any [\"proto\", \"library\"] this target depends upon directly." + , "The creation of C++ bindings for this proto library as well as of" + , "its dependencies will be taken care of (as anonymous targets, so no" + , "duplicate work will be carried out, even if the same proto library" + , "is used at various places)." + ] + , "shared": ["If non-empty, produce a shared instead of a static library."] + , "soversion": + [ "The SOVERSION for shared libraries. Individual version components are" + , "joined with \".\"." + ] + } + , "config_doc": + { "CC": + [ "The name of the C compiler to be used (when compiling pure C code)." + , "If None, the respective value from [\"CC\", \"defaults\"] will be taken." + ] + , "CXX": + [ "The name of the C++ compiler to be used." + , "If None, the respective value from [\"CC\", \"defaults\"] will be taken." + ] + , "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." + ] + , "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." + ] + , "LDFLAGS": + [ "The linker flags 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." + ] + , "ADD_CFLAGS": + [ "The flags to add to the default ones for CC." + , "For libraries that should be built in a non-standard way; usually" + , "adapting the default target [\"CC\", \"defaults\"] is the better" + , "choice." + ] + , "ADD_CXXFLAGS": + [ "The flags to add to the default ones for CXX." + , "For libraries that should be built in a non-standard way; usually" + , "adapting the default target [\"CC\", \"defaults\"] is the better" + , "choice." + ] + , "ADD_LDFLAGS": + [ "The linker flags to add to 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." + ] + , "AR": + [ "The archive tool to used for creating the library" + , "If None, the respective value from [\"CC\", \"defaults\"] will be taken." + ] + , "ENV": ["The environment for any action generated."] + , "BUILD_POSITION_INDEPENDENT": ["Build with -fPIC."] + } + , "artifacts_doc": + ["The actual library (libname.a) staged in the specified directory"] + , "runfiles_doc": ["The public headers of this library"] + , "provides_doc": + { "compile-deps": + [ "Map of artifacts specifying any additional files that, besides the runfiles," + , "have to be present in compile actions of targets depending on this library" + ] + , "link-deps": + [ "Map of artifacts specifying any additional files that, besides the artifacts," + , "have to be present in a link actions of targets depending on this library" + ] + , "link-args": + [ "List of strings that have to be added to the command line for linking actions" + , "in targets depending on on this library" + ] + } + , "anonymous": + { "proto-deps": + { "target": "proto" + , "provider": "proto" + , "rule_map": + { "library": ["./", "proto", "library"] + , "service library": ["./", "proto", "service library"] + } + } + } + , "imports": + { "artifacts": ["./", "..", "field_artifacts"] + , "static result": "lib result" + , "shared result": "shared result" + , "fPIC transition": ["transitions", "with fPIC"] + } + , "config_transitions": + { "deps": [{"type": "CALL_EXPRESSION", "name": "fPIC transition"}] + , "private-deps": [{"type": "CALL_EXPRESSION", "name": "fPIC transition"}] + , "proto-deps": [{"type": "CALL_EXPRESSION", "name": "fPIC transition"}] + } + , "expression": + { "type": "let*" + , "bindings": + [ ["name", {"type": "join", "$1": {"type": "FIELD", "name": "name"}}] + , ["pure C", {"type": "FIELD", "name": "pure C"}] + , [ "cflags" + , { "type": "++" + , "$1": + [ {"type": "FIELD", "name": "cflags"} + , { "type": "foreach" + , "var": "def" + , "range": {"type": "FIELD", "name": "defines"} + , "body": + {"type": "join", "$1": ["-D", {"type": "var", "name": "def"}]} + } + ] + } + ] + , [ "private-cflags" + , { "type": "++" + , "$1": + [ {"type": "FIELD", "name": "private-cflags"} + , { "type": "foreach" + , "var": "def" + , "range": {"type": "FIELD", "name": "private-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"} + } + } + ] + , [ "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"} + } + } + ] + , ["private-ldflags", {"type": "FIELD", "name": "private-ldflags"}] + , ["soversion", {"type": "FIELD", "name": "soversion"}] + , [ "deps-transition" + , {"type": "CALL_EXPRESSION", "name": "fPIC transition"} + ] + , ["public-fieldnames", ["deps", "proto-deps"]] + , ["private-fieldnames", ["deps", "private-deps", "proto-deps"]] + ] + , "body": + { "type": "if" + , "cond": {"type": "FIELD", "name": "shared"} + , "then": {"type": "CALL_EXPRESSION", "name": "shared result"} + , "else": {"type": "CALL_EXPRESSION", "name": "static result"} + } + } + } +, "binary": + { "doc": ["A binary written in C++"] + , "target_fields": ["srcs", "private-hdrs", "private-deps", "private-proto"] + , "string_fields": + [ "name" + , "stage" + , "pure C" + , "private-defines" + , "private-cflags" + , "private-ldflags" + ] + , "config_vars": + [ "CC" + , "CXX" + , "CFLAGS" + , "CXXFLAGS" + , "LDFLAGS" + , "ADD_CFLAGS" + , "ADD_CXXFLAGS" + , "ADD_LDFLAGS" + , "ENV" + , "BUILD_POSITION_INDEPENDENT" + ] + , "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" + ] + , "private-defines": + [ "List of defines set for source files local to this target." + , "Each list entry will be prepended by \"-D\"." + ] + , "private-cflags": + ["List of compile flags set for source files local to this target."] + , "private-ldflags": + ["Additional linker flags for linking external libraries."] + , "private-deps": ["Any other libraries this binary depends upon."] + , "private-proto": + [ "Any [\"proto\", \"library\"] this target depends upon directly." + , "The creation of C++ bindings for this proto library as well as of" + , "is dependencies will be taken care of (as anonymous targets, so no" + , "duplicate work will be carried out, even if the same proto library" + , "is used at various places)." + ] + } + , "config_doc": + { "CC": + ["The name of the C compiler to be used (when compiling pure C code)"] + , "CXX": ["The name of the C++ compiler to be used."] + , "CFLAGS": + [ "The flags for CXX to be used instead of the default ones" + , "taken from the [\"CC\", \"defaults\"] target" + ] + , "CXXFLAGS": + [ "The flags for CXX to be used instead of the default ones" + , "taken from the [\"CC\", \"defaults\"] target" + ] + , "LDFLAGS": + [ "The linker flags do be used instead of the default ones" + , "taken from the [\"CC\", \"defaults\"] target" + ] + , "ADD_CFLAGS": + [ "The flags to add to the default ones for CC" + , "taken from the [\"CC\", \"defaults\"] target" + ] + , "ADD_CXXFLAGS": + [ "The flags to add to the default ones for CXX" + , "taken from the [\"CC\", \"defaults\"] target" + ] + , "ADD_LDFLAGS": + [ "The linker flags to add to the default ones" + , "taken from the [\"CC\", \"defaults\"] target" + ] + , "ENV": ["The environment for any action generated."] + , "BUILD_POSITION_INDEPENDENT": ["Build with -fPIC."] + } + , "artifacts_doc": ["The final binary, staged to the given directory"] + , "runfiles_doc": ["None"] + , "anonymous": + { "private-proto-deps": + { "target": "private-proto" + , "provider": "proto" + , "rule_map": + { "library": ["./", "proto", "library"] + , "service library": ["./", "proto", "service library"] + } + } + } + , "imports": + {"artifacts": ["./", "..", "field_artifacts"], "bin result": "bin result"} + , "expression": + { "type": "let*" + , "bindings": + [ [ "name" + , { "type": "assert_non_empty" + , "msg": "A non-empty name has to be provided for binaries" + , "$1": {"type": "join", "$1": {"type": "FIELD", "name": "name"}} + } + ] + , ["pure C", {"type": "FIELD", "name": "pure C"}] + , [ "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"} + } + } + ] + , [ "private-hdrs" + , { "type": "to_subdir" + , "subdir": {"type": "var", "name": "stage"} + , "$1": + { "type": "let*" + , "bindings": [["fieldname", "private-hdrs"]] + , "body": {"type": "CALL_EXPRESSION", "name": "artifacts"} + } + } + ] + , [ "private-cflags" + , { "type": "++" + , "$1": + [ { "type": "foreach" + , "var": "def" + , "range": {"type": "FIELD", "name": "private-defines"} + , "body": + {"type": "join", "$1": ["-D", {"type": "var", "name": "def"}]} + } + , {"type": "FIELD", "name": "private-cflags"} + ] + } + ] + , ["private-ldflags", {"type": "FIELD", "name": "private-ldflags"}] + , ["private-fieldnames", ["private-deps", "private-proto-deps"]] + ] + , "body": {"type": "CALL_EXPRESSION", "name": "bin result"} + } + } +} diff --git a/rules/CC/TARGETS b/rules/CC/TARGETS new file mode 100644 index 0000000..8860e8b --- /dev/null +++ b/rules/CC/TARGETS @@ -0,0 +1,11 @@ +{ "defaults": + { "type": ["CC", "defaults"] + , "CC": ["cc"] + , "CXX": ["c++"] + , "CFLAGS": [] + , "CXXFLAGS": [] + , "LDFLAGS": [] + , "AR": ["ar"] + , "PATH": ["/bin", "/usr/bin"] + } +} diff --git a/rules/CC/auto/EXPRESSIONS b/rules/CC/auto/EXPRESSIONS new file mode 100644 index 0000000..ac19f7a --- /dev/null +++ b/rules/CC/auto/EXPRESSIONS @@ -0,0 +1,32 @@ +{ "last_list_entry": + { "vars": ["list"] + , "expression": + { "type": "foldl" + , "range": {"type": "var", "name": "list"} + , "start": null + , "body": {"type": "var", "name": "_"} + } + } +, "first_list_entry": + { "vars": ["list"] + , "imports": {"last": "last_list_entry"} + , "expression": + { "type": "let*" + , "bindings": + [ [ "list" + , { "type": "foldl" + , "range": {"type": "var", "name": "list", "default": []} + , "start": null + , "body": + { "type": "if" + , "cond": {"type": "var", "name": "$1"} + , "then": {"type": "var", "name": "$1"} + , "else": [{"type": "var", "name": "_"}] + } + } + ] + ] + , "body": {"type": "CALL_EXPRESSION", "name": "last"} + } + } +} diff --git a/rules/CC/auto/RULES b/rules/CC/auto/RULES new file mode 100644 index 0000000..4f38504 --- /dev/null +++ b/rules/CC/auto/RULES @@ -0,0 +1,955 @@ +{ "config": + { "doc": + [ "Generate a C/C++ config header" + , "" + , "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": + { "name": ["Name of the header file to generate (incl. file name ext)."] + , "guard": ["The include guard. Multiple segments are joined with \"_\"."] + , "stage": + ["The location of the header. Path segments are joined with \"/\"."] + , "hdrs": + [ "Additional header files to be available in the include path. Useful" + , "for providing additional header files to values given in" + , "\"have_{cfile,cxxfile,ctype,cxxtype,csymbol,cxxsymbol}\"." + ] + , "deps": + [ "Additional public header files from targets to be available in the" + , "include path. Useful for providing additional header files to values" + , "given in \"have_{cfile,cxxfile,ctype,cxxtype,csymbol,cxxsymbol}\"." + ] + } + , "config_doc": + { "CC": + [ "The name of the C compiler to be used by checks. If None, the" + , "respective value from [\"CC\", \"defaults\"] will be taken." + ] + , "CXX": + [ "The name of the C++ compiler to be used by checks. If None, the" + , "respective value from [\"CC\", \"defaults\"] will be taken." + ] + , "CFLAGS": + [ "The flags for CXX to be used instead of the default ones" + , "taken from the [\"CC\", \"defaults\"] target" + ] + , "CXXFLAGS": + [ "The flags for CXX to be used instead of the default ones" + , "taken from the [\"CC\", \"defaults\"] target" + ] + , "ADD_CFLAGS": + [ "The flags to add to the default ones for CC" + , "taken from the [\"CC\", \"defaults\"] target" + ] + , "ADD_CXXFLAGS": + [ "The flags to add to the default ones for CXX" + , "taken from the [\"CC\", \"defaults\"] target" + ] + , "ENV": ["The environment for running file/symbol/type/size checks."] + , "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*\", " + , "\"have_*\", and \"size_*\" values." + ] + , "defines1": + [ "Set a define to \"1\" unless its value is untrue. Must contain a list" + , "of pairs. The first element of each pair is the define name and the" + , "second argument is the value." + ] + , "defines01": + [ "Set a define to \"0\" or \"1\" depending on its value being true." + , "Must contain a list of pairs. The first element of each pair is the" + , "define name and the second argument is the value." + ] + , "have_cfile": + [ "Set a define to \"1\" if the specified C header is in the include" + , "path. Must contain a list of pairs. The first element of each pair is" + , "the define name and the second argument is the C header file name." + ] + , "have_cxxfile": + [ "Set a define to \"1\" if the specified C++ header is in the include" + , "path. Must contain a list of pairs. The first element of each pair is" + , "the define name and the second argument is the C++ header file name." + ] + , "have_ctype": + [ "Set a define to \"1\" if the specified C type is defined. Must" + , "contain a list of pairs. The first element of each pair is the define" + , "name and the second argument is name of the C type. If the specified" + , "C type is not a built-in type, additionally the headers" + , "\"sys/types.h\", \"stdint.h\", and \"stddef.h\" are checked as well." + ] + , "have_cxxtype": + [ "Set a define to \"1\" if the specified C++ type is defined. Must" + , "contain a list of pairs. The first element of each pair is the define" + , "name and the second argument is name of the C++ type. If the specified" + , "C++ type is not a built-in type, additionally the headers" + , "\"sys/types.h\", \"stdint.h\", and \"stddef.h\" are checked as well." + ] + , "have_csymbol": + [ "Set a define to \"1\" if the specified C symbol is defined by one of" + , "the specified headers in the include path. Must contain a list of" + , "pairs. The first element of each pair is the define name and the" + , "second argument is another pair. This pair's first value is the C" + , "symbol to search for and the second value is a list with the header" + , "file names to consider for searching." + ] + , "have_cxxsymbol": + [ "Set a define to \"1\" if the specified C++ symbol is defined by one of" + , "the specified headers in the include path. Must contain a list of" + , "pairs. The first element of each pair is the define name and the" + , "second argument is another pair. This pair's first value is the C++" + , "symbol to search for and the second value is a list with the header" + , "file names to consider for searching." + ] + , "size_ctype": + [ "Set a define to size of the specified C type. Must contain a list of" + , "pairs. The first element of each pair is the define name and the" + , "second argument is another pair. This pair's first value is the C" + , "type to check for and the second value is a list with possible sizes" + , "as numbers. If none of the specified sizes matches, the action fails." + ] + , "size_cxxtype": + [ "Set a define to size of the specified C++ type. Must contain a list of" + , "pairs. The first element of each pair is the define name and the" + , "second argument is another pair. This pair's first value is the C++" + , "type to check for and the second value is a list with possible sizes" + , "as numbers. If none of the specified sizes matches, the action fails." + ] + } + , "string_fields": ["name", "stage", "guard"] + , "target_fields": ["hdrs", "deps"] + , "config_vars": + [ "CC" + , "CXX" + , "CFLAGS" + , "CXXFLAGS" + , "ADD_CFLAGS" + , "ADD_CXXFLAGS" + , "ENV" + , "defines" + , "defines1" + , "defines01" + , "have_cfile" + , "have_cxxfile" + , "have_ctype" + , "have_cxxtype" + , "have_csymbol" + , "have_cxxsymbol" + , "size_ctype" + , "size_cxxtype" + ] + , "imports": + { "first": "first_list_entry" + , "last": "last_list_entry" + , "artifacts": ["./", "../..", "field_artifacts"] + , "compile-deps": ["./", "..", "compile-deps"] + , "compiler-cc": ["./", "..", "compiler-cc"] + , "compiler-cxx": ["./", "..", "compiler-cxx"] + , "flags-cc": ["./", "..", "flags-cc"] + , "flags-cxx": ["./", "..", "flags-cxx"] + , "default-ENV": ["./", "..", "default-ENV"] + } + , "implicit": {"defaults": [["./", "..", "defaults"]]} + , "expression": + { "type": "let*" + , "bindings": + [ ["name", {"type": "join", "$1": {"type": "FIELD", "name": "name"}}] + , [ "stage" + , { "type": "join" + , "separator": "/" + , "$1": {"type": "FIELD", "name": "stage"} + } + ] + , [ "guard" + , { "type": "assert_non_empty" + , "msg": "Config header include guard may not be empty" + , "$1": + { "type": "join" + , "separator": "_" + , "$1": {"type": "FIELD", "name": "guard"} + } + } + ] + , [ "includes" + , { "type": "to_subdir" + , "subdir": "include" + , "$1": + { "type": "disjoint_map_union" + , "msg": "Includes may not overlap" + , "$1": + [ { "type": "let*" + , "bindings": [["fieldname", "hdrs"]] + , "body": {"type": "CALL_EXPRESSION", "name": "artifacts"} + } + , { "type": "let*" + , "bindings": [["deps-fieldnames", ["deps"]]] + , "body": {"type": "CALL_EXPRESSION", "name": "compile-deps"} + } + ] + } + } + ] + , ["CC", {"type": "CALL_EXPRESSION", "name": "compiler-cc"}] + , ["CXX", {"type": "CALL_EXPRESSION", "name": "compiler-cxx"}] + , ["CFLAGS", {"type": "CALL_EXPRESSION", "name": "flags-cc"}] + , ["CXXFLAGS", {"type": "CALL_EXPRESSION", "name": "flags-cxx"}] + , [ "ENV" + , { "type": "map_union" + , "$1": + { "type": "++" + , "$1": + [ {"type": "CALL_EXPRESSION", "name": "default-ENV"} + , [ { "type": "var" + , "name": "ENV" + , "default": {"type": "empty_map"} + } + ] + ] + } + } + ] + , [ "c.flags" + , { "type": "BLOB" + , "data": + { "type": "join" + , "separator": "\n" + , "$1": {"type": "var", "name": "CFLAGS"} + } + } + ] + , [ "cxx.flags" + , { "type": "BLOB" + , "data": + { "type": "join" + , "separator": "\n" + , "$1": {"type": "var", "name": "CXXFLAGS"} + } + } + ] + , [ "file_check.sh" + , { "type": "BLOB" + , "data": + { "type": "join" + , "separator": "\n" + , "$1": + [ "set -eu" + , "[ $# -ge 4 ]" + , "CC=$1" + , "LANG=$2" + , "DEF=$3" + , "HDR=$4" + , "DEFINE=\"/* #undef $DEF */\"" + , "echo \"#include \\\"$HDR\\\"\" > test.$LANG" + , "if $CC @$LANG.flags -c test.$LANG -I ./include 2>/dev/null; then DEFINE=\"#define $DEF 1\"; fi" + , "echo \"$DEFINE\n\" > out.def" + ] + } + } + ] + , [ "type_check.sh" + , { "type": "BLOB" + , "data": + { "type": "join" + , "separator": "\n" + , "$1": + [ "set -eu" + , "[ $# -ge 4 ]" + , "CC=$1" + , "LANG=$2" + , "DEF=$3" + , "TYPE=$4" + , "INC=\"\"" + , "DEFINE=\"/* #undef $DEF */\"" + , "for HDR in \"\" \"sys/types.h\" \"stdint.h\" \"stddef.h\"; do" + , " if [ -n \"$HDR\" ]; then INC=\"#include \\\"$HDR\\\"\"; fi" + , " cat > test.$LANG << EOF" + , "$INC" + , "$TYPE* __test;" + , "EOF" + , " if $CC @$LANG.flags -c test.$LANG -I ./include 2>/dev/null; then" + , " DEFINE=\"#define $DEF 1\"" + , " break" + , " fi" + , "done" + , "echo \"$DEFINE\n\" > out.def" + ] + } + } + ] + , [ "symbol_check.sh" + , { "type": "BLOB" + , "data": + { "type": "join" + , "separator": "\n" + , "$1": + [ "set -eu" + , "[ $# -ge 4 ]" + , "CC=$1" + , "shift" + , "LANG=$1" + , "shift" + , "DEF=$1" + , "shift" + , "SYMBOL=$1" + , "shift" + , "DEFINE=\"/* #undef $DEF */\"" + , "for INC in \"$@\"; do" + , " cat > test.$LANG << EOF" + , "#include \"$INC\"" + , "#ifndef $SYMBOL" + , "void* __test = &$SYMBOL;" + , "#endif" + , "EOF" + , " if $CC @$LANG.flags -c test.$LANG -I ./include 2>/dev/null; then" + , " DEFINE=\"#define $DEF 1\"" + , " break" + , " fi" + , "done" + , "echo \"$DEFINE\n\" > out.def" + ] + } + } + ] + , [ "size_check.sh" + , { "type": "BLOB" + , "data": + { "type": "join" + , "separator": "\n" + , "$1": + [ "set -eu" + , "[ $# -ge 4 ]" + , "CC=$1" + , "shift" + , "LANG=$1" + , "shift" + , "DEF=$1" + , "shift" + , "TYPE=$1" + , "shift" + , "INC=\"\"" + , "for HDR in \"\" \"sys/types.h\" \"stdint.h\" \"stddef.h\"; do" + , " if [ -n \"$HDR\" ]; then INC=\"#include \\\"$HDR\\\"\"; fi" + , " for SIZE in \"$@\"; do" + , " SIZE=$(printf %.0f $SIZE)" + , " cat > test.$LANG << EOF" + , "$INC" + , "char __test[(sizeof($TYPE) == $SIZE) ? 1 : -1];" + , "EOF" + , " if $CC @$LANG.flags -c test.$LANG -I ./include 2>/dev/null; then" + , " DEFINE=\"#define $DEF $SIZE\"" + , " echo \"$DEFINE\n\" > out.def" + , " exit 0" + , " fi" + , " done" + , "done" + , "exit 1" + ] + } + } + ] + , [ "guard.def" + , { "type": "BLOB" + , "data": + { "type": "join" + , "separator": "\n" + , "$1": + [ { "type": "join" + , "separator": " " + , "$1": ["#ifndef", {"type": "var", "name": "guard"}] + } + , { "type": "join" + , "separator": " " + , "$1": ["#define", {"type": "var", "name": "guard"}] + } + , "\n\n" + ] + } + } + ] + , [ "plain.def" + , { "type": "BLOB" + , "data": + { "type": "join" + , "$1": + { "type": "foreach" + , "range": {"type": "var", "name": "defines", "default": []} + , "var": "pair" + , "body": + { "type": "let*" + , "bindings": + [ ["list", {"type": "var", "name": "pair"}] + , [ "def" + , { "type": "assert_non_empty" + , "msg": "Define name in 'defines' may not be empty" + , "$1": {"type": "CALL_EXPRESSION", "name": "first"} + } + ] + , ["val", {"type": "CALL_EXPRESSION", "name": "last"}] + ] + , "body": + { "type": "join" + , "separator": " " + , "$1": + { "type": "case*" + , "expr": {"type": "var", "name": "val"} + , "case": + [ [ null + , [ "/* #undef" + , {"type": "var", "name": "def"} + , "*/\n\n" + ] + ] + ] + , "default": + [ "#define" + , {"type": "var", "name": "def"} + , { "type": "join" + , "$1": [{"type": "var", "name": "val"}, "\n\n"] + } + ] + } + } + } + } + } + } + ] + , [ "int1.def" + , { "type": "BLOB" + , "data": + { "type": "join" + , "$1": + { "type": "foreach" + , "range": {"type": "var", "name": "defines1", "default": []} + , "var": "pair" + , "body": + { "type": "let*" + , "bindings": + [ ["list", {"type": "var", "name": "pair"}] + , [ "def" + , { "type": "assert_non_empty" + , "msg": "Define name in 'defines1' may not be empty" + , "$1": {"type": "CALL_EXPRESSION", "name": "first"} + } + ] + , ["val", {"type": "CALL_EXPRESSION", "name": "last"}] + ] + , "body": + { "type": "join" + , "separator": " " + , "$1": + { "type": "if" + , "cond": {"type": "var", "name": "val"} + , "then": + ["#define", {"type": "var", "name": "def"}, "1\n\n"] + , "else": + ["/* #undef", {"type": "var", "name": "def"}, "*/\n\n"] + } + } + } + } + } + } + ] + , [ "int01.def" + , { "type": "BLOB" + , "data": + { "type": "join" + , "$1": + { "type": "foreach" + , "range": {"type": "var", "name": "defines01", "default": []} + , "var": "pair" + , "body": + { "type": "let*" + , "bindings": + [ ["list", {"type": "var", "name": "pair"}] + , [ "def" + , { "type": "assert_non_empty" + , "msg": "Define name in 'defines01' may not be empty" + , "$1": {"type": "CALL_EXPRESSION", "name": "first"} + } + ] + , ["val", {"type": "CALL_EXPRESSION", "name": "last"}] + ] + , "body": + { "type": "join" + , "separator": " " + , "$1": + [ "#define" + , {"type": "var", "name": "def"} + , { "type": "if" + , "cond": {"type": "var", "name": "val"} + , "then": "1\n\n" + , "else": "0\n\n" + } + ] + } + } + } + } + } + ] + , [ "cfile-defs" + , { "type": "foreach" + , "range": {"type": "var", "name": "have_cfile", "default": []} + , "var": "pair" + , "body": + { "type": "let*" + , "bindings": + [ ["list", {"type": "var", "name": "pair"}] + , [ "def" + , { "type": "assert_non_empty" + , "msg": "Define name in 'have_cfile' may not be empty" + , "$1": {"type": "CALL_EXPRESSION", "name": "first"} + } + ] + , ["val", {"type": "CALL_EXPRESSION", "name": "last"}] + ] + , "body": + { "type": "lookup" + , "key": "out.def" + , "map": + { "type": "ACTION" + , "inputs": + { "type": "map_union" + , "$1": + [ {"type": "env", "vars": ["file_check.sh", "c.flags"]} + , {"type": "var", "name": "includes"} + ] + } + , "cmd": + [ "sh" + , "./file_check.sh" + , {"type": "var", "name": "CC"} + , "c" + , {"type": "var", "name": "def"} + , {"type": "var", "name": "val"} + ] + , "env": {"type": "var", "name": "ENV"} + , "outs": ["out.def"] + } + } + } + } + ] + , [ "cxxfile-defs" + , { "type": "foreach" + , "range": {"type": "var", "name": "have_cxxfile", "default": []} + , "var": "pair" + , "body": + { "type": "let*" + , "bindings": + [ ["list", {"type": "var", "name": "pair"}] + , [ "def" + , { "type": "assert_non_empty" + , "msg": "Define name in 'have_cxxfile' may not be empty" + , "$1": {"type": "CALL_EXPRESSION", "name": "first"} + } + ] + , ["val", {"type": "CALL_EXPRESSION", "name": "last"}] + ] + , "body": + { "type": "lookup" + , "key": "out.def" + , "map": + { "type": "ACTION" + , "inputs": + { "type": "map_union" + , "$1": + [ {"type": "env", "vars": ["file_check.sh", "cxx.flags"]} + , {"type": "var", "name": "includes"} + ] + } + , "cmd": + [ "sh" + , "./file_check.sh" + , {"type": "var", "name": "CXX"} + , "cxx" + , {"type": "var", "name": "def"} + , {"type": "var", "name": "val"} + ] + , "env": {"type": "var", "name": "ENV"} + , "outs": ["out.def"] + } + } + } + } + ] + , [ "ctype-defs" + , { "type": "foreach" + , "range": {"type": "var", "name": "have_ctype", "default": []} + , "var": "pair" + , "body": + { "type": "let*" + , "bindings": + [ ["list", {"type": "var", "name": "pair"}] + , [ "def" + , { "type": "assert_non_empty" + , "msg": "Define name in 'have_ctype' may not be empty" + , "$1": {"type": "CALL_EXPRESSION", "name": "first"} + } + ] + , ["type", {"type": "CALL_EXPRESSION", "name": "last"}] + ] + , "body": + { "type": "lookup" + , "key": "out.def" + , "map": + { "type": "ACTION" + , "inputs": + { "type": "map_union" + , "$1": + [ {"type": "env", "vars": ["type_check.sh", "c.flags"]} + , {"type": "var", "name": "includes"} + ] + } + , "cmd": + [ "sh" + , "./type_check.sh" + , {"type": "var", "name": "CC"} + , "c" + , {"type": "var", "name": "def"} + , {"type": "var", "name": "type"} + ] + , "env": {"type": "var", "name": "ENV"} + , "outs": ["out.def"] + } + } + } + } + ] + , [ "cxxtype-defs" + , { "type": "foreach" + , "range": {"type": "var", "name": "have_cxxtype", "default": []} + , "var": "pair" + , "body": + { "type": "let*" + , "bindings": + [ ["list", {"type": "var", "name": "pair"}] + , [ "def" + , { "type": "assert_non_empty" + , "msg": "Define name in 'have_cxxtype' may not be empty" + , "$1": {"type": "CALL_EXPRESSION", "name": "first"} + } + ] + , ["type", {"type": "CALL_EXPRESSION", "name": "last"}] + ] + , "body": + { "type": "lookup" + , "key": "out.def" + , "map": + { "type": "ACTION" + , "inputs": + { "type": "map_union" + , "$1": + [ {"type": "env", "vars": ["type_check.sh", "cxx.flags"]} + , {"type": "var", "name": "includes"} + ] + } + , "cmd": + [ "sh" + , "./type_check.sh" + , {"type": "var", "name": "CXX"} + , "cxx" + , {"type": "var", "name": "def"} + , {"type": "var", "name": "type"} + ] + , "env": {"type": "var", "name": "ENV"} + , "outs": ["out.def"] + } + } + } + } + ] + , [ "csymbol-defs" + , { "type": "foreach" + , "range": {"type": "var", "name": "have_csymbol", "default": []} + , "var": "pair" + , "body": + { "type": "let*" + , "bindings": + [ ["list", {"type": "var", "name": "pair"}] + , [ "def" + , { "type": "assert_non_empty" + , "msg": "Define name in 'have_csymbol' may not be empty" + , "$1": {"type": "CALL_EXPRESSION", "name": "first"} + } + ] + , ["list", {"type": "CALL_EXPRESSION", "name": "last"}] + , ["sym", {"type": "CALL_EXPRESSION", "name": "first"}] + , ["hdrs", {"type": "CALL_EXPRESSION", "name": "last"}] + ] + , "body": + { "type": "lookup" + , "key": "out.def" + , "map": + { "type": "ACTION" + , "inputs": + { "type": "map_union" + , "$1": + [ {"type": "env", "vars": ["symbol_check.sh", "c.flags"]} + , {"type": "var", "name": "includes"} + ] + } + , "cmd": + { "type": "++" + , "$1": + [ [ "sh" + , "./symbol_check.sh" + , {"type": "var", "name": "CC"} + , "c" + , {"type": "var", "name": "def"} + , {"type": "var", "name": "sym"} + ] + , {"type": "var", "name": "hdrs"} + ] + } + , "env": {"type": "var", "name": "ENV"} + , "outs": ["out.def"] + } + } + } + } + ] + , [ "cxxsymbol-defs" + , { "type": "foreach" + , "range": {"type": "var", "name": "have_cxxsymbol", "default": []} + , "var": "pair" + , "body": + { "type": "let*" + , "bindings": + [ ["list", {"type": "var", "name": "pair"}] + , [ "def" + , { "type": "assert_non_empty" + , "msg": "Define name in 'have_cxxsymbol' may not be empty" + , "$1": {"type": "CALL_EXPRESSION", "name": "first"} + } + ] + , ["list", {"type": "CALL_EXPRESSION", "name": "last"}] + , ["sym", {"type": "CALL_EXPRESSION", "name": "first"}] + , ["hdrs", {"type": "CALL_EXPRESSION", "name": "last"}] + ] + , "body": + { "type": "lookup" + , "key": "out.def" + , "map": + { "type": "ACTION" + , "inputs": + { "type": "map_union" + , "$1": + [ {"type": "env", "vars": ["symbol_check.sh", "cxx.flags"]} + , {"type": "var", "name": "includes"} + ] + } + , "cmd": + { "type": "++" + , "$1": + [ [ "sh" + , "./symbol_check.sh" + , {"type": "var", "name": "CXX"} + , "cxx" + , {"type": "var", "name": "def"} + , {"type": "var", "name": "sym"} + ] + , {"type": "var", "name": "hdrs"} + ] + } + , "env": {"type": "var", "name": "ENV"} + , "outs": ["out.def"] + } + } + } + } + ] + , [ "csize-defs" + , { "type": "foreach" + , "range": {"type": "var", "name": "size_ctype", "default": []} + , "var": "pair" + , "body": + { "type": "let*" + , "bindings": + [ ["list", {"type": "var", "name": "pair"}] + , [ "def" + , { "type": "assert_non_empty" + , "msg": "Define name in 'size_ctype' may not be empty" + , "$1": {"type": "CALL_EXPRESSION", "name": "first"} + } + ] + , ["list", {"type": "CALL_EXPRESSION", "name": "last"}] + , ["type", {"type": "CALL_EXPRESSION", "name": "first"}] + , ["sizes", {"type": "CALL_EXPRESSION", "name": "last"}] + ] + , "body": + { "type": "lookup" + , "key": "out.def" + , "map": + { "type": "ACTION" + , "inputs": + { "type": "map_union" + , "$1": + [ {"type": "env", "vars": ["size_check.sh", "c.flags"]} + , {"type": "var", "name": "includes"} + ] + } + , "cmd": + { "type": "++" + , "$1": + [ [ "sh" + , "./size_check.sh" + , {"type": "var", "name": "CC"} + , "c" + , {"type": "var", "name": "def"} + , {"type": "var", "name": "type"} + ] + , { "type": "foreach" + , "var": "size" + , "range": {"type": "var", "name": "sizes"} + , "body": + { "type": "json_encode" + , "$1": {"type": "var", "name": "size"} + } + } + ] + } + , "env": {"type": "var", "name": "ENV"} + , "outs": ["out.def"] + } + } + } + } + ] + , [ "cxxsize-defs" + , { "type": "foreach" + , "range": {"type": "var", "name": "size_cxxtype", "default": []} + , "var": "pair" + , "body": + { "type": "let*" + , "bindings": + [ ["list", {"type": "var", "name": "pair"}] + , [ "def" + , { "type": "assert_non_empty" + , "msg": "Define name in 'size_cxxtype' may not be empty" + , "$1": {"type": "CALL_EXPRESSION", "name": "first"} + } + ] + , ["list", {"type": "CALL_EXPRESSION", "name": "last"}] + , ["type", {"type": "CALL_EXPRESSION", "name": "first"}] + , ["sizes", {"type": "CALL_EXPRESSION", "name": "last"}] + ] + , "body": + { "type": "lookup" + , "key": "out.def" + , "map": + { "type": "ACTION" + , "inputs": + { "type": "map_union" + , "$1": + [ {"type": "env", "vars": ["size_check.sh", "cxx.flags"]} + , {"type": "var", "name": "includes"} + ] + } + , "cmd": + { "type": "++" + , "$1": + [ [ "sh" + , "./size_check.sh" + , {"type": "var", "name": "CXX"} + , "cxx" + , {"type": "var", "name": "def"} + , {"type": "var", "name": "type"} + ] + , { "type": "foreach" + , "var": "size" + , "range": {"type": "var", "name": "sizes"} + , "body": + { "type": "json_encode" + , "$1": {"type": "var", "name": "size"} + } + } + ] + } + , "env": {"type": "var", "name": "ENV"} + , "outs": ["out.def"] + } + } + } + } + ] + , ["end.def", {"type": "BLOB", "data": "\n#endif\n"}] + , [ "definitions" + , { "type": "enumerate" + , "$1": + { "type": "++" + , "$1": + [ [ {"type": "var", "name": "guard.def"} + , {"type": "var", "name": "int1.def"} + , {"type": "var", "name": "int01.def"} + ] + , {"type": "var", "name": "cfile-defs"} + , {"type": "var", "name": "cxxfile-defs"} + , {"type": "var", "name": "ctype-defs"} + , {"type": "var", "name": "cxxtype-defs"} + , {"type": "var", "name": "csymbol-defs"} + , {"type": "var", "name": "cxxsymbol-defs"} + , {"type": "var", "name": "csize-defs"} + , {"type": "var", "name": "cxxsize-defs"} + , [ {"type": "var", "name": "plain.def"} + , {"type": "var", "name": "end.def"} + ] + ] + } + } + ] + , [ "outfile" + , { "type": "ACTION" + , "inputs": {"type": "var", "name": "definitions"} + , "cmd": + [ "sh" + , "-c" + , { "type": "join" + , "separator": " " + , "$1": + [ "cat" + , { "type": "join_cmd" + , "$1": + { "type": "keys" + , "$1": {"type": "var", "name": "definitions"} + } + } + , "> out" + ] + } + ] + , "outs": ["out"] + , "env": {"type": "var", "name": "ENV"} + } + ] + , [ "outfile" + , { "type": "to_subdir" + , "subdir": {"type": "var", "name": "stage"} + , "$1": + { "type": "singleton_map" + , "key": {"type": "var", "name": "name"} + , "value": + { "type": "lookup" + , "key": "out" + , "map": {"type": "var", "name": "outfile"} + } + } + } + ] + ] + , "body": + { "type": "RESULT" + , "artifacts": {"type": "var", "name": "outfile"} + , "runfiles": {"type": "var", "name": "outfile"} + } + } + } +} diff --git a/rules/CC/proto/EXPRESSIONS b/rules/CC/proto/EXPRESSIONS new file mode 100644 index 0000000..1ab17a5 --- /dev/null +++ b/rules/CC/proto/EXPRESSIONS @@ -0,0 +1,308 @@ +{ "protoc-deps": + { "imports": {"map_provider": ["./", "../..", "field_map_provider"]} + , "expression": + { "type": "let*" + , "bindings": [["fieldname", "deps"], ["provider", "protoc-deps"]] + , "body": {"type": "CALL_EXPRESSION", "name": "map_provider"} + } + } +, "protoc-compile": + { "vars": + [ "CXX" + , "CXXFLAGS" + , "ADD_CXXFLAGS" + , "AR" + , "ENV" + , "name" + , "stage" + , "service support" + , "deps-transition" + , "public-fieldnames" + , "private-fieldnames" + ] + , "imports": + { "stage": ["", "stage_singleton_field"] + , "result": ["./", "..", "lib result"] + , "artifacts": ["./", "../..", "field_artifacts"] + , "artifacts_list": ["./", "../..", "field_artifacts_list"] + , "protoc-deps": "protoc-deps" + } + , "expression": + { "type": "let*" + , "bindings": + [ ["pure C", false] + , [ "protoc" + , { "type": "let*" + , "bindings": + [ ["fieldname", "protoc"] + , ["transition", {"type": "var", "name": "deps-transition"}] + , ["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"] + , ["transition", {"type": "var", "name": "deps-transition"}] + , ["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": "let*" + , "bindings": [["fieldname", "well_known_protos"]] + , "body": {"type": "CALL_EXPRESSION", "name": "artifacts"} + } + } + ] + , [ "proto srcs" + , { "type": "disjoint_map_union" + , "msg": "Sources may not conflict" + , "$1": + { "type": "let*" + , "bindings": [["fieldname", "srcs"]] + , "body": {"type": "CALL_EXPRESSION", "name": "artifacts_list"} + } + } + ] + , [ "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"} + } + ] + , ["cflags", []] + , ["private-cflags", ["-Wno-sign-conversion", "-Wno-unused-function"]] + , ["private-ldflags", []] + ] + , "body": {"type": "CALL_EXPRESSION", "name": "result"} + } + } +} diff --git a/rules/CC/proto/RULES b/rules/CC/proto/RULES new file mode 100644 index 0000000..d1cfc4e --- /dev/null +++ b/rules/CC/proto/RULES @@ -0,0 +1,93 @@ +{ "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", "CFLAGS", "ADD_CFLAGS", "AR", "ENV"] + , "implicit": + { "protoc": [["@", "protoc", "", "protoc"]] + , "defaults": [["./", "..", "defaults"]] + , "proto-deps": [["@", "protoc", "", "C++ runtime"]] + , "well_known_protos": [["@", "protoc", "", "well_known_protos"]] + } + , "imports": + { "protoc-compile": "protoc-compile" + , "host transition": ["transitions", "for host"] + } + , "config_transitions": + {"protoc": [{"type": "CALL_EXPRESSION", "name": "host transition"}]} + , "expression": + { "type": "let*" + , "bindings": + [ ["name", {"type": "join", "$1": {"type": "FIELD", "name": "name"}}] + , [ "stage" + , { "type": "join" + , "separator": "/" + , "$1": {"type": "FIELD", "name": "stage"} + } + ] + , [ "deps-transition" + , {"type": "CALL_EXPRESSION", "name": "host transition"} + ] + , ["public-fieldnames", ["deps", "proto-deps"]] + , ["private-fieldnames", ["deps", "proto-deps"]] + ] + , "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", "CXXFLAGS", "ADD_CXXFLAGS", "AR", "ENV"] + , "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"]] + } + , "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] + , ["name", {"type": "join", "$1": {"type": "FIELD", "name": "name"}}] + , [ "stage" + , { "type": "join" + , "separator": "/" + , "$1": {"type": "FIELD", "name": "stage"} + } + ] + , [ "deps-transition" + , {"type": "CALL_EXPRESSION", "name": "host transition"} + ] + , ["public-fieldnames", ["deps", "proto-deps"]] + , ["private-fieldnames", ["deps", "proto-deps"]] + ] + , "body": {"type": "CALL_EXPRESSION", "name": "protoc-compile"} + } + } +} diff --git a/rules/CC/test/RULES b/rules/CC/test/RULES new file mode 100644 index 0000000..60f33ab --- /dev/null +++ b/rules/CC/test/RULES @@ -0,0 +1,330 @@ +{ "test": + { "doc": ["A test written in C++"] + , "tainted": ["test"] + , "target_fields": ["srcs", "private-hdrs", "private-deps", "data"] + , "string_fields": + [ "name" + , "args" + , "stage" + , "pure C" + , "private-defines" + , "private-cflags" + , "private-ldflags" + ] + , "config_vars": + [ "ARCH" + , "HOST_ARCH" + , "CC" + , "CXX" + , "CFLAGS" + , "CXXFLAGS" + , "LDFLAGS" + , "ADD_CFLAGS" + , "ADD_CXXFLAGS" + , "ADD_LDFLAGS" + , "ENV" + , "BUILD_POSITION_INDEPENDENT" + , "TEST_ENV" + , "CC_TEST_LAUNCHER" + ] + , "implicit": + {"defaults": [["./", "..", "defaults"]], "runner": ["test_runner.py"]} + , "field_doc": + { "name": + [ "The name of the test" + , "" + , "Used to name the test binary as well as for staging the test result" + ] + , "args": ["Command line arguments for the test binary"] + , "srcs": ["The sources of the test binary"] + , "private-hdrs": + [ "Any additional header files that need to be present when compiling" + , "the test binary." + ] + , "private-defines": + [ "List of defines set for source files local to this target." + , "Each list entry will be prepended by \"-D\"." + ] + , "private-cflags": + ["List of compile flags set for source files local to this target."] + , "private-ldflags": + [ "Additional linker flags for linking external libraries (not built" + , "by this tool, typically system libraries)." + ] + , "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": + { "CC": ["The name of the C compiler to be used."] + , "CXX": ["The name of the C++ compiler to be used."] + , "CFLAGS": + [ "The flags for CC to be used instead of the default ones" + , "taken from the [\"CC\", \"defaults\"] target" + ] + , "CXXFLAGS": + [ "The flags for CXX to be used instead of the default ones" + , "taken from the [\"CC\", \"defaults\"] target" + ] + , "LDFLAGS": + [ "The linker flags do be used instead of the default ones" + , "taken from the [\"CC\", \"defaults\"] target" + ] + , "ADD_CFLAGS": + [ "The flags to add to the default ones for CC" + , "taken from the [\"CC\", \"defaults\"] target" + ] + , "ADD_CXXFLAGS": + [ "The flags to add to the default ones for CXX" + , "taken from the [\"CC\", \"defaults\"] target" + ] + , "ADD_LDFLAGS": + [ "The linker flags to add to the default ones" + , "taken from the [\"CC\", \"defaults\"] target" + ] + , "ENV": ["The environment for any action generated."] + , "BUILD_POSITION_INDEPENDENT": ["Build with -fPIC."] + , "TEST_ENV": ["The environment for executing the test runner."] + , "CC_TEST_LAUNCHER": + [ "List of strings representing the launcher that is prepend to the" + , "command line for running the test binary." + ] + } + , "artifacts_doc": + [ "result: the result of this test (\"PASS\" or \"FAIL\"); useful for" + , " generating test reports." + , "stdout/stderr: Any output the invocation of the test binary produced on" + , " the respective file descriptor" + , "time-start/time-stop: The time (decimally coded) in seconds since the" + , " epoch when the test invocation started and ended." + ] + , "runfiles_doc": + [ "A tree consisting of the artifacts staged at the name of the test." + , "As the built-in \"install\" rule only takes the runfiles of its" + , "\"private-deps\" argument, this gives an easy way of defining test" + , "suites." + ] + , "imports": + { "artifacts": ["./", "../..", "field_artifacts"] + , "runfiles": ["./", "../..", "field_runfiles"] + , "compile-deps": ["./", "..", "compile-deps"] + , "compile-args-deps": ["./", "..", "compile-args-deps"] + , "link-deps": ["./", "..", "link-deps"] + , "link-args-deps": ["./", "..", "link-args-deps"] + , "run-libs-deps": ["./", "..", "run-libs-deps"] + , "run-libs-args-deps": ["./", "..", "run-libs-args-deps"] + , "binary": ["./", "..", "bin artifact"] + , "host transition": ["transitions", "for host"] + } + , "config_transitions": + { "defaults": [{"type": "CALL_EXPRESSION", "name": "host transition"}] + , "private-deps": [{"type": "CALL_EXPRESSION", "name": "host transition"}] + , "data": [{"type": "CALL_EXPRESSION", "name": "host transition"}] + } + , "expression": + { "type": "let*" + , "bindings": + [ [ "name" + , { "type": "assert_non_empty" + , "msg": "A non-empty name has to be provided for binaries" + , "$1": {"type": "join", "$1": {"type": "FIELD", "name": "name"}} + } + ] + , ["pure C", {"type": "FIELD", "name": "pure C"}] + , [ "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"} + } + } + ] + , [ "private-hdrs" + , { "type": "to_subdir" + , "subdir": {"type": "var", "name": "stage"} + , "$1": + { "type": "let*" + , "bindings": [["fieldname", "private-hdrs"]] + , "body": {"type": "CALL_EXPRESSION", "name": "artifacts"} + } + } + ] + , ["host-trans", {"type": "CALL_EXPRESSION", "name": "host transition"}] + , ["defaults-transition", {"type": "var", "name": "host-trans"}] + , ["deps-transition", {"type": "var", "name": "host-trans"}] + , ["deps-fieldnames", ["private-deps"]] + , ["compile-deps", {"type": "CALL_EXPRESSION", "name": "compile-deps"}] + , [ "compile-args" + , { "type": "++" + , "$1": + [ { "type": "foreach" + , "var": "def" + , "range": {"type": "FIELD", "name": "private-defines"} + , "body": + {"type": "join", "$1": ["-D", {"type": "var", "name": "def"}]} + } + , {"type": "FIELD", "name": "private-cflags"} + , {"type": "CALL_EXPRESSION", "name": "compile-args-deps"} + ] + } + ] + , ["link-deps", {"type": "CALL_EXPRESSION", "name": "link-deps"}] + , [ "link-args" + , { "type": "++" + , "$1": + [ {"type": "CALL_EXPRESSION", "name": "link-args-deps"} + , {"type": "FIELD", "name": "private-ldflags"} + ] + } + ] + , ["run-libs", {"type": "CALL_EXPRESSION", "name": "run-libs-deps"}] + , [ "run-libs-args" + , {"type": "CALL_EXPRESSION", "name": "run-libs-args-deps"} + ] + , ["binary", {"type": "CALL_EXPRESSION", "name": "binary"}] + , [ "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" + , "value": {"type": "var", "name": "runner"} + } + } + } + } + } + ] + , [ "test-args" + , { "type": "singleton_map" + , "key": "test-args.json" + , "value": + { "type": "BLOB" + , "data": + { "type": "json_encode" + , "$1": {"type": "FIELD", "name": "args", "default": []} + } + } + } + ] + , [ "test-launcher" + , { "type": "singleton_map" + , "key": "test-launcher.json" + , "value": + { "type": "BLOB" + , "data": + { "type": "json_encode" + , "$1": + {"type": "var", "name": "CC_TEST_LAUNCHER", "default": []} + } + } + } + ] + , [ "data" + , { "type": "let*" + , "bindings": + [ ["fieldname", "data"] + , ["transition", {"type": "var", "name": "deps-transition"}] + ] + , "body": + { "type": "map_union" + , "$1": + [ {"type": "CALL_EXPRESSION", "name": "runfiles"} + , {"type": "CALL_EXPRESSION", "name": "artifacts"} + ] + } + } + ] + , [ "test-name" + , { "type": "join" + , "separator": "/" + , "$1": + [{"type": "var", "name": "stage"}, {"type": "var", "name": "name"}] + } + ] + , [ "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": "test-args"} + , {"type": "var", "name": "test-launcher"} + , {"type": "var", "name": "staged test binary"} + , {"type": "var", "name": "run-libs"} + ] + } + , "cmd": ["./runner"] + , "env": + { "type": "var" + , "name": "TEST_ENV" + , "default": {"type": "empty_map"} + } + , "may_fail": ["test"] + , "fail_message": + { "type": "join" + , "$1": + ["CC test ", {"type": "var", "name": "test-name"}, " failed"] + } + } + ] + , [ "runfiles" + , { "type": "singleton_map" + , "key": {"type": "var", "name": "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/rules/CC/test/TARGETS b/rules/CC/test/TARGETS new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/rules/CC/test/TARGETS @@ -0,0 +1 @@ +{} diff --git a/rules/CC/test/test_runner.py b/rules/CC/test/test_runner.py new file mode 100755 index 0000000..0647621 --- /dev/null +++ b/rules/CC/test/test_runner.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 +# Copyright 2022 Huawei Cloud Computing Technology Co., Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import json +import os +import subprocess +import time + +time_start = time.time() +time_stop = 0 +result = "UNKNOWN" +stderr = "" +stdout = "" + + +def dump_results(): + with open("result", "w") as f: + f.write("%s\n" % (result, )) + with open("time-start", "w") as f: + f.write("%d\n" % (time_start, )) + with open("time-stop", "w") as f: + f.write("%d\n" % (time_stop, )) + with open("stdout", "w") as f: + f.write("%s\n" % (stdout, )) + with open("stderr", "w") as f: + f.write("%s\n" % (stderr, )) + + +dump_results() + +TEMP_DIR = os.path.realpath("scratch") +os.makedirs(TEMP_DIR, exist_ok=True) + +WORK_DIR = os.path.realpath("work") +os.makedirs(WORK_DIR, exist_ok=True) + +ENV = dict(os.environ, TEST_TMPDIR=TEMP_DIR) + +with open('test-launcher.json') as f: + test_launcher = json.load(f) + +with open('test-args.json') as f: + test_args = json.load(f) + +ret = subprocess.run(test_launcher + ["../test"] + test_args, + cwd=WORK_DIR, + env=ENV, + capture_output=True) + +time_stop = time.time() +result = "PASS" if ret.returncode == 0 else "FAIL" +stdout = ret.stdout.decode("utf-8") +stderr = ret.stderr.decode("utf-8") + +dump_results() + +if result != "PASS": exit(1) diff --git a/rules/EXPRESSIONS b/rules/EXPRESSIONS new file mode 100644 index 0000000..b974026 --- /dev/null +++ b/rules/EXPRESSIONS @@ -0,0 +1,229 @@ +{ "field_artifacts_list": + { "doc": ["Query list of artifacts from target_field's targets"] + , "vars": ["fieldname", "transition"] + , "vars_doc": + { "fieldname": ["The name of the target_field to query."] + , "transition": ["The optional configuration transition for the targets."] + } + , "expression": + { "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_artifacts": + { "doc": ["Query and merge artifacts from target_field's targets"] + , "vars": ["fieldname", "transition"] + , "vars_doc": + { "fieldname": ["The name of the target_field to query."] + , "transition": ["The optional configuration transition for the targets."] + } + , "imports": {"artifacts_list": "field_artifacts_list"} + , "expression": + { "type": "disjoint_map_union" + , "msg": + ["artifacts", {"type": "var", "name": "fieldname"}, "must not overlap"] + , "$1": {"type": "CALL_EXPRESSION", "name": "artifacts_list"} + } + } +, "field_runfiles_list": + { "doc": ["Query list of runfiles from target_field's targets"] + , "vars": ["fieldname", "transition"] + , "vars_doc": + { "fieldname": ["The name of the target_field to query."] + , "transition": ["The optional configuration transition for the targets."] + } + , "expression": + { "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"}} + } + } + } +, "field_runfiles": + { "doc": ["Query and merge runfiles from target_field's targets"] + , "vars": ["fieldname", "transition"] + , "vars_doc": + { "fieldname": ["The name of the target_field to query."] + , "transition": ["The optional configuration transition for the targets."] + } + , "imports": {"runfiles_list": "field_runfiles_list"} + , "expression": + { "type": "disjoint_map_union" + , "msg": + ["runfiles", {"type": "var", "name": "fieldname"}, "must not overlap"] + , "$1": {"type": "CALL_EXPRESSION", "name": "runfiles_list"} + } + } +, "field_provider_list": + { "doc": ["Query list of providers from targets' provides map"] + , "vars": ["fieldname", "provider", "transition", "default"] + , "vars_doc": + { "fieldname": ["The name of the target_field to query."] + , "provider": ["The name of the map provider in the provides map."] + , "transition": ["The optional configuration transition for the targets."] + , "default": ["The default if the provider was not found (default: [])."] + } + , "expression": + { "type": "foreach" + , "var": "x" + , "range": {"type": "FIELD", "name": {"type": "var", "name": "fieldname"}} + , "body": + { "type": "DEP_PROVIDES" + , "dep": {"type": "var", "name": "x"} + , "provider": {"type": "var", "name": "provider"} + , "transition": + {"type": "var", "name": "transition", "default": {"type": "empty_map"}} + , "default": {"type": "var", "name": "default", "default": []} + } + } + } +, "field_map_provider": + { "doc": ["Query and merge map-providers from targets' provides map"] + , "vars": ["fieldname", "provider", "transition"] + , "vars_doc": + { "fieldname": ["The name of the target_field to query."] + , "provider": ["The name of the map provider in the provides map."] + , "transition": ["The optional configuration transition for the targets."] + } + , "imports": {"provider_list": "field_provider_list"} + , "expression": + { "type": "disjoint_map_union" + , "msg": + ["Overlapping entries in provider", {"type": "var", "name": "provider"}] + , "$1": + { "type": "let*" + , "bindings": [["default", {"type": "empty_map"}]] + , "body": {"type": "CALL_EXPRESSION", "name": "provider_list"} + } + } + } +, "field_list_provider": + { "doc": ["Query and merge list-providers from targets' provides map"] + , "vars": ["fieldname", "provider", "transition"] + , "vars_doc": + { "fieldname": ["The name of the target_field to query."] + , "provider": ["The name of the list provider in the provides map."] + , "transition": ["The optional configuration transition for the targets."] + } + , "imports": {"provider_list": "field_provider_list"} + , "expression": + {"type": "++", "$1": {"type": "CALL_EXPRESSION", "name": "provider_list"}} + } +, "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": "assert_non_empty" + , "msg": + ["No artifact specified in field", {"type": "var", "name": "fieldname"}] + , "$1": + { "type": "disjoint_map_union" + , "msg": + [ "Expecting (essentially) a single artifact in field" + , {"type": "var", "name": "fieldname"} + ] + , "$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"} + } + } + } + } + } + } + } +, "stage_artifact_to_singleton_field": + { "vars": ["artifact", "fieldname", "transition"] + , "expression": + { "type": "let*" + , "bindings": + [ [ "location" + , { "type": "++" + , "$1": + { "type": "foreach" + , "var": "src" + , "range": + {"type": "FIELD", "name": {"type": "var", "name": "fieldname"}} + , "body": + { "type": "keys" + , "$1": + { "type": "DEP_ARTIFACTS" + , "dep": {"type": "var", "name": "src"} + , "transition": + { "type": "var" + , "name": "transition" + , "default": {"type": "empty_map"} + } + } + } + } + } + ] + , [ "staged_artifact" + , { "type": "foreach_map" + , "range": {"type": "var", "name": "artifact"} + , "var_val": "val" + , "body": + { "type": "foreach" + , "range": {"type": "var", "name": "location"} + , "var": "pos" + , "body": + { "type": "singleton_map" + , "key": {"type": "var", "name": "pos"} + , "value": {"type": "var", "name": "val"} + } + } + } + ] + ] + , "body": + { "type": "disjoint_map_union" + , "$1": {"type": "++", "$1": {"type": "var", "name": "staged_artifact"}} + } + } + } +} diff --git a/rules/data/RULES b/rules/data/RULES new file mode 100644 index 0000000..feb1a73 --- /dev/null +++ b/rules/data/RULES @@ -0,0 +1,109 @@ +{ "staged": + { "doc": ["Stage data to a logical subdirectory."] + , "target_fields": ["srcs", "deps"] + , "string_fields": ["stage"] + , "field_doc": + { "srcs": ["The files to be staged"] + , "stage": + [ "The logical directory to stage the files to." + , "Individual directory components are joined with \"/\"." + ] + , "deps": + [ "Targets of with their runfiles should be added as well." + , "Their staging is not changed." + ] + } + , "artifacts_doc": + [ "The runfiles of the \"srcs\" targets staged to the directory" + , "specified in \"stage\" together the runfiles of the targets" + , "specied in the field \"deps\" (in their original location)." + ] + , "runfiles_doc": ["Same as artifacts"] + , "imports": + { "runfiles": ["./", "..", "field_runfiles"] + , "artifacts": ["./", "..", "field_artifacts"] + } + , "expression": + { "type": "let*" + , "bindings": + [ [ "stage" + , { "type": "join" + , "separator": "/" + , "$1": {"type": "FIELD", "name": "stage"} + } + ] + , [ "srcs" + , { "type": "let*" + , "bindings": [["fieldname", "srcs"]] + , "body": + { "type": "map_union" + , "$1": + [ {"type": "CALL_EXPRESSION", "name": "runfiles"} + , {"type": "CALL_EXPRESSION", "name": "artifacts"} + ] + } + } + ] + , [ "staged" + , { "type": "to_subdir" + , "subdir": {"type": "var", "name": "stage"} + , "$1": {"type": "var", "name": "srcs"} + } + ] + , [ "dep stage" + , { "type": "let*" + , "bindings": [["fieldname", "deps"]] + , "body": {"type": "CALL_EXPRESSION", "name": "runfiles"} + } + ] + , [ "total" + , { "type": "disjoint_map_union" + , "msg": "Conflict between staged data and dependencies" + , "$1": + [ {"type": "var", "name": "dep stage"} + , {"type": "var", "name": "staged"} + ] + } + ] + ] + , "body": + { "type": "RESULT" + , "artifacts": {"type": "var", "name": "total"} + , "runfiles": {"type": "var", "name": "total"} + } + } + } +, "overlay": + { "doc": + ["Overlay the artifacts of \"deps\" targets in a latest-wins fashion."] + , "target_fields": ["deps"] + , "field_doc": {"deps": ["The targets of which to overlay the artifacts"]} + , "artifacts_doc": + [ "Artifacts of the targets specified in \"deps\". For conflicting" + , "logical paths, the artifact is taken from the latest target (in" + , "the \"deps\" field) that defines that logical path" + ] + , "runfiles_doc": ["Same as artifacts"] + , "expression": + { "type": "let*" + , "bindings": + [ [ "all" + , { "type": "map_union" + , "$1": + { "type": "foreach" + , "var": "dep" + , "range": {"type": "FIELD", "name": "deps"} + , "body": + {"type": "DEP_ARTIFACTS", "dep": {"type": "var", "name": "dep"}} + } + } + ] + ] + , "body": + { "type": "RESULT" + , "artifacts": {"type": "var", "name": "all"} + , "runfiles": {"type": "var", "name": "all"} + } + } + } +} diff --git a/rules/patch/RULES b/rules/patch/RULES new file mode 100644 index 0000000..bba83c2 --- /dev/null +++ b/rules/patch/RULES @@ -0,0 +1,139 @@ +{ "file": + { "doc": ["Replace a file, logically in place, by a patched version"] + , "target_fields": ["src", "patch"] + , "string_fields": ["patch-part"] + , "config_vars": ["PATCH", "ENV"] + , "field_doc": + { "src": + ["The single source file to patch, typically an explict file reference."] + , "patch": ["The patch to apply."] + , "patch-part": + [ "If the patch contains hunks for multiple files, only apply hunks for" + , "the specified file path. Individual directory components are joined" + , "with \"/\". Note that the patch must be provided in unified format." + ] + } + , "artifacts_doc": + ["The patched file, staged to the position the of the original file"] + , "runfiles_doc": ["Same as artifacts"] + , "imports": + { "stage_field": ["./", "..", "stage_singleton_field"] + , "stage_artifact": ["./", "..", "stage_artifact_to_singleton_field"] + } + , "expression": + { "type": "let*" + , "bindings": + [ [ "orig" + , { "type": "let*" + , "bindings": [["fieldname", "src"], ["location", "orig"]] + , "body": {"type": "CALL_EXPRESSION", "name": "stage_field"} + } + ] + , [ "patch" + , { "type": "let*" + , "bindings": [["fieldname", "patch"], ["location", "patch"]] + , "body": {"type": "CALL_EXPRESSION", "name": "stage_field"} + } + ] + , [ "patch-part" + , { "type": "join" + , "separator": "\\/" + , "$1": {"type": "FIELD", "name": "patch-part"} + } + ] + , [ "splitpatch" + , { "type": "BLOB" + , "data": + { "type": "join" + , "separator": "\n" + , "$1": + [ "set -e" + , { "type": "join" + , "$1": + [ { "type": "join_cmd" + , "$1": + [ "sed" + , "-n" + , { "type": "join" + , "$1": + [ "/^--- " + , {"type": "var", "name": "patch-part"} + , "/," + , "/^[^-+@\\ ]\\|^---\\ /p" + ] + } + ] + } + , " $1 | sed '$d' > patch" + ] + } + ] + } + } + ] + , [ "patch" + , { "type": "if" + , "cond": {"type": "var", "name": "patch-part"} + , "then": + { "type": "ACTION" + , "inputs": + { "type": "map_union" + , "$1": + [ { "type": "to_subdir" + , "subdir": "in" + , "$1": {"type": "var", "name": "patch"} + } + , { "type": "singleton_map" + , "key": "splitpatch" + , "value": {"type": "var", "name": "splitpatch"} + } + ] + } + , "outs": ["patch"] + , "cmd": ["sh", "./splitpatch", "in/patch"] + , "env": + {"type": "var", "name": "ENV", "default": {"type": "empty_map"}} + } + , "else": {"type": "var", "name": "patch"} + } + ] + , [ "inputs" + , { "type": "map_union" + , "$1": + [{"type": "var", "name": "orig"}, {"type": "var", "name": "patch"}] + } + ] + , [ "patched" + , { "type": "ACTION" + , "inputs": {"type": "var", "name": "inputs"} + , "outs": ["patched"] + , "cmd": + [ {"type": "var", "name": "PATCH", "default": "patch"} + , "-s" + , "--read-only=ignore" + , "--follow-symlinks" + , "-o" + , "patched" + , "orig" + , "patch" + ] + } + ] + , [ "result" + , { "type": "let*" + , "bindings": + [ ["artifact", {"type": "var", "name": "patched"}] + , ["fieldname", "src"] + ] + , "body": {"type": "CALL_EXPRESSION", "name": "stage_artifact"} + } + ] + ] + , "body": + { "type": "RESULT" + , "artifacts": {"type": "var", "name": "result"} + , "runfiles": {"type": "var", "name": "result"} + } + } + } +} diff --git a/rules/proto/RULES b/rules/proto/RULES new file mode 100644 index 0000000..95fb87a --- /dev/null +++ b/rules/proto/RULES @@ -0,0 +1,99 @@ +{ "library": + { "doc": + [ "A proto library as abtract data structure." + , "" + , "Such a libray does not produce any artifacts itself, but it can be" + , "used as a dependency for various language-specific rules." + ] + , "target_fields": ["srcs", "deps"] + , "string_fields": ["stage", "name", "service"] + , "field_doc": + { "srcs": ["The proto files for this library"] + , "deps": ["Any other proto library this library depends on"] + , "stage": + [ "The directory to stage the source files to." + , "Directory components are joined by \"/\"." + ] + , "name": ["The name of the (abstract) library."] + , "service": + [ "If non empty, generate a service library (with acces sto \"rpc\"" + , "definitions) instead of a regular one." + ] + } + , "artifacts_doc": ["None"] + , "runfiles_doc": ["None"] + , "provides_doc": + { "proto": + [ "A list containing a single target-graph node with the defintion of" + , "this proto library. The node types generated are \"library\" and" + , "\"service library\"." + ] + } + , "imports": + { "artifacts_list": ["./", "..", "field_artifacts_list"] + , "list_provider": ["./", "..", "field_list_provider"] + } + , "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": "let*" + , "bindings": [["fieldname", "srcs"]] + , "body": + {"type": "CALL_EXPRESSION", "name": "artifacts_list"} + } + } + } + } + } + ] + ] + , [ "deps" + , { "type": "let*" + , "bindings": [["fieldname", "deps"], ["provider", "proto"]] + , "body": {"type": "CALL_EXPRESSION", "name": "list_provider"} + } + ] + , ["name", [{"type": "var", "name": "name"}]] + , ["stage", [{"type": "var", "name": "stage"}]] + , [ "proto" + , [ { "type": "ABSTRACT_NODE" + , "node_type": + { "type": "if" + , "cond": {"type": "FIELD", "name": "service"} + , "then": "service library" + , "else": "library" + } + , "target_fields": {"type": "env", "vars": ["srcs", "deps"]} + , "string_fields": {"type": "env", "vars": ["name", "stage"]} + } + ] + ] + ] + , "body": + {"type": "RESULT", "provides": {"type": "env", "vars": ["proto"]}} + } + } +} diff --git a/rules/shell/test/EXPRESSIONS b/rules/shell/test/EXPRESSIONS new file mode 100644 index 0000000..d1d7e64 --- /dev/null +++ b/rules/shell/test/EXPRESSIONS @@ -0,0 +1,206 @@ +{ "test-action": + { "vars": + [ "TEST_ENV" + , "ATTEMPT" + , "name" + , "test.sh" + , "keep" + , "runner" + , "deps-fieldname" + , "deps-transition" + ] + , "imports": + { "artifacts_list": ["./", "../..", "field_artifacts_list"] + , "runfiles_list": ["./", "../..", "field_runfiles_list"] + , "map_provider": ["./", "../..", "field_map_provider"] + } + , "expression": + { "type": "let*" + , "bindings": + [ [ "runner" + , { "type": "map_union" + , "$1": + { "type": "foreach" + , "var": "runner" + , "range": {"type": "var", "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": "env", "vars": ["runner"]} + } + } + } + } + ] + , [ "deps" + , { "type": "TREE" + , "$1": + { "type": "disjoint_map_union" + , "msg": + [ "Field" + , {"type": "var", "name": "deps-fieldname"} + , "has to stage in a conflict free way" + ] + , "$1": + { "type": "++" + , "$1": + { "type": "let*" + , "bindings": + [ ["fieldname", {"type": "var", "name": "deps-fieldname"}] + , ["transition", {"type": "var", "name": "deps-transition"}] + ] + , "body": + [ {"type": "CALL_EXPRESSION", "name": "runfiles_list"} + , {"type": "CALL_EXPRESSION", "name": "artifacts_list"} + ] + } + } + } + } + ] + , [ "run-libs" + , { "type": "TREE" + , "$1": + { "type": "let*" + , "bindings": + [ ["fieldname", {"type": "var", "name": "deps-fieldname"}] + , ["provider", "run-libs"] + , ["transition", {"type": "var", "name": "deps-transition"}] + ] + , "body": {"type": "CALL_EXPRESSION", "name": "map_provider"} + } + } + ] + , [ "attempt marker" + , { "type": "if" + , "cond": + { "type": "==" + , "$1": {"type": "var", "name": "ATTEMPT"} + , "$2": null + } + , "then": {"type": "empty_map"} + , "else": + { "type": "singleton_map" + , "key": "ATTEMPT" + , "value": + {"type": "BLOB", "data": {"type": "var", "name": "ATTEMPT"}} + } + } + ] + , [ "outs" + , { "type": "++" + , "$1": + [ ["result", "stdout", "stderr", "time-start", "time-stop"] + , { "type": "foreach" + , "var": "filename" + , "range": {"type": "var", "name": "keep"} + , "body": + { "type": "join" + , "$1": ["work/", {"type": "var", "name": "filename"}] + } + } + ] + } + ] + , [ "inputs" + , { "type": "map_union" + , "$1": + [ { "type": "singleton_map" + , "key": "work" + , "value": {"type": "var", "name": "deps"} + } + , { "type": "singleton_map" + , "key": "libs" + , "value": {"type": "var", "name": "run-libs"} + } + , {"type": "var", "name": "runner"} + , {"type": "var", "name": "test.sh"} + , {"type": "var", "name": "attempt marker"} + ] + } + ] + , [ "cmd" + , {"type": "++", "$1": [["./runner"], {"type": "var", "name": "keep"}]} + ] + , [ "test_env" + , {"type": "var", "name": "TEST_ENV", "default": {"type": "empty_map"}} + ] + ] + , "body": + { "type": "if" + , "cond": + {"type": "==", "$1": {"type": "var", "name": "ATTEMPT"}, "$2": null} + , "then": + { "type": "ACTION" + , "outs": {"type": "var", "name": "outs"} + , "inputs": {"type": "var", "name": "inputs"} + , "cmd": {"type": "var", "name": "cmd"} + , "env": {"type": "var", "name": "test_env"} + , "may_fail": ["test"] + , "fail_message": + { "type": "join" + , "$1": ["shell test ", {"type": "var", "name": "name"}, " failed"] + } + } + , "else": + { "type": "ACTION" + , "outs": {"type": "var", "name": "outs"} + , "inputs": {"type": "var", "name": "inputs"} + , "cmd": {"type": "var", "name": "cmd"} + , "env": {"type": "var", "name": "test_env"} + , "may_fail": ["test"] + , "no_cache": ["test"] + , "fail_message": + { "type": "join" + , "$1": + [ "shell test " + , {"type": "var", "name": "name"} + , " failed (Run " + , {"type": "var", "name": "ATTEMPT"} + , ")" + ] + } + } + } + } + } +, "test-result": + { "vars": + [ "TEST_ENV" + , "name" + , "test.sh" + , "keep" + , "runner" + , "deps-fieldname" + , "deps-transition" + ] + , "imports": {"action": "test-action"} + , "expression": + { "type": "let*" + , "bindings": + [ ["test-results", {"type": "CALL_EXPRESSION", "name": "action"}] + , [ "runfiles" + , { "type": "singleton_map" + , "key": {"type": "var", "name": "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/rules/shell/test/RULES b/rules/shell/test/RULES new file mode 100644 index 0000000..98bf27c --- /dev/null +++ b/rules/shell/test/RULES @@ -0,0 +1,186 @@ +{ "script": + { "doc": ["Shell test, given by a test script"] + , "target_fields": ["deps", "test"] + , "string_fields": ["keep", "name"] + , "config_vars": ["ARCH", "HOST_ARCH", "RUNS_PER_TEST", "TEST_ENV"] + , "field_doc": + { "test": + [ "The shell script for the test, launched with sh." + , "" + , "An empty directory is created to store any temporary files needed" + , "by the test, and it is made available in the environment variable" + , "TEST_TMPDIR. The test should not assume write permissions" + , "outside the working directory and the TEST_TMPDIR." + , "For convenience, the environment variable TMPDIR is also set to TEST_TMPDIR." + ] + , "name": + [ "A name for the test, used in reporting, as well as for staging" + , "the test result tree in the runfiles" + ] + , "keep": + [ "List of names (relative to the test working directory) of files that" + , "the test might generate that should be kept as part of the output." + , "This might be useful for further analysis of the test" + ] + , "deps": + [ "Any targets that should be staged (with artifacts and runfiles) into" + , "the tests working directory" + ] + } + , "config_doc": + { "RUNS_PER_TEST": + [ "The number of times the test should be run in order to detect flakyness." + , "If set, no test action will be taken from cache." + ] + , "TEST_ENV": ["The environment for executing the test runner."] + } + , "tainted": ["test"] + , "artifacts_doc": + [ "result: the result of this test (\"PASS\" or \"FAIL\"); useful for" + , " generating test reports." + , "stdout/stderr: Any output the invocation of the test binary produced on" + , " the respective file descriptor" + , "work: In this directory, all the files specified to \"keep\" are staged" + , "time-start/time-stop: The time (decimally coded) in seconds since the" + , " epoch when the test invocation started and ended." + ] + , "runfiles_doc": + [ "A tree consisting of the artifacts staged at the name of the test." + , "As the built-in \"install\" rule only takes the runfiles of its \"deps\"" + , "argument, this gives an easy way of defining test suites." + ] + , "implicit": + {"runner": ["test_runner.sh"], "summarizer": ["test_summary.py"]} + , "imports": + { "test-result": "test-result" + , "action": "test-action" + , "stage": ["./", "../..", "stage_singleton_field"] + , "host transition": ["transitions", "for host"] + } + , "config_transitions": + {"deps": [{"type": "CALL_EXPRESSION", "name": "host transition"}]} + , "expression": + { "type": "let*" + , "bindings": + [ [ "test.sh" + , { "type": "context" + , "msg": "Expecting 'test' to specify precisely one file containing a shell script" + , "$1": + { "type": "let*" + , "bindings": [["fieldname", "test"], ["location", "test.sh"]] + , "body": {"type": "CALL_EXPRESSION", "name": "stage"} + } + } + ] + , [ "name" + , { "type": "assert_non_empty" + , "msg": "Have to provide a non-empty name for the test (e.g., for result staging)" + , "$1": {"type": "join", "$1": {"type": "FIELD", "name": "name"}} + } + ] + , ["keep", {"type": "FIELD", "name": "keep"}] + , ["runner", {"type": "FIELD", "name": "runner"}] + , ["deps-fieldname", "deps"] + , [ "deps-transition" + , {"type": "CALL_EXPRESSION", "name": "host transition"} + ] + ] + , "body": + { "type": "if" + , "cond": {"type": "var", "name": "RUNS_PER_TEST"} + , "else": {"type": "CALL_EXPRESSION", "name": "test-result"} + , "then": + { "type": "let*" + , "bindings": + [ [ "attempts" + , { "type": "map_union" + , "$1": + { "type": "foreach" + , "var": "ATTEMPT" + , "range": + { "type": "range" + , "$1": {"type": "var", "name": "RUNS_PER_TEST"} + } + , "body": + { "type": "singleton_map" + , "key": {"type": "var", "name": "ATTEMPT"} + , "value": + { "type": "TREE" + , "$1": {"type": "CALL_EXPRESSION", "name": "action"} + } + } + } + } + ] + , [ "summarizer" + , { "type": "map_union" + , "$1": + { "type": "foreach" + , "var": "x" + , "range": {"type": "FIELD", "name": "summarizer"} + , "body": + { "type": "map_union" + , "$1": + { "type": "foreach" + , "var": "x" + , "range": + { "type": "values" + , "$1": + { "type": "DEP_ARTIFACTS" + , "dep": {"type": "var", "name": "x"} + } + } + , "body": + { "type": "singleton_map" + , "key": "summarizer" + , "value": {"type": "var", "name": "x"} + } + } + } + } + } + ] + , [ "summary" + , { "type": "ACTION" + , "inputs": + { "type": "map_union" + , "$1": + [ {"type": "var", "name": "attempts"} + , {"type": "var", "name": "summarizer"} + ] + } + , "outs": + ["stdout", "stderr", "result", "time-start", "time-stop"] + , "cmd": ["./summarizer"] + } + ] + , [ "artifacts" + , { "type": "map_union" + , "$1": + [ {"type": "var", "name": "summary"} + , { "type": "singleton_map" + , "key": "work" + , "value": + {"type": "TREE", "$1": {"type": "var", "name": "attempts"}} + } + ] + } + ] + , [ "runfiles" + , { "type": "singleton_map" + , "key": {"type": "var", "name": "name"} + , "value": + {"type": "TREE", "$1": {"type": "var", "name": "artifacts"}} + } + ] + ] + , "body": + { "type": "RESULT" + , "artifacts": {"type": "var", "name": "artifacts"} + , "runfiles": {"type": "var", "name": "runfiles"} + } + } + } + } + } +} diff --git a/rules/shell/test/TARGETS b/rules/shell/test/TARGETS new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/rules/shell/test/TARGETS @@ -0,0 +1 @@ +{} diff --git a/rules/shell/test/test_runner.sh b/rules/shell/test/test_runner.sh new file mode 100755 index 0000000..97c75ef --- /dev/null +++ b/rules/shell/test/test_runner.sh @@ -0,0 +1,59 @@ +#!/bin/sh +# Copyright 2022 Huawei Cloud Computing Technology Co., Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# 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) +export TMPDIR="${TEST_TMPDIR}" +export LD_LIBRARY_PATH=$(realpath ./libs):$LD_LIBRARY_PATH + +# Change to the working directory; note: while unlikely, 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 +if sh ../test.sh > ../stdout 2> ../stderr +then + RESULT=PASS +else + RESULT=FAIL +fi +date +%s > ../time-stop + +# Ensure all the promissed output files in the work directory +# are present, even if the test failed to create them. +for f in "$@" +do + touch "./${f}" +done + +echo "${RESULT}" > ../result + +if [ "${RESULT}" '!=' PASS ] +then + exit 1; +fi diff --git a/rules/shell/test/test_summary.py b/rules/shell/test/test_summary.py new file mode 100755 index 0000000..0b5e656 --- /dev/null +++ b/rules/shell/test/test_summary.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python3 +# Copyright 2022 Huawei Cloud Computing Technology Co., Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import os +import time + +RESULTS = {} + +time_start = time.time() +time_stop = 0 + +for attempt in os.listdir("."): + if os.path.isdir(attempt): + with open(os.path.join(attempt, "result")) as f: + result = f.read().strip() + RESULTS[result] = RESULTS.get(result, []) + [int(attempt)] + try: + with open(os.path.join(attempt, "time-start")) as f: + time_start = min(time_start, float(f.read().strip())) + except: + pass + try: + with open(os.path.join(attempt, "time-stop")) as f: + time_stop = max(time_start, float(f.read().strip())) + except: + pass + +result = "UNKNOWN" +if set(RESULTS.keys()) <= set(["PASS", "FAIL"]): + if not RESULTS.get("FAIL"): + result = "PASS" + elif not RESULTS.get("PASS"): + result = "FAIL" + else: + result = "FLAKY" +with open("result", "w") as f: + f.write("%s\n" % (result,)) + +with open("time-start", "w") as f: + f.write("%d\n" % (time_start,)) +with open("time-stop", "w") as f: + f.write("%d\n" % (time_stop,)) + +with open("stdout", "w") as f: + f.write("Summary: %s\n\n" % (result,)) + f.write("PASS: %s\n" % (sorted(RESULTS.get("PASS", [])),)) + f.write("FAIL: %s\n" % (sorted(RESULTS.get("FAIL", [])),)) + RESULTS.pop("PASS", None) + RESULTS.pop("FAIL", None) + if RESULTS: + f.write("\nother results: %r\n" % (RESULTS,)) + +with open("stderr", "w") as f: + pass diff --git a/rules/transitions/EXPRESSIONS b/rules/transitions/EXPRESSIONS new file mode 100644 index 0000000..92be685 --- /dev/null +++ b/rules/transitions/EXPRESSIONS @@ -0,0 +1,29 @@ +{ "for host": + { "vars": ["ARCH", "HOST_ARCH"] + , "expression": + { "type": "singleton_map" + , "key": "TARGET_ARCH" + , "value": + { "type": "var" + , "name": "HOST_ARCH" + , "default": {"type": "var", "name": "ARCH"} + } + } + } +, "with fPIC": + { "doc": + [ "Transition that enables BUILD_POSITION_INDEPENDENT if config_field" + , "\"shared\" is not empty." + ] + , "expression": + { "type": "if" + , "cond": {"type": "FIELD", "name": "shared"} + , "then": + { "type": "singleton_map" + , "key": "BUILD_POSITION_INDEPENDENT" + , "value": true + } + , "else": {"type": "empty_map"} + } + } +} |