summaryrefslogtreecommitdiff
path: root/rules
diff options
context:
space:
mode:
Diffstat (limited to 'rules')
-rw-r--r--rules/CC/EXPRESSIONS3364
-rw-r--r--rules/CC/RULES1066
-rw-r--r--rules/CC/TARGETS11
-rw-r--r--rules/CC/auto/RULES1379
-rw-r--r--rules/CC/auto/TARGETS1
-rwxr-xr-xrules/CC/auto/runner162
-rw-r--r--rules/CC/foreign/EXPRESSIONS123
-rw-r--r--rules/CC/foreign/RULES162
-rw-r--r--rules/CC/foreign/TARGETS7
-rw-r--r--rules/CC/foreign/cmake/EXPRESSIONS484
-rw-r--r--rules/CC/foreign/cmake/RULES772
-rwxr-xr-xrules/CC/foreign/expand_exec133
-rw-r--r--rules/CC/foreign/expand_exec.c99
-rw-r--r--rules/CC/foreign/make/EXPRESSIONS445
-rw-r--r--rules/CC/foreign/make/RULES803
-rw-r--r--rules/CC/foreign/shell/EXPRESSIONS363
-rw-r--r--rules/CC/foreign/shell/RULES624
-rwxr-xr-xrules/CC/include_scan43
-rw-r--r--rules/CC/include_scan.c436
-rwxr-xr-xrules/CC/include_scan.py58
-rw-r--r--rules/CC/pkgconfig/EXPRESSIONS296
-rw-r--r--rules/CC/pkgconfig/RULES124
-rw-r--r--rules/CC/pkgconfig/TARGETS1
-rwxr-xr-xrules/CC/pkgconfig/add_rpath24
-rw-r--r--rules/CC/prebuilt/EXPRESSIONS503
-rw-r--r--rules/CC/prebuilt/RULES147
-rwxr-xr-xrules/CC/prebuilt/read_pkgconfig.py77
-rw-r--r--rules/CC/proto/EXPRESSIONS489
-rw-r--r--rules/CC/proto/RULES371
-rw-r--r--rules/CC/proto/TARGETS16
-rw-r--r--rules/CC/test/EXPRESSIONS410
-rw-r--r--rules/CC/test/RULES287
-rw-r--r--rules/CC/test/TARGETS1
-rwxr-xr-xrules/CC/test/runner71
-rw-r--r--rules/EXPRESSIONS229
-rw-r--r--rules/data/EXPRESSIONS113
-rw-r--r--rules/data/RULES138
-rw-r--r--rules/lint/RULES278
-rw-r--r--rules/lint/TARGETS3
-rwxr-xr-xrules/lint/call_lint44
-rwxr-xr-xrules/lint/call_summary35
-rw-r--r--rules/patch/EXPRESSIONS77
-rw-r--r--rules/patch/RULES351
-rw-r--r--rules/patch/TARGETS6
-rw-r--r--rules/proto/RULES99
-rw-r--r--rules/shell/EXPRESSIONS171
-rw-r--r--rules/shell/RULES347
-rw-r--r--rules/shell/TARGETS1
-rw-r--r--rules/shell/test/EXPRESSIONS380
-rw-r--r--rules/shell/test/RULES364
-rw-r--r--rules/shell/test/TARGETS6
-rwxr-xr-xrules/shell/test/runner60
-rwxr-xr-xrules/shell/test/summarizer84
-rw-r--r--rules/test/RULES57
-rw-r--r--rules/transitions/EXPRESSIONS122
55 files changed, 16317 insertions, 0 deletions
diff --git a/rules/CC/EXPRESSIONS b/rules/CC/EXPRESSIONS
new file mode 100644
index 0000000..b347a79
--- /dev/null
+++ b/rules/CC/EXPRESSIONS
@@ -0,0 +1,3364 @@
+{ "default-CC":
+ { "vars": ["defaults-transition"]
+ , "imports": {"list_provider": ["./", "..", "field_list_provider"]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "defaults"]
+ , ["provider", "CC"]
+ , ["transition", {"type": "var", "name": "defaults-transition"}]
+ , ["CC", {"type": "CALL_EXPRESSION", "name": "list_provider"}]
+ , [ "CC"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "CC"}
+ , "then": {"type": "var", "name": "CC"}
+ , "else": ["cc"]
+ }
+ ]
+ ]
+ , "body": {"type": "var", "name": "CC"}
+ }
+ }
+, "default-CXX":
+ { "vars": ["defaults-transition"]
+ , "imports": {"list_provider": ["./", "..", "field_list_provider"]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "defaults"]
+ , ["provider", "CXX"]
+ , ["transition", {"type": "var", "name": "defaults-transition"}]
+ , ["CXX", {"type": "CALL_EXPRESSION", "name": "list_provider"}]
+ , [ "CXX"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "CXX"}
+ , "then": {"type": "var", "name": "CXX"}
+ , "else": ["c++"]
+ }
+ ]
+ ]
+ , "body": {"type": "var", "name": "CXX"}
+ }
+ }
+, "default-AR":
+ { "vars": ["defaults-transition"]
+ , "imports": {"list_provider": ["./", "..", "field_list_provider"]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "defaults"]
+ , ["provider", "AR"]
+ , ["transition", {"type": "var", "name": "defaults-transition"}]
+ , ["AR", {"type": "CALL_EXPRESSION", "name": "list_provider"}]
+ , [ "AR"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "AR"}
+ , "then": {"type": "var", "name": "AR"}
+ , "else": ["ar"]
+ }
+ ]
+ ]
+ , "body": {"type": "var", "name": "AR"}
+ }
+ }
+, "default-INCLUDE_SCANNER":
+ { "vars": ["defaults-transition"]
+ , "imports": {"map_provider": ["./", "..", "field_map_provider"]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "defaults"]
+ , ["provider", "INCLUDE_SCANNER"]
+ , ["transition", {"type": "var", "name": "defaults-transition"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "map_provider"}
+ }
+ }
+, "default-ARFLAGS":
+ { "vars": ["defaults-transition"]
+ , "imports": {"list_provider": ["./", "..", "field_list_provider"]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "defaults"]
+ , ["provider", "ARFLAGS"]
+ , ["transition", {"type": "var", "name": "defaults-transition"}]
+ , ["ARFLAGS", {"type": "CALL_EXPRESSION", "name": "list_provider"}]
+ , [ "ARFLAGS"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "ARFLAGS"}
+ , "then": {"type": "var", "name": "ARFLAGS"}
+ , "else": ["cqs"]
+ }
+ ]
+ ]
+ , "body": {"type": "var", "name": "ARFLAGS"}
+ }
+ }
+, "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"}]
+ ]
+ , "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"}]
+ ]
+ , "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"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "list_provider"}
+ }
+ }
+, "default-ENV":
+ { "vars": ["defaults-transition"]
+ , "imports": {"map_provider": ["./", "..", "field_map_provider"]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "defaults"]
+ , ["provider", "ENV"]
+ , ["transition", {"type": "var", "name": "defaults-transition"}]
+ , ["default", {"type": "empty_map"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "map_provider"}
+ }
+ }
+, "default-PATH":
+ { "vars": ["defaults-transition"]
+ , "imports": {"list_provider": ["./", "..", "field_list_provider"]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "defaults"]
+ , ["provider", "PATH"]
+ , ["transition", {"type": "var", "name": "defaults-transition"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "list_provider"}
+ }
+ }
+, "default-TOOLCHAIN":
+ { "vars": ["defaults-transition"]
+ , "imports": {"map_provider": ["./", "..", "field_map_provider"]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "defaults"]
+ , ["provider", "TOOLCHAIN"]
+ , ["transition", {"type": "var", "name": "defaults-transition"}]
+ , ["default", {"type": "empty_map"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "map_provider"}
+ }
+ }
+, "default-NON_SYSTEM_TOOLS":
+ { "vars": ["defaults-transition"]
+ , "expression":
+ { "type": "map_union"
+ , "$1":
+ { "type": "foreach"
+ , "var": "x"
+ , "range": {"type": "FIELD", "name": "defaults"}
+ , "body":
+ { "type": "DEP_PROVIDES"
+ , "dep": {"type": "var", "name": "x"}
+ , "provider": "NON_SYSTEM_TOOLS"
+ , "transition":
+ { "type": "var"
+ , "name": "defaults-transition"
+ , "default": {"type": "empty_map"}
+ }
+ , "default": {"type": "empty_map"}
+ }
+ }
+ }
+ }
+, "defaults-base-provides-list":
+ { "doc": ["Query list of providers from 'base' targets"]
+ , "vars": ["provider", "default"]
+ , "vars_doc":
+ { "provider": ["The name of the provider in the provides map."]
+ , "default": ["The default if provider is missing (default: [])."]
+ }
+ , "imports": {"provider_list": ["./", "..", "field_provider_list"]}
+ , "expression":
+ { "type": "let*"
+ , "bindings": [["fieldname", "base"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "provider_list"}
+ }
+ }
+, "defaults-base-provides-++":
+ { "doc": ["Query flattend list of providers from 'base' targets"]
+ , "vars": ["provider", "default"]
+ , "vars_doc":
+ { "provider": ["The name of the provider in the provides map."]
+ , "default": ["The default if provider is missing (default: [])."]
+ }
+ , "imports": {"base-provides-list": "defaults-base-provides-list"}
+ , "expression":
+ { "type": "++"
+ , "$1": {"type": "CALL_EXPRESSION", "name": "base-provides-list"}
+ }
+ }
+, "defaults-base-provides":
+ { "doc": ["Query provider from 'base' targets (last wins)"]
+ , "vars": ["provider", "default"]
+ , "vars_doc":
+ { "provider": ["The name of the provider in the provides map."]
+ , "default": ["The default if provider is missing (default: [])."]
+ }
+ , "imports": {"base-provides-list": "defaults-base-provides-list"}
+ , "expression":
+ { "type": "foldl"
+ , "var": "next"
+ , "start": {"type": "var", "name": "default", "default": []}
+ , "accum_var": "curr"
+ , "range": {"type": "CALL_EXPRESSION", "name": "base-provides-list"}
+ , "body":
+ { "type": "if"
+ , "cond": {"type": "var", "name": "next"}
+ , "then": {"type": "var", "name": "next"}
+ , "else": {"type": "var", "name": "curr"}
+ }
+ }
+ }
+, "debug-deps":
+ { "doc":
+ ["Collect debug dependencies (sources/headers) from given target_fields"]
+ , "vars":
+ [ "deps-provider"
+ , "deps-fieldnames"
+ , "deps-transition"
+ , "modified-transitions"
+ ]
+ , "vars_doc":
+ { "deps-provider": ["Name of provider to use (debug-srcs/debug-hdrs)."]
+ , "deps-fieldnames":
+ ["List of target_field names to collect dependencies from."]
+ , "deps-transition":
+ ["The optional configuration transition for the targets."]
+ , "modified-transitions":
+ ["Map telling fields that need to be transitioned differently"]
+ }
+ , "imports": {"provider_list": ["./", "..", "field_provider_list"]}
+ , "expression":
+ { "type": "map_union"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ { "type": "foreach"
+ , "var": "fieldname"
+ , "range": {"type": "var", "name": "deps-fieldnames"}
+ , "body":
+ { "type": "++"
+ , "$1":
+ { "type": "let*"
+ , "bindings":
+ [ ["provider", {"type": "var", "name": "deps-provider"}]
+ , [ "transition"
+ , { "type": "lookup"
+ , "map":
+ { "type": "var"
+ , "name": "modified-transitions"
+ , "default": {"type": "empty_map"}
+ }
+ , "key": {"type": "var", "name": "fieldname"}
+ , "default": {"type": "var", "name": "deps-transition"}
+ }
+ ]
+ , ["default", {"type": "empty_map"}]
+ ]
+ , "body": [{"type": "CALL_EXPRESSION", "name": "provider_list"}]
+ }
+ }
+ }
+ }
+ }
+ }
+, "compile-deps":
+ { "doc": ["Collect compile dependencies (headers) from given target_fields"]
+ , "vars":
+ [ "deps-fieldnames"
+ , "deps-transition"
+ , "modified-transitions"
+ , "component-fieldnames"
+ ]
+ , "vars_doc":
+ { "deps-fieldnames":
+ ["List of target_field names to collect dependencies from."]
+ , "deps-transition":
+ ["The optional configuration transition for the targets."]
+ , "modified-transitions":
+ ["Map telling fields that need to be transitioned differently"]
+ }
+ , "imports":
+ { "runfiles_list": ["./", "..", "field_runfiles_list"]
+ , "provider_list": ["./", "..", "field_provider_list"]
+ }
+ , "expression":
+ { "type": "disjoint_map_union"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ { "type": "++"
+ , "$1":
+ { "type": "foreach"
+ , "var": "fieldname"
+ , "range":
+ { "type": "++"
+ , "$1":
+ [ {"type": "var", "name": "deps-fieldnames"}
+ , { "type": "var"
+ , "name": "component-fieldnames"
+ , "default": []
+ }
+ ]
+ }
+ , "body":
+ { "type": "let*"
+ , "bindings":
+ [ ["provider", "compile-deps"]
+ , [ "transition"
+ , { "type": "lookup"
+ , "map":
+ { "type": "var"
+ , "name": "modified-transitions"
+ , "default": {"type": "empty_map"}
+ }
+ , "key": {"type": "var", "name": "fieldname"}
+ , "default": {"type": "var", "name": "deps-transition"}
+ }
+ ]
+ , ["default", {"type": "empty_map"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "provider_list"}
+ }
+ }
+ }
+ , { "type": "++"
+ , "$1":
+ { "type": "foreach"
+ , "var": "fieldname"
+ , "range": {"type": "var", "name": "deps-fieldnames"}
+ , "body":
+ { "type": "let*"
+ , "bindings":
+ [ [ "transition"
+ , { "type": "lookup"
+ , "map":
+ { "type": "var"
+ , "name": "modified-transitions"
+ , "default": {"type": "empty_map"}
+ }
+ , "key": {"type": "var", "name": "fieldname"}
+ , "default": {"type": "var", "name": "deps-transition"}
+ }
+ ]
+ , ["default", {"type": "empty_map"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "runfiles_list"}
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+, "compile-args-deps":
+ { "doc": ["Collect compile arguments from given target_fields"]
+ , "vars": ["deps-fieldnames", "deps-transition", "modified-transitions"]
+ , "vars_doc":
+ { "deps-fieldnames":
+ ["List of target_field names to collect arguments from."]
+ , "deps-transition":
+ ["The optional configuration transition for the targets."]
+ , "modified-transitions":
+ ["Map telling fields that need to be transitioned differently"]
+ }
+ , "imports": {"list_provider": ["./", "..", "field_list_provider"]}
+ , "expression":
+ { "type": "nub_right"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ { "type": "foreach"
+ , "var": "fieldname"
+ , "range": {"type": "var", "name": "deps-fieldnames"}
+ , "body":
+ { "type": "let*"
+ , "bindings":
+ [ ["provider", "compile-args"]
+ , [ "transition"
+ , { "type": "lookup"
+ , "map":
+ { "type": "var"
+ , "name": "modified-transitions"
+ , "default": {"type": "empty_map"}
+ }
+ , "key": {"type": "var", "name": "fieldname"}
+ , "default": {"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"
+ , "modified-transitions"
+ , "component-fieldnames"
+ ]
+ , "vars_doc":
+ { "deps-fieldnames":
+ ["List of target_field names to collect dependencies from."]
+ , "deps-transition":
+ ["The optional configuration transition for the targets."]
+ , "modified-transitions":
+ ["Map telling fields that need to be transitioned differently"]
+ }
+ , "imports":
+ { "artifacts_list": ["./", "..", "field_artifacts_list"]
+ , "provider_list": ["./", "..", "field_provider_list"]
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ [ "drop_artifacts"
+ , { "type": "set"
+ , "$1":
+ {"type": "var", "name": "component-fieldnames", "default": []}
+ }
+ ]
+ ]
+ , "body":
+ { "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": "lookup"
+ , "map":
+ { "type": "var"
+ , "name": "modified-transitions"
+ , "default": {"type": "empty_map"}
+ }
+ , "key": {"type": "var", "name": "fieldname"}
+ , "default": {"type": "var", "name": "deps-transition"}
+ }
+ ]
+ ]
+ , "body":
+ [ {"type": "CALL_EXPRESSION", "name": "provider_list"}
+ , { "type": "if"
+ , "cond":
+ { "type": "lookup"
+ , "map": {"type": "var", "name": "drop_artifacts"}
+ , "key": {"type": "var", "name": "fieldname"}
+ }
+ , "then": []
+ , "else":
+ {"type": "CALL_EXPRESSION", "name": "artifacts_list"}
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+, "link-args-deps":
+ { "doc": ["Collect linker arguments from given target_fields"]
+ , "vars": ["deps-fieldnames", "deps-transition", "modified-transitions"]
+ , "vars_doc":
+ { "deps-fieldnames":
+ ["List of target_field names to collect arguments from."]
+ , "deps-transition":
+ ["The optional configuration transition for the targets."]
+ , "modified-transitions":
+ ["Map telling fields that need to be transitioned differently"]
+ }
+ , "imports": {"list_provider": ["./", "..", "field_list_provider"]}
+ , "expression":
+ { "type": "nub_right"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ { "type": "foreach"
+ , "var": "fieldname"
+ , "range": {"type": "var", "name": "deps-fieldnames"}
+ , "body":
+ { "type": "let*"
+ , "bindings":
+ [ ["provider", "link-args"]
+ , [ "transition"
+ , { "type": "lookup"
+ , "map":
+ { "type": "var"
+ , "name": "modified-transitions"
+ , "default": {"type": "empty_map"}
+ }
+ , "key": {"type": "var", "name": "fieldname"}
+ , "default": {"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", "modified-transitions"]
+ , "vars_doc":
+ { "deps-fieldnames":
+ ["List of target_field names to collect dependencies from."]
+ , "deps-transition":
+ ["The optional configuration transition for the targets."]
+ , "modified-transitions":
+ ["Map telling fields that need to be transitioned differently"]
+ }
+ , "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": "lookup"
+ , "map":
+ { "type": "var"
+ , "name": "modified-transitions"
+ , "default": {"type": "empty_map"}
+ }
+ , "key": {"type": "var", "name": "fieldname"}
+ , "default": {"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", "modified-transitions"]
+ , "vars_doc":
+ { "deps-fieldnames":
+ ["List of target_field names to collect arguments from."]
+ , "deps-transition":
+ ["The optional configuration transition for the targets."]
+ , "modified-transitions":
+ ["Map telling fields that need to be transitioned differently"]
+ }
+ , "imports": {"list_provider": ["./", "..", "field_list_provider"]}
+ , "expression":
+ { "type": "nub_right"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ { "type": "foreach"
+ , "var": "fieldname"
+ , "range": {"type": "var", "name": "deps-fieldnames"}
+ , "body":
+ { "type": "let*"
+ , "bindings":
+ [ ["provider", "run-libs-args"]
+ , [ "transition"
+ , { "type": "lookup"
+ , "map":
+ { "type": "var"
+ , "name": "modified-transitions"
+ , "default": {"type": "empty_map"}
+ }
+ , "key": {"type": "var", "name": "fieldname"}
+ , "default": {"type": "var", "name": "deps-transition"}
+ }
+ ]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "list_provider"}
+ }
+ }
+ }
+ }
+ }
+, "pkg-map-provider-deps":
+ { "doc": ["Collect maps from provider \"package\" for given target_fields"]
+ , "vars":
+ ["pkg-key", "deps-fieldnames", "deps-transition", "modified-transitions"]
+ , "vars_doc":
+ { "pkg-key": ["Key to lookup in provider \"package\"."]
+ , "deps-fieldnames": ["List of target_field names to collect maps from."]
+ , "deps-transition":
+ ["The optional configuration transition for the targets."]
+ , "modified-transitions":
+ ["Map telling fields that need to be transitioned differently"]
+ }
+ , "imports": {"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": "let*"
+ , "bindings":
+ [ ["provider", "package"]
+ , ["default", {"type": "empty_map"}]
+ , [ "transition"
+ , { "type": "lookup"
+ , "map":
+ { "type": "var"
+ , "name": "modified-transitions"
+ , "default": {"type": "empty_map"}
+ }
+ , "key": {"type": "var", "name": "fieldname"}
+ , "default": {"type": "var", "name": "deps-transition"}
+ }
+ ]
+ ]
+ , "body":
+ { "type": "foreach"
+ , "range": {"type": "CALL_EXPRESSION", "name": "provider_list"}
+ , "var": "map"
+ , "body":
+ { "type": "lookup"
+ , "key": {"type": "var", "name": "pkg-key"}
+ , "map": {"type": "var", "name": "map"}
+ , "default": {"type": "empty_map"}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+, "cflags-files-deps":
+ { "doc": ["Collect cflags files from target_fields"]
+ , "vars": ["deps-fieldnames", "deps-transition", "modified-transitions"]
+ , "vars_doc":
+ { "deps-fieldnames": ["List of target_field names to collect files from."]
+ , "deps-transition":
+ ["The optional configuration transition for the targets."]
+ , "modified-transitions":
+ ["Map telling fields that need to be transitioned differently"]
+ }
+ , "imports": {"pkg-provider": "pkg-map-provider-deps"}
+ , "expression":
+ { "type": "let*"
+ , "bindings": [["pkg-key", "cflags-files"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "pkg-provider"}
+ }
+ }
+, "ldflags-files-deps":
+ { "doc": ["Collect cflags files from target_fields"]
+ , "vars": ["deps-fieldnames", "deps-transition", "modified-transitions"]
+ , "vars_doc":
+ { "deps-fieldnames": ["List of target_field names to collect files from."]
+ , "deps-transition":
+ ["The optional configuration transition for the targets."]
+ , "modified-transitions":
+ ["Map telling fields that need to be transitioned differently"]
+ }
+ , "imports": {"pkg-provider": "pkg-map-provider-deps"}
+ , "expression":
+ { "type": "let*"
+ , "bindings": [["pkg-key", "ldflags-files"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "pkg-provider"}
+ }
+ }
+, "pkg-prefix-lib-paths":
+ { "doc": ["Detect ldflags referring to local libs and prefix them."]
+ , "vars": ["pkg-ldflags", "pkg-libs", "flat-libs", "lib-prefix"]
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ [ "libs set"
+ , { "type": "set"
+ , "$1": {"type": "keys", "$1": {"type": "var", "name": "pkg-libs"}}
+ }
+ ]
+ ]
+ , "body":
+ { "type": "foreach"
+ , "var": "item"
+ , "range": {"type": "var", "name": "pkg-ldflags"}
+ , "body":
+ { "type": "if"
+ , "cond":
+ { "type": "lookup"
+ , "key": {"type": "var", "name": "item"}
+ , "map": {"type": "var", "name": "libs set"}
+ }
+ , "then":
+ { "type": "join"
+ , "$1":
+ { "type": "if"
+ , "cond": {"type": "var", "name": "flat-libs"}
+ , "then":
+ [ "-l:"
+ , {"type": "basename", "$1": {"type": "var", "name": "item"}}
+ ]
+ , "else":
+ [ {"type": "var", "name": "lib-prefix"}
+ , "/"
+ , {"type": "var", "name": "item"}
+ ]
+ }
+ }
+ , "else": {"type": "var", "name": "item"}
+ }
+ }
+ }
+ }
+, "pkg-prefix-flag-paths":
+ { "doc": ["Detect flags referring to local flag files and prefix them."]
+ , "vars": ["flags", "pkg-flag-files", "flag-prefix"]
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ [ "pkg-flag-files unprefix map"
+ , { "type": "map_union"
+ , "$1":
+ { "type": "foreach"
+ , "var": "name"
+ , "range":
+ {"type": "keys", "$1": {"type": "var", "name": "pkg-flag-files"}}
+ , "body":
+ { "type": "singleton_map"
+ , "key":
+ {"type": "join", "$1": ["@", {"type": "var", "name": "name"}]}
+ , "value": {"type": "var", "name": "name"}
+ }
+ }
+ }
+ ]
+ ]
+ , "body":
+ { "type": "foreach"
+ , "var": "item"
+ , "range": {"type": "var", "name": "flags"}
+ , "body":
+ { "type": "let*"
+ , "bindings":
+ [ [ "flag-file"
+ , { "type": "lookup"
+ , "map": {"type": "var", "name": "pkg-flag-files unprefix map"}
+ , "key": {"type": "var", "name": "item"}
+ }
+ ]
+ ]
+ , "body":
+ { "type": "if"
+ , "cond": {"type": "var", "name": "flag-file"}
+ , "then":
+ { "type": "join"
+ , "$1":
+ [ "@"
+ , {"type": "var", "name": "flag-prefix"}
+ , "/"
+ , {"type": "var", "name": "flag-file"}
+ ]
+ }
+ , "else": {"type": "var", "name": "item"}
+ }
+ }
+ }
+ }
+ }
+, "pkg-config":
+ { "vars":
+ [ "pkg-name"
+ , "pkg-prefix"
+ , "pkg-version"
+ , "pkg-cflags"
+ , "pkg-ldflags"
+ , "pkg-flag-files"
+ , "pkg-libs"
+ , "flat-libs"
+ , "pc-install-dir"
+ ]
+ , "imports":
+ { "pkg-prefix-lib-paths": "pkg-prefix-lib-paths"
+ , "pkg-prefix-flag-paths": "pkg-prefix-flag-paths"
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["lib-prefix", "${libdir}"]
+ , [ "pkg-ldflags"
+ , {"type": "CALL_EXPRESSION", "name": "pkg-prefix-lib-paths"}
+ ]
+ , [ "flag-prefix"
+ , { "type": "join"
+ , "$1": ["${prefix}/", {"type": "var", "name": "pc-install-dir"}]
+ }
+ ]
+ , ["flags", {"type": "var", "name": "pkg-cflags"}]
+ , [ "pkg-cflags"
+ , {"type": "CALL_EXPRESSION", "name": "pkg-prefix-flag-paths"}
+ ]
+ , ["flags", {"type": "var", "name": "pkg-ldflags"}]
+ , [ "pkg-ldflags"
+ , {"type": "CALL_EXPRESSION", "name": "pkg-prefix-flag-paths"}
+ ]
+ ]
+ , "body":
+ { "type": "singleton_map"
+ , "key":
+ {"type": "join", "$1": [{"type": "var", "name": "pkg-name"}, ".pc"]}
+ , "value":
+ { "type": "BLOB"
+ , "data":
+ { "type": "join"
+ , "separator": "\n"
+ , "$1":
+ [ { "type": "join"
+ , "$1":
+ [ "prefix="
+ , {"type": "var", "name": "pkg-prefix", "default": "/"}
+ ]
+ }
+ , "libdir=${prefix}/lib"
+ , "includedir=${prefix}/include"
+ , { "type": "join"
+ , "$1": ["Name: ", {"type": "var", "name": "pkg-name"}]
+ }
+ , { "type": "join"
+ , "$1":
+ [ "Version: "
+ , {"type": "var", "name": "pkg-version", "default": "unknown"}
+ ]
+ }
+ , { "type": "join"
+ , "$1":
+ [ "Description: Pkg-config for "
+ , {"type": "var", "name": "pkg-name"}
+ , ", generated by JustBuild"
+ ]
+ }
+ , "URL: unknown"
+ , { "type": "join"
+ , "separator": " "
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ ["Cflags:", "-I${includedir}"]
+ , {"type": "var", "name": "pkg-cflags"}
+ ]
+ }
+ }
+ , { "type": "join"
+ , "separator": " "
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ ["Libs:"]
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "flat-libs"}
+ , "then": ["-L${libdir}"]
+ }
+ , {"type": "var", "name": "pkg-ldflags"}
+ ]
+ }
+ }
+ , ""
+ ]
+ }
+ }
+ }
+ }
+ }
+, "objects":
+ { "vars":
+ [ "COMPILER"
+ , "COMPILE_FLAGS"
+ , "ENV"
+ , "TOOLCHAIN"
+ , "srcs"
+ , "hdrs"
+ , "private-hdrs"
+ , "compile-deps"
+ , "cflags-files"
+ , "component-fieldnames"
+ , "defaults-transition"
+ , "deps-transition"
+ , "modified-transitions"
+ ]
+ , "imports":
+ { "field_artifacts": ["./", "..", "field_artifacts"]
+ , "default-INCLUDE_SCANNER": "default-INCLUDE_SCANNER"
+ }
+ , "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"}
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ , [ "include_scan_tool"
+ , { "type": "disjoint_map_union"
+ , "msg": "Include scanner should be single artifact"
+ , "$1":
+ { "type": "foreach"
+ , "var": "artifact"
+ , "range":
+ { "type": "values"
+ , "$1":
+ {"type": "CALL_EXPRESSION", "name": "default-INCLUDE_SCANNER"}
+ }
+ , "body":
+ { "type": "singleton_map"
+ , "key": "include_scan"
+ , "value": {"type": "var", "name": "artifact"}
+ }
+ }
+ }
+ ]
+ , [ "my objects"
+ , { "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"}]
+ }
+ ]
+ , [ "out"
+ , { "type": "change_ending"
+ , "$1": {"type": "var", "name": "src_name"}
+ , "ending": ".o"
+ }
+ ]
+ , [ "work out"
+ , { "type": "join"
+ , "separator": "/"
+ , "$1": ["work", {"type": "var", "name": "out"}]
+ }
+ ]
+ , [ "cmdline"
+ , { "type": "++"
+ , "$1":
+ [ [{"type": "var", "name": "COMPILER"}]
+ , {"type": "var", "name": "COMPILE_FLAGS"}
+ , ["-I", "work", "-isystem", "include"]
+ , ["-c", {"type": "var", "name": "work 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"}
+ }
+ , { "type": "var"
+ , "name": "cflags-files"
+ , "default": {"type": "empty_map"}
+ }
+ , { "type": "var"
+ , "name": "TOOLCHAIN"
+ , "default": {"type": "empty_map"}
+ }
+ ]
+ }
+ ]
+ , [ "minimal include tree"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "include_scan_tool"}
+ , "then":
+ { "type": "from_subdir"
+ , "subdir": "out"
+ , "$1":
+ { "type": "ACTION"
+ , "out_dirs": ["out/include"]
+ , "inputs":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "inputs"}
+ , {"type": "var", "name": "include_scan_tool"}
+ ]
+ }
+ , "env":
+ { "type": "var"
+ , "name": "ENV"
+ , "default": {"type": "empty_map"}
+ }
+ , "cmd":
+ { "type": "++"
+ , "$1":
+ [ ["./include_scan"]
+ , ["out"]
+ , {"type": "var", "name": "cmdline"}
+ , ["-E", "-M"]
+ ]
+ }
+ }
+ }
+ , "else": {"type": "var", "name": "include tree"}
+ }
+ ]
+ , [ "minimal inputs"
+ , { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "inputs"}
+ , {"type": "var", "name": "minimal include tree"}
+ ]
+ }
+ ]
+ , [ "action output"
+ , { "type": "ACTION"
+ , "outs": [{"type": "var", "name": "work out"}]
+ , "inputs": {"type": "var", "name": "minimal inputs"}
+ , "env":
+ { "type": "var"
+ , "name": "ENV"
+ , "default": {"type": "empty_map"}
+ }
+ , "cmd":
+ { "type": "++"
+ , "$1":
+ [ {"type": "var", "name": "cmdline"}
+ , ["-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"}
+ }
+ }
+ }
+ ]
+ , [ "component artifacts"
+ , { "type": "disjoint_map_union"
+ , "$1":
+ { "type": "foreach"
+ , "var": "fieldname"
+ , "range":
+ {"type": "var", "name": "component-fieldnames", "default": []}
+ , "body":
+ { "type": "let*"
+ , "bindings":
+ [ [ "transition"
+ , { "type": "lookup"
+ , "map":
+ { "type": "var"
+ , "name": "modified-transitions"
+ , "default": {"type": "empty_map"}
+ }
+ , "key": {"type": "var", "name": "fieldname"}
+ , "default": {"type": "var", "name": "deps-transition"}
+ }
+ ]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "field_artifacts"}
+ }
+ }
+ }
+ ]
+ ]
+ , "body":
+ { "type": "disjoint_map_union"
+ , "msg": "Stating conflict between own objects and objects of components"
+ , "$1":
+ [ {"type": "var", "name": "my objects"}
+ , {"type": "var", "name": "component artifacts"}
+ ]
+ }
+ }
+ }
+, "lint information":
+ { "vars":
+ [ "CC"
+ , "CXX"
+ , "CFLAGS"
+ , "CXXFLAGS"
+ , "ADD_CFLAGS"
+ , "ADD_CXXFLAGS"
+ , "pure C"
+ , "srcs"
+ , "hdrs"
+ , "private-hdrs"
+ , "compile-deps"
+ , "cflags-files"
+ , "lint-deps fieldnames"
+ , "deps-transition"
+ , "deps-fieldnames"
+ , "compile-args"
+ , "defaults-transition"
+ , "modified-transitions"
+ ]
+ , "imports":
+ { "objects": "objects"
+ , "list_provider": ["./", "..", "field_list_provider"]
+ , "runfiles_list": ["./", "..", "field_runfiles_list"]
+ , "default-TOOLCHAIN": "default-TOOLCHAIN"
+ , "default-NON_SYSTEM_TOOLS": "default-NON_SYSTEM_TOOLS"
+ , "compiler": "compiler"
+ , "flags": "flags"
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["TOOLCHAIN_DIR", "toolchain"]
+ , ["TOOLCHAIN", {"type": "CALL_EXPRESSION", "name": "default-TOOLCHAIN"}]
+ , [ "TOOLCHAIN"
+ , { "type": "to_subdir"
+ , "subdir": {"type": "var", "name": "TOOLCHAIN_DIR"}
+ , "$1": {"type": "var", "name": "TOOLCHAIN"}
+ }
+ ]
+ , [ "NON_SYSTEM_TOOLS"
+ , {"type": "CALL_EXPRESSION", "name": "default-NON_SYSTEM_TOOLS"}
+ ]
+ , ["COMPILER", {"type": "CALL_EXPRESSION", "name": "compiler"}]
+ , [ "COMPILE_FLAGS"
+ , { "type": "++"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "flags"}
+ , {"type": "var", "name": "compile-args"}
+ ]
+ }
+ ]
+ , [ "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"}
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ , [ "direct-deps hdrs"
+ , { "type": "to_subdir"
+ , "subdir": "include"
+ , "$1":
+ { "type": "map_union"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ { "type": "foreach"
+ , "var": "fieldname"
+ , "range": {"type": "var", "name": "deps-fieldnames"}
+ , "body":
+ { "type": "let*"
+ , "bindings":
+ [ [ "transition"
+ , { "type": "lookup"
+ , "map":
+ { "type": "var"
+ , "name": "modified-transitions"
+ , "default": {"type": "empty_map"}
+ }
+ , "key": {"type": "var", "name": "fieldname"}
+ , "default": {"type": "var", "name": "deps-transition"}
+ }
+ ]
+ ]
+ , "body":
+ {"type": "CALL_EXPRESSION", "name": "runfiles_list"}
+ }
+ }
+ }
+ }
+ }
+ ]
+ , [ "own headers"
+ , { "type": "to_subdir"
+ , "subdir": "work"
+ , "$1":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "hdrs"}
+ , {"type": "var", "name": "private-hdrs"}
+ ]
+ }
+ }
+ ]
+ , [ "direct hdrs"
+ , { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "own headers"}
+ , {"type": "var", "name": "direct-deps hdrs"}
+ ]
+ }
+ ]
+ , [ "direct deps artifact names"
+ , {"type": "keys", "$1": {"type": "var", "name": "direct hdrs"}}
+ ]
+ , [ "hdr lint"
+ , { "type": "foreach"
+ , "range":
+ { "type": "++"
+ , "$1":
+ [ {"type": "keys", "$1": {"type": "var", "name": "private-hdrs"}}
+ , {"type": "keys", "$1": {"type": "var", "name": "hdrs"}}
+ ]
+ }
+ , "body":
+ { "type": "VALUE_NODE"
+ , "$1":
+ { "type": "RESULT"
+ , "artifacts": {"type": "var", "name": "all hdrs"}
+ , "provides":
+ { "type": "let*"
+ , "bindings":
+ [ [ "src"
+ , { "type": "join"
+ , "$1": ["work/", {"type": "var", "name": "_"}]
+ }
+ ]
+ , [ "cmd"
+ , { "type": "++"
+ , "$1":
+ [ [{"type": "var", "name": "COMPILER"}]
+ , {"type": "var", "name": "COMPILE_FLAGS"}
+ , [ "-I"
+ , "work"
+ , "-isystem"
+ , "include"
+ , "-E"
+ , {"type": "var", "name": "src"}
+ ]
+ ]
+ }
+ ]
+ ]
+ , "body":
+ { "type": "env"
+ , "vars": ["cmd", "src", "direct deps artifact names"]
+ }
+ }
+ }
+ }
+ }
+ ]
+ , [ "src lint"
+ , { "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"}
+ }
+ , { "type": "var"
+ , "name": "cflags-files"
+ , "default": {"type": "empty_map"}
+ }
+ , { "type": "var"
+ , "name": "TOOLCHAIN"
+ , "default": {"type": "empty_map"}
+ }
+ ]
+ }
+ ]
+ , [ "out"
+ , { "type": "change_ending"
+ , "$1": {"type": "var", "name": "src_name"}
+ , "ending": ".o"
+ }
+ ]
+ , [ "work out"
+ , { "type": "join"
+ , "separator": "/"
+ , "$1": ["work", {"type": "var", "name": "out"}]
+ }
+ ]
+ , [ "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"}]
+ ]
+ }
+ ]
+ ]
+ , "body":
+ { "type": "VALUE_NODE"
+ , "$1":
+ { "type": "RESULT"
+ , "artifacts": {"type": "var", "name": "inputs"}
+ , "provides":
+ { "type": "let*"
+ , "bindings":
+ [["src", {"type": "var", "name": "work src_name"}]]
+ , "body":
+ { "type": "env"
+ , "vars": ["cmd", "src", "direct deps artifact names"]
+ }
+ }
+ }
+ }
+ }
+ }
+ ]
+ , [ "dep lint nodes"
+ , { "type": "++"
+ , "$1":
+ { "type": "foreach"
+ , "var": "fieldname"
+ , "range": {"type": "var", "name": "lint-deps fieldnames"}
+ , "body":
+ { "type": "let*"
+ , "bindings":
+ [ ["provider", "lint"]
+ , [ "transition"
+ , { "type": "lookup"
+ , "map":
+ { "type": "var"
+ , "name": "modified-transitions"
+ , "default": {"type": "empty_map"}
+ }
+ , "key": {"type": "var", "name": "fieldname"}
+ , "default": {"type": "var", "name": "deps-transition"}
+ }
+ ]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "list_provider"}
+ }
+ }
+ }
+ ]
+ , [ "lint nodes"
+ , { "type": "++"
+ , "$1":
+ [ {"type": "var", "name": "hdr lint"}
+ , {"type": "var", "name": "src lint"}
+ , {"type": "var", "name": "dep lint nodes"}
+ ]
+ }
+ ]
+ , [ "lint nodes"
+ , {"type": "nub_right", "$1": {"type": "var", "name": "lint nodes"}}
+ ]
+ ]
+ , "body": {"type": "var", "name": "lint nodes"}
+ }
+ }
+, "compiler-cc":
+ { "vars": ["CC", "TOOLCHAIN_DIR", "NON_SYSTEM_TOOLS", "defaults-transition"]
+ , "imports": {"default-CC": "default-CC"}
+ , "expression":
+ { "type": "var"
+ , "name": "CC"
+ , "default":
+ { "type": "join"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ { "type": "if"
+ , "cond":
+ { "type": "lookup"
+ , "key": "CC"
+ , "map": {"type": "var", "name": "NON_SYSTEM_TOOLS"}
+ }
+ , "then": ["./", {"type": "var", "name": "TOOLCHAIN_DIR"}, "/"]
+ }
+ , {"type": "CALL_EXPRESSION", "name": "default-CC"}
+ ]
+ }
+ }
+ }
+ }
+, "compiler-cxx":
+ { "vars": ["CXX", "TOOLCHAIN_DIR", "NON_SYSTEM_TOOLS", "defaults-transition"]
+ , "imports": {"default-CXX": "default-CXX"}
+ , "expression":
+ { "type": "var"
+ , "name": "CXX"
+ , "default":
+ { "type": "join"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ { "type": "if"
+ , "cond":
+ { "type": "lookup"
+ , "key": "CXX"
+ , "map": {"type": "var", "name": "NON_SYSTEM_TOOLS"}
+ }
+ , "then": ["./", {"type": "var", "name": "TOOLCHAIN_DIR"}, "/"]
+ }
+ , {"type": "CALL_EXPRESSION", "name": "default-CXX"}
+ ]
+ }
+ }
+ }
+ }
+, "compiler":
+ { "vars":
+ [ "CC"
+ , "CXX"
+ , "pure C"
+ , "TOOLCHAIN_DIR"
+ , "NON_SYSTEM_TOOLS"
+ , "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"
+ , "cflags-files"
+ , "defaults-transition"
+ , "component-fieldnames"
+ , "deps-transition"
+ , "modified-transitions"
+ ]
+ , "imports":
+ { "compiler": "compiler"
+ , "flags": "flags"
+ , "objects": "objects"
+ , "default-AR": "default-AR"
+ , "default-ARFLAGS": "default-ARFLAGS"
+ , "default-ENV": "default-ENV"
+ , "default-PATH": "default-PATH"
+ , "default-TOOLCHAIN": "default-TOOLCHAIN"
+ , "default-NON_SYSTEM_TOOLS": "default-NON_SYSTEM_TOOLS"
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["TOOLCHAIN_DIR", "toolchain"]
+ , ["TOOLCHAIN", {"type": "CALL_EXPRESSION", "name": "default-TOOLCHAIN"}]
+ , [ "TOOLCHAIN"
+ , { "type": "to_subdir"
+ , "subdir": {"type": "var", "name": "TOOLCHAIN_DIR"}
+ , "$1": {"type": "var", "name": "TOOLCHAIN"}
+ }
+ ]
+ , [ "NON_SYSTEM_TOOLS"
+ , {"type": "CALL_EXPRESSION", "name": "default-NON_SYSTEM_TOOLS"}
+ ]
+ , ["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": "join"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ { "type": "if"
+ , "cond":
+ { "type": "lookup"
+ , "key": "AR"
+ , "map": {"type": "var", "name": "NON_SYSTEM_TOOLS"}
+ }
+ , "then":
+ ["./", {"type": "var", "name": "TOOLCHAIN_DIR"}, "/"]
+ }
+ , {"type": "CALL_EXPRESSION", "name": "default-AR"}
+ ]
+ }
+ }
+ }
+ ]
+ , ["ARFLAGS", {"type": "CALL_EXPRESSION", "name": "default-ARFLAGS"}]
+ , [ "ENV"
+ , { "type": "map_union"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "default-ENV"}
+ , {"type": "var", "name": "ENV", "default": {"type": "empty_map"}}
+ ]
+ }
+ ]
+ , [ "ENV_PATH"
+ , { "type": "lookup"
+ , "map": {"type": "var", "name": "ENV"}
+ , "key": "PATH"
+ }
+ ]
+ , [ "ENV"
+ , { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "ENV"}
+ , { "type": "singleton_map"
+ , "key": "PATH"
+ , "value":
+ { "type": "join"
+ , "separator": ":"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "default-PATH"}
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "ENV_PATH"}
+ , "then": [{"type": "var", "name": "ENV_PATH"}]
+ }
+ ]
+ }
+ }
+ }
+ ]
+ }
+ ]
+ , ["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": "let*"
+ , "bindings":
+ [ [ "staged objects"
+ , { "type": "to_subdir"
+ , "subdir": "work"
+ , "$1": {"type": "var", "name": "objects"}
+ }
+ ]
+ , [ "staged libpath"
+ , { "type": "join"
+ , "$1": ["work/", {"type": "var", "name": "libpath"}]
+ }
+ ]
+ , [ "staged lib"
+ , { "type": "ACTION"
+ , "outs": [{"type": "var", "name": "staged libpath"}]
+ , "inputs":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "TOOLCHAIN"}
+ , {"type": "var", "name": "staged objects"}
+ ]
+ }
+ , "env":
+ { "type": "var"
+ , "name": "ENV"
+ , "default": {"type": "empty_map"}
+ }
+ , "cmd":
+ { "type": "++"
+ , "$1":
+ [ [{"type": "var", "name": "AR", "default": "ar"}]
+ , {"type": "var", "name": "ARFLAGS"}
+ , [{"type": "var", "name": "staged libpath"}]
+ , { "type": "keys"
+ , "$1": {"type": "var", "name": "staged objects"}
+ }
+ ]
+ }
+ }
+ ]
+ , [ "lib artifact"
+ , { "type": "lookup"
+ , "map": {"type": "var", "name": "staged lib"}
+ , "key": {"type": "var", "name": "staged libpath"}
+ }
+ ]
+ ]
+ , "body":
+ { "type": "singleton_map"
+ , "key": {"type": "var", "name": "libpath"}
+ , "value": {"type": "var", "name": "lib artifact"}
+ }
+ }
+ }
+ ]
+ ]
+ , "body": {"type": "var", "name": "lib"}
+ }
+ }
+, "lib result":
+ { "vars":
+ [ "CC"
+ , "CXX"
+ , "CFLAGS"
+ , "CXXFLAGS"
+ , "ADD_CFLAGS"
+ , "ADD_CXXFLAGS"
+ , "AR"
+ , "ENV"
+ , "BUILD_POSITION_INDEPENDENT"
+ , "DEBUG"
+ , "LINT"
+ , "name"
+ , "pure C"
+ , "srcs"
+ , "hdrs"
+ , "private-hdrs"
+ , "cflags"
+ , "private-cflags"
+ , "ldflags"
+ , "private-ldflags"
+ , "stage"
+ , "pkg-name"
+ , "extra-provides"
+ , "public-fieldnames"
+ , "private-fieldnames"
+ , "component-fieldnames"
+ , "deps-transition"
+ , "modified-transitions"
+ , "defaults-transition"
+ ]
+ , "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"
+ , "cflags-files-deps": "cflags-files-deps"
+ , "ldflags-files-deps": "ldflags-files-deps"
+ , "lib artifact": "lib artifact"
+ , "debug-deps": "debug-deps"
+ , "lint": "lint information"
+ }
+ , "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"}
+ ]
+ }
+ }
+ ]
+ , [ "cflags-files"
+ , {"type": "CALL_EXPRESSION", "name": "cflags-files-deps"}
+ ]
+ , ["link-deps", {"type": "CALL_EXPRESSION", "name": "link-deps"}]
+ , ["lib", {"type": "CALL_EXPRESSION", "name": "lib artifact"}]
+ , ["lint-deps fieldnames", ["deps", "private-deps", "components"]]
+ , [ "lint"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "LINT"}
+ , "then": {"type": "CALL_EXPRESSION", "name": "lint"}
+ }
+ ]
+ , [ "link-args"
+ , { "type": "nub_right"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "keys", "$1": {"type": "var", "name": "lib"}}
+ , {"type": "var", "name": "ldflags", "default": []}
+ , {"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": "CALL_EXPRESSION", "name": "run-libs-args-deps"}
+ ]
+ , [ "ldflags-files"
+ , {"type": "CALL_EXPRESSION", "name": "ldflags-files-deps"}
+ ]
+ , [ "debug-srcs"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "DEBUG"}
+ , "then":
+ { "type": "map_union"
+ , "$1":
+ [ { "type": "let*"
+ , "bindings": [["deps-provider", "debug-srcs"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "debug-deps"}
+ }
+ , {"type": "var", "name": "srcs"}
+ , {"type": "var", "name": "private-hdrs"}
+ , {"type": "var", "name": "hdrs"}
+ ]
+ }
+ , "else": {"type": "empty_map"}
+ }
+ ]
+ , [ "debug-hdrs"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "DEBUG"}
+ , "then":
+ { "type": "map_union"
+ , "$1":
+ [ { "type": "let*"
+ , "bindings": [["deps-provider", "debug-hdrs"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "debug-deps"}
+ }
+ , {"type": "var", "name": "hdrs"}
+ ]
+ }
+ , "else": {"type": "empty_map"}
+ }
+ ]
+ , ["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"}
+ ]
+ }
+ }
+ ]
+ , [ "cflags-files"
+ , {"type": "CALL_EXPRESSION", "name": "cflags-files-deps"}
+ ]
+ , [ "package"
+ , { "type": "let*"
+ , "bindings": [["name", {"type": "var", "name": "pkg-name"}]]
+ , "body":
+ {"type": "env", "vars": ["name", "cflags-files", "ldflags-files"]}
+ }
+ ]
+ ]
+ , "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"
+ , "package"
+ , "debug-srcs"
+ , "debug-hdrs"
+ , "lint"
+ ]
+ }
+ , { "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"
+ , "cflags-files"
+ , "ldflags-files"
+ , "defaults-transition"
+ , "component-fieldnames"
+ , "deps-transition"
+ , "modified-transitions"
+ ]
+ , "imports":
+ { "compiler": "compiler"
+ , "flags": "flags"
+ , "objects": "objects"
+ , "default-ENV": "default-ENV"
+ , "default-PATH": "default-PATH"
+ , "default-LDFLAGS": "default-LDFLAGS"
+ , "default-TOOLCHAIN": "default-TOOLCHAIN"
+ , "default-NON_SYSTEM_TOOLS": "default-NON_SYSTEM_TOOLS"
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["BUILD_POSITION_INDEPENDENT", true]
+ , ["TOOLCHAIN_DIR", "toolchain"]
+ , ["TOOLCHAIN", {"type": "CALL_EXPRESSION", "name": "default-TOOLCHAIN"}]
+ , [ "TOOLCHAIN"
+ , { "type": "to_subdir"
+ , "subdir": {"type": "var", "name": "TOOLCHAIN_DIR"}
+ , "$1": {"type": "var", "name": "TOOLCHAIN"}
+ }
+ ]
+ , [ "NON_SYSTEM_TOOLS"
+ , {"type": "CALL_EXPRESSION", "name": "default-NON_SYSTEM_TOOLS"}
+ ]
+ , ["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": "CALL_EXPRESSION", "name": "default-ENV"}
+ , {"type": "var", "name": "ENV", "default": {"type": "empty_map"}}
+ ]
+ }
+ ]
+ , [ "ENV_PATH"
+ , { "type": "lookup"
+ , "map": {"type": "var", "name": "ENV"}
+ , "key": "PATH"
+ }
+ ]
+ , [ "ENV"
+ , { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "ENV"}
+ , { "type": "singleton_map"
+ , "key": "PATH"
+ , "value":
+ { "type": "join"
+ , "separator": ":"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "default-PATH"}
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "ENV_PATH"}
+ , "then": [{"type": "var", "name": "ENV_PATH"}]
+ }
+ ]
+ }
+ }
+ }
+ ]
+ }
+ ]
+ , ["objects", {"type": "CALL_EXPRESSION", "name": "objects"}]
+ , [ "base name"
+ , { "type": "if"
+ , "cond":
+ { "type": "or"
+ , "$1":
+ [ {"type": "var", "name": "objects"}
+ , {"type": "var", "name": "link-deps"}
+ ]
+ }
+ , "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": "or"
+ , "$1":
+ [ {"type": "var", "name": "objects"}
+ , {"type": "var", "name": "link-deps"}
+ ]
+ }
+ , "else": {"type": "empty_map"}
+ , "then":
+ { "type": "ACTION"
+ , "outs": [{"type": "var", "name": "libname"}]
+ , "inputs":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "TOOLCHAIN"}
+ , {"type": "var", "name": "objects"}
+ , {"type": "var", "name": "link-deps"}
+ , {"type": "var", "name": "run-libs"}
+ , { "type": "var"
+ , "name": "cflags-files"
+ , "default": {"type": "empty_map"}
+ }
+ , { "type": "var"
+ , "name": "ldflags-files"
+ , "default": {"type": "empty_map"}
+ }
+ ]
+ }
+ , "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"}
+ , ["-o", {"type": "var", "name": "libname"}]
+ , {"type": "keys", "$1": {"type": "var", "name": "objects"}}
+ , {"type": "var", "name": "link-args"}
+ , {"type": "var", "name": "run-libs-args"}
+ , {"type": "var", "name": "LDFLAGS"}
+ ]
+ }
+ }
+ }
+ ]
+ ]
+ , "body": {"type": "var", "name": "lib"}
+ }
+ }
+, "shared result":
+ { "vars":
+ [ "CC"
+ , "CXX"
+ , "CFLAGS"
+ , "CXXFLAGS"
+ , "LDFLAGS"
+ , "ADD_CXXFLAGS"
+ , "ADD_CFLAGS"
+ , "ADD_LDFLAGS"
+ , "ENV"
+ , "DEBUG"
+ , "LINT"
+ , "name"
+ , "pure C"
+ , "srcs"
+ , "hdrs"
+ , "private-hdrs"
+ , "cflags"
+ , "private-cflags"
+ , "ldflags"
+ , "private-ldflags"
+ , "soversion"
+ , "pkg-name"
+ , "extra-provides"
+ , "defaults-transition"
+ , "deps-transition"
+ , "modified-transitions"
+ , "public-fieldnames"
+ , "private-fieldnames"
+ , "component-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"
+ , "cflags-files-deps": "cflags-files-deps"
+ , "ldflags-files-deps": "ldflags-files-deps"
+ , "shared artifact": "shared artifact"
+ , "debug-deps": "debug-deps"
+ , "lint": "lint information"
+ }
+ , "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"}
+ ]
+ }
+ }
+ ]
+ , [ "cflags-files"
+ , {"type": "CALL_EXPRESSION", "name": "cflags-files-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": "ldflags", "default": []}
+ , {"type": "var", "name": "private-ldflags", "default": []}
+ , {"type": "CALL_EXPRESSION", "name": "run-libs-args-deps"}
+ ]
+ }
+ }
+ ]
+ , [ "ldflags-files"
+ , {"type": "CALL_EXPRESSION", "name": "ldflags-files-deps"}
+ ]
+ , ["lib", {"type": "CALL_EXPRESSION", "name": "shared artifact"}]
+ , [ "debug-srcs"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "DEBUG"}
+ , "then":
+ { "type": "map_union"
+ , "$1":
+ [ { "type": "let*"
+ , "bindings": [["deps-provider", "debug-srcs"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "debug-deps"}
+ }
+ , {"type": "var", "name": "srcs"}
+ , {"type": "var", "name": "private-hdrs"}
+ , {"type": "var", "name": "hdrs"}
+ ]
+ }
+ , "else": {"type": "empty_map"}
+ }
+ ]
+ , ["lint-deps fieldnames", ["deps", "private-deps", "components"]]
+ , [ "lint"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "LINT"}
+ , "then": {"type": "CALL_EXPRESSION", "name": "lint"}
+ }
+ ]
+ , [ "debug-hdrs"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "DEBUG"}
+ , "then":
+ { "type": "map_union"
+ , "$1":
+ [ { "type": "let*"
+ , "bindings": [["deps-provider", "debug-hdrs"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "debug-deps"}
+ }
+ , {"type": "var", "name": "hdrs"}
+ ]
+ }
+ , "else": {"type": "empty_map"}
+ }
+ ]
+ , ["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"}
+ ]
+ }
+ }
+ ]
+ , [ "cflags-files"
+ , {"type": "CALL_EXPRESSION", "name": "cflags-files-deps"}
+ ]
+ , ["link-deps", {"type": "empty_map"}]
+ , ["link-args", []]
+ , [ "run-libs"
+ , { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "lib"}
+ , {"type": "var", "name": "run-libs"}
+ ]
+ }
+ ]
+ , [ "run-libs-args"
+ , { "type": "nub_right"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "keys", "$1": {"type": "var", "name": "lib"}}
+ , {"type": "var", "name": "ldflags", "default": []}
+ ]
+ }
+ }
+ ]
+ , [ "ldflags-files"
+ , {"type": "CALL_EXPRESSION", "name": "ldflags-files-deps"}
+ ]
+ , [ "package"
+ , { "type": "let*"
+ , "bindings":
+ [ ["name", {"type": "var", "name": "pkg-name"}]
+ , [ "version"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "soversion"}
+ , "then":
+ { "type": "join"
+ , "separator": "."
+ , "$1": {"type": "var", "name": "soversion"}
+ }
+ , "else": null
+ }
+ ]
+ ]
+ , "body":
+ { "type": "env"
+ , "vars": ["name", "version", "cflags-files", "ldflags-files"]
+ }
+ }
+ ]
+ ]
+ , "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"
+ , "package"
+ , "debug-srcs"
+ , "debug-hdrs"
+ , "lint"
+ ]
+ }
+ , { "type": "var"
+ , "name": "extra-provides"
+ , "default": {"type": "empty_map"}
+ }
+ ]
+ }
+ }
+ }
+ }
+, "object artifacts":
+ { "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"
+ , "cflags-files"
+ , "defaults-transition"
+ , "modified-transitions"
+ , "component-fieldnames"
+ ]
+ , "imports":
+ { "compiler": "compiler"
+ , "flags": "flags"
+ , "objects": "objects"
+ , "default-AR": "default-AR"
+ , "default-ENV": "default-ENV"
+ , "default-PATH": "default-PATH"
+ , "default-TOOLCHAIN": "default-TOOLCHAIN"
+ , "default-NON_SYSTEM_TOOLS": "default-NON_SYSTEM_TOOLS"
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["TOOLCHAIN_DIR", "toolchain"]
+ , ["TOOLCHAIN", {"type": "CALL_EXPRESSION", "name": "default-TOOLCHAIN"}]
+ , [ "TOOLCHAIN"
+ , { "type": "to_subdir"
+ , "subdir": {"type": "var", "name": "TOOLCHAIN_DIR"}
+ , "$1": {"type": "var", "name": "TOOLCHAIN"}
+ }
+ ]
+ , [ "NON_SYSTEM_TOOLS"
+ , {"type": "CALL_EXPRESSION", "name": "default-NON_SYSTEM_TOOLS"}
+ ]
+ , ["COMPILER", {"type": "CALL_EXPRESSION", "name": "compiler"}]
+ , [ "COMPILE_FLAGS"
+ , { "type": "++"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "flags"}
+ , {"type": "var", "name": "compile-args"}
+ ]
+ }
+ ]
+ , [ "ENV"
+ , { "type": "map_union"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "default-ENV"}
+ , {"type": "var", "name": "ENV", "default": {"type": "empty_map"}}
+ ]
+ }
+ ]
+ , [ "ENV_PATH"
+ , { "type": "lookup"
+ , "map": {"type": "var", "name": "ENV"}
+ , "key": "PATH"
+ }
+ ]
+ , [ "ENV"
+ , { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "ENV"}
+ , { "type": "singleton_map"
+ , "key": "PATH"
+ , "value":
+ { "type": "join"
+ , "separator": ":"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "default-PATH"}
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "ENV_PATH"}
+ , "then": [{"type": "var", "name": "ENV_PATH"}]
+ }
+ ]
+ }
+ }
+ }
+ ]
+ }
+ ]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "objects"}
+ }
+ }
+, "object result":
+ { "vars":
+ [ "CC"
+ , "CXX"
+ , "CFLAGS"
+ , "CXXFLAGS"
+ , "ADD_CFLAGS"
+ , "ADD_CXXFLAGS"
+ , "AR"
+ , "ENV"
+ , "BUILD_POSITION_INDEPENDENT"
+ , "BUILD_OBJECT_ONLY_DROP_OBJECT_LINKING"
+ , "DEBUG"
+ , "LINT"
+ , "name"
+ , "pure C"
+ , "srcs"
+ , "hdrs"
+ , "private-hdrs"
+ , "cflags"
+ , "private-cflags"
+ , "ldflags"
+ , "private-ldflags"
+ , "stage"
+ , "pkg-name"
+ , "extra-provides"
+ , "public-fieldnames"
+ , "private-fieldnames"
+ , "component-fieldnames"
+ , "deps-transition"
+ , "modified-transitions"
+ , "defaults-transition"
+ ]
+ , "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"
+ , "cflags-files-deps": "cflags-files-deps"
+ , "ldflags-files-deps": "ldflags-files-deps"
+ , "object artifacts": "object artifacts"
+ , "debug-deps": "debug-deps"
+ , "lint": "lint information"
+ }
+ , "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"}
+ ]
+ }
+ }
+ ]
+ , [ "cflags-files"
+ , {"type": "CALL_EXPRESSION", "name": "cflags-files-deps"}
+ ]
+ , ["link-deps", {"type": "CALL_EXPRESSION", "name": "link-deps"}]
+ , ["objects", {"type": "CALL_EXPRESSION", "name": "object artifacts"}]
+ , ["lint-deps fieldnames", ["deps", "private-deps", "components"]]
+ , [ "lint"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "LINT"}
+ , "then": {"type": "CALL_EXPRESSION", "name": "lint"}
+ }
+ ]
+ , [ "link-args"
+ , { "type": "nub_right"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ { "type": "if"
+ , "cond":
+ { "type": "var"
+ , "name": "BUILD_OBJECT_ONLY_DROP_OBJECT_LINKING"
+ }
+ , "then": []
+ , "else":
+ {"type": "keys", "$1": {"type": "var", "name": "objects"}}
+ }
+ , {"type": "var", "name": "ldflags", "default": []}
+ , {"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"}
+ }
+ ]
+ , [ "ldflags-files"
+ , {"type": "CALL_EXPRESSION", "name": "ldflags-files-deps"}
+ ]
+ , [ "debug-srcs"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "DEBUG"}
+ , "then":
+ { "type": "map_union"
+ , "$1":
+ [ { "type": "let*"
+ , "bindings": [["deps-provider", "debug-srcs"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "debug-deps"}
+ }
+ , {"type": "var", "name": "srcs"}
+ , {"type": "var", "name": "private-hdrs"}
+ , {"type": "var", "name": "hdrs"}
+ ]
+ }
+ , "else": {"type": "empty_map"}
+ }
+ ]
+ , [ "debug-hdrs"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "DEBUG"}
+ , "then":
+ { "type": "map_union"
+ , "$1":
+ [ { "type": "let*"
+ , "bindings": [["deps-provider", "debug-hdrs"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "debug-deps"}
+ }
+ , {"type": "var", "name": "hdrs"}
+ ]
+ }
+ , "else": {"type": "empty_map"}
+ }
+ ]
+ , ["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"}
+ ]
+ }
+ }
+ ]
+ , [ "cflags-files"
+ , {"type": "CALL_EXPRESSION", "name": "cflags-files-deps"}
+ ]
+ , [ "package"
+ , { "type": "let*"
+ , "bindings": [["name", {"type": "var", "name": "pkg-name"}]]
+ , "body":
+ {"type": "env", "vars": ["name", "cflags-files", "ldflags-files"]}
+ }
+ ]
+ ]
+ , "body":
+ { "type": "RESULT"
+ , "artifacts": {"type": "var", "name": "objects"}
+ , "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"
+ , "package"
+ , "debug-srcs"
+ , "debug-hdrs"
+ , "lint"
+ ]
+ }
+ , { "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"
+ , "cflags-files"
+ , "ldflags-files"
+ , "defaults-transition"
+ ]
+ , "imports":
+ { "compiler": "compiler"
+ , "flags": "flags"
+ , "objects": "objects"
+ , "default-ENV": "default-ENV"
+ , "default-PATH": "default-PATH"
+ , "default-LDFLAGS": "default-LDFLAGS"
+ , "default-TOOLCHAIN": "default-TOOLCHAIN"
+ , "default-NON_SYSTEM_TOOLS": "default-NON_SYSTEM_TOOLS"
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["TOOLCHAIN_DIR", "toolchain"]
+ , ["TOOLCHAIN", {"type": "CALL_EXPRESSION", "name": "default-TOOLCHAIN"}]
+ , [ "TOOLCHAIN"
+ , { "type": "to_subdir"
+ , "subdir": {"type": "var", "name": "TOOLCHAIN_DIR"}
+ , "$1": {"type": "var", "name": "TOOLCHAIN"}
+ }
+ ]
+ , [ "NON_SYSTEM_TOOLS"
+ , {"type": "CALL_EXPRESSION", "name": "default-NON_SYSTEM_TOOLS"}
+ ]
+ , ["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": "CALL_EXPRESSION", "name": "default-ENV"}
+ , {"type": "var", "name": "ENV", "default": {"type": "empty_map"}}
+ ]
+ }
+ ]
+ , [ "ENV_PATH"
+ , { "type": "lookup"
+ , "map": {"type": "var", "name": "ENV"}
+ , "key": "PATH"
+ }
+ ]
+ , [ "ENV"
+ , { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "ENV"}
+ , { "type": "singleton_map"
+ , "key": "PATH"
+ , "value":
+ { "type": "join"
+ , "separator": ":"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "default-PATH"}
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "ENV_PATH"}
+ , "then": [{"type": "var", "name": "ENV_PATH"}]
+ }
+ ]
+ }
+ }
+ }
+ ]
+ }
+ ]
+ , ["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"}
+ }
+ ]
+ , [ "binpath (in work)"
+ , {"type": "join", "$1": ["work/", {"type": "var", "name": "binpath"}]}
+ ]
+ , ["TOOLCHAIN_DIR", "../toolchain"]
+ , ["COMPILER", {"type": "CALL_EXPRESSION", "name": "compiler"}]
+ , [ "ENV"
+ , { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "ENV"}
+ , { "type": "singleton_map"
+ , "key": "PATH"
+ , "value":
+ { "type": "join"
+ , "separator": ":"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "default-PATH"}
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "ENV_PATH"}
+ , "then": [{"type": "var", "name": "ENV_PATH"}]
+ }
+ ]
+ }
+ }
+ }
+ ]
+ }
+ ]
+ , [ "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": "link-args"}
+ , {"type": "var", "name": "run-libs-args"}
+ , {"type": "var", "name": "LDFLAGS"}
+ ]
+ }
+ ]
+ , [ "binary (in work)"
+ , { "type": "ACTION"
+ , "outs": [{"type": "var", "name": "binpath (in work)"}]
+ , "inputs":
+ { "type": "disjoint_map_union"
+ , "$1":
+ [ {"type": "var", "name": "TOOLCHAIN"}
+ , { "type": "to_subdir"
+ , "subdir": "work"
+ , "$1":
+ { "type": "disjoint_map_union"
+ , "$1":
+ [ {"type": "var", "name": "objects"}
+ , {"type": "var", "name": "link-deps"}
+ , {"type": "var", "name": "run-libs"}
+ , { "type": "var"
+ , "name": "cflags-files"
+ , "default": {"type": "empty_map"}
+ }
+ , { "type": "var"
+ , "name": "ldflags-files"
+ , "default": {"type": "empty_map"}
+ }
+ ]
+ }
+ }
+ ]
+ }
+ , "cmd": {"type": "var", "name": "cmd"}
+ , "cwd": "work"
+ , "env": {"type": "var", "name": "ENV"}
+ }
+ ]
+ , [ "binary"
+ , { "type": "singleton_map"
+ , "key": {"type": "var", "name": "binpath"}
+ , "value":
+ { "type": "lookup"
+ , "map": {"type": "var", "name": "binary (in work)"}
+ , "key": {"type": "var", "name": "binpath (in work)"}
+ }
+ }
+ ]
+ ]
+ , "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"
+ , "DEBUG"
+ , "LINT"
+ , "name"
+ , "pure C"
+ , "srcs"
+ , "private-hdrs"
+ , "private-cflags"
+ , "private-ldflags"
+ , "stage"
+ , "private-fieldnames"
+ , "component-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"
+ , "cflags-files-deps": "cflags-files-deps"
+ , "ldflags-files-deps": "ldflags-files-deps"
+ , "binary": "bin artifact"
+ , "debug-deps": "debug-deps"
+ , "lint": "lint information"
+ }
+ , "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"}
+ ]
+ , [ "cflags-files"
+ , {"type": "CALL_EXPRESSION", "name": "cflags-files-deps"}
+ ]
+ , [ "ldflags-files"
+ , {"type": "CALL_EXPRESSION", "name": "ldflags-files-deps"}
+ ]
+ , ["package", {"type": "singleton_map", "key": "to_bin", "value": true}]
+ , [ "debug-srcs"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "DEBUG"}
+ , "then":
+ { "type": "map_union"
+ , "$1":
+ [ { "type": "let*"
+ , "bindings": [["deps-provider", "debug-srcs"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "debug-deps"}
+ }
+ , {"type": "var", "name": "srcs"}
+ , {"type": "var", "name": "private-hdrs"}
+ ]
+ }
+ , "else": {"type": "empty_map"}
+ }
+ ]
+ , [ "debug-hdrs"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "DEBUG"}
+ , "then":
+ { "type": "map_union"
+ , "$1":
+ [ { "type": "let*"
+ , "bindings": [["deps-provider", "debug-hdrs"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "debug-deps"}
+ }
+ , {"type": "var", "name": "compile-deps"}
+ ]
+ }
+ , "else": {"type": "empty_map"}
+ }
+ ]
+ , [ "lint"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "LINT"}
+ , "then":
+ { "type": "let*"
+ , "bindings":
+ [ ["hdrs", {"type": "empty_map"}]
+ , ["lint-deps fieldnames", ["private-deps"]]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "lint"}
+ }
+ }
+ ]
+ ]
+ , "body":
+ { "type": "RESULT"
+ , "artifacts": {"type": "CALL_EXPRESSION", "name": "binary"}
+ , "provides":
+ { "type": "env"
+ , "vars": ["run-libs", "package", "debug-srcs", "debug-hdrs", "lint"]
+ }
+ }
+ }
+ }
+, "install-with-deps stage":
+ { "vars":
+ [ "pc-install-dir"
+ , "targets"
+ , "prefix"
+ , "flat-libs"
+ , "hdrs-only"
+ , "skip-debug-stage"
+ ]
+ , "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"
+ , "pkg-config": "pkg-config"
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ [ "install-stage"
+ , { "type": "disjoint_map_union"
+ , "msg": "install stages may not overlap"
+ , "$1":
+ { "type": "foreach"
+ , "var": "target"
+ , "range": {"type": "var", "name": "targets"}
+ , "body":
+ { "type": "let*"
+ , "bindings":
+ [ [ "runfiles"
+ , { "type": "DEP_RUNFILES"
+ , "dep": {"type": "var", "name": "target"}
+ , "default": {"type": "empty_map"}
+ }
+ ]
+ , [ "compile-deps"
+ , { "type": "DEP_PROVIDES"
+ , "dep": {"type": "var", "name": "target"}
+ , "provider": "compile-deps"
+ , "default": {"type": "empty_map"}
+ }
+ ]
+ , [ "headers"
+ , { "type": "disjoint_map_union"
+ , "msg": "headers may not overlap"
+ , "$1":
+ [ {"type": "var", "name": "runfiles"}
+ , {"type": "var", "name": "compile-deps"}
+ ]
+ }
+ ]
+ , [ "debug-srcs"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "skip-debug-stage"}
+ , "then": {"type": "empty_map"}
+ , "else":
+ { "type": "DEP_PROVIDES"
+ , "dep": {"type": "var", "name": "target"}
+ , "provider": "debug-srcs"
+ , "default": {"type": "empty_map"}
+ }
+ }
+ ]
+ , [ "debug-hdrs"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "skip-debug-stage"}
+ , "then": {"type": "empty_map"}
+ , "else":
+ { "type": "DEP_PROVIDES"
+ , "dep": {"type": "var", "name": "target"}
+ , "provider": "debug-hdrs"
+ , "default": {"type": "empty_map"}
+ }
+ }
+ ]
+ ]
+ , "body":
+ { "type": "if"
+ , "cond": {"type": "var", "name": "hdrs-only"}
+ , "then": {"type": "var", "name": "headers"}
+ , "else":
+ { "type": "let*"
+ , "bindings":
+ [ [ "artifacts"
+ , { "type": "DEP_ARTIFACTS"
+ , "dep": {"type": "var", "name": "target"}
+ , "default": {"type": "empty_map"}
+ }
+ ]
+ , [ "link-deps"
+ , { "type": "DEP_PROVIDES"
+ , "dep": {"type": "var", "name": "target"}
+ , "provider": "link-deps"
+ , "default": {"type": "empty_map"}
+ }
+ ]
+ , [ "run-libs"
+ , { "type": "DEP_PROVIDES"
+ , "dep": {"type": "var", "name": "target"}
+ , "provider": "run-libs"
+ , "default": {"type": "empty_map"}
+ }
+ ]
+ , [ "package"
+ , { "type": "DEP_PROVIDES"
+ , "dep": {"type": "var", "name": "target"}
+ , "provider": "package"
+ , "default": {"type": "empty_map"}
+ }
+ ]
+ , [ "to_bin"
+ , { "type": "lookup"
+ , "key": "to_bin"
+ , "map": {"type": "var", "name": "package"}
+ }
+ ]
+ , [ "binaries"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "to_bin"}
+ , "then": {"type": "var", "name": "artifacts"}
+ , "else": {"type": "empty_map"}
+ }
+ ]
+ , [ "libraries"
+ , { "type": "disjoint_map_union"
+ , "msg": "libraries may not overlap"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ { "type": "if"
+ , "cond": {"type": "var", "name": "to_bin"}
+ , "then": []
+ , "else": [{"type": "var", "name": "artifacts"}]
+ }
+ , [{"type": "var", "name": "link-deps"}]
+ , [{"type": "var", "name": "run-libs"}]
+ ]
+ }
+ }
+ ]
+ , [ "pkg-name"
+ , { "type": "lookup"
+ , "key": "name"
+ , "map": {"type": "var", "name": "package"}
+ }
+ ]
+ , [ "pkg-config"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "pkg-name"}
+ , "then":
+ { "type": "let*"
+ , "bindings":
+ [ ["pkg-prefix", {"type": "var", "name": "prefix"}]
+ , [ "pkg-version"
+ , { "type": "lookup"
+ , "key": "version"
+ , "map": {"type": "var", "name": "package"}
+ }
+ ]
+ , [ "pkg-cflags"
+ , { "type": "DEP_PROVIDES"
+ , "dep": {"type": "var", "name": "target"}
+ , "provider": "compile-args"
+ , "default": []
+ }
+ ]
+ , [ "pkg-ldflags"
+ , { "type": "++"
+ , "$1":
+ [ { "type": "DEP_PROVIDES"
+ , "dep": {"type": "var", "name": "target"}
+ , "provider": "link-args"
+ , "default": []
+ }
+ , { "type": "DEP_PROVIDES"
+ , "dep": {"type": "var", "name": "target"}
+ , "provider": "run-libs-args"
+ , "default": []
+ }
+ ]
+ }
+ ]
+ , [ "pkg-flag-files"
+ , { "type": "map_union"
+ , "$1":
+ [ { "type": "lookup"
+ , "key": "cflags-files"
+ , "map": {"type": "var", "name": "package"}
+ , "default": {"type": "empty_map"}
+ }
+ , { "type": "lookup"
+ , "key": "ldflags-files"
+ , "map": {"type": "var", "name": "package"}
+ , "default": {"type": "empty_map"}
+ }
+ ]
+ }
+ ]
+ , [ "pkg-libs"
+ , {"type": "var", "name": "libraries"}
+ ]
+ , [ "flat-libs"
+ , {"type": "var", "name": "flat-libs"}
+ ]
+ ]
+ , "body":
+ { "type": "map_union"
+ , "$1":
+ [ { "type": "CALL_EXPRESSION"
+ , "name": "pkg-config"
+ }
+ , {"type": "var", "name": "pkg-flag-files"}
+ ]
+ }
+ }
+ , "else": {"type": "empty_map"}
+ }
+ ]
+ ]
+ , "body":
+ { "type": "map_union"
+ , "$1":
+ [ { "type": "to_subdir"
+ , "subdir": "bin"
+ , "flat": true
+ , "msg": "install binaries may not overlap"
+ , "$1": {"type": "var", "name": "binaries"}
+ }
+ , { "type": "to_subdir"
+ , "subdir": "include"
+ , "$1":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "headers"}
+ , {"type": "var", "name": "debug-hdrs"}
+ ]
+ }
+ }
+ , { "type": "to_subdir"
+ , "subdir": "lib"
+ , "flat": {"type": "var", "name": "flat-libs"}
+ , "msg": "install libraries may not overlap"
+ , "$1": {"type": "var", "name": "libraries"}
+ }
+ , { "type": "to_subdir"
+ , "subdir": {"type": "var", "name": "pc-install-dir"}
+ , "$1": {"type": "var", "name": "pkg-config"}
+ }
+ , { "type": "to_subdir"
+ , "subdir": "work"
+ , "$1": {"type": "var", "name": "debug-srcs"}
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ ]
+ ]
+ , "body": {"type": "var", "name": "install-stage"}
+ }
+ }
+, "install-with-deps result":
+ { "vars":
+ [ "pc-install-dir"
+ , "targets"
+ , "prefix"
+ , "flat-libs"
+ , "hdrs-only"
+ , "skip-debug-stage"
+ ]
+ , "imports": {"install stage": "install-with-deps stage"}
+ , "expression":
+ { "type": "RESULT"
+ , "artifacts": {"type": "CALL_EXPRESSION", "name": "install stage"}
+ }
+ }
+}
diff --git a/rules/CC/RULES b/rules/CC/RULES
new file mode 100644
index 0000000..a8158d4
--- /dev/null
+++ b/rules/CC/RULES
@@ -0,0 +1,1066 @@
+{ "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 sensible"
+ , "use of this rule. As targets form a different root, the defaults"
+ , "can be provided without changing this directory."
+ ]
+ , "target_fields": ["base", "toolchain", "deps", "include_scanner"]
+ , "string_fields":
+ [ "CC"
+ , "CXX"
+ , "CFLAGS"
+ , "CXXFLAGS"
+ , "LDFLAGS"
+ , "ARFLAGS"
+ , "ADD_COMPILE_FLAGS"
+ , "ADD_CFLAGS"
+ , "ADD_CXXFLAGS"
+ , "ADD_LDFLAGS"
+ , "AR"
+ , "PATH"
+ , "SYSTEM_TOOLS"
+ ]
+ , "config_vars": ["ARCH", "HOST_ARCH", "TARGET_ARCH", "DEBUG"]
+ , "field_doc":
+ { "base": ["Other targets (using the same rule) to inherit values from."]
+ , "toolchain":
+ [ "Optional toolchain directory. A collection of artifacts that provide"
+ , "the tools CC, CXX, and AR (if needed). Note that only artifacts of"
+ , "the specified targets are considered (no runfiles etc.). Specifying"
+ , "this field extends artifacts from \"base\". If the toolchain"
+ , "supports cross-compilation, it should perform a dispatch on the"
+ , "configuration variable \"BUILD_ARCH\" to determine for which"
+ , "architecture to generate code for."
+ ]
+ , "deps":
+ [ "Optional CC libraries any CC library and CC binary implicitly depend"
+ , "on. Those are typically \"libstdc++\" or \"libc++\" for C++ targets."
+ , "Specifying this field extends dependencies from \"base\"."
+ ]
+ , "CC": ["The C compiler to use"]
+ , "CXX": ["The C++ compiler to use"]
+ , "AR": ["The archiver tool to use"]
+ , "SYSTEM_TOOLS":
+ [ "List of tools (\"CC\", \"CXX\", or \"AR\") that should be taken from"
+ , "the system instead of from \"toolchain\" (if specified)."
+ ]
+ , "CFLAGS":
+ [ "Flags for C compilation. Specifying this field overwrites"
+ , "values from \"base\"."
+ ]
+ , "CXXFLAGS":
+ [ "Flags for C++ compilation. Specifying this field overwrites"
+ , "values from \"base\"."
+ ]
+ , "LDFLAGS":
+ [ "Linker flags for linking the final CC library. Specifying this field"
+ , "overwrites values from \"base\"."
+ ]
+ , "ARFLAGS":
+ [ "Arguments to tell the archiver to create an archive with the specified"
+ , "object files. If the \"ARFLAGS\" specified in the defaults target are"
+ , "empty, the rules will use [\"cqs\"]."
+ ]
+ , "ADD_COMPILE_FLAGS":
+ [ "Additional compilation flags for C and C++. Specifying this field"
+ , "extends values from \"base\" for both, \"CFLAGS\" and \"CXXFLAGS\"."
+ ]
+ , "ADD_CFLAGS":
+ [ "Additional compilation flags specific for C. Specifying this field"
+ , "extends values from \"base\"."
+ ]
+ , "ADD_CXXFLAGS":
+ [ "Additional compilation flags specific for C++. Specifying this field"
+ , "extends values from \"base\"."
+ ]
+ , "ADD_LDFLAGS":
+ [ "Additional linker flags for linking the final CC library. Specifying"
+ , "this field extends values from \"base\"."
+ ]
+ , "PATH":
+ [ "Path for looking up the compilers. Individual paths are joined"
+ , "with \":\". Specifying this field extends values from \"base\"."
+ ]
+ , "include_scanner":
+ [ "Specify an include scanner to be run before each compile action, which"
+ , "removes unused headers from the include tree. The given target must"
+ , "contain a single executable artifact, a script or binary. The tool"
+ , "specified must accept as first argument the <out_dir> path and as"
+ , "remaining arguments the argv of the preprocessor command (-E -M)."
+ , "The input headers are located in the local directory \"include\" and"
+ , "the scanner should copy all used headers to \"<out_dir>/include\"."
+ , "Specifying this field overwrites values from \"base\"."
+ ]
+ }
+ , "config_doc":
+ { "ARCH":
+ [ "The unqualified architecture. Is taken as a default for \"HOST_ARCH\""
+ , "and \"TARGET_ARCH\" if not set."
+ ]
+ , "HOST_ARCH":
+ ["The architecture on which the build actions are carried out."]
+ , "TARGET_ARCH": ["The architecture for which to build."]
+ , "DEBUG": ["Compute the debug-stage, needed for local debugging."]
+ }
+ , "imports":
+ { "base-provides": "defaults-base-provides"
+ , "base-provides-++": "defaults-base-provides-++"
+ , "base-provides-list": "defaults-base-provides-list"
+ , "artifacts_list": ["./", "..", "field_artifacts_list"]
+ , "artifacts": ["./", "..", "field_artifacts"]
+ , "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"
+ , "cflags-files-deps": "cflags-files-deps"
+ , "ldflags-files-deps": "ldflags-files-deps"
+ , "for host": ["transitions", "for host"]
+ , "debug-deps": "debug-deps"
+ }
+ , "config_transitions":
+ { "toolchain": [{"type": "CALL_EXPRESSION", "name": "for host"}]
+ , "include_scanner": [{"type": "CALL_EXPRESSION", "name": "for host"}]
+ }
+ , "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"}]
+ , ["ARFLAGS", {"type": "FIELD", "name": "ARFLAGS"}]
+ , ["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", "LDFLAGS"]
+ , [ "LDFLAGS"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "LDFLAGS"}
+ , "then": {"type": "var", "name": "LDFLAGS"}
+ , "else": {"type": "CALL_EXPRESSION", "name": "base-provides-++"}
+ }
+ ]
+ , ["provider", "ARFLAGS"]
+ , [ "ARFLAGS"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "ARFLAGS"}
+ , "then": {"type": "var", "name": "ARFLAGS"}
+ , "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", "PATH"]
+ , [ "PATH"
+ , { "type": "nub_left"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "var", "name": "PATH"}
+ , {"type": "CALL_EXPRESSION", "name": "base-provides-++"}
+ ]
+ }
+ }
+ ]
+ , ["provider", "ENV"]
+ , ["default", {"type": "empty_map"}]
+ , ["ENV", {"type": "CALL_EXPRESSION", "name": "base-provides"}]
+ , ["provider", "INCLUDE_SCANNER"]
+ , ["default", {"type": "empty_map"}]
+ , [ "INCLUDE_SCANNER"
+ , { "type": "if"
+ , "cond": {"type": "FIELD", "name": "include_scanner"}
+ , "then":
+ { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "include_scanner"]
+ , ["transition", {"type": "CALL_EXPRESSION", "name": "for host"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "artifacts"}
+ }
+ , "else":
+ { "type": "disjoint_map_union"
+ , "$1": {"type": "CALL_EXPRESSION", "name": "base-provides-list"}
+ }
+ }
+ ]
+ , ["provider", "NON_SYSTEM_TOOLS"]
+ , ["default", {"type": "empty_map"}]
+ , [ "NON_SYSTEM_TOOLS"
+ , { "type": "map_union"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ [{"type": "CALL_EXPRESSION", "name": "base-provides"}]
+ , { "type": "if"
+ , "cond": {"type": "FIELD", "name": "CC"}
+ , "then":
+ [ { "type": "singleton_map"
+ , "key": "CC"
+ , "value":
+ { "type": "if"
+ , "cond": {"type": "FIELD", "name": "toolchain"}
+ , "then": true
+ , "else": false
+ }
+ }
+ ]
+ }
+ , { "type": "if"
+ , "cond": {"type": "FIELD", "name": "CXX"}
+ , "then":
+ [ { "type": "singleton_map"
+ , "key": "CXX"
+ , "value":
+ { "type": "if"
+ , "cond": {"type": "FIELD", "name": "toolchain"}
+ , "then": true
+ , "else": false
+ }
+ }
+ ]
+ }
+ , { "type": "if"
+ , "cond": {"type": "FIELD", "name": "AR"}
+ , "then":
+ [ { "type": "singleton_map"
+ , "key": "AR"
+ , "value":
+ { "type": "if"
+ , "cond": {"type": "FIELD", "name": "toolchain"}
+ , "then": true
+ , "else": false
+ }
+ }
+ ]
+ }
+ , { "type": "foreach"
+ , "range": {"type": "FIELD", "name": "SYSTEM_TOOLS"}
+ , "var": "tool"
+ , "body":
+ { "type": "singleton_map"
+ , "key": {"type": "var", "name": "tool"}
+ , "value": false
+ }
+ }
+ ]
+ }
+ }
+ ]
+ , ["provider", "TOOLCHAIN"]
+ , ["default", {"type": "empty_map"}]
+ , [ "TOOLCHAIN"
+ , { "type": "disjoint_map_union"
+ , "msg": "toolchain artifacts may not overlap"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "base-provides-list"}
+ , { "type": "if"
+ , "cond": {"type": "FIELD", "name": "toolchain"}
+ , "then":
+ { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "toolchain"]
+ , [ "transition"
+ , {"type": "CALL_EXPRESSION", "name": "for host"}
+ ]
+ ]
+ , "body":
+ {"type": "CALL_EXPRESSION", "name": "artifacts_list"}
+ }
+ }
+ ]
+ }
+ }
+ ]
+ , [ "CFLAGS"
+ , { "type": "++"
+ , "$1":
+ [ {"type": "var", "name": "CFLAGS"}
+ , {"type": "FIELD", "name": "ADD_COMPILE_FLAGS"}
+ , {"type": "FIELD", "name": "ADD_CFLAGS"}
+ ]
+ }
+ ]
+ , [ "CXXFLAGS"
+ , { "type": "++"
+ , "$1":
+ [ {"type": "var", "name": "CXXFLAGS"}
+ , {"type": "FIELD", "name": "ADD_COMPILE_FLAGS"}
+ , {"type": "FIELD", "name": "ADD_CXXFLAGS"}
+ ]
+ }
+ ]
+ , [ "LDFLAGS"
+ , { "type": "++"
+ , "$1":
+ [ {"type": "var", "name": "LDFLAGS"}
+ , {"type": "FIELD", "name": "ADD_LDFLAGS"}
+ ]
+ }
+ ]
+ , ["deps-fieldnames", ["base", "deps"]]
+ , ["compile-deps", {"type": "CALL_EXPRESSION", "name": "compile-deps"}]
+ , [ "compile-args"
+ , {"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": "CALL_EXPRESSION", "name": "run-libs-args-deps"}
+ ]
+ , [ "cflags-files"
+ , {"type": "CALL_EXPRESSION", "name": "cflags-files-deps"}
+ ]
+ , [ "ldflags-files"
+ , {"type": "CALL_EXPRESSION", "name": "ldflags-files-deps"}
+ ]
+ , ["package", {"type": "env", "vars": ["cflags-files", "ldflags-files"]}]
+ , [ "debug-srcs"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "DEBUG"}
+ , "then":
+ { "type": "let*"
+ , "bindings": [["deps-provider", "debug-srcs"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "debug-deps"}
+ }
+ , "else": {"type": "empty_map"}
+ }
+ ]
+ , [ "debug-hdrs"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "DEBUG"}
+ , "then":
+ { "type": "map_union"
+ , "$1":
+ [ { "type": "let*"
+ , "bindings": [["deps-provider", "debug-hdrs"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "debug-deps"}
+ }
+ , {"type": "var", "name": "compile-deps"}
+ ]
+ }
+ , "else": {"type": "empty_map"}
+ }
+ ]
+ ]
+ , "body":
+ { "type": "RESULT"
+ , "provides":
+ { "type": "env"
+ , "vars":
+ [ "CC"
+ , "CXX"
+ , "CFLAGS"
+ , "CXXFLAGS"
+ , "LDFLAGS"
+ , "AR"
+ , "ARFLAGS"
+ , "PATH"
+ , "ENV"
+ , "INCLUDE_SCANNER"
+ , "TOOLCHAIN"
+ , "NON_SYSTEM_TOOLS"
+ , "compile-deps"
+ , "compile-args"
+ , "link-deps"
+ , "link-args"
+ , "run-libs"
+ , "run-libs-args"
+ , "package"
+ , "debug-srcs"
+ , "debug-hdrs"
+ ]
+ }
+ }
+ }
+ }
+, "library":
+ { "doc": ["A C++ library"]
+ , "target_fields":
+ [ "srcs"
+ , "hdrs"
+ , "private-hdrs"
+ , "deps"
+ , "private-deps"
+ , "proto"
+ , "private-proto"
+ , "components"
+ ]
+ , "string_fields":
+ [ "name"
+ , "stage"
+ , "pure C"
+ , "defines"
+ , "private-defines"
+ , "cflags"
+ , "private-cflags"
+ , "ldflags"
+ , "private-ldflags"
+ , "soversion"
+ , "pkg-name"
+ ]
+ , "config_fields": ["shared"]
+ , "config_vars":
+ [ "CC"
+ , "CXX"
+ , "CFLAGS"
+ , "CXXFLAGS"
+ , "LDFLAGS"
+ , "ADD_CFLAGS"
+ , "ADD_CXXFLAGS"
+ , "ADD_LDFLAGS"
+ , "AR"
+ , "ENV"
+ , "BUILD_POSITION_INDEPENDENT"
+ , "BUILD_OBJECT_ONLY"
+ , "BUILD_OBJECT_ONLY_DROP_OBJECT_LINKING"
+ , "DEBUG"
+ , "LINT"
+ ]
+ , "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."
+ ]
+ , "components":
+ [ "Any other libraries that are considered part of this library;"
+ , "all object files of those are included unconditionally into this"
+ , "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 rather 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."]
+ , "ldflags":
+ [ "Additional linker flags for linking external libraries for this"
+ , "target and its consumers (not built by this tool, typically system"
+ , "libraries)."
+ ]
+ , "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)."
+ ]
+ , "private-proto":
+ [ "Any [\"proto\", \"library\"] this target depends upon privately."
+ , "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 \".\"."
+ ]
+ , "pkg-name":
+ [ "Name to use for pkg-config files. If this field is empty, the field"
+ , "\"name\" is used instead."
+ ]
+ , "defaults": ["The C/C++ toolchain to use"]
+ }
+ , "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."]
+ , "DEBUG": ["Compute the debug-stage, needed for local debugging."]
+ , "BUILD_OBJECT_ONLY":
+ [ "If true, produce an object library, resulting in object files"
+ , "added to the linker line of all depending targets. If this"
+ , "configuration is set, the \"shared\" option is ignored. This"
+ , "variable is cleared for all dependencies."
+ ]
+ , "BUILD_OBJECT_ONLY_DROP_OBJECT_LINKING":
+ [ "If true, do not include the objects in the provided \"link-args\"."
+ , "This allows consuming libraries that pick on the objects themselves"
+ , "to still forward the \"link-args\" of that library, and thus getting"
+ , "correct linking instructions for the resulting library."
+ ]
+ , "LINT":
+ [ "Also provide nodes describing compile actions and header files;"
+ , "those can be used by lint rules (doing also the config transition)"
+ , "for additional checks."
+ ]
+ }
+ , "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 this library"
+ ]
+ , "debug-srcs": ["Map of all sources needed for debugging."]
+ , "debug-hdrs": ["Map of all additional headers needed for debugging."]
+ , "run-libs":
+ [ "Map of artifacts specifying libraries that have to be present at"
+ , "runtime (as well as during linking)."
+ ]
+ , "run-libs-args":
+ [ "Additional arguments for linking that are related to the run-libs."
+ , "Those are added on the linker command line after the regular link-args."
+ ]
+ , "package":
+ [ "Information related to packaging the library. This provider is a map,"
+ , "specifying \"name\" and \"version\" of the package, as well as"
+ , "additional stages \"cflags-files\" and \"ldflags-files\" for files"
+ , "with compile-flags or link-flags, respctively."
+ ]
+ }
+ , "anonymous":
+ { "proto-deps":
+ { "target": "proto"
+ , "provider": "proto"
+ , "rule_map":
+ { "library": ["./", "proto", "library"]
+ , "service library": ["./", "proto", "service library"]
+ }
+ }
+ , "private-proto-deps":
+ { "target": "private-proto"
+ , "provider": "proto"
+ , "rule_map":
+ { "library": ["./", "proto", "library"]
+ , "service library": ["./", "proto", "service library"]
+ }
+ }
+ }
+ , "imports":
+ { "artifacts": ["./", "..", "field_artifacts"]
+ , "runfiles": ["./", "..", "field_runfiles"]
+ , "static result": "lib result"
+ , "shared result": "shared result"
+ , "object result": "object result"
+ , "fPIC transition": ["transitions", "with fPIC, not object-only"]
+ , "component transition": ["transitions", "with fPIC, object-only"]
+ }
+ , "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"}]
+ , "private-proto-deps":
+ [{"type": "CALL_EXPRESSION", "name": "fPIC transition"}]
+ , "defaults": [{"type": "CALL_EXPRESSION", "name": "fPIC transition"}]
+ , "components":
+ [{"type": "CALL_EXPRESSION", "name": "component 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"}
+ }
+ }
+ ]
+ , [ "component transition"
+ , {"type": "CALL_EXPRESSION", "name": "component transition"}
+ ]
+ , [ "component hdrs"
+ , { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "components"]
+ , ["transition", {"type": "var", "name": "component transition"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "runfiles"}
+ }
+ ]
+ , [ "hdrs"
+ , { "type": "disjoint_map_union"
+ , "msg": "Staging conflict between component and own header files"
+ , "$1":
+ [ {"type": "var", "name": "hdrs"}
+ , {"type": "var", "name": "component hdrs"}
+ ]
+ }
+ ]
+ , [ "private-hdrs"
+ , { "type": "to_subdir"
+ , "subdir": {"type": "var", "name": "stage"}
+ , "$1":
+ { "type": "let*"
+ , "bindings": [["fieldname", "private-hdrs"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "artifacts"}
+ }
+ }
+ ]
+ , ["ldflags", {"type": "FIELD", "name": "ldflags"}]
+ , ["private-ldflags", {"type": "FIELD", "name": "private-ldflags"}]
+ , ["soversion", {"type": "FIELD", "name": "soversion"}]
+ , [ "pkg-name"
+ , { "type": "if"
+ , "cond": {"type": "FIELD", "name": "pkg-name"}
+ , "then":
+ {"type": "join", "$1": {"type": "FIELD", "name": "pkg-name"}}
+ , "else": {"type": "var", "name": "name"}
+ }
+ ]
+ , [ "defaults-transition"
+ , {"type": "CALL_EXPRESSION", "name": "fPIC transition"}
+ ]
+ , [ "deps-transition"
+ , {"type": "CALL_EXPRESSION", "name": "fPIC transition"}
+ ]
+ , ["public-fieldnames", ["deps", "proto-deps", "defaults"]]
+ , [ "private-fieldnames"
+ , [ "deps"
+ , "private-deps"
+ , "proto-deps"
+ , "private-proto-deps"
+ , "defaults"
+ , "components"
+ ]
+ ]
+ , ["component-fieldnames", ["components"]]
+ , [ "modified-transitions"
+ , { "type": "singleton_map"
+ , "key": "components"
+ , "value": {"type": "var", "name": "component transition"}
+ }
+ ]
+ , [ "shared"
+ , { "type": "and"
+ , "$1":
+ [ {"type": "FIELD", "name": "shared"}
+ , { "type": "not"
+ , "$1": {"type": "var", "name": "BUILD_OBJECT_ONLY"}
+ }
+ ]
+ }
+ ]
+ ]
+ , "body":
+ { "type": "cond"
+ , "cond":
+ [ [ {"type": "var", "name": "shared"}
+ , {"type": "CALL_EXPRESSION", "name": "shared result"}
+ ]
+ , [ {"type": "var", "name": "BUILD_OBJECT_ONLY"}
+ , {"type": "CALL_EXPRESSION", "name": "object result"}
+ ]
+ ]
+ , "default": {"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"
+ , "DEBUG"
+ , "LINT"
+ ]
+ , "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)."
+ ]
+ , "defaults": ["The C/C++ toolchain to use"]
+ }
+ , "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."]
+ , "DEBUG": ["Compute the debug-stage, needed for local debugging."]
+ , "LINT":
+ [ "Also provide nodes describing compile actions and header files;"
+ , "those can be used by lint rules (doing also the config transition)"
+ , "for additional checks."
+ ]
+ }
+ , "artifacts_doc": ["The final binary, staged to the given directory"]
+ , "runfiles_doc": ["None"]
+ , "provides_doc":
+ { "debug-srcs": ["Map of all sources needed for debugging."]
+ , "debug-hdrs": ["Map of all additional headers needed for debugging."]
+ }
+ , "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", "defaults"]
+ ]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "bin result"}
+ }
+ }
+, "install-with-deps":
+ { "doc":
+ [ "Install target's artifacts with transitive dependencies. Depending on"
+ , "the target, artifacts and dependencies will be installed to"
+ , "subdirectories \"bin\", \"include\", and \"lib\". For library targets,"
+ , "a pkg-config file is generated and provided in \"lib/pkgconfig\"."
+ , "In debug mode, depending on the target, additional artifacts needed for"
+ , "local debugging are gathered and installed, depending on target, to"
+ , "\"work\" and \"include\"."
+ ]
+ , "config_vars": ["PREFIX"]
+ , "target_fields": ["targets"]
+ , "string_fields": ["flat-libs", "prefix", "hdrs-only", "skip-debug-stage"]
+ , "imports": {"install result": "install-with-deps result"}
+ , "field_doc":
+ { "targets": ["Targets to install artifacts from."]
+ , "flat-libs":
+ [ "Install libraries flat to the \"lib\" subdirectory. Be aware that"
+ , "conflicts may occur if any of the (transitive) libraries happen to"
+ , "have the same base name."
+ ]
+ , "prefix":
+ [ "The prefix used for pkg-config files. The path will be made absolute"
+ , "and individual directory components are joined with \"/\". If no"
+ , "prefix is specified, the value from the config variable \"PREFIX\" is"
+ , "taken, with the default value being \"/\"."
+ ]
+ , "hdrs-only": ["Only collect headers from deps (without subdirectory)."]
+ , "skip-debug-stage":
+ [ "If in debug mode, skip installing additional artifacts gathered if no"
+ , "local debugging is needed, but debug targets are nonetheless desired."
+ ]
+ }
+ , "config_doc":
+ { "PREFIX":
+ [ "The absolute path that is used as prefix inside generated pkg-config"
+ , "files. The default value for this variable is \"/\". This variable"
+ , "is ignored if the field \"prefix\" is set."
+ ]
+ }
+ , "artifacts_doc":
+ ["Installed artifacts in subdirectories (\"bin\"/\"include\"/\"lib\")."]
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["pc-install-dir", "lib/pkgconfig"]
+ , ["targets", {"type": "FIELD", "name": "targets"}]
+ , [ "prefix"
+ , { "type": "if"
+ , "cond": {"type": "FIELD", "name": "prefix"}
+ , "then":
+ { "type": "join"
+ , "separator": "/"
+ , "$1":
+ {"type": "++", "$1": [[""], {"type": "FIELD", "name": "prefix"}]}
+ }
+ , "else": {"type": "var", "name": "PREFIX", "default": "/"}
+ }
+ ]
+ , ["flat-libs", {"type": "FIELD", "name": "flat-libs"}]
+ , ["hdrs-only", {"type": "FIELD", "name": "hdrs-only"}]
+ , ["skip-debug-stage", {"type": "FIELD", "name": "skip-debug-stage"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "install 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/RULES b/rules/CC/auto/RULES
new file mode 100644
index 0000000..34886d8
--- /dev/null
+++ b/rules/CC/auto/RULES
@@ -0,0 +1,1379 @@
+{ "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}\"."
+ ]
+ , "defaults": ["The C/C++ toolchain to use"]
+ , "shell defaults": ["The shell toolchain to use"]
+ }
+ , "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. If the header file defines the"
+ , "symbol as a macro it is considered available and assumed to work."
+ ]
+ , "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. If the header file defines the"
+ , "symbol as a macro it is considered available and assumed to work."
+ ]
+ , "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":
+ { "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"]
+ , "default-PATH": ["./", "..", "default-PATH"]
+ , "default-TOOLCHAIN": ["./", "..", "default-TOOLCHAIN"]
+ , "default-NON_SYSTEM_TOOLS": ["./", "..", "default-NON_SYSTEM_TOOLS"]
+ , "map_provider": ["./", "../..", "field_map_provider"]
+ , "list_provider": ["./", "../..", "field_list_provider"]
+ , "sh": ["./", "../../shell", "sh"]
+ , "sh-PATH": ["./", "../../shell", "PATH"]
+ }
+ , "implicit":
+ { "defaults": [["./", "..", "defaults"]]
+ , "shell defaults": [["./", "../../shell", "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"}
+ }
+ ]
+ }
+ }
+ ]
+ , ["TOOLCHAIN_DIR", "toolchain"]
+ , ["TOOLCHAIN", {"type": "CALL_EXPRESSION", "name": "default-TOOLCHAIN"}]
+ , [ "shell TOOLCHAIN"
+ , { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "shell defaults"]
+ , ["provider", "TOOLCHAIN"]
+ , ["default", {"type": "empty_map"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "map_provider"}
+ }
+ ]
+ , [ "TOOLCHAIN"
+ , { "type": "disjoint_map_union"
+ , "msg": "Shell and CC toolchain must not conflict"
+ , "$1":
+ [ {"type": "var", "name": "TOOLCHAIN"}
+ , {"type": "var", "name": "shell TOOLCHAIN"}
+ ]
+ }
+ ]
+ , [ "TOOLCHAIN"
+ , { "type": "to_subdir"
+ , "subdir": {"type": "var", "name": "TOOLCHAIN_DIR"}
+ , "$1": {"type": "var", "name": "TOOLCHAIN"}
+ }
+ ]
+ , [ "sh"
+ , { "type": "let*"
+ , "bindings": [["fieldname", "shell defaults"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "sh"}
+ }
+ ]
+ , [ "bin dirs"
+ , { "type": "let*"
+ , "bindings":
+ [["fieldname", "shell defaults"], ["provider", "bin dirs"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "list_provider"}
+ }
+ ]
+ , [ "bin dirs"
+ , { "type": "foreach"
+ , "range": {"type": "var", "name": "bin dirs"}
+ , "body":
+ { "type": "join"
+ , "$1":
+ [ "./"
+ , {"type": "var", "name": "TOOLCHAIN_DIR"}
+ , "/"
+ , {"type": "var", "name": "_"}
+ ]
+ }
+ }
+ ]
+ , [ "NON_SYSTEM_TOOLS"
+ , {"type": "CALL_EXPRESSION", "name": "default-NON_SYSTEM_TOOLS"}
+ ]
+ , ["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": "CALL_EXPRESSION", "name": "default-ENV"}
+ , {"type": "var", "name": "ENV", "default": {"type": "empty_map"}}
+ ]
+ }
+ ]
+ , [ "ENV_PATH"
+ , { "type": "lookup"
+ , "map": {"type": "var", "name": "ENV"}
+ , "key": "PATH"
+ }
+ ]
+ , [ "ENV"
+ , { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "ENV"}
+ , { "type": "singleton_map"
+ , "key": "PATH"
+ , "value":
+ { "type": "join"
+ , "separator": ":"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "default-PATH"}
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "ENV_PATH"}
+ , "then": [{"type": "var", "name": "ENV_PATH"}]
+ }
+ , { "type": "let*"
+ , "bindings": [["fieldname", "shell defaults"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "sh-PATH"}
+ }
+ , {"type": "var", "name": "bin dirs"}
+ ]
+ }
+ }
+ }
+ ]
+ }
+ ]
+ , [ "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_symbol.$LANG << EOF"
+ , "#include \"$INC\""
+ , "void* __test = &$SYMBOL;"
+ , "EOF"
+ , " if $CC @$LANG.flags -c test_symbol.$LANG -I ./include 2>/dev/null; then"
+ , " DEFINE=\"#define $DEF 1\""
+ , " break"
+ , " fi"
+ , " cat > test_macro.$LANG << EOF"
+ , "#include \"$INC\""
+ , "#ifndef $SYMBOL"
+ , "#error not defined as macro"
+ , "#endif"
+ , "EOF"
+ , " if $CC @$LANG.flags -c test_macro.$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":
+ [ [ "def"
+ , { "type": "assert_non_empty"
+ , "msg": "Define name in 'defines' may not be empty"
+ , "$1":
+ { "type": "[]"
+ , "index": 0
+ , "list": {"type": "var", "name": "pair"}
+ }
+ }
+ ]
+ , [ "val"
+ , { "type": "[]"
+ , "index": -1
+ , "list": {"type": "var", "name": "pair"}
+ }
+ ]
+ ]
+ , "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":
+ [ [ "def"
+ , { "type": "assert_non_empty"
+ , "msg": "Define name in 'defines1' may not be empty"
+ , "$1":
+ { "type": "[]"
+ , "index": 0
+ , "list": {"type": "var", "name": "pair"}
+ }
+ }
+ ]
+ , [ "val"
+ , { "type": "[]"
+ , "index": -1
+ , "list": {"type": "var", "name": "pair"}
+ }
+ ]
+ ]
+ , "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":
+ [ [ "def"
+ , { "type": "assert_non_empty"
+ , "msg": "Define name in 'defines01' may not be empty"
+ , "$1":
+ { "type": "[]"
+ , "index": 0
+ , "list": {"type": "var", "name": "pair"}
+ }
+ }
+ ]
+ , [ "val"
+ , { "type": "[]"
+ , "index": -1
+ , "list": {"type": "var", "name": "pair"}
+ }
+ ]
+ ]
+ , "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":
+ [ [ "def"
+ , { "type": "assert_non_empty"
+ , "msg": "Define name in 'have_cfile' may not be empty"
+ , "$1":
+ { "type": "[]"
+ , "index": 0
+ , "list": {"type": "var", "name": "pair"}
+ }
+ }
+ ]
+ , [ "val"
+ , { "type": "[]"
+ , "index": -1
+ , "list": {"type": "var", "name": "pair"}
+ }
+ ]
+ ]
+ , "body":
+ { "type": "lookup"
+ , "key": "out.def"
+ , "map":
+ { "type": "ACTION"
+ , "inputs":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "TOOLCHAIN"}
+ , {"type": "env", "vars": ["file_check.sh", "c.flags"]}
+ , {"type": "var", "name": "includes"}
+ ]
+ }
+ , "cmd":
+ [ {"type": "var", "name": "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":
+ [ [ "def"
+ , { "type": "assert_non_empty"
+ , "msg": "Define name in 'have_cxxfile' may not be empty"
+ , "$1":
+ { "type": "[]"
+ , "index": 0
+ , "list": {"type": "var", "name": "pair"}
+ }
+ }
+ ]
+ , [ "val"
+ , { "type": "[]"
+ , "index": -1
+ , "list": {"type": "var", "name": "pair"}
+ }
+ ]
+ ]
+ , "body":
+ { "type": "lookup"
+ , "key": "out.def"
+ , "map":
+ { "type": "ACTION"
+ , "inputs":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "TOOLCHAIN"}
+ , {"type": "env", "vars": ["file_check.sh", "cxx.flags"]}
+ , {"type": "var", "name": "includes"}
+ ]
+ }
+ , "cmd":
+ [ {"type": "var", "name": "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":
+ [ [ "def"
+ , { "type": "assert_non_empty"
+ , "msg": "Define name in 'have_ctype' may not be empty"
+ , "$1":
+ { "type": "[]"
+ , "index": 0
+ , "list": {"type": "var", "name": "pair"}
+ }
+ }
+ ]
+ , [ "type"
+ , { "type": "[]"
+ , "index": -1
+ , "list": {"type": "var", "name": "pair"}
+ }
+ ]
+ ]
+ , "body":
+ { "type": "lookup"
+ , "key": "out.def"
+ , "map":
+ { "type": "ACTION"
+ , "inputs":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "TOOLCHAIN"}
+ , {"type": "env", "vars": ["type_check.sh", "c.flags"]}
+ , {"type": "var", "name": "includes"}
+ ]
+ }
+ , "cmd":
+ [ {"type": "var", "name": "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":
+ [ [ "def"
+ , { "type": "assert_non_empty"
+ , "msg": "Define name in 'have_cxxtype' may not be empty"
+ , "$1":
+ { "type": "[]"
+ , "index": 0
+ , "list": {"type": "var", "name": "pair"}
+ }
+ }
+ ]
+ , [ "type"
+ , { "type": "[]"
+ , "index": -1
+ , "list": {"type": "var", "name": "pair"}
+ }
+ ]
+ ]
+ , "body":
+ { "type": "lookup"
+ , "key": "out.def"
+ , "map":
+ { "type": "ACTION"
+ , "inputs":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "TOOLCHAIN"}
+ , {"type": "env", "vars": ["type_check.sh", "cxx.flags"]}
+ , {"type": "var", "name": "includes"}
+ ]
+ }
+ , "cmd":
+ [ {"type": "var", "name": "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":
+ [ [ "def"
+ , { "type": "assert_non_empty"
+ , "msg": "Define name in 'have_csymbol' may not be empty"
+ , "$1":
+ { "type": "[]"
+ , "index": 0
+ , "list": {"type": "var", "name": "pair"}
+ }
+ }
+ ]
+ , [ "sym, hdrs"
+ , { "type": "[]"
+ , "index": -1
+ , "list": {"type": "var", "name": "pair"}
+ }
+ ]
+ , [ "sym"
+ , { "type": "[]"
+ , "index": 0
+ , "list": {"type": "var", "name": "sym, hdrs"}
+ }
+ ]
+ , [ "hdrs"
+ , { "type": "[]"
+ , "index": -1
+ , "list": {"type": "var", "name": "sym, hdrs"}
+ }
+ ]
+ ]
+ , "body":
+ { "type": "lookup"
+ , "key": "out.def"
+ , "map":
+ { "type": "ACTION"
+ , "inputs":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "TOOLCHAIN"}
+ , {"type": "env", "vars": ["symbol_check.sh", "c.flags"]}
+ , {"type": "var", "name": "includes"}
+ ]
+ }
+ , "cmd":
+ { "type": "++"
+ , "$1":
+ [ [ {"type": "var", "name": "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":
+ [ [ "def"
+ , { "type": "assert_non_empty"
+ , "msg": "Define name in 'have_csymbol' may not be empty"
+ , "$1":
+ { "type": "[]"
+ , "index": 0
+ , "list": {"type": "var", "name": "pair"}
+ }
+ }
+ ]
+ , [ "sym, hdrs"
+ , { "type": "[]"
+ , "index": -1
+ , "list": {"type": "var", "name": "pair"}
+ }
+ ]
+ , [ "sym"
+ , { "type": "[]"
+ , "index": 0
+ , "list": {"type": "var", "name": "sym, hdrs"}
+ }
+ ]
+ , [ "hdrs"
+ , { "type": "[]"
+ , "index": -1
+ , "list": {"type": "var", "name": "sym, hdrs"}
+ }
+ ]
+ ]
+ , "body":
+ { "type": "lookup"
+ , "key": "out.def"
+ , "map":
+ { "type": "ACTION"
+ , "inputs":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "TOOLCHAIN"}
+ , {"type": "env", "vars": ["symbol_check.sh", "cxx.flags"]}
+ , {"type": "var", "name": "includes"}
+ ]
+ }
+ , "cmd":
+ { "type": "++"
+ , "$1":
+ [ [ {"type": "var", "name": "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":
+ [ [ "def"
+ , { "type": "assert_non_empty"
+ , "msg": "Define name in 'have_csymbol' may not be empty"
+ , "$1":
+ { "type": "[]"
+ , "index": 0
+ , "list": {"type": "var", "name": "pair"}
+ }
+ }
+ ]
+ , [ "type, sizes"
+ , { "type": "[]"
+ , "index": -1
+ , "list": {"type": "var", "name": "pair"}
+ }
+ ]
+ , [ "type"
+ , { "type": "[]"
+ , "index": 0
+ , "list": {"type": "var", "name": "type, sizes"}
+ }
+ ]
+ , [ "sizes"
+ , { "type": "[]"
+ , "index": -1
+ , "list": {"type": "var", "name": "type, sizes"}
+ }
+ ]
+ ]
+ , "body":
+ { "type": "lookup"
+ , "key": "out.def"
+ , "map":
+ { "type": "ACTION"
+ , "inputs":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "TOOLCHAIN"}
+ , {"type": "env", "vars": ["size_check.sh", "c.flags"]}
+ , {"type": "var", "name": "includes"}
+ ]
+ }
+ , "cmd":
+ { "type": "++"
+ , "$1":
+ [ [ {"type": "var", "name": "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":
+ [ [ "def"
+ , { "type": "assert_non_empty"
+ , "msg": "Define name in 'have_csymbol' may not be empty"
+ , "$1":
+ { "type": "[]"
+ , "index": 0
+ , "list": {"type": "var", "name": "pair"}
+ }
+ }
+ ]
+ , [ "type, sizes"
+ , { "type": "[]"
+ , "index": -1
+ , "list": {"type": "var", "name": "pair"}
+ }
+ ]
+ , [ "type"
+ , { "type": "[]"
+ , "index": 0
+ , "list": {"type": "var", "name": "type, sizes"}
+ }
+ ]
+ , [ "sizes"
+ , { "type": "[]"
+ , "index": -1
+ , "list": {"type": "var", "name": "type, sizes"}
+ }
+ ]
+ ]
+ , "body":
+ { "type": "lookup"
+ , "key": "out.def"
+ , "map":
+ { "type": "ACTION"
+ , "inputs":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "TOOLCHAIN"}
+ , {"type": "env", "vars": ["size_check.sh", "cxx.flags"]}
+ , {"type": "var", "name": "includes"}
+ ]
+ }
+ , "cmd":
+ { "type": "++"
+ , "$1":
+ [ [ {"type": "var", "name": "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": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "TOOLCHAIN"}
+ , {"type": "var", "name": "definitions"}
+ ]
+ }
+ , "cmd":
+ [ {"type": "var", "name": "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"}
+ }
+ }
+ }
+, "config_file":
+ { "doc":
+ [ "Generate a C/C++ config header from a given template"
+ , ""
+ , "Generate a C/C++ configuration header using defines specified via the"
+ , "target configuration. In the usual case, a target using this rule is"
+ , "configured by depending on it from a target that uses the built-in"
+ , "\"configure\" rule."
+ , ""
+ , "The actual generation of the header file from the template"
+ , "is done by the implicit dependency on the \"runner\" target which"
+ , "can be changed globally by setting this target in the"
+ , "target layer of this repository."
+ ]
+ , "field_doc":
+ { "output":
+ [ "Name of the header file to generate (incl. file name ext). Components are joined with /."
+ ]
+ , "input": ["The input configuration file, used as template."]
+ , "magic_string":
+ [ "The magic string (e.g., \"cmakedefine\") which identifies in which line"
+ , "we have to \"#define\" or \"#undef\" variables according to what is"
+ , "defined in the config field \"defines\"."
+ ]
+ , "@only": ["If set, only replace @VAR@ and not ${VAR}"]
+ , "runner": ["The program generating the header file from the template."]
+ }
+ , "config_doc":
+ { "defines":
+ [ "Set a define to a specific value unless its value is \"null\". Must"
+ , "contain a list of pairs. The first element of each pair is the define"
+ , "name and the second argument is the value to set. Strings must be"
+ , "properly escaped. Defines generated from this field are added last,"
+ , "so that they can refer to defines from other \"defines*\" values."
+ ]
+ }
+ , "string_fields": ["magic_string", "@only", "output"]
+ , "target_fields": ["input"]
+ , "config_vars": ["defines"]
+ , "imports":
+ { "stage_singleton_field": ["", "stage_singleton_field"]
+ , "default-PATH": ["./", "..", "default-PATH"]
+ }
+ , "implicit": {"runner": ["runner"], "defaults": [["./", "..", "defaults"]]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ [ "runner"
+ , { "type": "let*"
+ , "bindings": [["fieldname", "runner"], ["location", "runner"]]
+ , "body":
+ {"type": "CALL_EXPRESSION", "name": "stage_singleton_field"}
+ }
+ ]
+ , [ "dict-defines"
+ , { "type": "map_union"
+ , "$1":
+ { "type": "foreach"
+ , "range": {"type": "var", "name": "defines", "default": []}
+ , "var": "pair"
+ , "body":
+ { "type": "let*"
+ , "bindings":
+ [ [ "key"
+ , { "type": "[]"
+ , "index": 0
+ , "list": {"type": "var", "name": "pair"}
+ }
+ ]
+ , [ "val"
+ , { "type": "[]"
+ , "index": -1
+ , "list": {"type": "var", "name": "pair"}
+ }
+ ]
+ ]
+ , "body":
+ { "type": "singleton_map"
+ , "key": {"type": "var", "name": "key"}
+ , "value": {"type": "var", "name": "val"}
+ }
+ }
+ }
+ }
+ ]
+ , [ "magic_string"
+ , { "type": "assert_non_empty"
+ , "msg": "A non-empty string has to be provided for magic_string"
+ , "$1":
+ {"type": "join", "$1": {"type": "FIELD", "name": "magic_string"}}
+ }
+ ]
+ , [ "@only"
+ , { "type": "if"
+ , "cond": {"type": "FIELD", "name": "@only"}
+ , "then": "true"
+ , "else": "false"
+ }
+ ]
+ , [ "param-blob"
+ , { "type": "singleton_map"
+ , "key": "param-file"
+ , "value":
+ { "type": "BLOB"
+ , "data":
+ { "type": "json_encode"
+ , "$1": {"type": "var", "name": "dict-defines"}
+ }
+ }
+ }
+ ]
+ , [ "input-blob"
+ , { "type": "let*"
+ , "bindings": [["fieldname", "input"], ["location", "input-file"]]
+ , "body":
+ {"type": "CALL_EXPRESSION", "name": "stage_singleton_field"}
+ }
+ ]
+ , ["PATH", {"type": "CALL_EXPRESSION", "name": "default-PATH"}]
+ , [ "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": "empty_map"}
+ }
+ ]
+ , [ "outfile"
+ , { "type": "ACTION"
+ , "inputs":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "param-blob"}
+ , {"type": "var", "name": "input-blob"}
+ , {"type": "var", "name": "runner"}
+ ]
+ }
+ , "cmd":
+ [ "./runner"
+ , "input-file"
+ , "param-file"
+ , {"type": "var", "name": "magic_string"}
+ , {"type": "var", "name": "@only"}
+ ]
+ , "env": {"type": "var", "name": "ENV"}
+ , "outs": ["out"]
+ }
+ ]
+ , [ "outfile"
+ , { "type": "singleton_map"
+ , "key":
+ { "type": "join"
+ , "separator": "/"
+ , "$1": {"type": "FIELD", "name": "output"}
+ }
+ , "value":
+ { "type": "lookup"
+ , "key": "out"
+ , "map": {"type": "var", "name": "outfile"}
+ }
+ }
+ ]
+ ]
+ , "body":
+ { "type": "RESULT"
+ , "artifacts": {"type": "var", "name": "outfile"}
+ , "runfiles": {"type": "var", "name": "outfile"}
+ }
+ }
+ }
+}
diff --git a/rules/CC/auto/TARGETS b/rules/CC/auto/TARGETS
new file mode 100644
index 0000000..0967ef4
--- /dev/null
+++ b/rules/CC/auto/TARGETS
@@ -0,0 +1 @@
+{}
diff --git a/rules/CC/auto/runner b/rules/CC/auto/runner
new file mode 100755
index 0000000..2da44af
--- /dev/null
+++ b/rules/CC/auto/runner
@@ -0,0 +1,162 @@
+#!/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 re
+from sys import argv
+from typing import Union
+
+
+def get_tokens(line: str, magic_string: str) -> tuple[Union[re.Match[str], None], bool]:
+ """Tokenize lines (strings) like the following
+ #cmakedefine FOO bar
+ #cmakedefine FOO @FOO@
+ #cmakedefine FOO ${FOO}
+ #cmakedefine01 FOO
+
+ where "cmakedefine" is the magic_string. Let us name "FOO" as the token_key,
+ and the corresponding value (i.e., bar, @FOO@, ${FOO}, the empty string) as
+ the token_value. The function handles any combination of spaces around the
+ magic_string, the token_key and the token_value.
+ """
+ x = re.search(
+ r"#(.*)(" + magic_string + r"[01]*" + r")([\s]*)([a-zA-Z0-9_]+)([\s]*)(.*)",
+ line,
+ )
+ if x:
+ return x, x.groups()[1] == f"{magic_string}01"
+ return None, False
+
+
+def handle01(line: str, tokens: re.Match[str], defined: bool) -> str:
+ groups = tokens.groups()
+ return re.sub(
+ tokens.group()[1:],
+ groups[0] # spaces
+ + "define"
+ + groups[2] # spaces
+ + groups[3] # token_key
+ + " "
+ + str(1 if defined else 0),
+ line,
+ )
+
+
+def undefine(tokens: re.Match[str]) -> str:
+ groups = tokens.groups()
+ return "/* #" + groups[0] + "undef" + groups[2] + groups[3] + " */"
+
+
+def replace_value(tokens: re.Match[str], key: str, value: str) -> str:
+ groups = tokens.groups()
+ return f"#{groups[0]}define{groups[2]}{key}{groups[4]}{value}"
+
+
+def compute_value(token_value: str, at_only: bool, param: dict[str, str]):
+ # example of possible token_values
+ # - foo (a simple string)
+ # - @FOO@
+ # - ${FOO}
+ # - any combination of the above
+
+ def replace_pattern_in_string(
+ pattern: str, line: str, param: dict[str, str]
+ ) -> str:
+
+ def get_value_for_match(match: re.Match[str]) -> str:
+ key = match.group(1)
+ return param.get(key, "")
+
+ return re.sub(pattern, get_value_for_match, line)
+
+ token_value = replace_pattern_in_string(r"@([A-Za-z0-9_]+)@", token_value, param)
+ if at_only:
+ return token_value
+ return replace_pattern_in_string(r"\${([A-Za-z0-9_]+)}", token_value, param)
+
+
+if __name__ == "__main__":
+ input_file = argv[1]
+ param_file = argv[2]
+ magic_string = argv[3]
+ at_only = argv[4] == "true"
+
+ with open(param_file) as f:
+ param = json.loads(f.read())
+
+ # In many cases, CMake simply defines some variables (without any associated
+ # value). We handle this situation by assigning to the boolean True the empty
+ # string. Note that no False value should be found, because the right way to set
+ # a variable to False in the TARGETS file is to *do not mention* that variable
+ # at all.
+ # If a value is deliberately set to null, we will drop that key
+ drop_keys: list[str] = []
+ for k, v in param.items():
+ if isinstance(v, bool):
+ param[k] = ""
+ if v == None:
+ drop_keys.append(k)
+ for k in drop_keys:
+ del param[k]
+
+ with open(input_file) as i:
+ with open("out", "w") as o:
+ for line in i.readlines():
+ # drop trailing '\n'
+ line = line[:-1]
+
+ tokens, is_01 = get_tokens(line, magic_string)
+ # no magic string
+ if not tokens:
+ # it can be a simple comment, or a line without the magic string but with the @KEY@ or ${KEY} pattern
+ line = compute_value(line, at_only, param)
+ print(line, file=o)
+ continue
+
+ # line contains magic_string
+ groups = tokens.groups()
+
+ token_key: str = groups[3]
+
+ if is_01:
+ line = handle01(line, tokens, token_key in param)
+ print(line, file=o)
+ continue
+
+ if token_key not in param:
+ line = undefine(tokens)
+ print(line, file=o)
+ continue
+
+ # we are in one of this situations
+ # cmakedefine FOO
+ # cmakedefine FOO "foo"
+ # cmakedefine FOO @FOO@${FOO}foo
+
+ # i.e., the token_value can be any combination of keys (defined
+ # as @key@ or ${key}) and strings
+
+ # therefore, we need to further tokenize the token_value
+
+ # it is convenient to first tokenize
+
+ token_value: str = groups[5]
+
+ value = compute_value(token_value, at_only, param)
+
+ line = replace_value(tokens, token_key, value)
+
+ print(line, file=o)
diff --git a/rules/CC/foreign/EXPRESSIONS b/rules/CC/foreign/EXPRESSIONS
new file mode 100644
index 0000000..2988b32
--- /dev/null
+++ b/rules/CC/foreign/EXPRESSIONS
@@ -0,0 +1,123 @@
+{ "default-MAKE":
+ { "vars": ["defaults-transition"]
+ , "imports": {"list_provider": ["./", "../..", "field_list_provider"]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "foreign-defaults"]
+ , ["provider", "MAKE"]
+ , ["transition", {"type": "var", "name": "defaults-transition"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "list_provider"}
+ }
+ }
+, "default-CMAKE":
+ { "vars": ["defaults-transition"]
+ , "imports": {"list_provider": ["./", "../..", "field_list_provider"]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "foreign-defaults"]
+ , ["provider", "CMAKE"]
+ , ["transition", {"type": "var", "name": "defaults-transition"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "list_provider"}
+ }
+ }
+, "default-ENV":
+ { "vars": ["defaults-transition"]
+ , "imports": {"map_provider": ["", "field_map_provider"]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "foreign-defaults"]
+ , ["provider", "ENV"]
+ , ["transition", {"type": "var", "name": "defaults-transition"}]
+ , ["default", {"type": "empty_map"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "map_provider"}
+ }
+ }
+, "default-PATH":
+ { "vars": ["defaults-transition"]
+ , "imports": {"list_provider": ["./", "../..", "field_list_provider"]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "foreign-defaults"]
+ , ["provider", "PATH"]
+ , ["transition", {"type": "var", "name": "defaults-transition"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "list_provider"}
+ }
+ }
+, "default-TOOLCHAIN":
+ { "vars": ["defaults-transition"]
+ , "imports": {"map_provider": ["", "field_map_provider"]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "foreign-defaults"]
+ , ["provider", "TOOLCHAIN"]
+ , ["transition", {"type": "var", "name": "defaults-transition"}]
+ , ["default", {"type": "empty_map"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "map_provider"}
+ }
+ }
+, "default-NON_SYSTEM_TOOLS":
+ { "vars": ["defaults-transition"]
+ , "expression":
+ { "type": "map_union"
+ , "$1":
+ { "type": "foreach"
+ , "var": "x"
+ , "range": {"type": "FIELD", "name": "foreign-defaults"}
+ , "body":
+ { "type": "DEP_PROVIDES"
+ , "dep": {"type": "var", "name": "x"}
+ , "provider": "NON_SYSTEM_TOOLS"
+ , "transition":
+ { "type": "var"
+ , "name": "defaults-transition"
+ , "default": {"type": "empty_map"}
+ }
+ , "default": {"type": "empty_map"}
+ }
+ }
+ }
+ }
+, "strip-prefix":
+ { "doc":
+ [ "Returns list of artifact maps (each map contains a single artifact)"
+ , "with the given prefix being stripped from their path."
+ ]
+ , "vars": ["artifacts", "paths", "prefix"]
+ , "vars_doc":
+ { "artifacts": ["A single map containing all artifacts."]
+ , "paths": ["List of (unprefixed) artifacts paths to consider."]
+ , "prefix": ["Prefix to strip from the artifact's path."]
+ }
+ , "expression":
+ { "type": "foreach"
+ , "var": "path"
+ , "range": {"type": "var", "name": "paths"}
+ , "body":
+ { "type": "singleton_map"
+ , "key": {"type": "var", "name": "path"}
+ , "value":
+ { "type": "lookup"
+ , "key":
+ { "type": "join"
+ , "separator": "/"
+ , "$1":
+ [ {"type": "var", "name": "prefix"}
+ , {"type": "var", "name": "path"}
+ ]
+ }
+ , "map": {"type": "var", "name": "artifacts"}
+ }
+ }
+ }
+ }
+}
diff --git a/rules/CC/foreign/RULES b/rules/CC/foreign/RULES
new file mode 100644
index 0000000..e6463f8
--- /dev/null
+++ b/rules/CC/foreign/RULES
@@ -0,0 +1,162 @@
+{ "defaults":
+ { "doc":
+ [ "A rule to provide defaults for foreign rules."
+ , "All foreign rules take their defaults for MAKE, CMAKE, etc from"
+ , "the target [\"CC/foreign\", \"defaults\"]."
+ ]
+ , "target_fields": ["base", "toolchain"]
+ , "string_fields": ["MAKE", "CMAKE", "PATH", "SYSTEM_TOOLS"]
+ , "field_doc":
+ { "base": ["Other targets (using the same rule) to inherit values from."]
+ , "toolchain":
+ [ "Optional toolchain directory. A collection of artifacts that provide"
+ , "the tools MAKE, CMAKE. Note that only artifacts of"
+ , "the specified targets are considered (no runfiles etc.). Specifying"
+ , "this field extends artifacts from \"base\"."
+ ]
+ , "MAKE": ["The make binary to use"]
+ , "CMAKE": ["The cmake binary to use"]
+ , "SYSTEM_TOOLS":
+ [ "List of tools (\"MAKE\", \"CMAKE\") that should be taken from"
+ , "the system instead of from \"toolchain\" (if specified)."
+ ]
+ , "PATH":
+ [ "Path for looking up the tools. Individual paths are joined with"
+ , "with \":\". Specifying this field extends values from \"base\"."
+ ]
+ }
+ , "config_vars": ["ARCH", "HOST_ARCH"]
+ , "imports":
+ { "base-provides": ["./", "..", "defaults-base-provides"]
+ , "base-provides-++": ["./", "..", "defaults-base-provides-++"]
+ , "base-provides-list": ["./", "..", "defaults-base-provides-list"]
+ , "artifacts_list": ["./", "../..", "field_artifacts_list"]
+ , "for host": ["transitions", "for host"]
+ }
+ , "config_transitions":
+ {"toolchain": [{"type": "CALL_EXPRESSION", "name": "for host"}]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["MAKE", {"type": "FIELD", "name": "MAKE"}]
+ , ["CMAKE", {"type": "FIELD", "name": "CMAKE"}]
+ , ["PATH", {"type": "FIELD", "name": "PATH"}]
+ , ["provider", "MAKE"]
+ , [ "MAKE"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "MAKE"}
+ , "then": {"type": "var", "name": "MAKE"}
+ , "else": {"type": "CALL_EXPRESSION", "name": "base-provides"}
+ }
+ ]
+ , ["provider", "CMAKE"]
+ , [ "CMAKE"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "CMAKE"}
+ , "then": {"type": "var", "name": "CMAKE"}
+ , "else": {"type": "CALL_EXPRESSION", "name": "base-provides"}
+ }
+ ]
+ , ["provider", "PATH"]
+ , [ "PATH"
+ , { "type": "nub_left"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "var", "name": "PATH"}
+ , {"type": "CALL_EXPRESSION", "name": "base-provides-++"}
+ ]
+ }
+ }
+ ]
+ , ["provider", "ENV"]
+ , ["default", {"type": "empty_map"}]
+ , ["ENV", {"type": "CALL_EXPRESSION", "name": "base-provides"}]
+ , ["provider", "NON_SYSTEM_TOOLS"]
+ , ["default", {"type": "empty_map"}]
+ , [ "NON_SYSTEM_TOOLS"
+ , { "type": "map_union"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "base-provides-list"}
+ , { "type": "if"
+ , "cond": {"type": "FIELD", "name": "MAKE"}
+ , "then":
+ [ { "type": "singleton_map"
+ , "key": "MAKE"
+ , "value":
+ { "type": "if"
+ , "cond": {"type": "FIELD", "name": "toolchain"}
+ , "then": true
+ , "else": false
+ }
+ }
+ ]
+ }
+ , { "type": "if"
+ , "cond": {"type": "FIELD", "name": "CMAKE"}
+ , "then":
+ [ { "type": "singleton_map"
+ , "key": "CMAKE"
+ , "value":
+ { "type": "if"
+ , "cond": {"type": "FIELD", "name": "toolchain"}
+ , "then": true
+ , "else": false
+ }
+ }
+ ]
+ }
+ , { "type": "foreach"
+ , "range": {"type": "FIELD", "name": "SYSTEM_TOOLS"}
+ , "var": "tool"
+ , "body":
+ { "type": "singleton_map"
+ , "key": {"type": "var", "name": "tool"}
+ , "value": false
+ }
+ }
+ ]
+ }
+ }
+ ]
+ , ["provider", "TOOLCHAIN"]
+ , ["default", {"type": "empty_map"}]
+ , [ "TOOLCHAIN"
+ , { "type": "disjoint_map_union"
+ , "msg": "toolchain artifacts may not overlap"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "base-provides-list"}
+ , { "type": "if"
+ , "cond": {"type": "FIELD", "name": "toolchain"}
+ , "then":
+ { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "toolchain"]
+ , [ "transition"
+ , {"type": "CALL_EXPRESSION", "name": "for host"}
+ ]
+ ]
+ , "body":
+ {"type": "CALL_EXPRESSION", "name": "artifacts_list"}
+ }
+ }
+ ]
+ }
+ }
+ ]
+ ]
+ , "body":
+ { "type": "RESULT"
+ , "provides":
+ { "type": "env"
+ , "vars":
+ ["MAKE", "CMAKE", "PATH", "ENV", "TOOLCHAIN", "NON_SYSTEM_TOOLS"]
+ }
+ }
+ }
+ }
+}
diff --git a/rules/CC/foreign/TARGETS b/rules/CC/foreign/TARGETS
new file mode 100644
index 0000000..5fbb6a9
--- /dev/null
+++ b/rules/CC/foreign/TARGETS
@@ -0,0 +1,7 @@
+{ "defaults":
+ { "type": ["CC/foreign", "defaults"]
+ , "MAKE": ["make"]
+ , "CMAKE": ["cmake"]
+ , "PATH": ["/bin", "/usr/bin"]
+ }
+}
diff --git a/rules/CC/foreign/cmake/EXPRESSIONS b/rules/CC/foreign/cmake/EXPRESSIONS
new file mode 100644
index 0000000..e0ceab2
--- /dev/null
+++ b/rules/CC/foreign/cmake/EXPRESSIONS
@@ -0,0 +1,484 @@
+{ "cmake-build":
+ { "vars":
+ [ "ARCH"
+ , "HOST_ARCH"
+ , "source_dir"
+ , "cmake_subdir"
+ , "localbase_dir"
+ , "cmake_options"
+ , "cmake_defines"
+ , "cmake_jobs"
+ , "cmake_targets"
+ , "pre_cmds"
+ , "post_cmds"
+ , "CC"
+ , "CXX"
+ , "CFLAGS"
+ , "CXXFLAGS"
+ , "LDFLAGS"
+ , "ADD_CFLAGS"
+ , "ADD_CXXFLAGS"
+ , "ADD_LDFLAGS"
+ , "ENV"
+ , "AR"
+ , "BUILD_POSITION_INDEPENDENT"
+ , "defaults-transition"
+ , "expand_exec"
+ , "TIMEOUT_SCALE"
+ , "FOREIGN_EXECUTION_PROPERTIES"
+ , "resolve_symlinks"
+ ]
+ , "imports":
+ { "artifacts": ["", "field_artifacts"]
+ , "flags-cc": ["CC", "flags-cc"]
+ , "flags-cxx": ["CC", "flags-cxx"]
+ , "compiler-cc": ["CC", "compiler-cc"]
+ , "compiler-cxx": ["CC", "compiler-cxx"]
+ , "default-LDFLAGS": ["CC", "default-LDFLAGS"]
+ , "default-AR": ["CC", "default-AR"]
+ , "default-ENV": ["CC", "default-ENV"]
+ , "default-PATH": ["CC", "default-PATH"]
+ , "default-TOOLCHAIN": ["CC", "default-TOOLCHAIN"]
+ , "default-NON_SYSTEM_TOOLS": ["CC", "default-NON_SYSTEM_TOOLS"]
+ , "foreign-MAKE": ["CC/foreign", "default-MAKE"]
+ , "foreign-CMAKE": ["CC/foreign", "default-CMAKE"]
+ , "foreign-ENV": ["CC/foreign", "default-ENV"]
+ , "foreign-PATH": ["CC/foreign", "default-PATH"]
+ , "foreign-TOOLCHAIN": ["CC/foreign", "default-TOOLCHAIN"]
+ , "foreign-NON_SYSTEM_TOOLS": ["CC/foreign", "default-NON_SYSTEM_TOOLS"]
+ , "map_provider": ["", "field_map_provider"]
+ , "sh": ["shell", "sh"]
+ , "sh-PATH": ["shell", "PATH"]
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["TOOLCHAIN_DIR", "toolchain"]
+ , [ "shell TOOLCHAIN"
+ , { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "shell defaults"]
+ , ["provider", "TOOLCHAIN"]
+ , ["default", {"type": "empty_map"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "map_provider"}
+ }
+ ]
+ , [ "sh"
+ , { "type": "let*"
+ , "bindings": [["fieldname", "shell defaults"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "sh"}
+ }
+ ]
+ , [ "TOOLCHAIN"
+ , { "type": "disjoint_map_union"
+ , "msg": "Toolchain trees may not overlap"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "foreign-TOOLCHAIN"}
+ , {"type": "CALL_EXPRESSION", "name": "default-TOOLCHAIN"}
+ , {"type": "var", "name": "shell TOOLCHAIN"}
+ ]
+ }
+ ]
+ , [ "TOOLCHAIN"
+ , { "type": "to_subdir"
+ , "subdir": {"type": "var", "name": "TOOLCHAIN_DIR"}
+ , "$1": {"type": "var", "name": "TOOLCHAIN"}
+ }
+ ]
+ , [ "NON_SYSTEM_TOOLS"
+ , { "type": "map_union"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "foreign-NON_SYSTEM_TOOLS"}
+ , {"type": "CALL_EXPRESSION", "name": "default-NON_SYSTEM_TOOLS"}
+ ]
+ }
+ ]
+ , [ "CMAKE_FLAGS"
+ , { "type": "++"
+ , "$1":
+ [ { "type": "foreach"
+ , "var": "define"
+ , "range": {"type": "var", "name": "cmake_defines"}
+ , "body":
+ { "type": "join"
+ , "$1": ["-D", {"type": "var", "name": "define"}]
+ }
+ }
+ , {"type": "var", "name": "cmake_options"}
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "BUILD_POSITION_INDEPENDENT"}
+ , "then": ["-DCMAKE_POSITION_INDEPENDENT_CODE=ON"]
+ }
+ , ["-DCMAKE_INSTALL_RPATH=$ORIGIN;$ORIGIN/../lib"]
+ ]
+ }
+ ]
+ , ["BUILD_POSITION_INDEPENDENT", null]
+ , [ "MAKE"
+ , { "type": "join"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ { "type": "if"
+ , "cond":
+ { "type": "lookup"
+ , "key": "MAKE"
+ , "map": {"type": "var", "name": "NON_SYSTEM_TOOLS"}
+ }
+ , "then": ["./", {"type": "var", "name": "TOOLCHAIN_DIR"}, "/"]
+ }
+ , {"type": "CALL_EXPRESSION", "name": "foreign-MAKE"}
+ ]
+ }
+ }
+ ]
+ , [ "CMAKE"
+ , { "type": "join"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ { "type": "if"
+ , "cond":
+ { "type": "lookup"
+ , "key": "CMAKE"
+ , "map": {"type": "var", "name": "NON_SYSTEM_TOOLS"}
+ }
+ , "then": ["./", {"type": "var", "name": "TOOLCHAIN_DIR"}, "/"]
+ }
+ , {"type": "CALL_EXPRESSION", "name": "foreign-CMAKE"}
+ ]
+ }
+ }
+ ]
+ , ["CC", {"type": "CALL_EXPRESSION", "name": "compiler-cc"}]
+ , ["CXX", {"type": "CALL_EXPRESSION", "name": "compiler-cxx"}]
+ , [ "CFLAGS"
+ , { "type": "join"
+ , "separator": " "
+ , "$1": {"type": "CALL_EXPRESSION", "name": "flags-cc"}
+ }
+ ]
+ , [ "CXXFLAGS"
+ , { "type": "join"
+ , "separator": " "
+ , "$1": {"type": "CALL_EXPRESSION", "name": "flags-cxx"}
+ }
+ ]
+ , [ "LDFLAGS"
+ , { "type": "join"
+ , "separator": " "
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ { "type": "var"
+ , "name": "LDFLAGS"
+ , "default":
+ {"type": "CALL_EXPRESSION", "name": "default-LDFLAGS"}
+ }
+ , {"type": "var", "name": "ldflags", "default": []}
+ ]
+ }
+ }
+ ]
+ , [ "AR"
+ , { "type": "var"
+ , "name": "AR"
+ , "default":
+ { "type": "join"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ { "type": "if"
+ , "cond":
+ { "type": "lookup"
+ , "key": "AR"
+ , "map": {"type": "var", "name": "NON_SYSTEM_TOOLS"}
+ }
+ , "then":
+ ["./", {"type": "var", "name": "TOOLCHAIN_DIR"}, "/"]
+ }
+ , {"type": "CALL_EXPRESSION", "name": "default-AR"}
+ ]
+ }
+ }
+ }
+ ]
+ , [ "sh-PATH"
+ , { "type": "join"
+ , "separator": ":"
+ , "$1":
+ { "type": "let*"
+ , "bindings": [["fieldname", "shell defaults"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "sh-PATH"}
+ }
+ }
+ ]
+ , [ "sh-ENV"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "sh-PATH"}
+ , "then":
+ { "type": "singleton_map"
+ , "key": "PATH"
+ , "value": {"type": "var", "name": "sh-PATH"}
+ }
+ , "else": {"type": "empty_map"}
+ }
+ ]
+ , [ "PATH"
+ , { "type": "join"
+ , "separator": ":"
+ , "$1":
+ { "type": "nub_left"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "foreign-PATH"}
+ , {"type": "CALL_EXPRESSION", "name": "default-PATH"}
+ ]
+ }
+ }
+ }
+ ]
+ , [ "ENV"
+ , { "type": "map_union"
+ , "$1":
+ [ { "type": "env"
+ , "vars":
+ [ "CC"
+ , "CXX"
+ , "CXXFLAGS"
+ , "CFLAGS"
+ , "LDFLAGS"
+ , "AR"
+ , "MAKE"
+ , "CMAKE"
+ ]
+ }
+ , {"type": "var", "name": "sh-ENV"}
+ , {"type": "CALL_EXPRESSION", "name": "default-ENV"}
+ , {"type": "CALL_EXPRESSION", "name": "foreign-ENV"}
+ , {"type": "var", "name": "ENV", "default": {"type": "empty_map"}}
+ ]
+ }
+ ]
+ , [ "CMAKE_JOBS"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "cmake_jobs"}
+ , "then":
+ [ { "type": "join"
+ , "$1":
+ [ "CMAKE_BUILD_PARALLEL_LEVEL="
+ , { "type": "join_cmd"
+ , "$1": {"type": "var", "name": "cmake_jobs"}
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ , [ "CMAKE_SUBDIR"
+ , { "type": "join"
+ , "separator": "/"
+ , "$1": {"type": "var", "name": "cmake_subdir", "default": []}
+ }
+ ]
+ , [ "cmake_targets"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "cmake_targets"}
+ , "then": {"type": "var", "name": "cmake_targets"}
+ , "else": ["install"]
+ }
+ ]
+ , [ "script"
+ , { "type": "singleton_map"
+ , "key": "run_cmake.sh"
+ , "value":
+ { "type": "BLOB"
+ , "data":
+ { "type": "join"
+ , "separator": "\n"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ [ "set -eu"
+ , "mkdir scratch"
+ , "readonly ROOT=\"$(pwd)\""
+ , "export TMPDIR=\"$(pwd)/scratch\""
+ , "export TOOLCHAIN=\"$(pwd)/toolchain\""
+ , "export LOCALBASE=\"$(pwd)/localbase\""
+ , { "type": "if"
+ , "cond":
+ { "type": "lookup"
+ , "key": "CC"
+ , "map": {"type": "var", "name": "NON_SYSTEM_TOOLS"}
+ }
+ , "then": "export CC=$(pwd)/${CC}"
+ , "else": ""
+ }
+ , { "type": "if"
+ , "cond":
+ { "type": "lookup"
+ , "key": "CXX"
+ , "map": {"type": "var", "name": "NON_SYSTEM_TOOLS"}
+ }
+ , "then": "export CXX=$(pwd)/${CXX}"
+ , "else": ""
+ }
+ , { "type": "if"
+ , "cond":
+ { "type": "lookup"
+ , "key": "AR"
+ , "map": {"type": "var", "name": "NON_SYSTEM_TOOLS"}
+ }
+ , "then": "export AR=$(pwd)/${AR}"
+ , "else": ""
+ }
+ , { "type": "if"
+ , "cond":
+ { "type": "lookup"
+ , "key": "MAKE"
+ , "map": {"type": "var", "name": "NON_SYSTEM_TOOLS"}
+ }
+ , "then": "export MAKE=$(pwd)/${MAKE}"
+ , "else": ""
+ }
+ , { "type": "if"
+ , "cond":
+ { "type": "lookup"
+ , "key": "CMAKE"
+ , "map": {"type": "var", "name": "NON_SYSTEM_TOOLS"}
+ }
+ , "then": "export CMAKE=$(pwd)/${CMAKE}"
+ , "else": ""
+ }
+ , { "type": "join"
+ , "$1":
+ [ "export PATH="
+ , { "type": "join_cmd"
+ , "$1": [{"type": "var", "name": "PATH"}]
+ }
+ , "${PATH:+:}\"${PATH}\""
+ ]
+ }
+ ]
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "pre_cmds"}
+ , "then":
+ { "type": "++"
+ , "$1":
+ [ ["(", "set --", "cd ./source"]
+ , {"type": "var", "name": "pre_cmds"}
+ , [")"]
+ ]
+ }
+ }
+ , [ "readonly CMAKE_SUBDIR=\"$1\""
+ , "readonly CMAKE_AR=$(command -v $2)"
+ , "shift 2"
+ ]
+ , [ { "type": "join"
+ , "separator": " "
+ , "$1":
+ [ "${ROOT}/expand_exec TMPDIR LOCALBASE CC CXX CFLAGS CXXFLAGS LDFLAGS AR"
+ , "--"
+ , "${CMAKE} -S\"source/${CMAKE_SUBDIR}\" -Bbuild"
+ , "-DCMAKE_MAKE_PROGRAM=${MAKE}"
+ , "-DCMAKE_AR=${CMAKE_AR}"
+ , "-DCMAKE_INSTALL_PREFIX=./install"
+ , "-DCMAKE_PREFIX_PATH=\"$(pwd)/localbase\""
+ , "-DPKG_CONFIG_ARGN=--define-prefix"
+ , "--no-warn-unused-cli"
+ , "\"$@\""
+ , ">configure.log 2>&1 || (cat configure.log && exit 1)"
+ ]
+ }
+ ]
+ , { "type": "foreach"
+ , "range": {"type": "var", "name": "cmake_targets"}
+ , "var": "target"
+ , "body":
+ { "type": "join"
+ , "separator": " "
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "var", "name": "CMAKE_JOBS"}
+ , [ "${ROOT}/expand_exec TMPDIR LOCALBASE CC CXX CFLAGS CXXFLAGS LDFLAGS AR"
+ , "--"
+ , "${CMAKE} --build build --target"
+ , { "type": "join_cmd"
+ , "$1": [{"type": "var", "name": "target"}]
+ }
+ , ">>build.log 2>&1 || (cat configure.log build.log && exit 1)"
+ ]
+ ]
+ }
+ }
+ }
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "resolve_symlinks"}
+ , "then":
+ [ "mv install install_with_symlinks"
+ , "cp -rL install_with_symlinks install >copy.log 2>&1 || (echo 'ERROR: symlink resolve failed with:' && cat copy.log && exit 1)"
+ ]
+ }
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "post_cmds"}
+ , "then":
+ { "type": "++"
+ , "$1":
+ [ [ "("
+ , "set --"
+ , "readonly CMAKE_SOURCE_DIR=\"$(pwd)/source\""
+ , "readonly CMAKE_BINARY_DIR=\"$(pwd)/build\""
+ , "cd ./install"
+ ]
+ , {"type": "var", "name": "post_cmds"}
+ , [")"]
+ ]
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ ]
+ ]
+ , "body":
+ { "type": "ACTION"
+ , "inputs":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "TOOLCHAIN"}
+ , {"type": "var", "name": "source_dir"}
+ , {"type": "var", "name": "expand_exec"}
+ , { "type": "var"
+ , "name": "localbase_dir"
+ , "default": {"type": "empty_map"}
+ }
+ , {"type": "var", "name": "script"}
+ ]
+ }
+ , "cmd":
+ { "type": "++"
+ , "$1":
+ [ [ {"type": "var", "name": "sh"}
+ , "run_cmake.sh"
+ , {"type": "var", "name": "CMAKE_SUBDIR"}
+ , {"type": "var", "name": "AR"}
+ ]
+ , {"type": "var", "name": "CMAKE_FLAGS"}
+ ]
+ }
+ , "out_dirs": ["install"]
+ , "env": {"type": "var", "name": "ENV"}
+ , "timeout scaling":
+ {"type": "var", "name": "TIMEOUT_SCALE", "default": 10.0}
+ , "execution properties":
+ {"type": "var", "name": "FOREIGN_EXECUTION_PROPERTIES"}
+ }
+ }
+ }
+}
diff --git a/rules/CC/foreign/cmake/RULES b/rules/CC/foreign/cmake/RULES
new file mode 100644
index 0000000..917b4af
--- /dev/null
+++ b/rules/CC/foreign/cmake/RULES
@@ -0,0 +1,772 @@
+{ "data":
+ { "doc":
+ [ "Data produced by CMake configure, build, and install."
+ , ""
+ , "All variables accessible to commands and options are: \"TMPDIR\","
+ , "\"LOCALBASE\", \"CC\", \"CXX\", \"CFLAGS\", \"CXXFLAGS\", \"LDFLAGS\","
+ , "and \"AR\". \"LOCALBASE\" contains the path to the installed artifacts"
+ , "from \"deps\"."
+ ]
+ , "target_fields": ["project"]
+ , "string_fields":
+ [ "subdir"
+ , "options"
+ , "defines"
+ , "targets"
+ , "jobs"
+ , "pre_cmds"
+ , "post_cmds"
+ , "out_files"
+ , "out_dirs"
+ , "resolve_symlinks"
+ ]
+ , "config_vars":
+ [ "ARCH"
+ , "HOST_ARCH"
+ , "CC"
+ , "CXX"
+ , "CFLAGS"
+ , "CXXFLAGS"
+ , "LDFLAGS"
+ , "ADD_CFLAGS"
+ , "ADD_CXXFLAGS"
+ , "ADD_LDFLAGS"
+ , "ENV"
+ , "AR"
+ , "BUILD_POSITION_INDEPENDENT"
+ , "TIMEOUT_SCALE"
+ , "FOREIGN_EXECUTION_PROPERTIES"
+ ]
+ , "implicit":
+ { "defaults": [["CC", "defaults"]]
+ , "foreign-defaults": [["CC/foreign", "defaults"]]
+ , "shell defaults": [["shell", "defaults"]]
+ , "expand_exec": [["./", "..", "expand_exec"]]
+ }
+ , "field_doc":
+ { "project":
+ ["The CMake project directory. It should contain a single tree artifact"]
+ , "subdir":
+ [ "The subdirectory that contains the entry CMakeLists.txt. Individual"
+ , "directory components are joined with \"/\"."
+ ]
+ , "options":
+ [ "CMake options for the configuration phase."
+ , "(e.g., [\"-GNinja\", \"-Ax64\"])"
+ ]
+ , "defines":
+ [ "CMake defines for the configuration phase."
+ , "(e.g., [\"CMAKE_BUILD_TYPE=Release\"])"
+ ]
+ , "targets":
+ [ "The CMake targets to build in the specified order"
+ , "(default: [\"install\"])."
+ ]
+ , "jobs":
+ [ "Number of jobs to run simultaneously. If omitted, CMake's default"
+ , "number is used."
+ ]
+ , "pre_cmds":
+ [ "List of commands executed in the project directory before calling"
+ , "CMake. Useful for renaming files or directories. Note that data"
+ , "between \"pre_cmds\" and \"post_cmds\" can be exchanged via"
+ , "\"$TMPDIR\" which is uniquely reserved for this action."
+ ]
+ , "post_cmds":
+ [ "List of commands executed in the install directory after successful"
+ , "installation but before the output files are collected. Useful for"
+ , "renaming files or directories. Note that data between \"pre_cmds\" and"
+ , "\"post_cmds\" can be exchanged via \"$TMPDIR\", which is uniquely"
+ , "reserved for this action. The CMake source and build directory can be"
+ , "accessed via \"$CMAKE_SOURCE_DIR\" and \"$CMAKE_BINARY_DIR\","
+ , "respectively."
+ ]
+ , "resolve_symlinks":
+ [ "Resolve all symlinks in the install directory. This operation is"
+ , "performed immediately after the install, before \"post_cmds\" are run."
+ ]
+ , "out_files":
+ [ "Paths to the produced output files. The paths are considered relative"
+ , "to the install directory."
+ , "Note that \"out_files\" and \"out_dirs\" may not overlap."
+ ]
+ , "out_dirs":
+ [ "Paths to the produced output directories. The paths are considered"
+ , "relative to the install directory."
+ , "Note that \"out_files\" and \"out_dirs\" may not overlap."
+ ]
+ }
+ , "config_doc":
+ { "CC":
+ [ "The name of the C compiler to be used."
+ , "If null, the respective value from [\"CC\", \"defaults\"] will be taken."
+ ]
+ , "CXX":
+ [ "The name of the C++ compiler to be used."
+ , "If null, 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 linked 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 linked in a non-standard way; usually"
+ , "adapting the default target [\"CC\", \"defaults\"] is the better"
+ , "choice."
+ ]
+ , "ENV":
+ [ "The environment for any action generated."
+ , "If null, the respective value from [\"CC\", \"defaults\"] will be taken."
+ ]
+ , "AR":
+ [ "The archive tool to used for creating the library."
+ , "If null, the respective value from [\"CC\", \"defaults\"] will be taken."
+ ]
+ , "BUILD_POSITION_INDEPENDENT": ["Build position independent code."]
+ , "TIMEOUT_SCALE":
+ [ "The scaling of the timeout for the invocation of the foreign build."
+ , "Defaults to 10."
+ ]
+ , "FOREIGN_EXECUTION_PROPERTIES":
+ [ "A map with extra remote-execution properties to be added to the foreign build action."
+ ]
+ }
+ , "imports":
+ { "stage_field": ["", "stage_singleton_field"]
+ , "cmake-build": "cmake-build"
+ , "strip-prefix": ["./", "..", "strip-prefix"]
+ , "for host": ["transitions", "for host"]
+ , "map_provider": ["", "field_map_provider"]
+ , "sh": ["shell", "sh"]
+ }
+ , "config_transitions":
+ { "defaults":
+ [{"type": "empty_map"}, {"type": "CALL_EXPRESSION", "name": "for host"}]
+ , "expand_exec": [{"type": "CALL_EXPRESSION", "name": "for host"}]
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["install_prefix", "install"]
+ , [ "source_dir"
+ , { "type": "let*"
+ , "bindings": [["fieldname", "project"], ["location", "source"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "stage_field"}
+ }
+ ]
+ , [ "installed_out_files"
+ , { "type": "foreach"
+ , "var": "file_path"
+ , "range": {"type": "FIELD", "name": "out_files"}
+ , "body":
+ { "type": "join"
+ , "separator": "/"
+ , "$1":
+ [ {"type": "var", "name": "install_prefix"}
+ , {"type": "var", "name": "file_path"}
+ ]
+ }
+ }
+ ]
+ , [ "installed_out_dirs"
+ , { "type": "foreach"
+ , "var": "dir_path"
+ , "range": {"type": "FIELD", "name": "out_dirs"}
+ , "body":
+ { "type": "join"
+ , "separator": "/"
+ , "$1":
+ [ {"type": "var", "name": "install_prefix"}
+ , {"type": "var", "name": "dir_path"}
+ ]
+ }
+ }
+ ]
+ , ["cmake_subdir", {"type": "FIELD", "name": "subdir"}]
+ , ["cmake_options", {"type": "FIELD", "name": "options"}]
+ , ["cmake_defines", {"type": "FIELD", "name": "defines"}]
+ , ["cmake_targets", {"type": "FIELD", "name": "targets"}]
+ , ["cmake_jobs", {"type": "FIELD", "name": "jobs"}]
+ , ["pre_cmds", {"type": "FIELD", "name": "pre_cmds"}]
+ , ["post_cmds", {"type": "FIELD", "name": "post_cmds"}]
+ , ["resolve_symlinks", {"type": "FIELD", "name": "resolve_symlinks"}]
+ , ["defaults-transition", {"type": "empty_map"}]
+ , [ "expand_exec"
+ , { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "expand_exec"]
+ , ["location", "expand_exec"]
+ , ["transition", {"type": "CALL_EXPRESSION", "name": "for host"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "stage_field"}
+ }
+ ]
+ , [ "full_install_dir"
+ , {"type": "CALL_EXPRESSION", "name": "cmake-build"}
+ ]
+ , ["TOOLCHAIN_DIR", "toolchain"]
+ , [ "shell TOOLCHAIN"
+ , { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "shell defaults"]
+ , ["provider", "TOOLCHAIN"]
+ , ["default", {"type": "empty_map"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "map_provider"}
+ }
+ ]
+ , [ "sh"
+ , { "type": "let*"
+ , "bindings": [["fieldname", "shell defaults"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "sh"}
+ }
+ ]
+ , [ "install_dir"
+ , { "type": "ACTION"
+ , "inputs":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "shell TOOLCHAIN"}
+ , {"type": "var", "name": "full_install_dir"}
+ ]
+ }
+ , "cmd": [{"type": "var", "name": "sh"}, "-c", ":"]
+ , "outs": {"type": "var", "name": "installed_out_files"}
+ , "out_dirs": {"type": "var", "name": "installed_out_dirs"}
+ }
+ ]
+ , [ "out_files"
+ , { "type": "let*"
+ , "bindings":
+ [ ["artifacts", {"type": "var", "name": "install_dir"}]
+ , ["paths", {"type": "FIELD", "name": "out_files"}]
+ , ["prefix", {"type": "var", "name": "install_prefix"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "strip-prefix"}
+ }
+ ]
+ , [ "out_dirs"
+ , { "type": "let*"
+ , "bindings":
+ [ ["artifacts", {"type": "var", "name": "install_dir"}]
+ , ["paths", {"type": "FIELD", "name": "out_dirs"}]
+ , ["prefix", {"type": "var", "name": "install_prefix"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "strip-prefix"}
+ }
+ ]
+ ]
+ , "body":
+ { "type": "RESULT"
+ , "artifacts":
+ { "type": "map_union"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "var", "name": "out_files"}
+ , {"type": "var", "name": "out_dirs"}
+ ]
+ }
+ }
+ }
+ }
+ }
+, "library":
+ { "doc":
+ [ "Library produced by CMake configure, build, and install."
+ , ""
+ , "All variables accessible to commands and options are: \"TMPDIR\","
+ , "\"LOCALBASE\", \"CC\", \"CXX\", \"CFLAGS\", \"CXXFLAGS\", \"LDFLAGS\","
+ , "and \"AR\". \"LOCALBASE\" contains the path to the installed artifacts"
+ , "from \"deps\"."
+ ]
+ , "target_fields": ["project", "deps"]
+ , "string_fields":
+ [ "subdir"
+ , "name"
+ , "version"
+ , "stage"
+ , "options"
+ , "defines"
+ , "jobs"
+ , "pre_cmds"
+ , "post_cmds"
+ , "out_hdrs"
+ , "out_hdr_dirs"
+ , "out_libs"
+ , "cflags"
+ , "ldflags"
+ , "pkg-config"
+ , "hdr_prefix"
+ , "lib_prefix"
+ , "pc_prefix"
+ , "resolve_symlinks"
+ ]
+ , "config_vars":
+ [ "ARCH"
+ , "HOST_ARCH"
+ , "CC"
+ , "CXX"
+ , "CFLAGS"
+ , "CXXFLAGS"
+ , "LDFLAGS"
+ , "ADD_CFLAGS"
+ , "ADD_CXXFLAGS"
+ , "ADD_LDFLAGS"
+ , "ENV"
+ , "AR"
+ , "BUILD_POSITION_INDEPENDENT"
+ , "TIMEOUT_SCALE"
+ , "FOREIGN_EXECUTION_PROPERTIES"
+ ]
+ , "implicit":
+ { "defaults": [["CC", "defaults"]]
+ , "foreign-defaults": [["CC/foreign", "defaults"]]
+ , "shell defaults": [["shell", "defaults"]]
+ , "config_reader": [["CC", "prebuilt/read_pkgconfig.py"]]
+ , "expand_exec": [["./", "..", "expand_exec"]]
+ }
+ , "field_doc":
+ { "project":
+ ["The CMake project directory. It should contain a single tree artifact"]
+ , "subdir":
+ [ "The subdirectory that contains the entry CMakeLists.txt. Individual"
+ , "directory components are joined with \"/\"."
+ ]
+ , "name":
+ [ "The name of the library (without leading \"lib\" or trailing file name"
+ , "extension), also used as name for pkg-config files."
+ ]
+ , "version":
+ [ "The library version, used for pkg-config files. Individual version"
+ , "components are joined with \".\"."
+ ]
+ , "options":
+ [ "CMake options for the configuration phase"
+ , "(e.g., [\"-GNinja\", \"-Ax64\"]). Variables can be accessed via"
+ , "\"$(<varname>)\", e.g., \"$(TMPDIR)\" for variable \"$TMPDIR\"."
+ ]
+ , "defines":
+ [ "CMake defines for the configuration phase"
+ , "(e.g., [\"CMAKE_BUILD_TYPE=Release\"]). Variables can be accessed via"
+ , "\"$(<varname>)\", e.g., \"$(TMPDIR)\" for variable \"$TMPDIR\"."
+ ]
+ , "jobs":
+ [ "Number of jobs to run simultaneously. If omitted, CMake's default"
+ , "number is used."
+ ]
+ , "pre_cmds":
+ [ "List of commands executed in the project directory before calling"
+ , "CMake. Useful for renaming files or directories. Note that data"
+ , "between \"pre_cmds\" and \"post_cmds\" can be exchanged via"
+ , "\"$TMPDIR\" which is uniquely reserved for this action."
+ ]
+ , "post_cmds":
+ [ "List of commands executed in the install directory after successful"
+ , "installation but before the output files are collected. Useful for"
+ , "renaming files or directories (e.g., in case of SONAME mismatch). Note"
+ , "that data between \"pre_cmds\" and \"post_cmds\" can be exchanged via"
+ , "\"$TMPDIR\", which is uniquely reserved for this action. The CMake"
+ , "source and build directory can be accessed via \"$CMAKE_SOURCE_DIR\""
+ , "and \"$CMAKE_BINARY_DIR\", respectively."
+ ]
+ , "resolve_symlinks":
+ [ "Resolve all symlinks in the install directory. This operation is"
+ , "performed immediately after the install, before \"post_cmds\" are run."
+ ]
+ , "out_hdrs":
+ [ "Paths to produced public header files. The path is considered"
+ , "relative to the include directory, which be set via \"hdr_prefix\"."
+ , "Note that \"out_hdrs\" and \"out_hdr_dirs\" may not overlap."
+ ]
+ , "out_hdr_dirs":
+ [ "Paths to produced public header directories. The path is considered"
+ , "relative to the include directory, which be set via \"hdr_prefix\"."
+ , "Note that \"out_hdrs\" and \"out_hdr_dirs\" may not overlap."
+ ]
+ , "out_libs":
+ [ "Paths to produced library files. The path is considered relative"
+ , "to the library directory, which be set via \"lib_prefix\"."
+ , "Order matters in the case of one library depending on another."
+ ]
+ , "cflags":
+ ["List of compile flags set for this target and its consumers."]
+ , "ldflags":
+ [ "Additional linker flags that are required for the consumer of the"
+ , "produced libraries."
+ ]
+ , "stage":
+ [ "The logical location of the public headers and library files."
+ , "Individual directory components are joined with \"/\"."
+ ]
+ , "deps": ["Public dependency on other CC libraries."]
+ , "pkg-config":
+ [ "Pkg-config file for optional infer of public cflags and ldflags. If"
+ , "multiple files are specified (e.g., one depends on the other), the"
+ , "first one is used as entry. Note that if this field is non-empty the"
+ , "tool \"pkg-config\" must be available in \"PATH\", which is taken"
+ , "from [\"CC\", \"defaults\"] or the \"ENV\" variable."
+ ]
+ , "hdr_prefix":
+ [ "Prefix where headers will be installed by CMake. Individual directory"
+ , "components are joined with \"/\". Defaults to \"include\" if not set."
+ ]
+ , "lib_prefix":
+ [ "Prefix where libraries will be installed by CMake. Individual"
+ , "directory components are joined with \"/\". Defaults to \"lib\" if"
+ , "not set."
+ ]
+ , "pc_prefix":
+ [ "Prefix where pkg-config files will be installed by CMake. Individual"
+ , "directory components are joined with \"/\". Defaults to"
+ , "\"lib/pkgconfig\" if not set."
+ ]
+ }
+ , "config_doc":
+ { "CC":
+ [ "The name of the C compiler to be used."
+ , "If null, the respective value from [\"CC\", \"defaults\"] will be taken."
+ ]
+ , "CXX":
+ [ "The name of the C++ compiler to be used."
+ , "If null, 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":
+ ["Global ld flags, for common link args,such as -Wl,-z,noexecstack"]
+ , "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 linked in a non-standard way; usually"
+ , "adapting the default target [\"CC\", \"defaults\"] is the better"
+ , "choice."
+ ]
+ , "ENV":
+ [ "The environment for any action generated."
+ , "If null, the respective value from [\"CC\", \"defaults\"] will be taken."
+ ]
+ , "AR":
+ [ "The archive tool to used for creating the library"
+ , "If null, the respective value from [\"CC\", \"defaults\"] will be taken."
+ ]
+ , "BUILD_POSITION_INDEPENDENT": ["Build position independent code."]
+ , "TIMEOUT_SCALE":
+ [ "The scaling of the timeout for the invocation of the foreign build."
+ , "Defaults to 10."
+ ]
+ , "FOREIGN_EXECUTION_PROPERTIES":
+ [ "A map with extra remote-execution properties to be added to the foreign build action."
+ ]
+ }
+ , "imports":
+ { "stage_field": ["", "stage_singleton_field"]
+ , "cmake-build": "cmake-build"
+ , "strip-prefix": ["./", "..", "strip-prefix"]
+ , "prebuilt result": ["CC/prebuilt", "prebuilt result"]
+ , "install-deps": ["CC", "install-with-deps stage"]
+ , "for host": ["transitions", "for host"]
+ , "map_provider": ["", "field_map_provider"]
+ , "sh": ["shell", "sh"]
+ }
+ , "config_transitions":
+ { "defaults":
+ [{"type": "empty_map"}, {"type": "CALL_EXPRESSION", "name": "for host"}]
+ , "expand_exec": [{"type": "CALL_EXPRESSION", "name": "for host"}]
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ [ "hdr_prefix"
+ , { "type": "join"
+ , "separator": "/"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ ["install"]
+ , { "type": "if"
+ , "cond": {"type": "FIELD", "name": "hdr_prefix"}
+ , "then": {"type": "FIELD", "name": "hdr_prefix"}
+ , "else": ["include"]
+ }
+ ]
+ }
+ }
+ ]
+ , [ "lib_prefix"
+ , { "type": "join"
+ , "separator": "/"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ ["install"]
+ , { "type": "if"
+ , "cond": {"type": "FIELD", "name": "lib_prefix"}
+ , "then": {"type": "FIELD", "name": "lib_prefix"}
+ , "else": ["lib"]
+ }
+ ]
+ }
+ }
+ ]
+ , [ "pc_prefix"
+ , { "type": "join"
+ , "separator": "/"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ ["install"]
+ , { "type": "if"
+ , "cond": {"type": "FIELD", "name": "pc_prefix"}
+ , "then": {"type": "FIELD", "name": "pc_prefix"}
+ , "else": ["lib", "pkgconfig"]
+ }
+ ]
+ }
+ }
+ ]
+ , [ "source_dir"
+ , { "type": "let*"
+ , "bindings": [["fieldname", "project"], ["location", "source"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "stage_field"}
+ }
+ ]
+ , [ "localbase_dir"
+ , { "type": "to_subdir"
+ , "subdir": "localbase"
+ , "msg": "dependency installation files may not overlap"
+ , "$1":
+ { "type": "let*"
+ , "bindings":
+ [ ["pc-install-dir", "lib/pkgconfig"]
+ , ["targets", {"type": "FIELD", "name": "deps"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "install-deps"}
+ }
+ }
+ ]
+ , [ "installed_dirs"
+ , { "type": "foreach"
+ , "var": "dir_path"
+ , "range": {"type": "FIELD", "name": "out_hdr_dirs"}
+ , "body":
+ { "type": "join"
+ , "separator": "/"
+ , "$1":
+ [ {"type": "var", "name": "hdr_prefix"}
+ , {"type": "var", "name": "dir_path"}
+ ]
+ }
+ }
+ ]
+ , [ "installed_files"
+ , { "type": "++"
+ , "$1":
+ [ { "type": "foreach"
+ , "var": "lib_path"
+ , "range": {"type": "FIELD", "name": "out_libs"}
+ , "body":
+ { "type": "join"
+ , "separator": "/"
+ , "$1":
+ [ {"type": "var", "name": "lib_prefix"}
+ , {"type": "var", "name": "lib_path"}
+ ]
+ }
+ }
+ , { "type": "foreach"
+ , "var": "hdr_path"
+ , "range": {"type": "FIELD", "name": "out_hdrs"}
+ , "body":
+ { "type": "join"
+ , "separator": "/"
+ , "$1":
+ [ {"type": "var", "name": "hdr_prefix"}
+ , {"type": "var", "name": "hdr_path"}
+ ]
+ }
+ }
+ , { "type": "foreach"
+ , "var": "pc_path"
+ , "range": {"type": "FIELD", "name": "pkg-config"}
+ , "body":
+ { "type": "join"
+ , "separator": "/"
+ , "$1":
+ [ {"type": "var", "name": "pc_prefix"}
+ , {"type": "var", "name": "pc_path"}
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ , ["cmake_subdir", {"type": "FIELD", "name": "subdir"}]
+ , ["cmake_options", {"type": "FIELD", "name": "options"}]
+ , ["cmake_defines", {"type": "FIELD", "name": "defines"}]
+ , ["cmake_jobs", {"type": "FIELD", "name": "jobs"}]
+ , ["pre_cmds", {"type": "FIELD", "name": "pre_cmds"}]
+ , ["post_cmds", {"type": "FIELD", "name": "post_cmds"}]
+ , ["resolve_symlinks", {"type": "FIELD", "name": "resolve_symlinks"}]
+ , ["defaults-transition", {"type": "empty_map"}]
+ , [ "expand_exec"
+ , { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "expand_exec"]
+ , ["location", "expand_exec"]
+ , ["transition", {"type": "CALL_EXPRESSION", "name": "for host"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "stage_field"}
+ }
+ ]
+ , [ "full_install_dir"
+ , {"type": "CALL_EXPRESSION", "name": "cmake-build"}
+ ]
+ , [ "shell TOOLCHAIN"
+ , { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "shell defaults"]
+ , ["provider", "TOOLCHAIN"]
+ , ["default", {"type": "empty_map"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "map_provider"}
+ }
+ ]
+ , [ "sh"
+ , { "type": "let*"
+ , "bindings": [["fieldname", "shell defaults"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "sh"}
+ }
+ ]
+ , [ "install_dir"
+ , { "type": "ACTION"
+ , "inputs":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "shell TOOLCHAIN"}
+ , {"type": "var", "name": "full_install_dir"}
+ ]
+ }
+ , "cmd": [{"type": "var", "name": "sh"}, "-c", ":"]
+ , "outs": {"type": "var", "name": "installed_files"}
+ , "out_dirs": {"type": "var", "name": "installed_dirs"}
+ }
+ ]
+ , [ "hdrs"
+ , { "type": "++"
+ , "$1":
+ [ { "type": "let*"
+ , "bindings":
+ [ ["artifacts", {"type": "var", "name": "install_dir"}]
+ , ["paths", {"type": "FIELD", "name": "out_hdrs"}]
+ , ["prefix", {"type": "var", "name": "hdr_prefix"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "strip-prefix"}
+ }
+ , { "type": "let*"
+ , "bindings":
+ [ ["artifacts", {"type": "var", "name": "install_dir"}]
+ , ["paths", {"type": "FIELD", "name": "out_hdr_dirs"}]
+ , ["prefix", {"type": "var", "name": "hdr_prefix"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "strip-prefix"}
+ }
+ ]
+ }
+ ]
+ , [ "libs"
+ , { "type": "let*"
+ , "bindings":
+ [ ["artifacts", {"type": "var", "name": "install_dir"}]
+ , ["paths", {"type": "FIELD", "name": "out_libs"}]
+ , ["prefix", {"type": "var", "name": "lib_prefix"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "strip-prefix"}
+ }
+ ]
+ , [ "config_reader"
+ , { "type": "let*"
+ , "bindings":
+ [["fieldname", "config_reader"], ["location", "config_reader"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "stage_field"}
+ }
+ ]
+ , [ "pkg-configs"
+ , { "type": "let*"
+ , "bindings":
+ [ ["artifacts", {"type": "var", "name": "install_dir"}]
+ , ["paths", {"type": "FIELD", "name": "pkg-config"}]
+ , ["prefix", {"type": "var", "name": "pc_prefix"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "strip-prefix"}
+ }
+ ]
+ , [ "name"
+ , { "type": "assert_non_empty"
+ , "msg": "name is required for cmake library"
+ , "$1": {"type": "join", "$1": {"type": "FIELD", "name": "name"}}
+ }
+ ]
+ , ["version", {"type": "FIELD", "name": "version"}]
+ , ["cflags", {"type": "FIELD", "name": "cflags"}]
+ , ["ldflags", {"type": "FIELD", "name": "ldflags"}]
+ , [ "stage"
+ , { "type": "join"
+ , "separator": "/"
+ , "$1": {"type": "FIELD", "name": "stage"}
+ }
+ ]
+ , ["deps-fieldnames", ["deps", "defaults"]]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "prebuilt result"}
+ }
+ }
+}
diff --git a/rules/CC/foreign/expand_exec b/rules/CC/foreign/expand_exec
new file mode 100755
index 0000000..df3000e
--- /dev/null
+++ b/rules/CC/foreign/expand_exec
@@ -0,0 +1,133 @@
+#!/bin/sh
+# Copyright 2023 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.
+
+set -e
+
+check_var_name() {
+ local NAME="$1"
+ if ! expr match "${NAME}" "[A-Z_a-z][0-9A-Z_a-z]*$" >/dev/null; then
+ echo "expand_exec error: invalid variable name '${NAME}'"
+ return 1
+ fi
+ return 0
+}
+
+in_list() {
+ local NAME="$1"
+ local VAR_LIST="$2"
+ check_var_name "${NAME}" && expr match "${NAME}" "\(${VAR_LIST}\)$" >/dev/null
+}
+
+EXPANDED_VAR=
+expand_var() {
+ local NAME="$1"
+ check_var_name "${NAME}" && EXPANDED_VAR="$(eval "printf \"%s\" \"\${$NAME}\"")"
+}
+
+PARSED_ARG=
+parse_arg() {
+ local ARG="$1"
+ local VAR_LIST="$2"
+ local RESULT=""
+ local VAR_NAME=""
+ local PARSE_EXPR=false
+ local PARSE_VAR_NAME=false
+
+ while [ ${#ARG} -gt 0 ]; do
+ local NEXT="${ARG#?}"
+ c="${ARG%"${NEXT}"}"
+ ARG="${NEXT}"
+
+ if $PARSE_VAR_NAME; then
+ # parse <var> from $(<var>)
+ if [ "$c" = ")" ]; then
+ # expand var if in cases list
+ if in_list "${VAR_NAME}" "${VAR_LIST}" && expand_var "${VAR_NAME}"; then
+ RESULT="${RESULT}${EXPANDED_VAR}"
+ else
+ RESULT="${RESULT}\$(${VAR_NAME})"
+ fi
+ VAR_NAME=""
+ PARSE_VAR_NAME=false
+ else
+ # accumulate VAR_NAME
+ VAR_NAME="${VAR_NAME}$c"
+ if [ ${#ARG} -eq 0 ]; then
+ # flush unterminated var name
+ RESULT="${RESULT}\$(${VAR_NAME}"
+ fi
+ fi
+ else
+ # parse single char
+ if $PARSE_EXPR; then
+ if [ "$c" = "(" ]; then
+ # found "$("
+ PARSE_VAR_NAME=true
+ else
+ RESULT="${RESULT}\$$c"
+ fi
+ PARSE_EXPR=false
+ elif [ "$c" = "$" ]; then
+ # found "$"
+ PARSE_EXPR=true
+ else
+ # append char
+ RESULT="${RESULT}$c"
+ fi
+ fi
+ done
+
+ PARSED_ARG="'"
+ while [ ${#RESULT} -gt 0 ]; do
+ local NEXT="${RESULT#?}"
+ c="${RESULT%"${NEXT}"}"
+ RESULT="${NEXT}"
+ if [ "$c" = "'" ]; then
+ PARSED_ARG="${PARSED_ARG}'\\''"
+ else
+ PARSED_ARG="${PARSED_ARG}$c"
+ fi
+ done
+ PARSED_ARG="${PARSED_ARG}'"
+}
+
+# usage: ./expand_exec [VARS...] -- ARGS...
+expand_exec() {
+ local VAR_LIST=""
+ local VAR_SEP=""
+ local EXEC_VEC=""
+ local EXEC_SEP=""
+ local READ_ARGS=false
+
+ while [ "$#" -ge 1 ]; do
+ local ARG="$1";shift
+ if $READ_ARGS; then
+ parse_arg "${ARG}" "${VAR_LIST}"
+ EXEC_VEC="${EXEC_VEC}${EXEC_SEP}${PARSED_ARG}"
+ EXEC_SEP=" "
+ else
+ if [ "${ARG}" = "--" ]; then
+ READ_ARGS=true
+ elif check_var_name "${ARG}"; then
+ VAR_LIST="${VAR_LIST}${VAR_SEP}${ARG}"
+ VAR_SEP="\|"
+ fi
+ fi
+ done
+
+ exec /bin/sh -c "${EXEC_VEC}"
+}
+
+expand_exec "$@"
diff --git a/rules/CC/foreign/expand_exec.c b/rules/CC/foreign/expand_exec.c
new file mode 100644
index 0000000..a4ff311
--- /dev/null
+++ b/rules/CC/foreign/expand_exec.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2023 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.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/* usage: ./expand_exec [VARS...] -- ARGS... */
+int main(int argc, const char *argv[]) {
+ char **outv;
+ const char **varv;
+ int i, j, varc, sep = 0, retval = 0;
+ for (i = 1; i < argc; ++i)
+ if (strcmp(argv[i], "--") == 0) {
+ sep = i;
+ break;
+ }
+ varc = sep - 1;
+ argc -= sep + 1;
+ if (sep == 0 || argc < 1)
+ return 1; /* error: missing sep or args */
+ varv = &argv[1];
+ argv = &argv[sep + 1];
+ outv = (char **)calloc((size_t)(argc + 1), sizeof(char *));
+ for (i = 0; i < argc; ++i) { /* iterate ARGS */
+ const char *arg = argv[i];
+ size_t arg_pos = 0, arg_len = strlen(arg);
+ size_t out_pos = 0, out_len = arg_len;
+ size_t str_pos = 0, str_len = 0;
+ char *out = (char *)calloc((size_t)(out_len + 1), sizeof(char));
+ for (; arg_pos < arg_len; ++arg_pos) {
+ if (strncmp(&arg[arg_pos], "$(", 2) == 0) {
+ const char *start = &arg[arg_pos + 2];
+ const char *end = strchr(start, ')');
+ if (end == NULL) {
+ retval = 2; /* error: unterminated $(VAR) expression */
+ free(out);
+ goto cleanup;
+ }
+ for (j = 0; j < varc; ++j) { /* lookup VAR */
+ const char *var = varv[j];
+ size_t len_var = strlen(var);
+ if ((size_t)(end - start) != len_var)
+ continue;
+ if (strncmp(&arg[arg_pos + 2], var, len_var) == 0) {
+ size_t val_len, out_len_new;
+ const char *val = getenv(var);
+ if (val == NULL)
+ val = "";
+ val_len = strlen(val);
+ out_len_new = out_pos + str_len + val_len;
+ if (out_len_new > out_len) {
+ out = (char *)realloc(out, out_len_new + 1);
+ out_len = out_len_new;
+ }
+ strncat(out, &arg[str_pos], str_len); /* concat preceding substr */
+ strncat(out, val, val_len); /* concat variable value */
+ arg_pos += len_var + 2;
+ out_pos += str_len + val_len;
+ str_pos = arg_pos + 1;
+ str_len = 0;
+ break;
+ }
+ }
+ if (j != varc)
+ continue; /* success */
+ }
+ ++str_len;
+ }
+ if (str_len > 0) {
+ if (out_pos + str_len > out_len) {
+ out = (char *)realloc(out, out_pos + str_len + 1);
+ }
+ strncat(out, &arg[str_pos], str_len);
+ }
+ outv[i] = out;
+ }
+ execvp(outv[0], outv);
+ retval = 3; /* error: exec failed */
+cleanup:
+ for (i = 0; i < argc; ++i)
+ if (outv[i] != NULL)
+ free(outv[i]);
+ free(outv);
+ return retval;
+}
diff --git a/rules/CC/foreign/make/EXPRESSIONS b/rules/CC/foreign/make/EXPRESSIONS
new file mode 100644
index 0000000..57b0a94
--- /dev/null
+++ b/rules/CC/foreign/make/EXPRESSIONS
@@ -0,0 +1,445 @@
+{ "make-build":
+ { "vars":
+ [ "source_dir"
+ , "subdir"
+ , "localbase_dir"
+ , "configure"
+ , "configure_options"
+ , "make_targets"
+ , "make_prefix"
+ , "make_options"
+ , "make_jobs"
+ , "pre_cmds"
+ , "post_cmds"
+ , "CC"
+ , "CXX"
+ , "CFLAGS"
+ , "CXXFLAGS"
+ , "LDFLAGS"
+ , "ADD_CFLAGS"
+ , "ADD_CXXFLAGS"
+ , "ADD_LDFLAGS"
+ , "ENV"
+ , "AR"
+ , "PREFIX"
+ , "BUILD_POSITION_INDEPENDENT"
+ , "TIMEOUT_SCALE"
+ , "defaults-transition"
+ , "expand_exec"
+ , "resolve_symlinks"
+ ]
+ , "imports":
+ { "artifacts": ["", "field_artifacts"]
+ , "flags-cc": ["CC", "flags-cc"]
+ , "flags-cxx": ["CC", "flags-cxx"]
+ , "compiler-cc": ["CC", "compiler-cc"]
+ , "compiler-cxx": ["CC", "compiler-cxx"]
+ , "default-LDFLAGS": ["CC", "default-LDFLAGS"]
+ , "default-AR": ["CC", "default-AR"]
+ , "default-ENV": ["CC", "default-ENV"]
+ , "default-PATH": ["CC", "default-PATH"]
+ , "default-TOOLCHAIN": ["CC", "default-TOOLCHAIN"]
+ , "default-NON_SYSTEM_TOOLS": ["CC", "default-NON_SYSTEM_TOOLS"]
+ , "foreign-MAKE": ["CC/foreign", "default-MAKE"]
+ , "foreign-ENV": ["CC/foreign", "default-ENV"]
+ , "foreign-PATH": ["CC/foreign", "default-PATH"]
+ , "foreign-TOOLCHAIN": ["CC/foreign", "default-TOOLCHAIN"]
+ , "foreign-NON_SYSTEM_TOOLS": ["CC/foreign", "default-NON_SYSTEM_TOOLS"]
+ , "map_provider": ["", "field_map_provider"]
+ , "sh": ["shell", "sh"]
+ , "sh-PATH": ["shell", "PATH"]
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["TOOLCHAIN_DIR", "toolchain"]
+ , [ "shell TOOLCHAIN"
+ , { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "shell defaults"]
+ , ["provider", "TOOLCHAIN"]
+ , ["default", {"type": "empty_map"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "map_provider"}
+ }
+ ]
+ , [ "sh"
+ , { "type": "let*"
+ , "bindings": [["fieldname", "shell defaults"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "sh"}
+ }
+ ]
+ , [ "TOOLCHAIN"
+ , { "type": "disjoint_map_union"
+ , "msg": "Toolchain trees may not overlap"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "foreign-TOOLCHAIN"}
+ , {"type": "CALL_EXPRESSION", "name": "default-TOOLCHAIN"}
+ , {"type": "var", "name": "shell TOOLCHAIN"}
+ ]
+ }
+ ]
+ , [ "TOOLCHAIN"
+ , { "type": "to_subdir"
+ , "subdir": {"type": "var", "name": "TOOLCHAIN_DIR"}
+ , "$1": {"type": "var", "name": "TOOLCHAIN"}
+ }
+ ]
+ , [ "NON_SYSTEM_TOOLS"
+ , { "type": "map_union"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "foreign-NON_SYSTEM_TOOLS"}
+ , {"type": "CALL_EXPRESSION", "name": "default-NON_SYSTEM_TOOLS"}
+ ]
+ }
+ ]
+ , [ "MAKE"
+ , { "type": "join"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ { "type": "if"
+ , "cond":
+ { "type": "lookup"
+ , "key": "MAKE"
+ , "map": {"type": "var", "name": "NON_SYSTEM_TOOLS"}
+ }
+ , "then": ["./", {"type": "var", "name": "TOOLCHAIN_DIR"}, "/"]
+ }
+ , {"type": "CALL_EXPRESSION", "name": "foreign-MAKE"}
+ ]
+ }
+ }
+ ]
+ , ["CC", {"type": "CALL_EXPRESSION", "name": "compiler-cc"}]
+ , ["CXX", {"type": "CALL_EXPRESSION", "name": "compiler-cxx"}]
+ , [ "CFLAGS"
+ , { "type": "join"
+ , "separator": " "
+ , "$1": {"type": "CALL_EXPRESSION", "name": "flags-cc"}
+ }
+ ]
+ , [ "CXXFLAGS"
+ , { "type": "join"
+ , "separator": " "
+ , "$1": {"type": "CALL_EXPRESSION", "name": "flags-cxx"}
+ }
+ ]
+ , [ "LDFLAGS"
+ , { "type": "join"
+ , "separator": " "
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ ["-Wl,-rpath,$ORIGIN", "-Wl,-rpath,$ORIGIN/../lib"]
+ , { "type": "var"
+ , "name": "LDFLAGS"
+ , "default":
+ {"type": "CALL_EXPRESSION", "name": "default-LDFLAGS"}
+ }
+ , {"type": "var", "name": "ldflags", "default": []}
+ ]
+ }
+ }
+ ]
+ , [ "AR"
+ , { "type": "var"
+ , "name": "AR"
+ , "default":
+ { "type": "join"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ { "type": "if"
+ , "cond":
+ { "type": "lookup"
+ , "key": "AR"
+ , "map": {"type": "var", "name": "NON_SYSTEM_TOOLS"}
+ }
+ , "then":
+ ["./", {"type": "var", "name": "TOOLCHAIN_DIR"}, "/"]
+ }
+ , {"type": "CALL_EXPRESSION", "name": "default-AR"}
+ ]
+ }
+ }
+ }
+ ]
+ , [ "PREFIX"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "make_prefix"}
+ , "then":
+ { "type": "join"
+ , "separator": "/"
+ , "$1":
+ { "type": "++"
+ , "$1": [[""], {"type": "var", "name": "make_prefix"}]
+ }
+ }
+ , "else": {"type": "var", "name": "PREFIX", "default": "/"}
+ }
+ ]
+ , [ "sh-PATH"
+ , { "type": "join"
+ , "separator": ":"
+ , "$1":
+ { "type": "let*"
+ , "bindings": [["fieldname", "shell defaults"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "sh-PATH"}
+ }
+ }
+ ]
+ , [ "sh-ENV"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "sh-PATH"}
+ , "then":
+ { "type": "singleton_map"
+ , "key": "PATH"
+ , "value": {"type": "var", "name": "sh-PATH"}
+ }
+ , "else": {"type": "empty_map"}
+ }
+ ]
+ , [ "PATH"
+ , { "type": "join"
+ , "separator": ":"
+ , "$1":
+ { "type": "nub_left"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "foreign-PATH"}
+ , {"type": "CALL_EXPRESSION", "name": "default-PATH"}
+ ]
+ }
+ }
+ }
+ ]
+ , [ "ENV"
+ , { "type": "map_union"
+ , "$1":
+ [ { "type": "env"
+ , "vars":
+ [ "CC"
+ , "CXX"
+ , "CFLAGS"
+ , "CXXFLAGS"
+ , "LDFLAGS"
+ , "AR"
+ , "MAKE"
+ , "PREFIX"
+ ]
+ }
+ , {"type": "var", "name": "sh-ENV"}
+ , {"type": "CALL_EXPRESSION", "name": "default-ENV"}
+ , {"type": "CALL_EXPRESSION", "name": "foreign-ENV"}
+ , {"type": "var", "name": "ENV", "default": {"type": "empty_map"}}
+ ]
+ }
+ ]
+ , [ "SUBDIR"
+ , { "type": "join"
+ , "separator": "/"
+ , "$1": {"type": "var", "name": "subdir", "default": []}
+ }
+ ]
+ , [ "configure_args"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "configure"}
+ , "then":
+ { "type": "++"
+ , "$1":
+ [ {"type": "var", "name": "configure_options", "default": []}
+ , [ { "type": "join"
+ , "$1": ["--prefix=", {"type": "var", "name": "PREFIX"}]
+ }
+ ]
+ ]
+ }
+ }
+ ]
+ , [ "make_targets"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "make_targets"}
+ , "then": {"type": "var", "name": "make_targets"}
+ , "else": ["install"]
+ }
+ ]
+ , [ "script"
+ , { "type": "singleton_map"
+ , "key": "run_make.sh"
+ , "value":
+ { "type": "BLOB"
+ , "data":
+ { "type": "join"
+ , "separator": "\n"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ [ "set -eu"
+ , "mkdir scratch"
+ , "readonly ROOT=\"$(pwd)\""
+ , "export TMPDIR=\"$(pwd)/scratch\""
+ , "export DESTDIR=\"$(pwd)/install\""
+ , "export TOOLCHAIN=\"$(pwd)/toolchain\""
+ , "export LOCALBASE=\"$(pwd)/localbase\""
+ , { "type": "if"
+ , "cond":
+ { "type": "lookup"
+ , "key": "CC"
+ , "map": {"type": "var", "name": "NON_SYSTEM_TOOLS"}
+ }
+ , "then": "export CC=$(pwd)/${CC}"
+ , "else": ""
+ }
+ , { "type": "if"
+ , "cond":
+ { "type": "lookup"
+ , "key": "CXX"
+ , "map": {"type": "var", "name": "NON_SYSTEM_TOOLS"}
+ }
+ , "then": "export CXX=$(pwd)/${CXX}"
+ , "else": ""
+ }
+ , { "type": "if"
+ , "cond":
+ { "type": "lookup"
+ , "key": "AR"
+ , "map": {"type": "var", "name": "NON_SYSTEM_TOOLS"}
+ }
+ , "then": "export AR=$(pwd)/${AR}"
+ , "else": ""
+ }
+ , { "type": "if"
+ , "cond":
+ { "type": "lookup"
+ , "key": "MAKE"
+ , "map": {"type": "var", "name": "NON_SYSTEM_TOOLS"}
+ }
+ , "then": "export MAKE=$(pwd)/${MAKE}"
+ , "else": ""
+ }
+ , { "type": "join"
+ , "$1":
+ [ "export PATH="
+ , { "type": "join_cmd"
+ , "$1": [{"type": "var", "name": "PATH"}]
+ }
+ , "${PATH:+:}\"${PATH}\""
+ ]
+ }
+ ]
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "pre_cmds"}
+ , "then":
+ { "type": "++"
+ , "$1":
+ [ ["(", "set --", "cd ./source"]
+ , {"type": "var", "name": "pre_cmds"}
+ , [")"]
+ ]
+ }
+ }
+ , ["readonly SUBDIR=\"$1\"", "shift"]
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "configure_args"}
+ , "then":
+ [ "( cd \"source/${SUBDIR}\""
+ , { "type": "join"
+ , "$1":
+ [ "${ROOT}/expand_exec TMPDIR DESTDIR LOCALBASE CC CXX CFLAGS CXXFLAGS LDFLAGS AR PREFIX -- ./configure "
+ , { "type": "join_cmd"
+ , "$1": {"type": "var", "name": "configure_args"}
+ }
+ , " >\"${ROOT}/configure.log\" 2>&1 || (cat \"${ROOT}/configure.log\" && exit 1)"
+ ]
+ }
+ , ")"
+ ]
+ }
+ , { "type": "foreach"
+ , "range": {"type": "var", "name": "make_targets"}
+ , "var": "target"
+ , "body":
+ { "type": "join"
+ , "separator": " "
+ , "$1":
+ [ "${ROOT}/expand_exec TMPDIR DESTDIR LOCALBASE CC CXX CFLAGS CXXFLAGS LDFLAGS AR PREFIX"
+ , "--"
+ , "${MAKE} -C \"source/${SUBDIR}\" DESTDIR=${DESTDIR} \"$@\""
+ , { "type": "join_cmd"
+ , "$1": [{"type": "var", "name": "target"}]
+ }
+ , ">>build.log 2>&1 || (cat build.log && exit 1)"
+ ]
+ }
+ }
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "resolve_symlinks"}
+ , "then":
+ [ "mv install install_with_symlinks"
+ , "cp -rL install_with_symlinks install >copy.log 2>&1 || (echo 'ERROR: symlink resolve failed with:' && cat copy.log && exit 1)"
+ ]
+ }
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "post_cmds"}
+ , "then":
+ { "type": "++"
+ , "$1":
+ [ ["(", "set --", "cd ./install"]
+ , {"type": "var", "name": "post_cmds"}
+ , [")"]
+ ]
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ ]
+ ]
+ , "body":
+ { "type": "ACTION"
+ , "inputs":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "TOOLCHAIN"}
+ , {"type": "var", "name": "source_dir"}
+ , {"type": "var", "name": "expand_exec"}
+ , { "type": "var"
+ , "name": "localbase_dir"
+ , "default": {"type": "empty_map"}
+ }
+ , {"type": "var", "name": "script"}
+ ]
+ }
+ , "cmd":
+ { "type": "++"
+ , "$1":
+ [ [{"type": "var", "name": "sh"}, "run_make.sh"]
+ , [{"type": "var", "name": "SUBDIR"}]
+ , {"type": "var", "name": "make_options"}
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "make_jobs"}
+ , "then":
+ [ { "type": "join"
+ , "$1":
+ { "type": "++"
+ , "$1": [["-j"], {"type": "var", "name": "make_jobs"}]
+ }
+ }
+ ]
+ }
+ ]
+ }
+ , "out_dirs": ["install"]
+ , "env": {"type": "var", "name": "ENV"}
+ , "timeout scaling":
+ {"type": "var", "name": "TIMEOUT_SCALE", "default": 10.0}
+ , "execution properties":
+ {"type": "var", "name": "FOREIGN_EXECUTION_PROPERTIES"}
+ }
+ }
+ }
+}
diff --git a/rules/CC/foreign/make/RULES b/rules/CC/foreign/make/RULES
new file mode 100644
index 0000000..771a058
--- /dev/null
+++ b/rules/CC/foreign/make/RULES
@@ -0,0 +1,803 @@
+{ "data":
+ { "doc":
+ [ "Data produced by Configure and Make build and install."
+ , ""
+ , "All variables accessible to commands and options are: \"TMPDIR\","
+ , "\"LOCALBASE\", \"CC\", \"CXX\", \"CFLAGS\", \"CXXFLAGS\", \"LDFLAGS\","
+ , "\"AR\", and \"PREFIX\". \"LOCALBASE\" contains the path to the"
+ , "installed artifacts from \"deps\"."
+ ]
+ , "target_fields": ["project"]
+ , "string_fields":
+ [ "subdir"
+ , "configure"
+ , "configure_options"
+ , "targets"
+ , "prefix"
+ , "options"
+ , "jobs"
+ , "pre_cmds"
+ , "post_cmds"
+ , "out_files"
+ , "out_dirs"
+ , "resolve_symlinks"
+ ]
+ , "config_vars":
+ [ "ARCH"
+ , "HOST_ARCH"
+ , "CC"
+ , "CXX"
+ , "CFLAGS"
+ , "CXXFLAGS"
+ , "LDFLAGS"
+ , "ADD_CFLAGS"
+ , "ADD_CXXFLAGS"
+ , "ADD_LDFLAGS"
+ , "ENV"
+ , "AR"
+ , "PREFIX"
+ , "BUILD_POSITION_INDEPENDENT"
+ , "TIMEOUT_SCALE"
+ , "FOREIGN_EXECUTION_PROPERTIES"
+ ]
+ , "implicit":
+ { "defaults": [["CC", "defaults"]]
+ , "foreign-defaults": [["CC/foreign", "defaults"]]
+ , "shell defaults": [["shell", "defaults"]]
+ , "expand_exec": [["./", "..", "expand_exec"]]
+ }
+ , "field_doc":
+ { "project":
+ ["The Make project directory. It should contain a single tree artifact"]
+ , "subdir":
+ [ "The subdirectory that contains the configure and Makefile. Individual"
+ , "directory components are joined with \"/\"."
+ ]
+ , "configure": ["Run ./configure if non-empty."]
+ , "configure_options":
+ [ "The configure options (the \"--prefix\" option is automatically set."
+ , "Variables can be accessed via \"$(<varname>)\", e.g., \"$(TMPDIR)\""
+ , "for variable \"$TMPDIR\"."
+ ]
+ , "targets":
+ [ "The Make targets to build in the specified order"
+ , "(default: [\"install\"])."
+ ]
+ , "prefix":
+ [ "The prefix used for the Make target. The path will be made absolute"
+ , "and individual directory components are joined with \"/\". If no"
+ , "prefix is specified, the value from the config variable \"PREFIX\" is"
+ , "taken, with the default value being \"/\"."
+ ]
+ , "options":
+ [ "Make options for the configuration phase"
+ , "(e.g., [\"-f\", \"Makefile\", \"ARCH=x86\", \"LD=$(CC)\"]). Variables"
+ , "can be accessed via \"$(<varname>)\", e.g., \"$(TMPDIR)\" for"
+ , "variable \"$TMPDIR\"."
+ ]
+ , "jobs":
+ [ "Number of jobs to run simultaneously. If omitted, Make's default"
+ , "number is used."
+ ]
+ , "pre_cmds":
+ [ "List of commands executed in the project directory before calling"
+ , "Configure or Make. Useful for renaming files or directories. Note"
+ , "that data between \"pre_cmds\" and \"post_cmds\" can be exchanged via"
+ , "\"$TMPDIR\", which is uniquely reserved for this action."
+ ]
+ , "post_cmds":
+ [ "List of commands executed in the install directory after successful"
+ , "installation but before the output files are collected. Useful for"
+ , "renaming files or directories. Note that data between \"pre_cmds\" and"
+ , "\"post_cmds\" can be exchanged via \"$TMPDIR\", which is uniquely"
+ , "reserved for this action."
+ ]
+ , "resolve_symlinks":
+ [ "Resolve all symlinks in the install directory. This operation is"
+ , "performed immediately after the install, before \"post_cmds\" are run."
+ ]
+ , "out_files":
+ [ "Paths to the produced output files. The paths are considered relative"
+ , "to the install directory."
+ , "Note that \"out_files\" and \"out_dirs\" may not overlap."
+ ]
+ , "out_dirs":
+ [ "Paths to the produced output directories. The paths are considered"
+ , "relative to the install directory."
+ , "Note that \"out_files\" and \"out_dirs\" may not overlap."
+ ]
+ }
+ , "config_doc":
+ { "CC":
+ [ "The name of the C compiler to be used."
+ , "If null, the respective value from [\"CC\", \"defaults\"] will be taken."
+ ]
+ , "CXX":
+ [ "The name of the C++ compiler to be used."
+ , "If null, 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 linked 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 linked in a non-standard way; usually"
+ , "adapting the default target [\"CC\", \"defaults\"] is the better"
+ , "choice."
+ ]
+ , "ENV":
+ [ "The environment for any action generated."
+ , "If null, the respective value from [\"CC\", \"defaults\"] will be taken."
+ ]
+ , "AR":
+ [ "The archive tool to used for creating the library."
+ , "If null, the respective value from [\"CC\", \"defaults\"] will be taken."
+ ]
+ , "PREFIX":
+ [ "The absolute path that is used as prefix inside generated pkg-config"
+ , "files. The default value for this variable is \"/\". This variable"
+ , "is ignored if the field \"prefix\" is set."
+ ]
+ , "BUILD_POSITION_INDEPENDENT": ["Build position independent code."]
+ , "TIMEOUT_SCALE":
+ [ "The scaling of the timeout for the invocation of the foreign build."
+ , "Defaults to 10."
+ ]
+ , "FOREIGN_EXECUTION_PROPERTIES":
+ [ "A map with extra remote-execution properties to be added to the foreign build action."
+ ]
+ }
+ , "imports":
+ { "stage_field": ["", "stage_singleton_field"]
+ , "make-build": "make-build"
+ , "strip-prefix": ["./", "..", "strip-prefix"]
+ , "for host": ["transitions", "for host"]
+ , "map_provider": ["", "field_map_provider"]
+ , "sh": ["shell", "sh"]
+ }
+ , "config_transitions":
+ { "defaults":
+ [{"type": "empty_map"}, {"type": "CALL_EXPRESSION", "name": "for host"}]
+ , "expand_exec": [{"type": "CALL_EXPRESSION", "name": "for host"}]
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["install_prefix", "install"]
+ , [ "source_dir"
+ , { "type": "let*"
+ , "bindings": [["fieldname", "project"], ["location", "source"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "stage_field"}
+ }
+ ]
+ , [ "installed_out_files"
+ , { "type": "foreach"
+ , "var": "file_path"
+ , "range": {"type": "FIELD", "name": "out_files"}
+ , "body":
+ { "type": "join"
+ , "separator": "/"
+ , "$1":
+ [ {"type": "var", "name": "install_prefix"}
+ , {"type": "var", "name": "file_path"}
+ ]
+ }
+ }
+ ]
+ , [ "installed_out_dirs"
+ , { "type": "foreach"
+ , "var": "dir_path"
+ , "range": {"type": "FIELD", "name": "out_dirs"}
+ , "body":
+ { "type": "join"
+ , "separator": "/"
+ , "$1":
+ [ {"type": "var", "name": "install_prefix"}
+ , {"type": "var", "name": "dir_path"}
+ ]
+ }
+ }
+ ]
+ , ["subdir", {"type": "FIELD", "name": "subdir"}]
+ , ["configure", {"type": "FIELD", "name": "configure"}]
+ , ["configure_options", {"type": "FIELD", "name": "configure_options"}]
+ , ["make_targets", {"type": "FIELD", "name": "targets"}]
+ , ["make_prefix", {"type": "FIELD", "name": "prefix"}]
+ , ["make_options", {"type": "FIELD", "name": "options"}]
+ , ["make_jobs", {"type": "FIELD", "name": "jobs"}]
+ , ["pre_cmds", {"type": "FIELD", "name": "pre_cmds"}]
+ , ["post_cmds", {"type": "FIELD", "name": "post_cmds"}]
+ , ["resolve_symlinks", {"type": "FIELD", "name": "resolve_symlinks"}]
+ , ["defaults-transition", {"type": "empty_map"}]
+ , [ "expand_exec"
+ , { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "expand_exec"]
+ , ["location", "expand_exec"]
+ , ["transition", {"type": "CALL_EXPRESSION", "name": "for host"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "stage_field"}
+ }
+ ]
+ , ["full_install_dir", {"type": "CALL_EXPRESSION", "name": "make-build"}]
+ , ["TOOLCHAIN_DIR", "toolchain"]
+ , [ "shell TOOLCHAIN"
+ , { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "shell defaults"]
+ , ["provider", "TOOLCHAIN"]
+ , ["default", {"type": "empty_map"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "map_provider"}
+ }
+ ]
+ , [ "sh"
+ , { "type": "let*"
+ , "bindings": [["fieldname", "shell defaults"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "sh"}
+ }
+ ]
+ , [ "install_dir"
+ , { "type": "ACTION"
+ , "inputs":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "shell TOOLCHAIN"}
+ , {"type": "var", "name": "full_install_dir"}
+ ]
+ }
+ , "cmd": [{"type": "var", "name": "sh"}, "-c", ":"]
+ , "outs": {"type": "var", "name": "installed_out_files"}
+ , "out_dirs": {"type": "var", "name": "installed_out_dirs"}
+ }
+ ]
+ , [ "out_files"
+ , { "type": "let*"
+ , "bindings":
+ [ ["artifacts", {"type": "var", "name": "install_dir"}]
+ , ["paths", {"type": "FIELD", "name": "out_files"}]
+ , ["prefix", {"type": "var", "name": "install_prefix"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "strip-prefix"}
+ }
+ ]
+ , [ "out_dirs"
+ , { "type": "let*"
+ , "bindings":
+ [ ["artifacts", {"type": "var", "name": "install_dir"}]
+ , ["paths", {"type": "FIELD", "name": "out_dirs"}]
+ , ["prefix", {"type": "var", "name": "install_prefix"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "strip-prefix"}
+ }
+ ]
+ ]
+ , "body":
+ { "type": "RESULT"
+ , "artifacts":
+ { "type": "map_union"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "var", "name": "out_files"}
+ , {"type": "var", "name": "out_dirs"}
+ ]
+ }
+ }
+ }
+ }
+ }
+, "library":
+ { "doc":
+ [ "Library produced by Configure and Make build and install."
+ , ""
+ , "All variables accessible to commands and options are: \"TMPDIR\","
+ , "\"LOCALBASE\", \"CC\", \"CXX\", \"CFLAGS\", \"CXXFLAGS\", \"LDFLAGS\","
+ , "\"AR\", and \"PREFIX\". \"LOCALBASE\" contains the path to the"
+ , "installed artifacts from \"deps\"."
+ ]
+ , "target_fields": ["project", "deps"]
+ , "string_fields":
+ [ "subdir"
+ , "name"
+ , "version"
+ , "stage"
+ , "configure"
+ , "configure_options"
+ , "targets"
+ , "prefix"
+ , "options"
+ , "jobs"
+ , "pre_cmds"
+ , "post_cmds"
+ , "out_hdrs"
+ , "out_hdr_dirs"
+ , "out_libs"
+ , "cflags"
+ , "ldflags"
+ , "pkg-config"
+ , "hdr_prefix"
+ , "lib_prefix"
+ , "pc_prefix"
+ , "resolve_symlinks"
+ ]
+ , "config_vars":
+ [ "ARCH"
+ , "HOST_ARCH"
+ , "CC"
+ , "CXX"
+ , "CFLAGS"
+ , "CXXFLAGS"
+ , "LDFLAGS"
+ , "ADD_CFLAGS"
+ , "ADD_CXXFLAGS"
+ , "ADD_LDFLAGS"
+ , "ENV"
+ , "AR"
+ , "PREFIX"
+ , "BUILD_POSITION_INDEPENDENT"
+ , "TIMEOUT_SCALE"
+ , "FOREIGN_EXECUTION_PROPERTIES"
+ ]
+ , "implicit":
+ { "defaults": [["CC", "defaults"]]
+ , "foreign-defaults": [["CC/foreign", "defaults"]]
+ , "shell defaults": [["shell", "defaults"]]
+ , "config_reader": [["CC", "prebuilt/read_pkgconfig.py"]]
+ , "expand_exec": [["./", "..", "expand_exec"]]
+ }
+ , "field_doc":
+ { "project":
+ ["The Make project directory. It should contain a single tree artifact"]
+ , "subdir":
+ [ "The subdirectory that contains the configure and Makefile. Individual"
+ , "directory components are joined with \"/\"."
+ ]
+ , "name":
+ [ "The name of the library (without leading \"lib\" or trailing file name"
+ , "extension), also used as name for pkg-config files."
+ ]
+ , "version":
+ [ "The library version, used for pkg-config files. Individual version"
+ , "components are joined with \".\"."
+ ]
+ , "configure": ["Run ./configure if non-empty."]
+ , "configure_options":
+ ["The configure options (the \"--prefix\" option is automatically set."]
+ , "targets":
+ [ "The Make targets to build in the specified order"
+ , "(default: [\"install\"])."
+ ]
+ , "prefix":
+ [ "The prefix used for the Make target. The path will be made absolute"
+ , "and individual directory components are joined with \"/\". If no"
+ , "prefix is specified, the value from the config variable \"PREFIX\" is"
+ , "taken, with the default value being \"/\"."
+ ]
+ , "options":
+ [ "Make options for the build phase."
+ , "(e.g., [\"-f\", \"Makefile\", \"ARCH=x86\"])"
+ ]
+ , "jobs":
+ [ "Number of jobs to run simultaneously. If omitted, Make's default"
+ , "number is used."
+ ]
+ , "pre_cmds":
+ [ "List of commands executed in the project directory before calling"
+ , "Configure or Make. Useful for renaming files or directories. Note"
+ , "that data between \"pre_cmds\" and \"post_cmds\" can be exchanged via"
+ , "\"$TMPDIR\", which is uniquely reserved for this action."
+ ]
+ , "post_cmds":
+ [ "List of commands executed in the install directory after successful"
+ , "installation but before the output files are collected. Useful for"
+ , "renaming files or directories (e.g., in case of SONAME mismatch). Note"
+ , "that data between \"pre_cmds\" and \"post_cmds\" can be exchanged via"
+ , "\"$TMPDIR\", which is uniquely reserved for this action."
+ ]
+ , "resolve_symlinks":
+ [ "Resolve all symlinks in the install directory. This operation is"
+ , "performed immediately after the install, before \"post_cmds\" are run."
+ ]
+ , "out_hdrs":
+ [ "Paths to produced public header files. The path is considered"
+ , "relative to the include directory, which be set via \"hdr_prefix\"."
+ , "Note that \"out_hdrs\" and \"out_hdr_dirs\" may not overlap."
+ ]
+ , "out_hdr_dirs":
+ [ "Paths to produced public header directories. The path is considered"
+ , "relative to the include directory, which be set via \"hdr_prefix\"."
+ , "Note that \"out_hdrs\" and \"out_hdr_dirs\" may not overlap."
+ ]
+ , "out_libs":
+ [ "Paths to produced library files. The path is considered relative"
+ , "to the library directory, which be set via \"lib_prefix\"."
+ , "Order matters in the case of one library depending on another."
+ ]
+ , "cflags":
+ ["List of compile flags set for this target and its consumers."]
+ , "ldflags":
+ [ "Additional linker flags that are required for the consumer of the"
+ , "produced libraries."
+ ]
+ , "stage":
+ [ "The logical location of the public headers and library files."
+ , "Individual directory components are joined with \"/\"."
+ ]
+ , "deps": ["Public dependency on other CC libraries."]
+ , "pkg-config":
+ [ "Pkg-config file for optional infer of public cflags and ldflags. If"
+ , "multiple files are specified (e.g., one depends on the other), the"
+ , "first one is used as entry. Note that if this field is non-empty the"
+ , "tool \"pkg-config\" must be available in \"PATH\", which is taken"
+ , "from [\"CC\", \"defaults\"] or the \"ENV\" variable."
+ ]
+ , "hdr_prefix":
+ [ "Prefix where headers will be installed by Make. Individual directory"
+ , "components are joined with \"/\". Defaults to \"include\" if not set."
+ ]
+ , "lib_prefix":
+ [ "Prefix where libraries will be installed by Make. Individual"
+ , "directory components are joined with \"/\". Defaults to \"lib\" if"
+ , "not set."
+ ]
+ , "pc_prefix":
+ [ "Prefix where pkg-config files will be installed by Make. Individual"
+ , "directory components are joined with \"/\". Defaults to"
+ , "\"lib/pkgconfig\" if not set."
+ ]
+ }
+ , "config_doc":
+ { "CC":
+ [ "The name of the C compiler to be used."
+ , "If null, the respective value from [\"CC\", \"defaults\"] will be taken."
+ ]
+ , "CXX":
+ [ "The name of the C++ compiler to be used."
+ , "If null, 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":
+ ["Global ld flags, for common link args,such as -Wl,-z,noexecstack"]
+ , "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 linked in a non-standard way; usually"
+ , "adapting the default target [\"CC\", \"defaults\"] is the better"
+ , "choice."
+ ]
+ , "ENV":
+ [ "The environment for any action generated."
+ , "If null, the respective value from [\"CC\", \"defaults\"] will be taken."
+ ]
+ , "AR":
+ [ "The archive tool to used for creating the library"
+ , "If null, the respective value from [\"CC\", \"defaults\"] will be taken."
+ ]
+ , "PREFIX":
+ [ "The absolute path that is used as prefix inside generated pkg-config"
+ , "files. The default value for this variable is \"/\". This variable"
+ , "is ignored if the field \"prefix\" is set."
+ ]
+ , "BUILD_POSITION_INDEPENDENT": ["Build position independent code."]
+ , "TIMEOUT_SCALE":
+ [ "The scaling of the timeout for the invocation of the foreign build."
+ , "Defaults to 10."
+ ]
+ , "FOREIGN_EXECUTION_PROPERTIES":
+ [ "A map with extra remote-execution properties to be added to the foreign build action."
+ ]
+ }
+ , "imports":
+ { "stage_field": ["", "stage_singleton_field"]
+ , "make-build": "make-build"
+ , "strip-prefix": ["./", "..", "strip-prefix"]
+ , "prebuilt result": ["CC/prebuilt", "prebuilt result"]
+ , "install-deps": ["CC", "install-with-deps stage"]
+ , "for host": ["transitions", "for host"]
+ , "map_provider": ["", "field_map_provider"]
+ , "sh": ["shell", "sh"]
+ }
+ , "config_transitions":
+ { "defaults":
+ [{"type": "empty_map"}, {"type": "CALL_EXPRESSION", "name": "for host"}]
+ , "expand_exec": [{"type": "CALL_EXPRESSION", "name": "for host"}]
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ [ "hdr_prefix"
+ , { "type": "join"
+ , "separator": "/"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ ["install"]
+ , { "type": "if"
+ , "cond": {"type": "FIELD", "name": "hdr_prefix"}
+ , "then": {"type": "FIELD", "name": "hdr_prefix"}
+ , "else": ["include"]
+ }
+ ]
+ }
+ }
+ ]
+ , [ "lib_prefix"
+ , { "type": "join"
+ , "separator": "/"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ ["install"]
+ , { "type": "if"
+ , "cond": {"type": "FIELD", "name": "lib_prefix"}
+ , "then": {"type": "FIELD", "name": "lib_prefix"}
+ , "else": ["lib"]
+ }
+ ]
+ }
+ }
+ ]
+ , [ "pc_prefix"
+ , { "type": "join"
+ , "separator": "/"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ ["install"]
+ , { "type": "if"
+ , "cond": {"type": "FIELD", "name": "pc_prefix"}
+ , "then": {"type": "FIELD", "name": "pc_prefix"}
+ , "else": ["lib", "pkgconfig"]
+ }
+ ]
+ }
+ }
+ ]
+ , [ "source_dir"
+ , { "type": "let*"
+ , "bindings": [["fieldname", "project"], ["location", "source"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "stage_field"}
+ }
+ ]
+ , [ "localbase_dir"
+ , { "type": "to_subdir"
+ , "subdir": "localbase"
+ , "msg": "dependency installation files may not overlap"
+ , "$1":
+ { "type": "let*"
+ , "bindings":
+ [ ["pc-install-dir", "lib/pkgconfig"]
+ , ["targets", {"type": "FIELD", "name": "deps"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "install-deps"}
+ }
+ }
+ ]
+ , [ "installed_dirs"
+ , { "type": "foreach"
+ , "var": "dir_path"
+ , "range": {"type": "FIELD", "name": "out_hdr_dirs"}
+ , "body":
+ { "type": "join"
+ , "separator": "/"
+ , "$1":
+ [ {"type": "var", "name": "hdr_prefix"}
+ , {"type": "var", "name": "dir_path"}
+ ]
+ }
+ }
+ ]
+ , [ "installed_files"
+ , { "type": "++"
+ , "$1":
+ [ { "type": "foreach"
+ , "var": "lib_path"
+ , "range": {"type": "FIELD", "name": "out_libs"}
+ , "body":
+ { "type": "join"
+ , "separator": "/"
+ , "$1":
+ [ {"type": "var", "name": "lib_prefix"}
+ , {"type": "var", "name": "lib_path"}
+ ]
+ }
+ }
+ , { "type": "foreach"
+ , "var": "hdr_path"
+ , "range": {"type": "FIELD", "name": "out_hdrs"}
+ , "body":
+ { "type": "join"
+ , "separator": "/"
+ , "$1":
+ [ {"type": "var", "name": "hdr_prefix"}
+ , {"type": "var", "name": "hdr_path"}
+ ]
+ }
+ }
+ , { "type": "foreach"
+ , "var": "pc_path"
+ , "range": {"type": "FIELD", "name": "pkg-config"}
+ , "body":
+ { "type": "join"
+ , "separator": "/"
+ , "$1":
+ [ {"type": "var", "name": "pc_prefix"}
+ , {"type": "var", "name": "pc_path"}
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ , ["subdir", {"type": "FIELD", "name": "subdir"}]
+ , ["configure", {"type": "FIELD", "name": "configure"}]
+ , ["configure_options", {"type": "FIELD", "name": "configure_options"}]
+ , ["make_targets", {"type": "FIELD", "name": "targets"}]
+ , ["make_prefix", {"type": "FIELD", "name": "prefix"}]
+ , ["make_options", {"type": "FIELD", "name": "options"}]
+ , ["make_jobs", {"type": "FIELD", "name": "jobs"}]
+ , ["pre_cmds", {"type": "FIELD", "name": "pre_cmds"}]
+ , ["post_cmds", {"type": "FIELD", "name": "post_cmds"}]
+ , ["resolve_symlinks", {"type": "FIELD", "name": "resolve_symlinks"}]
+ , ["defaults-transition", {"type": "empty_map"}]
+ , [ "expand_exec"
+ , { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "expand_exec"]
+ , ["location", "expand_exec"]
+ , ["transition", {"type": "CALL_EXPRESSION", "name": "for host"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "stage_field"}
+ }
+ ]
+ , ["full_install_dir", {"type": "CALL_EXPRESSION", "name": "make-build"}]
+ , [ "shell TOOLCHAIN"
+ , { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "shell defaults"]
+ , ["provider", "TOOLCHAIN"]
+ , ["default", {"type": "empty_map"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "map_provider"}
+ }
+ ]
+ , [ "sh"
+ , { "type": "let*"
+ , "bindings": [["fieldname", "shell defaults"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "sh"}
+ }
+ ]
+ , [ "install_dir"
+ , { "type": "ACTION"
+ , "inputs":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "shell TOOLCHAIN"}
+ , {"type": "var", "name": "full_install_dir"}
+ ]
+ }
+ , "cmd": [{"type": "var", "name": "sh"}, "-c", ":"]
+ , "outs": {"type": "var", "name": "installed_files"}
+ , "out_dirs": {"type": "var", "name": "installed_dirs"}
+ }
+ ]
+ , [ "hdrs"
+ , { "type": "++"
+ , "$1":
+ [ { "type": "let*"
+ , "bindings":
+ [ ["artifacts", {"type": "var", "name": "install_dir"}]
+ , ["paths", {"type": "FIELD", "name": "out_hdrs"}]
+ , ["prefix", {"type": "var", "name": "hdr_prefix"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "strip-prefix"}
+ }
+ , { "type": "let*"
+ , "bindings":
+ [ ["artifacts", {"type": "var", "name": "install_dir"}]
+ , ["paths", {"type": "FIELD", "name": "out_hdr_dirs"}]
+ , ["prefix", {"type": "var", "name": "hdr_prefix"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "strip-prefix"}
+ }
+ ]
+ }
+ ]
+ , [ "libs"
+ , { "type": "let*"
+ , "bindings":
+ [ ["artifacts", {"type": "var", "name": "install_dir"}]
+ , ["paths", {"type": "FIELD", "name": "out_libs"}]
+ , ["prefix", {"type": "var", "name": "lib_prefix"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "strip-prefix"}
+ }
+ ]
+ , [ "config_reader"
+ , { "type": "let*"
+ , "bindings":
+ [["fieldname", "config_reader"], ["location", "config_reader"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "stage_field"}
+ }
+ ]
+ , [ "pkg-configs"
+ , { "type": "let*"
+ , "bindings":
+ [ ["artifacts", {"type": "var", "name": "install_dir"}]
+ , ["paths", {"type": "FIELD", "name": "pkg-config"}]
+ , ["prefix", {"type": "var", "name": "pc_prefix"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "strip-prefix"}
+ }
+ ]
+ , [ "name"
+ , { "type": "assert_non_empty"
+ , "msg": "name is required for make library"
+ , "$1": {"type": "join", "$1": {"type": "FIELD", "name": "name"}}
+ }
+ ]
+ , ["version", {"type": "FIELD", "name": "version"}]
+ , ["cflags", {"type": "FIELD", "name": "cflags"}]
+ , ["ldflags", {"type": "FIELD", "name": "ldflags"}]
+ , [ "stage"
+ , { "type": "join"
+ , "separator": "/"
+ , "$1": {"type": "FIELD", "name": "stage"}
+ }
+ ]
+ , ["deps-fieldnames", ["deps", "defaults"]]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "prebuilt result"}
+ }
+ }
+}
diff --git a/rules/CC/foreign/shell/EXPRESSIONS b/rules/CC/foreign/shell/EXPRESSIONS
new file mode 100644
index 0000000..7ca2741
--- /dev/null
+++ b/rules/CC/foreign/shell/EXPRESSIONS
@@ -0,0 +1,363 @@
+{ "shell-build":
+ { "vars":
+ [ "cmds"
+ , "sources"
+ , "localbase"
+ , "installed_files"
+ , "installed_dirs"
+ , "CC"
+ , "CXX"
+ , "CFLAGS"
+ , "CXXFLAGS"
+ , "LDFLAGS"
+ , "ADD_CFLAGS"
+ , "ADD_CXXFLAGS"
+ , "ADD_LDFLAGS"
+ , "ENV"
+ , "AR"
+ , "PREFIX"
+ , "BUILD_POSITION_INDEPENDENT"
+ , "TIMEOUT_SCALE"
+ , "FOREIGN_EXECUTION_PROPERTIES"
+ , "resolve_symlinks"
+ ]
+ , "imports":
+ { "artifacts": ["", "field_artifacts"]
+ , "flags-cc": ["CC", "flags-cc"]
+ , "flags-cxx": ["CC", "flags-cxx"]
+ , "compiler-cc": ["CC", "compiler-cc"]
+ , "compiler-cxx": ["CC", "compiler-cxx"]
+ , "default-LDFLAGS": ["CC", "default-LDFLAGS"]
+ , "default-AR": ["CC", "default-AR"]
+ , "default-PATH": ["CC", "default-PATH"]
+ , "default-TOOLCHAIN": ["CC", "default-TOOLCHAIN"]
+ , "default-NON_SYSTEM_TOOLS": ["CC", "default-NON_SYSTEM_TOOLS"]
+ , "foreign-MAKE": ["CC/foreign", "default-MAKE"]
+ , "foreign-CMAKE": ["CC/foreign", "default-CMAKE"]
+ , "foreign-PATH": ["CC/foreign", "default-PATH"]
+ , "foreign-TOOLCHAIN": ["CC/foreign", "default-TOOLCHAIN"]
+ , "foreign-NON_SYSTEM_TOOLS": ["CC/foreign", "default-NON_SYSTEM_TOOLS"]
+ , "map_provider": ["", "field_map_provider"]
+ , "sh": ["shell", "sh"]
+ , "sh-PATH": ["shell", "PATH"]
+ , "sh prolog": ["shell", "prolog"]
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["TOOLCHAIN_DIR", "toolchain"]
+ , [ "shell TOOLCHAIN"
+ , { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "shell defaults"]
+ , ["provider", "TOOLCHAIN"]
+ , ["default", {"type": "empty_map"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "map_provider"}
+ }
+ ]
+ , [ "sh"
+ , { "type": "let*"
+ , "bindings": [["fieldname", "shell defaults"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "sh"}
+ }
+ ]
+ , [ "TOOLCHAIN"
+ , { "type": "disjoint_map_union"
+ , "msg": "Toolchain trees may not overlap"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "foreign-TOOLCHAIN"}
+ , {"type": "CALL_EXPRESSION", "name": "default-TOOLCHAIN"}
+ , {"type": "var", "name": "shell TOOLCHAIN"}
+ ]
+ }
+ ]
+ , [ "TOOLCHAIN"
+ , { "type": "to_subdir"
+ , "subdir": {"type": "var", "name": "TOOLCHAIN_DIR"}
+ , "$1": {"type": "var", "name": "TOOLCHAIN"}
+ }
+ ]
+ , [ "NON_SYSTEM_TOOLS"
+ , { "type": "map_union"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "foreign-NON_SYSTEM_TOOLS"}
+ , {"type": "CALL_EXPRESSION", "name": "default-NON_SYSTEM_TOOLS"}
+ ]
+ }
+ ]
+ , [ "MAKE"
+ , { "type": "join"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ { "type": "if"
+ , "cond":
+ { "type": "lookup"
+ , "key": "MAKE"
+ , "map": {"type": "var", "name": "NON_SYSTEM_TOOLS"}
+ }
+ , "then": ["./", {"type": "var", "name": "TOOLCHAIN_DIR"}, "/"]
+ }
+ , {"type": "CALL_EXPRESSION", "name": "foreign-MAKE"}
+ ]
+ }
+ }
+ ]
+ , [ "CMAKE"
+ , { "type": "join"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ { "type": "if"
+ , "cond":
+ { "type": "lookup"
+ , "key": "CMAKE"
+ , "map": {"type": "var", "name": "NON_SYSTEM_TOOLS"}
+ }
+ , "then": ["./", {"type": "var", "name": "TOOLCHAIN_DIR"}, "/"]
+ }
+ , {"type": "CALL_EXPRESSION", "name": "foreign-CMAKE"}
+ ]
+ }
+ }
+ ]
+ , ["CC", {"type": "CALL_EXPRESSION", "name": "compiler-cc"}]
+ , ["CXX", {"type": "CALL_EXPRESSION", "name": "compiler-cxx"}]
+ , [ "CFLAGS"
+ , { "type": "join"
+ , "separator": " "
+ , "$1": {"type": "CALL_EXPRESSION", "name": "flags-cc"}
+ }
+ ]
+ , [ "CXXFLAGS"
+ , { "type": "join"
+ , "separator": " "
+ , "$1": {"type": "CALL_EXPRESSION", "name": "flags-cxx"}
+ }
+ ]
+ , [ "LDFLAGS"
+ , { "type": "join"
+ , "separator": " "
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ ["-Wl,-rpath,$ORIGIN", "-Wl,-rpath,$ORIGIN/../lib"]
+ , { "type": "var"
+ , "name": "LDFLAGS"
+ , "default":
+ {"type": "CALL_EXPRESSION", "name": "default-LDFLAGS"}
+ }
+ , {"type": "var", "name": "ldflags", "default": []}
+ ]
+ }
+ }
+ ]
+ , [ "AR"
+ , { "type": "var"
+ , "name": "AR"
+ , "default":
+ { "type": "join"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ { "type": "if"
+ , "cond":
+ { "type": "lookup"
+ , "key": "AR"
+ , "map": {"type": "var", "name": "NON_SYSTEM_TOOLS"}
+ }
+ , "then":
+ ["./", {"type": "var", "name": "TOOLCHAIN_DIR"}, "/"]
+ }
+ , {"type": "CALL_EXPRESSION", "name": "default-AR"}
+ ]
+ }
+ }
+ }
+ ]
+ , [ "PREFIX"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "make_prefix"}
+ , "then":
+ { "type": "join"
+ , "separator": "/"
+ , "$1":
+ { "type": "++"
+ , "$1": [[""], {"type": "var", "name": "make_prefix"}]
+ }
+ }
+ , "else": {"type": "var", "name": "PREFIX", "default": "/"}
+ }
+ ]
+ , [ "PATH"
+ , { "type": "join"
+ , "separator": ":"
+ , "$1":
+ { "type": "nub_left"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "foreign-PATH"}
+ , {"type": "CALL_EXPRESSION", "name": "default-PATH"}
+ , { "type": "let*"
+ , "bindings": [["fieldname", "shell defaults"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "sh-PATH"}
+ }
+ ]
+ }
+ }
+ }
+ ]
+ , [ "ENV"
+ , { "type": "map_union"
+ , "$1":
+ [ { "type": "env"
+ , "vars":
+ [ "MAKE"
+ , "CMAKE"
+ , "CC"
+ , "CXX"
+ , "CFLAGS"
+ , "CXXFLAGS"
+ , "LDFLAGS"
+ , "AR"
+ , "PREFIX"
+ ]
+ }
+ , {"type": "var", "name": "ENV", "default": {"type": "empty_map"}}
+ ]
+ }
+ ]
+ , [ "localbase"
+ , { "type": "to_subdir"
+ , "subdir": "localbase"
+ , "$1": {"type": "var", "name": "localbase"}
+ }
+ ]
+ , [ "work_dir"
+ , { "type": "to_subdir"
+ , "subdir": "work"
+ , "$1": {"type": "var", "name": "sources"}
+ }
+ ]
+ , [ "script"
+ , { "type": "singleton_map"
+ , "key": "run_cmds.sh"
+ , "value":
+ { "type": "BLOB"
+ , "data":
+ { "type": "join"
+ , "separator": "\n"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ { "type": "let*"
+ , "bindings": [["fieldname", "shell defaults"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "sh prolog"}
+ }
+ , [ "set -eu"
+ , "mkdir -p scratch work install"
+ , "export ACTION_DIR=\"$(pwd)\""
+ , "export TMPDIR=\"$(pwd)/scratch\""
+ , "export WORKDIR=\"$(pwd)/work\""
+ , "export TOOLCHAIN=\"$(pwd)/toolchain\""
+ , "export LOCALBASE=\"$(pwd)/localbase\""
+ , "export DESTDIR=\"$(pwd)/install\""
+ , { "type": "if"
+ , "cond":
+ { "type": "lookup"
+ , "key": "CC"
+ , "map": {"type": "var", "name": "NON_SYSTEM_TOOLS"}
+ }
+ , "then": "export CC=$(pwd)/${CC}"
+ , "else": ""
+ }
+ , { "type": "if"
+ , "cond":
+ { "type": "lookup"
+ , "key": "CXX"
+ , "map": {"type": "var", "name": "NON_SYSTEM_TOOLS"}
+ }
+ , "then": "export CXX=$(pwd)/${CXX}"
+ , "else": ""
+ }
+ , { "type": "if"
+ , "cond":
+ { "type": "lookup"
+ , "key": "AR"
+ , "map": {"type": "var", "name": "NON_SYSTEM_TOOLS"}
+ }
+ , "then": "export AR=$(pwd)/${AR}"
+ , "else": ""
+ }
+ , { "type": "if"
+ , "cond":
+ { "type": "lookup"
+ , "key": "MAKE"
+ , "map": {"type": "var", "name": "NON_SYSTEM_TOOLS"}
+ }
+ , "then": "export MAKE=$(pwd)/${MAKE}"
+ , "else": ""
+ }
+ , { "type": "if"
+ , "cond":
+ { "type": "lookup"
+ , "key": "CMAKE"
+ , "map": {"type": "var", "name": "NON_SYSTEM_TOOLS"}
+ }
+ , "then": "export CMAKE=$(pwd)/${CMAKE}"
+ , "else": ""
+ }
+ , { "type": "join"
+ , "$1":
+ [ "export PATH="
+ , { "type": "join_cmd"
+ , "$1": [{"type": "var", "name": "PATH"}]
+ }
+ , "${PATH:+:}\"${PATH}\""
+ ]
+ }
+ ]
+ , ["(", "set --", "cd ./work"]
+ , {"type": "var", "name": "cmds"}
+ , [")"]
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "resolve_symlinks"}
+ , "then":
+ [ "mv install install_with_symlinks"
+ , "cp -rL install_with_symlinks install >copy.log 2>&1 || (echo 'ERROR: symlink resolve failed with:' && cat copy.log && exit 1)"
+ ]
+ }
+ ]
+ }
+ }
+ }
+ }
+ ]
+ , [ "artifacts"
+ , { "type": "ACTION"
+ , "inputs":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "TOOLCHAIN"}
+ , {"type": "var", "name": "work_dir"}
+ , {"type": "var", "name": "localbase"}
+ , {"type": "var", "name": "script"}
+ ]
+ }
+ , "cmd": [{"type": "var", "name": "sh"}, "run_cmds.sh"]
+ , "outs": {"type": "var", "name": "installed_files"}
+ , "out_dirs": {"type": "var", "name": "installed_dirs"}
+ , "env": {"type": "var", "name": "ENV"}
+ , "timeout scaling":
+ {"type": "var", "name": "TIMEOUT_SCALE", "default": 10.0}
+ , "execution properties":
+ {"type": "var", "name": "FOREIGN_EXECUTION_PROPERTIES"}
+ }
+ ]
+ ]
+ , "body": {"type": "var", "name": "artifacts"}
+ }
+ }
+}
diff --git a/rules/CC/foreign/shell/RULES b/rules/CC/foreign/shell/RULES
new file mode 100644
index 0000000..182e46a
--- /dev/null
+++ b/rules/CC/foreign/shell/RULES
@@ -0,0 +1,624 @@
+{ "data":
+ { "doc":
+ [ "Data produced by generic shell commands with toolchain support."
+ , ""
+ , "All variables accessible to commands and options are: \"TMPDIR\","
+ , "\"LOCALBASE\", \"WORKDIR\", \"DESTDIR\", \"CC\", \"CXX\", \"CFLAGS\","
+ , "\"CXXFLAGS\", \"LDFLAGS\", and \"AR\". \"LOCALBASE\" contains the path"
+ , "to the staged artifacts from \"localbase\" and the installed artifacts"
+ , "from \"deps\". Furthermore, the variable \"ACTION_DIR\" points to the"
+ , "current action directory, if needed for achieving reproducibility."
+ ]
+ , "target_fields": ["project", "localbase", "deps"]
+ , "string_fields": ["cmds", "outs", "out_dirs", "resolve_symlinks"]
+ , "config_vars":
+ [ "CC"
+ , "CXX"
+ , "CFLAGS"
+ , "CXXFLAGS"
+ , "LDFLAGS"
+ , "ADD_CFLAGS"
+ , "ADD_CXXFLAGS"
+ , "ADD_LDFLAGS"
+ , "ENV"
+ , "AR"
+ , "PREFIX"
+ , "BUILD_POSITION_INDEPENDENT"
+ , "TIMEOUT_SCALE"
+ , "FOREIGN_EXECUTION_PROPERTIES"
+ ]
+ , "implicit":
+ { "defaults": [["CC", "defaults"]]
+ , "foreign-defaults": [["CC/foreign", "defaults"]]
+ , "shell defaults": [["shell", "defaults"]]
+ }
+ , "field_doc":
+ { "project":
+ [ "The project directory. The disjoint union of the artifacts of the"
+ , "targets specified here are taken as project directory."
+ , "Its path can be accessed via the \"WORKDIR\" variable."
+ ]
+ , "localbase": ["Artifacts to stage to \"LOCALBASE\"."]
+ , "deps": ["CC targets to install to \"LOCALBASE\"."]
+ , "cmds":
+ [ "List of commands to execute by \"sh\". Multiple commands will be"
+ , "joined with the newline character."
+ ]
+ , "resolve_symlinks":
+ [ "Resolve all symlinks in the install directory. This operation is"
+ , "performed immediately after \"cmds\" were executed."
+ ]
+ , "outs": ["Paths to the produced output files in \"DESTDIR\"."]
+ , "out_dirs": ["Paths to the produced output directories in \"DESTDIR\"."]
+ }
+ , "config_doc":
+ { "CC":
+ [ "The name of the C compiler to be used."
+ , "If null, the respective value from [\"CC\", \"defaults\"] will be taken."
+ ]
+ , "CXX":
+ [ "The name of the C++ compiler to be used."
+ , "If null, 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 linked 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 linked in a non-standard way; usually"
+ , "adapting the default target [\"CC\", \"defaults\"] is the better"
+ , "choice."
+ ]
+ , "ENV":
+ [ "The environment for any action generated."
+ , "If null, the respective value from [\"CC\", \"defaults\"] will be taken."
+ ]
+ , "AR":
+ [ "The archive tool to used for creating the library."
+ , "If null, the respective value from [\"CC\", \"defaults\"] will be taken."
+ ]
+ , "PREFIX":
+ [ "The absolute path that is used as prefix inside generated pkg-config"
+ , "files. The default value for this variable is \"/\". This variable"
+ , "is ignored if the field \"prefix\" is set."
+ ]
+ , "BUILD_POSITION_INDEPENDENT": ["Build position independent code."]
+ , "TIMEOUT_SCALE":
+ [ "The scaling of the timeout for the invocation of the foreign build."
+ , "Defaults to 10."
+ ]
+ , "FOREIGN_EXECUTION_PROPERTIES":
+ [ "A map with extra remote-execution properties to be added to the foreign build action."
+ ]
+ }
+ , "imports":
+ { "artifacts": ["", "field_artifacts"]
+ , "stage_field": ["", "stage_singleton_field"]
+ , "shell-build": "shell-build"
+ , "install-deps": ["CC", "install-with-deps stage"]
+ , "strip-prefix": ["CC/foreign", "strip-prefix"]
+ , "for host": ["transitions", "for host"]
+ }
+ , "config_transitions":
+ { "defaults":
+ [{"type": "empty_map"}, {"type": "CALL_EXPRESSION", "name": "for host"}]
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["cmds", {"type": "FIELD", "name": "cmds"}]
+ , [ "sources"
+ , { "type": "let*"
+ , "bindings": [["fieldname", "project"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "artifacts"}
+ }
+ ]
+ , [ "localbase"
+ , { "type": "disjoint_map_union"
+ , "msg": "localbase and installed dependency files may not overlap"
+ , "$1":
+ [ { "type": "let*"
+ , "bindings":
+ [ ["pc-install-dir", "lib/pkgconfig"]
+ , ["targets", {"type": "FIELD", "name": "deps"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "install-deps"}
+ }
+ , { "type": "let*"
+ , "bindings": [["fieldname", "localbase"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "artifacts"}
+ }
+ ]
+ }
+ ]
+ , ["outs", {"type": "FIELD", "name": "outs"}]
+ , ["out_dirs", {"type": "FIELD", "name": "out_dirs"}]
+ , ["install_prefix", "install"]
+ , [ "installed_files"
+ , { "type": "foreach"
+ , "var": "file_path"
+ , "range": {"type": "var", "name": "outs"}
+ , "body":
+ { "type": "join"
+ , "separator": "/"
+ , "$1":
+ [ {"type": "var", "name": "install_prefix"}
+ , {"type": "var", "name": "file_path"}
+ ]
+ }
+ }
+ ]
+ , [ "installed_dirs"
+ , { "type": "foreach"
+ , "var": "dir_path"
+ , "range": {"type": "var", "name": "out_dirs"}
+ , "body":
+ { "type": "join"
+ , "separator": "/"
+ , "$1":
+ [ {"type": "var", "name": "install_prefix"}
+ , {"type": "var", "name": "dir_path"}
+ ]
+ }
+ }
+ ]
+ , ["resolve_symlinks", {"type": "FIELD", "name": "resolve_symlinks"}]
+ , ["artifacts", {"type": "CALL_EXPRESSION", "name": "shell-build"}]
+ ]
+ , "body":
+ { "type": "RESULT"
+ , "artifacts":
+ { "type": "map_union"
+ , "$1":
+ { "type": "let*"
+ , "bindings":
+ [ ["artifacts", {"type": "var", "name": "artifacts"}]
+ , [ "paths"
+ , { "type": "++"
+ , "$1":
+ [ {"type": "var", "name": "outs"}
+ , {"type": "var", "name": "out_dirs"}
+ ]
+ }
+ ]
+ , ["prefix", {"type": "var", "name": "install_prefix"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "strip-prefix"}
+ }
+ }
+ }
+ }
+ }
+, "library":
+ { "doc":
+ [ "Library produced by generic shell commands with toolchain support."
+ , ""
+ , "All variables accessible to commands and options are: \"TMPDIR\","
+ , "\"LOCALBASE\", \"WORKDIR\", \"DESTDIR\", \"CC\", \"CXX\", \"CFLAGS\","
+ , "\"CXXFLAGS\", \"LDFLAGS\", and \"AR\". \"LOCALBASE\" contains the path"
+ , "to the staged artifacts from \"localbase\" and the installed artifacts"
+ , "from \"deps\". Furthermore, the variable \"ACTION_DIR\" points to the"
+ , "current action directory, if needed for achieving reproducibility."
+ ]
+ , "target_fields": ["project", "localbase", "deps"]
+ , "string_fields":
+ [ "name"
+ , "version"
+ , "stage"
+ , "cmds"
+ , "out_hdrs"
+ , "out_hdr_dirs"
+ , "out_libs"
+ , "cflags"
+ , "ldflags"
+ , "pkg-config"
+ , "hdr_prefix"
+ , "lib_prefix"
+ , "pc_prefix"
+ , "resolve_symlinks"
+ ]
+ , "config_vars":
+ [ "CC"
+ , "CXX"
+ , "CFLAGS"
+ , "CXXFLAGS"
+ , "LDFLAGS"
+ , "ADD_CFLAGS"
+ , "ADD_CXXFLAGS"
+ , "ADD_LDFLAGS"
+ , "ENV"
+ , "AR"
+ , "PREFIX"
+ , "BUILD_POSITION_INDEPENDENT"
+ , "TIMEOUT_SCALE"
+ , "FOREIGN_EXECUTION_PROPERTIES"
+ ]
+ , "implicit":
+ { "defaults": [["CC", "defaults"]]
+ , "foreign-defaults": [["CC/foreign", "defaults"]]
+ , "shell defaults": [["shell", "defaults"]]
+ , "config_reader": [["CC", "prebuilt/read_pkgconfig.py"]]
+ }
+ , "field_doc":
+ { "project":
+ [ "The project directory. The disjoint union of the artifacts of the"
+ , "targets specified here are taken as project directory."
+ , "Its path can be accessed via the \"WORKDIR\" variable."
+ ]
+ , "name":
+ [ "The name of the library (without leading \"lib\" or trailing file name"
+ , "extension), also used as name for pkg-config files."
+ ]
+ , "version":
+ [ "The library version, used for pkg-config files. Individual version"
+ , "components are joined with \".\"."
+ ]
+ , "localbase": ["Artifacts to stage to \"LOCALBASE\"."]
+ , "cmds":
+ [ "List of commands to execute by \"sh\". Multiple commands will be"
+ , "joined with the newline character."
+ ]
+ , "resolve_symlinks":
+ [ "Resolve all symlinks in the install directory. This operation is"
+ , "performed immediately after \"cmds\" were executed."
+ ]
+ , "out_hdrs":
+ [ "Paths to produced public header files. The path is considered"
+ , "relative to the include directory, which be set via \"hdr_prefix\"."
+ , "Note that \"out_hdrs\" and \"out_hdr_dirs\" may not overlap."
+ ]
+ , "out_hdr_dirs":
+ [ "Paths to produced public header directories. The path is considered"
+ , "relative to the include directory, which be set via \"hdr_prefix\"."
+ , "Note that \"out_hdrs\" and \"out_hdr_dirs\" may not overlap."
+ ]
+ , "out_libs":
+ [ "Paths to produced library files. The path is considered relative"
+ , "to the library directory, which be set via \"lib_prefix\"."
+ , "Order matters in the case of one library depending on another."
+ ]
+ , "cflags":
+ ["List of compile flags set for this target and its consumers."]
+ , "ldflags":
+ [ "Additional linker flags that are required for the consumer of the"
+ , "produced libraries."
+ ]
+ , "stage":
+ [ "The logical location of the public headers and library files."
+ , "Individual directory components are joined with \"/\"."
+ ]
+ , "deps": ["Public dependency on other CC libraries."]
+ , "pkg-config":
+ [ "Pkg-config file for optional infer of public cflags and ldflags. If"
+ , "multiple files are specified (e.g., one depends on the other), the"
+ , "first one is used as entry. Note that if this field is non-empty the"
+ , "tool \"pkg-config\" must be available in \"PATH\", which is taken"
+ , "from [\"CC\", \"defaults\"] or the \"ENV\" variable."
+ ]
+ , "hdr_prefix":
+ [ "Prefix where headers will be installed by Make. Individual directory"
+ , "components are joined with \"/\". Defaults to \"include\" if not set."
+ ]
+ , "lib_prefix":
+ [ "Prefix where libraries will be installed by Make. Individual"
+ , "directory components are joined with \"/\". Defaults to \"lib\" if"
+ , "not set."
+ ]
+ , "pc_prefix":
+ [ "Prefix where pkg-config files will be installed by Make. Individual"
+ , "directory components are joined with \"/\". Defaults to"
+ , "\"lib/pkgconfig\" if not set."
+ ]
+ }
+ , "config_doc":
+ { "CC":
+ [ "The name of the C compiler to be used."
+ , "If null, the respective value from [\"CC\", \"defaults\"] will be taken."
+ ]
+ , "CXX":
+ [ "The name of the C++ compiler to be used."
+ , "If null, 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 linked 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 linked in a non-standard way; usually"
+ , "adapting the default target [\"CC\", \"defaults\"] is the better"
+ , "choice."
+ ]
+ , "ENV":
+ [ "The environment for any action generated."
+ , "If null, the respective value from [\"CC\", \"defaults\"] will be taken."
+ ]
+ , "AR":
+ [ "The archive tool to used for creating the library."
+ , "If null, the respective value from [\"CC\", \"defaults\"] will be taken."
+ ]
+ , "PREFIX":
+ [ "The absolute path that is used as prefix inside generated pkg-config"
+ , "files. The default value for this variable is \"/\". This variable"
+ , "is ignored if the field \"prefix\" is set."
+ ]
+ , "BUILD_POSITION_INDEPENDENT": ["Build position independent code."]
+ , "TIMEOUT_SCALE":
+ [ "The scaling of the timeout for the invocation of the foreign build."
+ , "Defaults to 10."
+ ]
+ , "FOREIGN_EXECUTION_PROPERTIES":
+ [ "A map with extra remote-execution properties to be added to the foreign build action."
+ ]
+ }
+ , "imports":
+ { "artifacts": ["", "field_artifacts"]
+ , "stage_field": ["", "stage_singleton_field"]
+ , "shell-build": "shell-build"
+ , "prebuilt result": ["CC/prebuilt", "prebuilt result"]
+ , "install-deps": ["CC", "install-with-deps stage"]
+ , "strip-prefix": ["CC/foreign", "strip-prefix"]
+ , "for host": ["transitions", "for host"]
+ }
+ , "config_transitions":
+ { "defaults":
+ [{"type": "empty_map"}, {"type": "CALL_EXPRESSION", "name": "for host"}]
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ [ "hdr_prefix"
+ , { "type": "join"
+ , "separator": "/"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ ["install"]
+ , { "type": "if"
+ , "cond": {"type": "FIELD", "name": "hdr_prefix"}
+ , "then": {"type": "FIELD", "name": "hdr_prefix"}
+ , "else": ["include"]
+ }
+ ]
+ }
+ }
+ ]
+ , [ "lib_prefix"
+ , { "type": "join"
+ , "separator": "/"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ ["install"]
+ , { "type": "if"
+ , "cond": {"type": "FIELD", "name": "lib_prefix"}
+ , "then": {"type": "FIELD", "name": "lib_prefix"}
+ , "else": ["lib"]
+ }
+ ]
+ }
+ }
+ ]
+ , [ "pc_prefix"
+ , { "type": "join"
+ , "separator": "/"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ ["install"]
+ , { "type": "if"
+ , "cond": {"type": "FIELD", "name": "pc_prefix"}
+ , "then": {"type": "FIELD", "name": "pc_prefix"}
+ , "else": ["lib", "pkgconfig"]
+ }
+ ]
+ }
+ }
+ ]
+ , [ "sources"
+ , { "type": "let*"
+ , "bindings": [["fieldname", "project"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "artifacts"}
+ }
+ ]
+ , [ "localbase"
+ , { "type": "disjoint_map_union"
+ , "msg": "localbase and installed dependency files may not overlap"
+ , "$1":
+ [ { "type": "let*"
+ , "bindings":
+ [ ["pc-install-dir", "lib/pkgconfig"]
+ , ["targets", {"type": "FIELD", "name": "deps"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "install-deps"}
+ }
+ , { "type": "let*"
+ , "bindings": [["fieldname", "localbase"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "artifacts"}
+ }
+ ]
+ }
+ ]
+ , [ "installed_dirs"
+ , { "type": "foreach"
+ , "var": "dir_path"
+ , "range": {"type": "FIELD", "name": "out_hdr_dirs"}
+ , "body":
+ { "type": "join"
+ , "separator": "/"
+ , "$1":
+ [ {"type": "var", "name": "hdr_prefix"}
+ , {"type": "var", "name": "dir_path"}
+ ]
+ }
+ }
+ ]
+ , [ "installed_files"
+ , { "type": "++"
+ , "$1":
+ [ { "type": "foreach"
+ , "var": "lib_path"
+ , "range": {"type": "FIELD", "name": "out_libs"}
+ , "body":
+ { "type": "join"
+ , "separator": "/"
+ , "$1":
+ [ {"type": "var", "name": "lib_prefix"}
+ , {"type": "var", "name": "lib_path"}
+ ]
+ }
+ }
+ , { "type": "foreach"
+ , "var": "hdr_path"
+ , "range": {"type": "FIELD", "name": "out_hdrs"}
+ , "body":
+ { "type": "join"
+ , "separator": "/"
+ , "$1":
+ [ {"type": "var", "name": "hdr_prefix"}
+ , {"type": "var", "name": "hdr_path"}
+ ]
+ }
+ }
+ , { "type": "foreach"
+ , "var": "pc_path"
+ , "range": {"type": "FIELD", "name": "pkg-config"}
+ , "body":
+ { "type": "join"
+ , "separator": "/"
+ , "$1":
+ [ {"type": "var", "name": "pc_prefix"}
+ , {"type": "var", "name": "pc_path"}
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ , ["cmds", {"type": "FIELD", "name": "cmds"}]
+ , ["resolve_symlinks", {"type": "FIELD", "name": "resolve_symlinks"}]
+ , ["defaults-transition", {"type": "empty_map"}]
+ , ["install_dir", {"type": "CALL_EXPRESSION", "name": "shell-build"}]
+ , [ "hdrs"
+ , { "type": "++"
+ , "$1":
+ [ { "type": "let*"
+ , "bindings":
+ [ ["artifacts", {"type": "var", "name": "install_dir"}]
+ , ["paths", {"type": "FIELD", "name": "out_hdrs"}]
+ , ["prefix", {"type": "var", "name": "hdr_prefix"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "strip-prefix"}
+ }
+ , { "type": "let*"
+ , "bindings":
+ [ ["artifacts", {"type": "var", "name": "install_dir"}]
+ , ["paths", {"type": "FIELD", "name": "out_hdr_dirs"}]
+ , ["prefix", {"type": "var", "name": "hdr_prefix"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "strip-prefix"}
+ }
+ ]
+ }
+ ]
+ , [ "libs"
+ , { "type": "let*"
+ , "bindings":
+ [ ["artifacts", {"type": "var", "name": "install_dir"}]
+ , ["paths", {"type": "FIELD", "name": "out_libs"}]
+ , ["prefix", {"type": "var", "name": "lib_prefix"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "strip-prefix"}
+ }
+ ]
+ , [ "config_reader"
+ , { "type": "let*"
+ , "bindings":
+ [["fieldname", "config_reader"], ["location", "config_reader"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "stage_field"}
+ }
+ ]
+ , [ "pkg-configs"
+ , { "type": "let*"
+ , "bindings":
+ [ ["artifacts", {"type": "var", "name": "install_dir"}]
+ , ["paths", {"type": "FIELD", "name": "pkg-config"}]
+ , ["prefix", {"type": "var", "name": "pc_prefix"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "strip-prefix"}
+ }
+ ]
+ , [ "name"
+ , { "type": "assert_non_empty"
+ , "msg": "name is required for make library"
+ , "$1": {"type": "join", "$1": {"type": "FIELD", "name": "name"}}
+ }
+ ]
+ , ["version", {"type": "FIELD", "name": "version"}]
+ , ["cflags", {"type": "FIELD", "name": "cflags"}]
+ , ["ldflags", {"type": "FIELD", "name": "ldflags"}]
+ , [ "stage"
+ , { "type": "join"
+ , "separator": "/"
+ , "$1": {"type": "FIELD", "name": "stage"}
+ }
+ ]
+ , ["deps-fieldnames", ["deps", "defaults"]]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "prebuilt result"}
+ }
+ }
+}
diff --git a/rules/CC/include_scan b/rules/CC/include_scan
new file mode 100755
index 0000000..b7c1590
--- /dev/null
+++ b/rules/CC/include_scan
@@ -0,0 +1,43 @@
+#!/bin/sh
+# Copyright 2024 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.
+
+#
+# Include scanner
+# Parse file paths from command's space-separated stdout, select those that
+# start with "include/", and copy them to the user-defined output directory.
+#
+# Usage:
+# include_scan OUT_DIR ARGV...
+#
+# Example:
+# ./include_scan.sh out gcc -isystem include foo.c -E -M
+# -> Generates output directory "out/include" from gcc's output
+
+set -eu
+
+readonly OUT_DIR="$1"
+shift
+
+STDOUT="$("$@")" || exit $?
+for FILE in $(echo "$STDOUT" | tr ' ' '\n' | sort | uniq); do
+ FILE="$(realpath -s -m --relative-to=. "${FILE}")"
+ if expr match "${FILE}" 'include/' >/dev/null; then
+ OUT_PATH="${OUT_DIR}/${FILE}"
+ if ! cp -n "${FILE}" "${OUT_PATH}" 2>/dev/null; then
+ mkdir -p "$(dirname "${OUT_PATH}")"
+ cp -n "${FILE}" "${OUT_PATH}"
+ fi
+ fi
+done
diff --git a/rules/CC/include_scan.c b/rules/CC/include_scan.c
new file mode 100644
index 0000000..ea013ad
--- /dev/null
+++ b/rules/CC/include_scan.c
@@ -0,0 +1,436 @@
+/* Copyright 2024 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.
+ */
+
+/*
+ * Include scanner
+ * Parse file paths from command's space-separated stdout, select those that
+ * start with "include/", and copy them to the user-defined output directory.
+ *
+ * Usage:
+ * include_scan OUT_DIR ARGV...
+ *
+ * Example:
+ * ./include_scan out gcc -isystem include foo.c -E -M
+ * -> Generates output directory "out/include" from gcc's output
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <error.h>
+#include <fcntl.h>
+#include <libgen.h> /* dirname */
+#include <linux/limits.h> /* PATH_MAX */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h> /* mkdir */
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#define READ_SIZE PATH_MAX /* support up to PATH_MAX path lengths */
+#define LIST_SIZE 1024 /* initial capacity of include list */
+
+/* Buffer that can load in chunks, while maintaining previously unread data */
+struct ShiftBuffer {
+ char *pos; /* position in full buffer */
+ char *start; /* start of buffer's second half */
+ size_t size; /* size of data in buffer's second half */
+ char buffer[READ_SIZE * 2 + 1];
+};
+
+/* List of includes that dynamically resizes */
+struct IncludeList {
+ char **pos; /* position for reading */
+ size_t size; /* number of list entries */
+ size_t capacity; /* maximum capacity */
+ char **list;
+};
+
+int helper_mkdir_p(char *path, mode_t mode);
+int helper_pathcmp(const void *a, const void *b);
+void helper_normpath(char *out_path, const char *in_path, size_t len);
+int helper_copyfile(const char *from, const char *to, int wopen_mayfail);
+
+/* ShiftBuffer functions */
+void sbuf_init(struct ShiftBuffer *sbuf);
+void sbuf_addpos(struct ShiftBuffer *sbuf, size_t offset);
+char *sbuf_pos(struct ShiftBuffer *sbuf);
+char *sbuf_end(struct ShiftBuffer *sbuf);
+int sbuf_eof(struct ShiftBuffer *sbuf);
+int sbuf_load(struct ShiftBuffer *sbuf, int fd);
+int sbuf_shift(struct ShiftBuffer *sbuf);
+
+/* IncludeList functions */
+void incl_init(struct IncludeList *incl);
+void incl_free(struct IncludeList *incl);
+void incl_resize(struct IncludeList *incl, size_t new_cap);
+void incl_append(struct IncludeList *incl, char *path);
+void incl_setpos(struct IncludeList *incl, size_t pos);
+char *incl_next(struct IncludeList *incl);
+
+/* Parse paths from fd's space-separated string, select those that start with
+ * pattern, and return normalized and deduplicated list.
+ */
+void parse_paths(struct IncludeList *incl, int fd, char const *pattern,
+ char const *prefix);
+
+int main(int argc, const char *argv[]) {
+ int fd[2];
+ pid_t pid;
+ int status = 0;
+ int retval = 0;
+ char *path = NULL;
+ char *prefix;
+ size_t prefix_len = 0;
+ struct IncludeList incl;
+
+ if (argc < 3) {
+ fprintf(stderr, "usage: %s PREFIX FILE ARGV...\n", argv[0]);
+ fprintf(stderr, "Missing arguments\n");
+ exit(EXIT_FAILURE);
+ }
+ if (pipe(fd) < 0) {
+ fprintf(stderr, "Failed to create pipe\n");
+ return 1;
+ }
+ pid = fork();
+ if (-1 == pid) {
+ fprintf(stderr, "Failed to fork process\n");
+ return 1;
+ }
+
+ if (pid == 0) { /* exec in child */
+ dup2(fd[1], STDOUT_FILENO);
+ close(fd[1]);
+ close(fd[0]);
+ execvp(argv[2], (char *const *)(argv + 2));
+ exit(EXIT_FAILURE);
+ }
+
+ close(fd[1]);
+
+ /* obtain include list from paths starting with "include/" */
+ incl_init(&incl);
+ prefix_len = strlen(argv[1]);
+ prefix = (char *)calloc(prefix_len + 2, sizeof(char));
+ strcat(prefix, argv[1]);
+ strcat(prefix + prefix_len, "/");
+ prefix_len += 1;
+ parse_paths(&incl, fd[0], "include/", prefix);
+ free(prefix);
+ close(fd[0]);
+
+ /* wait for child to finish */
+ while (1) {
+ if (waitpid(pid, &status, 0) == -1) {
+ fprintf(stderr, "Waiting for child failed with: %s\n", strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ if (WIFEXITED(status)) {
+ retval = WEXITSTATUS(status);
+ break;
+ } else if (WIFSIGNALED(status)) {
+ const int kSignalBit = 128;
+ int sig = WTERMSIG(status);
+ retval = kSignalBit + sig;
+ fprintf(stderr, "Child got killed by signal %d\n", sig);
+ break;
+ }
+ }
+
+ if (retval != 0) {
+ fprintf(stderr, "Include scanner received non-zero exit code from child\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /* copy files from unprefixed path */
+ incl_setpos(&incl, 0);
+ while ((path = incl_next(&incl)) != NULL) {
+ char *const to = path;
+ char *const from = to + prefix_len;
+ if (!helper_copyfile(from, to, /*wopen_mayfail=*/1)) {
+ if (helper_mkdir_p(to, 0755) != 0) {
+ fprintf(stderr, "mkdir failed: %s\n", to);
+ exit(EXIT_FAILURE);
+ }
+ if (!helper_copyfile(from, to, /*wopen_mayfail=*/0)) {
+ fprintf(stderr, "copy failed: %s\n", to);
+ exit(EXIT_FAILURE);
+ }
+ }
+ }
+
+ incl_free(&incl);
+
+ return 0;
+}
+
+void parse_paths(struct IncludeList *incl, int fd, char const *pattern,
+ char const *prefix) {
+ size_t path_len;
+ size_t prefix_len = strlen(prefix);
+ size_t pattern_len = strlen(pattern);
+
+ struct ShiftBuffer sbuf;
+ sbuf_init(&sbuf);
+
+ while (sbuf_load(&sbuf, fd) || !sbuf_eof(&sbuf)) {
+ do {
+ char *pos = sbuf_pos(&sbuf);
+ char *end = strchr(pos, ' ');
+ if (end == NULL) { /* not found */
+ if (!sbuf_shift(&sbuf)) {
+ fprintf(stderr, "File path too long for buffer\n");
+ exit(EXIT_FAILURE);
+ }
+ break; /* read next chunk in sbuf */
+ }
+
+ if (end >= sbuf_end(&sbuf)) { /* eof */
+ end = sbuf_end(&sbuf) - 1;
+ }
+
+ /* match prefix */
+ path_len = (size_t)end - (size_t)pos;
+ if (path_len >= pattern_len && strncmp(pattern, pos, pattern_len) == 0) {
+ size_t new_len = prefix_len + path_len + 1;
+ char *new_path = (char *)calloc(new_len, sizeof(char));
+ strcat(new_path, prefix);
+ helper_normpath(new_path + prefix_len, pos, path_len);
+ new_path[new_len - 1] = '\0';
+ incl_append(incl, new_path);
+ }
+ sbuf_addpos(&sbuf, path_len + 1);
+ } while (!sbuf_eof(&sbuf));
+ }
+
+ /* deduplicate */
+ if (incl->size > 1) {
+ size_t cmp_pos = 0;
+ size_t next_pos = 1;
+ if (incl->size > 2) {
+ qsort(incl->list, incl->size, sizeof(char *), helper_pathcmp);
+ }
+ /* uniq */
+ for (; next_pos < incl->size; ++next_pos) {
+ if (strcmp(incl->list[cmp_pos], incl->list[next_pos]) != 0) {
+ cmp_pos = next_pos;
+ } else { /* remove duplicate */
+ free(incl->list[next_pos]);
+ incl->list[next_pos] = NULL;
+ }
+ }
+ incl->size = cmp_pos + 1;
+ }
+}
+
+int helper_mkdir_p(char *path, mode_t mode) {
+ char *p = path;
+ while ((p = strchr(p + 1, '/'))) {
+ int ret;
+ *p = '\0';
+ ret = mkdir(path, mode);
+ *p = '/';
+ if (ret == -1 && errno != EEXIST)
+ return -1;
+ }
+ return 0;
+}
+
+int helper_pathcmp(const void *a, const void *b) {
+ return strcmp(*(const char **)a, *(const char **)b);
+}
+
+void helper_normpath(char *out_path, const char *in_path, size_t len) {
+ char *out_pos = out_path;
+ const char *in_pos = in_path;
+
+ while (in_pos < in_path + len) {
+ size_t seg_len;
+ const char *seg_end = strchr(in_pos, '/');
+ if (seg_end == NULL || seg_end > in_path + len - 1) {
+ seg_end = in_path + len - 1; /* last valid char */
+ }
+ seg_len = (size_t)seg_end - (size_t)in_pos + 1;
+ if (seg_len == 2 && strncmp(in_pos, "./", 2) == 0) {
+ in_pos += 2;
+ } else if (seg_len == 3 && strncmp(in_pos, "../", 3) == 0) {
+ in_pos += 3;
+ if (out_pos > out_path) {
+ *(out_pos - 1) = '\0';
+ out_pos = strrchr(out_path, '/') + 1;
+ } else {
+ out_pos = NULL;
+ }
+ if (out_pos == NULL) {
+ fprintf(stderr, "Cannot normalize upwards path %s\n", in_path);
+ exit(EXIT_FAILURE);
+ }
+ } else {
+ assert(out_pos + seg_len <= out_path + len);
+ strncpy(out_pos, in_pos, seg_len);
+ out_pos += seg_len;
+ in_pos += seg_len;
+ }
+ }
+}
+
+int helper_copyfile(const char *from, const char *to, int wopen_mayfail) {
+ FILE *in, *out;
+ char buf[READ_SIZE] = {'\0'};
+ size_t size;
+
+ out = fopen(to, "w");
+ if (out == NULL) {
+ if (errno == EEXIST) {
+ return 1; /* ok */
+ }
+ if (!wopen_mayfail) {
+ fprintf(stderr, "Cannot open output file for writing %s\n", to);
+ }
+ return 0;
+ }
+
+ in = fopen(from, "r");
+ if (in == NULL) {
+ fclose(out);
+ fprintf(stderr, "Cannot open input file for reading %s\n", from);
+ return 0;
+ }
+
+ while ((size = fread(buf, sizeof(*buf), sizeof(buf), in)) > 0) {
+ if (size != fwrite(buf, sizeof(*buf), size, out)) {
+ fclose(in);
+ fclose(out);
+ fprintf(stderr, "Failed writing output file %s\n", to);
+ return 0;
+ }
+ }
+
+ if (!feof(in)) {
+ fclose(in);
+ fclose(out);
+ fprintf(stderr, "Failed reading input file %s\n", from);
+ return 0;
+ }
+
+ fclose(in);
+ fclose(out);
+
+ return 1;
+}
+
+void sbuf_init(struct ShiftBuffer *sbuf) {
+ memset(sbuf->buffer, '\0', sizeof(sbuf->buffer));
+ sbuf->start = sbuf->buffer + READ_SIZE;
+ sbuf->pos = sbuf->start;
+ sbuf->size = 0;
+}
+
+void sbuf_addpos(struct ShiftBuffer *sbuf, size_t offset) {
+ sbuf->pos += offset;
+}
+
+char *sbuf_pos(struct ShiftBuffer *sbuf) { return sbuf->pos; }
+
+char *sbuf_end(struct ShiftBuffer *sbuf) { return sbuf->start + sbuf->size; }
+
+int sbuf_eof(struct ShiftBuffer *sbuf) { return sbuf->pos >= sbuf_end(sbuf); }
+
+int sbuf_load(struct ShiftBuffer *sbuf, int fd) {
+ int buf_size = 0;
+ int read_size = 0;
+ char *buf_pos = sbuf->start;
+ if (sbuf->pos >= sbuf_end(sbuf)) {
+ sbuf->pos = sbuf->start;
+ }
+ assert(sbuf->pos <= sbuf->start);
+ do {
+ read_size = read(fd, buf_pos, READ_SIZE - buf_size);
+ if (read_size < 0) {
+ fprintf(stderr, "read fd failed\n");
+ exit(EXIT_FAILURE);
+ }
+ buf_size += read_size;
+ buf_pos += read_size;
+ } while (buf_size < READ_SIZE && read_size != 0);
+ sbuf->size = buf_size;
+ if (read_size == 0) { /* finished, insert space to mark end of data */
+ *(sbuf->start + sbuf->size) = ' ';
+ }
+ return buf_size;
+}
+
+int sbuf_shift(struct ShiftBuffer *sbuf) {
+ if (!sbuf_eof(sbuf) && sbuf->pos >= sbuf->start) {
+ size_t size = (size_t)sbuf_end(sbuf) - (size_t)sbuf->pos;
+ char *new_pos = sbuf->start - size;
+ strncpy(new_pos, sbuf->pos, size);
+ sbuf->pos = new_pos;
+ return 1;
+ }
+ return 0; /* cannot shift, still valid data in buffer's first half */
+}
+
+void incl_init(struct IncludeList *incl) {
+ incl->list = (char **)calloc(LIST_SIZE + 1, sizeof(char *));
+ incl->pos = incl->list;
+ incl->size = 0;
+ incl->capacity = LIST_SIZE;
+}
+
+void incl_free(struct IncludeList *incl) {
+ char *path = NULL;
+ incl_setpos(incl, 0);
+ while ((path = incl_next(incl)) != NULL) {
+ free(path);
+ }
+ free(incl->list);
+}
+
+void incl_resize(struct IncludeList *incl, size_t new_cap) {
+ char **new_list = (char **)calloc(new_cap + 1, sizeof(char *));
+ assert(new_cap > incl->capacity);
+ memcpy(new_list, incl->list, sizeof(*incl->list) * incl->capacity);
+ incl_free(incl);
+ incl->list = new_list;
+ incl->capacity = new_cap;
+}
+
+void incl_append(struct IncludeList *incl, char *path) {
+ if (incl->size == incl->capacity) {
+ incl_resize(incl, incl->capacity * 2);
+ }
+ incl->list[incl->size++] = path;
+}
+
+void incl_setpos(struct IncludeList *incl, size_t pos) {
+ assert(pos <= incl->size);
+ incl->pos = incl->list + pos;
+}
+
+char *incl_next(struct IncludeList *incl) {
+ char **pos = incl->pos;
+ char **end = incl->list + incl->size;
+ assert(pos <= end);
+ while (pos < end) {
+ pos = incl->pos++;
+ if (*pos != NULL) {
+ return *pos;
+ }
+ }
+ return NULL;
+}
diff --git a/rules/CC/include_scan.py b/rules/CC/include_scan.py
new file mode 100755
index 0000000..e169ec5
--- /dev/null
+++ b/rules/CC/include_scan.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python3
+# Copyright 2024 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.
+
+#
+# Include scanner
+# Parse file paths from command's space-separated stdout, select those that
+# start with "include/", and copy them to the user-defined output directory.
+#
+# Usage:
+# include_scan OUT_DIR ARGV...
+#
+# Example:
+# ./include_scan.py out gcc -isystem include foo.c -E -M
+# -> Generates output directory "out/include" from gcc's output
+
+import subprocess
+import sys
+import os
+import shutil
+
+
+def include_scan(out_dir: str, cmd: list[str]):
+ proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
+ stdout, _ = proc.communicate()
+ if not stdout or proc.returncode != 0:
+ exit(proc.returncode)
+
+ items = stdout.decode('utf-8').replace('\n', ' ')
+ paths = {os.path.normpath(i) for i in items.split(' ')}
+ includes = {p for p in paths if p.startswith('include/')}
+
+ for path in includes:
+ out_path = os.path.join(out_dir, path)
+ try:
+ shutil.copyfile(path, out_path, follow_symlinks=False)
+ except:
+ try:
+ os.makedirs(os.path.dirname(out_path), exist_ok=True)
+ shutil.copyfile(path, out_path, follow_symlinks=False)
+ except Exception as e:
+ print(e, file=sys.stderr)
+ exit(1)
+
+
+if __name__ == '__main__':
+ include_scan(out_dir=sys.argv[1], cmd=sys.argv[2:])
diff --git a/rules/CC/pkgconfig/EXPRESSIONS b/rules/CC/pkgconfig/EXPRESSIONS
new file mode 100644
index 0000000..72d66fd
--- /dev/null
+++ b/rules/CC/pkgconfig/EXPRESSIONS
@@ -0,0 +1,296 @@
+{ "pkgconfig result":
+ { "vars": ["ENV", "name", "args", "stage"]
+ , "imports":
+ { "default-ENV": ["./", "..", "default-ENV"]
+ , "default-PATH": ["./", "..", "default-PATH"]
+ , "stage": ["", "stage_singleton_field"]
+ , "list_provider": ["", "field_list_provider"]
+ , "map_provider": ["", "field_map_provider"]
+ , "sh": ["shell", "sh"]
+ , "sh-PATH": ["shell", "PATH"]
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ [ "ENV"
+ , { "type": "map_union"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "default-ENV"}
+ , {"type": "var", "name": "ENV", "default": {"type": "empty_map"}}
+ ]
+ }
+ ]
+ , [ "ENV_PATH"
+ , { "type": "lookup"
+ , "map": {"type": "var", "name": "ENV"}
+ , "key": "PATH"
+ }
+ ]
+ , [ "ENV_PKG_CONFIG_PATH"
+ , { "type": "lookup"
+ , "map": {"type": "var", "name": "ENV"}
+ , "key": "PKG_CONFIG_PATH"
+ }
+ ]
+ , [ "sh-PATH"
+ , { "type": "let*"
+ , "bindings": [["fieldname", "shell defaults"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "sh-PATH"}
+ }
+ ]
+ , [ "pkgconfig PATH"
+ , { "type": "let*"
+ , "bindings":
+ [["fieldname", "pkgconfig defaults"], ["provider", "PATH"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "list_provider"}
+ }
+ ]
+ , [ "PKG_CONFIG_PATH"
+ , { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "pkgconfig defaults"]
+ , ["provider", "PKG_CONFIG_PATH"]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "list_provider"}
+ }
+ ]
+ , [ "final PATH"
+ , { "type": "join"
+ , "separator": ":"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "var", "name": "pkgconfig PATH"}
+ , {"type": "CALL_EXPRESSION", "name": "default-PATH"}
+ , {"type": "var", "name": "sh-PATH"}
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "ENV_PATH"}
+ , "then": [{"type": "var", "name": "ENV_PATH"}]
+ }
+ ]
+ }
+ }
+ ]
+ , [ "final PKG_CONFIG_PATH"
+ , { "type": "join"
+ , "separator": ":"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "var", "name": "PKG_CONFIG_PATH"}
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "ENV_PKG_CONFIG_PATH"}
+ , "then": [{"type": "var", "name": "ENV_PKG_CONFIG_PATH"}]
+ }
+ ]
+ }
+ }
+ ]
+ , [ "ENV"
+ , { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "ENV"}
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "final PATH"}
+ , "else": {"type": "empty_map"}
+ , "then":
+ { "type": "singleton_map"
+ , "key": "PATH"
+ , "value": {"type": "var", "name": "final PATH"}
+ }
+ }
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "final PKG_CONFIG_PATH"}
+ , "else": {"type": "empty_map"}
+ , "then":
+ { "type": "singleton_map"
+ , "key": "PKG_CONFIG_PATH"
+ , "value": {"type": "var", "name": "final PKG_CONFIG_PATH"}
+ }
+ }
+ ]
+ }
+ ]
+ , ["TOOLCHAIN_DIR", "toolchain"]
+ , [ "shell TOOLCHAIN"
+ , { "type": "to_subdir"
+ , "subdir": {"type": "var", "name": "TOOLCHAIN_DIR"}
+ , "$1":
+ { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "shell defaults"]
+ , ["provider", "TOOLCHAIN"]
+ , ["default", {"type": "empty_map"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "map_provider"}
+ }
+ }
+ ]
+ , [ "sh"
+ , { "type": "let*"
+ , "bindings": [["fieldname", "shell defaults"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "sh"}
+ }
+ ]
+ , [ "pkg-config"
+ , { "type": "join"
+ , "$1":
+ { "type": "let*"
+ , "bindings":
+ [["fieldname", "pkgconfig defaults"], ["provider", "pkg-config"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "list_provider"}
+ }
+ }
+ ]
+ , [ "pkg-config"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "pkg-config"}
+ , "then": {"type": "var", "name": "pkg-config"}
+ , "else": "pkg-config"
+ }
+ ]
+ , [ "cflags-filename"
+ , {"type": "join", "$1": [{"type": "var", "name": "name"}, ".cflags"]}
+ ]
+ , [ "cflags-files"
+ , { "type": "to_subdir"
+ , "subdir": {"type": "var", "name": "stage"}
+ , "$1":
+ { "type": "ACTION"
+ , "inputs": {"type": "var", "name": "shell TOOLCHAIN"}
+ , "cmd":
+ [ {"type": "var", "name": "sh"}
+ , "-c"
+ , { "type": "join"
+ , "separator": " "
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ [{"type": "var", "name": "pkg-config"}]
+ , [ { "type": "join_cmd"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "var", "name": "args", "default": []}
+ , ["--cflags", {"type": "var", "name": "name"}]
+ ]
+ }
+ }
+ ]
+ , [">"]
+ , [ { "type": "join_cmd"
+ , "$1": [{"type": "var", "name": "cflags-filename"}]
+ }
+ ]
+ ]
+ }
+ }
+ ]
+ , "env": {"type": "var", "name": "ENV"}
+ , "outs": [{"type": "var", "name": "cflags-filename"}]
+ }
+ }
+ ]
+ , [ "compile-args"
+ , { "type": "foreach_map"
+ , "var_key": "flag-file"
+ , "range": {"type": "var", "name": "cflags-files"}
+ , "body":
+ {"type": "join", "$1": ["@", {"type": "var", "name": "flag-file"}]}
+ }
+ ]
+ , [ "ldflags-filename"
+ , {"type": "join", "$1": [{"type": "var", "name": "name"}, ".ldflags"]}
+ ]
+ , [ "ldflags-files"
+ , { "type": "ACTION"
+ , "inputs": {"type": "var", "name": "shell TOOLCHAIN"}
+ , "cmd":
+ [ {"type": "var", "name": "sh"}
+ , "-c"
+ , { "type": "join"
+ , "separator": " "
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ [{"type": "var", "name": "pkg-config"}]
+ , [ { "type": "join_cmd"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "var", "name": "args", "default": []}
+ , ["--libs", {"type": "var", "name": "name"}]
+ ]
+ }
+ }
+ ]
+ , [">", "ldflags.raw"]
+ ]
+ }
+ }
+ ]
+ , "env": {"type": "var", "name": "ENV"}
+ , "outs": ["ldflags.raw"]
+ }
+ ]
+ , [ "add_rpath"
+ , { "type": "let*"
+ , "bindings": [["fieldname", "add_rpath"], ["location", "add_rpath"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "stage"}
+ }
+ ]
+ , [ "ldflags-files"
+ , { "type": "to_subdir"
+ , "subdir": {"type": "var", "name": "stage"}
+ , "$1":
+ { "type": "ACTION"
+ , "inputs":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "add_rpath"}
+ , {"type": "var", "name": "ldflags-files"}
+ , {"type": "var", "name": "shell TOOLCHAIN"}
+ ]
+ }
+ , "cmd":
+ [ {"type": "var", "name": "sh"}
+ , "-c"
+ , { "type": "join"
+ , "separator": " "
+ , "$1":
+ [ "./add_rpath $(cat ldflags.raw)"
+ , ">"
+ , { "type": "join_cmd"
+ , "$1": [{"type": "var", "name": "ldflags-filename"}]
+ }
+ ]
+ }
+ ]
+ , "env": {"type": "var", "name": "ENV"}
+ , "outs": [{"type": "var", "name": "ldflags-filename"}]
+ }
+ }
+ ]
+ , [ "link-args"
+ , { "type": "foreach_map"
+ , "var_key": "flag-file"
+ , "range": {"type": "var", "name": "ldflags-files"}
+ , "body":
+ {"type": "join", "$1": ["@", {"type": "var", "name": "flag-file"}]}
+ }
+ ]
+ , ["package", {"type": "env", "vars": ["cflags-files", "ldflags-files"]}]
+ , ["compile-deps", {"type": "empty_map"}]
+ , ["link-deps", {"type": "empty_map"}]
+ ]
+ , "body":
+ { "type": "RESULT"
+ , "provides":
+ { "type": "env"
+ , "vars":
+ ["compile-deps", "compile-args", "link-deps", "link-args", "package"]
+ }
+ }
+ }
+ }
+}
diff --git a/rules/CC/pkgconfig/RULES b/rules/CC/pkgconfig/RULES
new file mode 100644
index 0000000..f72fdf6
--- /dev/null
+++ b/rules/CC/pkgconfig/RULES
@@ -0,0 +1,124 @@
+{ "defaults":
+ { "doc": ["A rule to provide defaults for pkgconfig"]
+ , "string_fields": ["pkg-config", "PATH", "PKG_CONFIG_PATH"]
+ , "target_fields": ["base"]
+ , "field_doc":
+ { "pkg-config":
+ ["The name of the pkg-config binary to use, potentially with full path."]
+ , "PATH": ["Additional paths to add to \"PATH\" when calling pkg-config"]
+ , "PKG_CONFIG_PATH":
+ [ "Additional paths to add to \"PKG_CONFIG_PATH\" when calling pkg-config"
+ ]
+ , "base": ["Other targets (using the same rule) to inherit from."]
+ }
+ , "imports":
+ { "base-provides": ["./", "..", "defaults-base-provides"]
+ , "base-provides-++": ["./", "..", "defaults-base-provides-++"]
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["pkg-config", {"type": "FIELD", "name": "pkg-config"}]
+ , ["provider", "pkg-config"]
+ , [ "pkg-config"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "pkg-config"}
+ , "then": {"type": "var", "name": "pkg-config"}
+ , "else": {"type": "CALL_EXPRESSION", "name": "base-provides"}
+ }
+ ]
+ , ["PATH", {"type": "FIELD", "name": "PATH"}]
+ , ["provider", "PATH"]
+ , [ "PATH"
+ , { "type": "nub_left"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "var", "name": "PATH"}
+ , {"type": "CALL_EXPRESSION", "name": "base-provides-++"}
+ ]
+ }
+ }
+ ]
+ , ["PKG_CONFIG_PATH", {"type": "FIELD", "name": "PKG_CONFIG_PATH"}]
+ , ["provider", "PKG_CONFIG_PATH"]
+ , [ "PKG_CONFIG_PATH"
+ , { "type": "nub_left"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "var", "name": "PKG_CONFIG_PATH"}
+ , {"type": "CALL_EXPRESSION", "name": "base-provides-++"}
+ ]
+ }
+ }
+ ]
+ ]
+ , "body":
+ { "type": "RESULT"
+ , "provides":
+ {"type": "env", "vars": ["pkg-config", "PATH", "PKG_CONFIG_PATH"]}
+ }
+ }
+ }
+, "system_library":
+ { "doc": ["A system library via pkg-config"]
+ , "string_fields": ["name", "args", "stage"]
+ , "implicit":
+ { "defaults": [["./", "..", "defaults"]]
+ , "shell defaults": [["shell", "defaults"]]
+ , "add_rpath": ["add_rpath"]
+ , "pkgconfig defaults": ["defaults"]
+ }
+ , "config_vars": ["PKG_CONFIG_ARGS", "ENV"]
+ , "field_doc":
+ { "name": ["The pkg-config name of the library."]
+ , "args":
+ [ "Additional pkg-config arguments (e.g., \"--define-prefix\" or"
+ , "\"--static\"), appended to the config variable \"PKG_CONFIG_ARGS\"."
+ ]
+ , "stage": ["The stage of the internally created flag files."]
+ , "defaults": ["The C/C++ toolchain to use"]
+ , "pkgconfig defaults": ["The pkgconfig configuration to use"]
+ }
+ , "config_doc":
+ { "PKG_CONFIG_ARGS":
+ [ "Additional pkg-config arguments (e.g., \"--define-prefix\" or"
+ , "\"--static\")."
+ ]
+ , "ENV":
+ [ "The environment for any action generated. May contain colon-separated"
+ , "\"PKG_CONFIG_PATH\" for looking up pkg-config files; this variable,"
+ , "as well as \"PATH\", is prefixed by the values provided in"
+ , "the \"defaults\"."
+ ]
+ }
+ , "imports": {"pkgconfig result": "pkgconfig result"}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ [ "name"
+ , { "type": "assert_non_empty"
+ , "msg": "system_library requires non-empty name"
+ , "$1": {"type": "join", "$1": {"type": "FIELD", "name": "name"}}
+ }
+ ]
+ , [ "args"
+ , { "type": "++"
+ , "$1":
+ [ {"type": "var", "name": "PKG_CONFIG_ARGS", "default": []}
+ , {"type": "FIELD", "name": "args"}
+ ]
+ }
+ ]
+ , [ "stage"
+ , { "type": "join"
+ , "separator": "/"
+ , "$1": {"type": "FIELD", "name": "stage"}
+ }
+ ]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "pkgconfig result"}
+ }
+ }
+}
diff --git a/rules/CC/pkgconfig/TARGETS b/rules/CC/pkgconfig/TARGETS
new file mode 100644
index 0000000..705d1d7
--- /dev/null
+++ b/rules/CC/pkgconfig/TARGETS
@@ -0,0 +1 @@
+{"defaults": {"type": "defaults"}}
diff --git a/rules/CC/pkgconfig/add_rpath b/rules/CC/pkgconfig/add_rpath
new file mode 100755
index 0000000..d020f2b
--- /dev/null
+++ b/rules/CC/pkgconfig/add_rpath
@@ -0,0 +1,24 @@
+#!/bin/sh
+# Copyright 2023 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.
+
+for x in "$@"
+do
+ echo -n '' "$x"
+ case $x in
+ -L*) echo -n '' -Xlinker -rpath -Xlinker "$(expr "$x" : "..\(.*\)")"
+ ;;
+ esac
+done
+echo
diff --git a/rules/CC/prebuilt/EXPRESSIONS b/rules/CC/prebuilt/EXPRESSIONS
new file mode 100644
index 0000000..b84e494
--- /dev/null
+++ b/rules/CC/prebuilt/EXPRESSIONS
@@ -0,0 +1,503 @@
+{ "check-file-ending":
+ { "doc": ["Returns true if all file names end with the given ending."]
+ , "vars": ["files", "ending", "invert"]
+ , "vars_doc":
+ { "files": ["Artifact map that contains the files."]
+ , "ending": ["The ending to check for (without \".\")."]
+ , "invert": ["Invert condition to file name not ending with \"ending\"."]
+ }
+ , "expression":
+ { "type": "and"
+ , "$1":
+ { "type": "foreach"
+ , "var": "file"
+ , "range": {"type": "keys", "$1": {"type": "var", "name": "files"}}
+ , "body":
+ { "type": "let*"
+ , "bindings":
+ [ [ "is-equal"
+ , { "type": "=="
+ , "$1": {"type": "var", "name": "file"}
+ , "$2":
+ { "type": "change_ending"
+ , "$1": {"type": "var", "name": "file"}
+ , "ending":
+ { "type": "join"
+ , "$1": [".", {"type": "var", "name": "ending"}]
+ }
+ }
+ }
+ ]
+ ]
+ , "body":
+ { "type": "if"
+ , "cond": {"type": "var", "name": "invert", "default": false}
+ , "then":
+ { "type": "if"
+ , "cond": {"type": "var", "name": "is-equal"}
+ , "then": false
+ , "else": true
+ }
+ , "else": {"type": "var", "name": "is-equal"}
+ }
+ }
+ }
+ }
+ }
+, "check-libs-non-static":
+ { "doc":
+ [ "Returns true if all libs are non-static libraries or false otherwise."
+ , "Throws if static and non-static libraries are mixed."
+ ]
+ , "vars": ["libs"]
+ , "vars_doc": {"libs": ["List of artifact maps that contain the libraries."]}
+ , "imports": {"check-file-ending": "check-file-ending"}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["files", {"type": "map_union", "$1": {"type": "var", "name": "libs"}}]
+ , [ "static"
+ , { "type": "let*"
+ , "bindings": [["ending", "a"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "check-file-ending"}
+ }
+ ]
+ , [ "shared"
+ , { "type": "let*"
+ , "bindings": [["ending", "a"], ["invert", true]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "check-file-ending"}
+ }
+ ]
+ ]
+ , "body":
+ { "type": "if"
+ , "cond":
+ { "type": "or"
+ , "$1":
+ [ {"type": "var", "name": "static"}
+ , {"type": "var", "name": "shared"}
+ ]
+ }
+ , "then": {"type": "var", "name": "shared"}
+ , "else":
+ { "type": "fail"
+ , "msg": "Prebuilt library types (static/shared) may not be mixed."
+ }
+ }
+ }
+ }
+, "prebuilt result":
+ { "vars":
+ [ "ENV"
+ , "name"
+ , "version"
+ , "stage"
+ , "cflags"
+ , "ldflags"
+ , "libs"
+ , "hdrs"
+ , "config_reader"
+ , "pkg-configs"
+ , "deps-fieldnames"
+ ]
+ , "imports":
+ { "check-libs-non-static": "check-libs-non-static"
+ , "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"]
+ , "cflags-files-deps": ["./", "..", "cflags-files-deps"]
+ , "ldflags-files-deps": ["./", "..", "ldflags-files-deps"]
+ , "default-ENV": ["./", "..", "default-ENV"]
+ , "default-PATH": ["./", "..", "default-PATH"]
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ [ "shared"
+ , {"type": "CALL_EXPRESSION", "name": "check-libs-non-static"}
+ ]
+ , [ "lib-stage"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "shared"}
+ , "then": "."
+ , "else": {"type": "var", "name": "stage"}
+ }
+ ]
+ , [ "staged-libs"
+ , { "type": "foreach"
+ , "var": "lib"
+ , "range": {"type": "var", "name": "libs"}
+ , "body":
+ { "type": "to_subdir"
+ , "subdir": {"type": "var", "name": "lib-stage"}
+ , "flat": true
+ , "msg": "prebuilt libraries may not overlap"
+ , "$1": {"type": "var", "name": "lib"}
+ }
+ }
+ ]
+ , [ "link-args"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "shared"}
+ , "then": []
+ , "else":
+ { "type": "++"
+ , "$1":
+ { "type": "foreach"
+ , "var": "libs"
+ , "range": {"type": "var", "name": "staged-libs"}
+ , "body": {"type": "keys", "$1": {"type": "var", "name": "libs"}}
+ }
+ }
+ }
+ ]
+ , [ "run-libs-args"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "shared"}
+ , "then":
+ { "type": "++"
+ , "$1":
+ { "type": "foreach"
+ , "var": "libs"
+ , "range": {"type": "var", "name": "staged-libs"}
+ , "body": {"type": "keys", "$1": {"type": "var", "name": "libs"}}
+ }
+ }
+ }
+ ]
+ , [ "libs"
+ , { "type": "disjoint_map_union"
+ , "msg": "prebuilt libraries may not overlap"
+ , "$1": {"type": "var", "name": "staged-libs"}
+ }
+ ]
+ , [ "hdrs"
+ , { "type": "to_subdir"
+ , "subdir": {"type": "var", "name": "stage"}
+ , "$1":
+ { "type": "disjoint_map_union"
+ , "msg": "prebuilt headers may not overlap"
+ , "$1": {"type": "var", "name": "hdrs"}
+ }
+ }
+ ]
+ , ["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": "nub_right"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "var", "name": "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": "run-libs-args"}
+ , {"type": "var", "name": "ldflags"}
+ , {"type": "CALL_EXPRESSION", "name": "run-libs-args-deps"}
+ ]
+ }
+ }
+ ]
+ , [ "ENV"
+ , { "type": "map_union"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "default-ENV"}
+ , {"type": "var", "name": "ENV", "default": {"type": "empty_map"}}
+ ]
+ }
+ ]
+ , [ "ENV_PATH"
+ , { "type": "lookup"
+ , "map": {"type": "var", "name": "ENV"}
+ , "key": "PATH"
+ }
+ ]
+ , [ "ENV"
+ , { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "ENV"}
+ , { "type": "singleton_map"
+ , "key": "PATH"
+ , "value":
+ { "type": "join"
+ , "separator": ":"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "default-PATH"}
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "ENV_PATH"}
+ , "then": [{"type": "var", "name": "ENV_PATH"}]
+ }
+ ]
+ }
+ }
+ }
+ ]
+ }
+ ]
+ , [ "main-pkg-config"
+ , { "type": "foldl"
+ , "range":
+ { "type": "++"
+ , "$1":
+ { "type": "foreach"
+ , "var": "configs"
+ , "range": {"type": "var", "name": "pkg-configs", "default": []}
+ , "body":
+ {"type": "keys", "$1": {"type": "var", "name": "configs"}}
+ }
+ }
+ , "start": null
+ , "accum_var": "name"
+ , "var": "config"
+ , "body":
+ { "type": "if"
+ , "cond": {"type": "var", "name": "name"}
+ , "then": {"type": "var", "name": "name"}
+ , "else": {"type": "var", "name": "config"}
+ }
+ }
+ ]
+ , [ "reader-inputs"
+ , { "type": "to_subdir"
+ , "subdir": "lib"
+ , "$1":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "libs"}
+ , {"type": "var", "name": "link-deps"}
+ , {"type": "var", "name": "run-libs"}
+ , { "type": "to_subdir"
+ , "subdir": "pkgconfig"
+ , "flat": true
+ , "$1":
+ { "type": "map_union"
+ , "$1": {"type": "var", "name": "pkg-configs", "default": []}
+ }
+ }
+ ]
+ }
+ }
+ ]
+ , [ "pc-args"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "shared"}
+ , "then": []
+ , "else": ["--static"]
+ }
+ ]
+ , [ "cflags-filename"
+ , {"type": "join", "$1": [{"type": "var", "name": "name"}, ".cflags"]}
+ ]
+ , [ "cflags-file"
+ , { "type": "to_subdir"
+ , "subdir": {"type": "var", "name": "stage"}
+ , "$1":
+ { "type": "if"
+ , "cond": {"type": "var", "name": "pkg-configs"}
+ , "then":
+ { "type": "ACTION"
+ , "inputs":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "config_reader"}
+ , {"type": "var", "name": "reader-inputs"}
+ ]
+ }
+ , "cmd":
+ { "type": "++"
+ , "$1":
+ [ [ "./config_reader"
+ , {"type": "var", "name": "cflags-filename"}
+ , {"type": "var", "name": "main-pkg-config"}
+ ]
+ , {"type": "var", "name": "pc-args"}
+ ]
+ }
+ , "env": {"type": "var", "name": "ENV"}
+ , "outs": [{"type": "var", "name": "cflags-filename"}]
+ }
+ , "else": {"type": "empty_map"}
+ }
+ }
+ ]
+ , [ "cflags-files"
+ , { "type": "map_union"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "cflags-files-deps"}
+ , {"type": "var", "name": "cflags-file"}
+ ]
+ }
+ ]
+ , [ "compile-args"
+ , { "type": "++"
+ , "$1":
+ [ {"type": "var", "name": "compile-args"}
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "cflags-file"}
+ , "then":
+ [ { "type": "join"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ ["@"]
+ , { "type": "keys"
+ , "$1": {"type": "var", "name": "cflags-file"}
+ }
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ , [ "ldflags-filename"
+ , {"type": "join", "$1": [{"type": "var", "name": "name"}, ".ldflags"]}
+ ]
+ , [ "ldflags-file"
+ , { "type": "to_subdir"
+ , "subdir": {"type": "var", "name": "stage"}
+ , "$1":
+ { "type": "if"
+ , "cond": {"type": "var", "name": "pkg-configs"}
+ , "then":
+ { "type": "ACTION"
+ , "inputs":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "config_reader"}
+ , {"type": "var", "name": "reader-inputs"}
+ ]
+ }
+ , "cmd":
+ { "type": "++"
+ , "$1":
+ [ [ "./config_reader"
+ , {"type": "var", "name": "ldflags-filename"}
+ , {"type": "var", "name": "main-pkg-config"}
+ ]
+ , {"type": "var", "name": "pc-args"}
+ ]
+ }
+ , "env": {"type": "var", "name": "ENV"}
+ , "outs": [{"type": "var", "name": "ldflags-filename"}]
+ }
+ , "else": {"type": "empty_map"}
+ }
+ }
+ ]
+ , [ "ldflags-files"
+ , { "type": "map_union"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "ldflags-files-deps"}
+ , {"type": "var", "name": "ldflags-file"}
+ ]
+ }
+ ]
+ , [ "run-libs"
+ , { "type": "map_union"
+ , "$1":
+ [ { "type": "if"
+ , "cond": {"type": "var", "name": "shared"}
+ , "then": {"type": "var", "name": "libs"}
+ , "else": {"type": "empty_map"}
+ }
+ , {"type": "var", "name": "run-libs"}
+ ]
+ }
+ ]
+ , [ "run-libs-args"
+ , { "type": "++"
+ , "$1":
+ [ {"type": "var", "name": "run-libs-args"}
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "ldflags-file"}
+ , "then":
+ [ { "type": "join"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ ["@"]
+ , { "type": "keys"
+ , "$1": {"type": "var", "name": "ldflags-file"}
+ }
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ , [ "package"
+ , { "type": "let*"
+ , "bindings":
+ [ ["name", {"type": "var", "name": "name"}]
+ , [ "version"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "version"}
+ , "then":
+ { "type": "join"
+ , "separator": "."
+ , "$1": {"type": "var", "name": "version"}
+ }
+ , "else": null
+ }
+ ]
+ ]
+ , "body":
+ { "type": "env"
+ , "vars": ["name", "version", "cflags-files", "ldflags-files"]
+ }
+ }
+ ]
+ ]
+ , "body":
+ { "type": "RESULT"
+ , "artifacts": {"type": "var", "name": "libs"}
+ , "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"
+ , "package"
+ ]
+ }
+ ]
+ }
+ }
+ }
+ }
+}
diff --git a/rules/CC/prebuilt/RULES b/rules/CC/prebuilt/RULES
new file mode 100644
index 0000000..16f9f26
--- /dev/null
+++ b/rules/CC/prebuilt/RULES
@@ -0,0 +1,147 @@
+{ "library":
+ { "doc": ["A prebuilt C++ library"]
+ , "target_fields": ["lib", "hdrs", "deps", "pkg-config"]
+ , "string_fields":
+ ["name", "version", "stage", "defines", "cflags", "ldflags"]
+ , "implicit":
+ { "defaults": [["./", "..", "defaults"]]
+ , "config_reader": [["CC", "prebuilt/read_pkgconfig.py"]]
+ }
+ , "config_vars": ["ENV"]
+ , "field_doc":
+ { "name":
+ [ "The name of the library (without leading \"lib\" or trailing file name"
+ , "extension), also used as name for pkg-config files."
+ ]
+ , "version":
+ [ "The library version, used for pkg-config files. Individual version"
+ , "components are joined with \".\"."
+ ]
+ , "lib":
+ [ "The actual prebuilt library. If multiple libraries are specified"
+ , "(e.g., one depends on the other), the order matters. Library types"
+ , "cannot be mixed. All of them have to be either static or shared."
+ ]
+ , "hdrs": ["Any public header files of the library."]
+ , "deps": ["Any other libraries this library depends upon."]
+ , "stage":
+ [ "The logical location of all header and source files, as well as the"
+ , "resulting library file. Individual directory components are joined"
+ , "with \"/\"."
+ ]
+ , "defines":
+ [ "List of defines set for this target and its consumers."
+ , "Each list entry will be prepended by \"-D\"."
+ ]
+ , "cflags":
+ ["List of compile flags set for this target and its consumers."]
+ , "ldflags":
+ ["Additional linker flags (typically for linking system libraries)."]
+ , "pkg-config":
+ [ "Pkg-config file for optional infer of public cflags and ldflags. If"
+ , "multiple files are specified (e.g., one depends on the other), the"
+ , "first one is used as entry. Note that if this field is non-empty the"
+ , "tool \"pkg-config\" must be available in \"PATH\", which is taken"
+ , "from [\"CC\", \"defaults\"] or the \"ENV\" variable."
+ ]
+ }
+ , "artifacts_doc":
+ [ "The actual library (libname.a or libname.so). Only static libraries are"
+ , "staged in the specified directory."
+ ]
+ , "runfiles_doc": ["The public headers staged to the specified directory."]
+ , "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"
+ ]
+ , "run-libs":
+ [ "Map of artifacts specifying all files, including the artifacts of this"
+ , "library if shared, that have to be present in 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 this library."
+ ]
+ , "run-libs-args":
+ [ "List of strings that have to be added to the command line for linking"
+ , "runtime libraries in targets depending on this library."
+ ]
+ , "compile-args":
+ [ "List of strings that have to be added to the command line for compile"
+ , "actions in targets depending on this library."
+ ]
+ }
+ , "imports":
+ { "artifacts": ["./", "../..", "field_artifacts"]
+ , "artifacts_list": ["./", "../..", "field_artifacts_list"]
+ , "stage_field": ["", "stage_singleton_field"]
+ , "prebuilt result": "prebuilt result"
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ [ "name"
+ , { "type": "assert_non_empty"
+ , "msg": "name is required for prebuilt library"
+ , "$1": {"type": "join", "$1": {"type": "FIELD", "name": "name"}}
+ }
+ ]
+ , ["version", {"type": "FIELD", "name": "version"}]
+ , [ "stage"
+ , { "type": "join"
+ , "separator": "/"
+ , "$1": {"type": "FIELD", "name": "stage"}
+ }
+ ]
+ , [ "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"}]}
+ }
+ ]
+ }
+ ]
+ , ["ldflags", {"type": "FIELD", "name": "ldflags"}]
+ , [ "libs"
+ , { "type": "let*"
+ , "bindings": [["fieldname", "lib"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "artifacts_list"}
+ }
+ ]
+ , [ "hdrs"
+ , { "type": "let*"
+ , "bindings": [["fieldname", "hdrs"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "artifacts_list"}
+ }
+ ]
+ , [ "config_reader"
+ , { "type": "let*"
+ , "bindings":
+ [["fieldname", "config_reader"], ["location", "config_reader"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "stage_field"}
+ }
+ ]
+ , [ "pkg-configs"
+ , { "type": "let*"
+ , "bindings": [["fieldname", "pkg-config"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "artifacts_list"}
+ }
+ ]
+ , ["deps-fieldnames", ["deps"]]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "prebuilt result"}
+ }
+ }
+}
diff --git a/rules/CC/prebuilt/read_pkgconfig.py b/rules/CC/prebuilt/read_pkgconfig.py
new file mode 100755
index 0000000..115c305
--- /dev/null
+++ b/rules/CC/prebuilt/read_pkgconfig.py
@@ -0,0 +1,77 @@
+#!/usr/bin/env python3
+# Copyright 2023 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 subprocess
+import sys
+from pathlib import Path
+from typing import Dict, List, Set
+
+
+def run_pkgconfig(args: List[str], env: Dict[str, str]) -> str:
+ result = subprocess.run(["pkg-config"] + args, env=env, capture_output=True)
+ if result.returncode != 0:
+ print(result.stderr.decode("utf-8"), file=sys.stderr)
+ exit(1)
+ return result.stdout.decode("utf-8").strip()
+
+
+def read_ldflags(pkg: str, args: List[str], env: Dict[str, str]) -> str:
+ def libname(filename: str) -> str:
+ return filename.split(".")[0]
+
+ local_libs = {
+ libname(f)
+ for it in os.walk(".") for f in it[2] if f.startswith("lib")
+ }
+
+ link_flags = run_pkgconfig(args + ["--libs-only-l", pkg], env).split(" ")
+
+ # deduplicate, keep right-most
+ seen: Set[str] = set()
+ link_flags = [
+ f for f in link_flags[::-1] if f not in seen and not seen.add(f)
+ ][::-1]
+
+ def is_local(flag: str) -> bool:
+ if not flag.startswith("-l"):
+ return False
+ lib = libname(flag[3:]) if flag.startswith("-l:") else f"lib{flag[2:]}"
+ return lib in local_libs
+
+ return " ".join([f for f in link_flags if not is_local(f)])
+
+
+def read_pkgconfig() -> None:
+ if len(sys.argv) < 3:
+ print(f"usage: read_pkgconfig OUT_NAME PC_FILE [PC_ARGS...]")
+ exit(1)
+
+ name = sys.argv[1]
+ pkg = Path(sys.argv[2]).stem
+ args = sys.argv[3:]
+ env = dict(os.environ, PKG_CONFIG_PATH="./lib/pkgconfig")
+
+ if name.endswith(".cflags"):
+ data = run_pkgconfig(args + ["--cflags-only-other", pkg], env)
+ else:
+ data = read_ldflags(pkg, args, env)
+
+ with open(f"{name}", 'w') as f:
+ f.write(data)
+
+
+if __name__ == "__main__":
+ read_pkgconfig()
diff --git a/rules/CC/proto/EXPRESSIONS b/rules/CC/proto/EXPRESSIONS
new file mode 100644
index 0000000..0b44506
--- /dev/null
+++ b/rules/CC/proto/EXPRESSIONS
@@ -0,0 +1,489 @@
+{ "default-PROTOC":
+ { "vars": ["defaults-transition"]
+ , "imports": {"list_provider": ["./", "../..", "field_list_provider"]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "proto-defaults"]
+ , ["provider", "PROTOC"]
+ , ["transition", {"type": "var", "name": "defaults-transition"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "list_provider"}
+ }
+ }
+, "default-PROTOCFLAGS":
+ { "vars": ["defaults-transition"]
+ , "imports": {"list_provider": ["./", "../..", "field_list_provider"]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "proto-defaults"]
+ , ["provider", "PROTOCFLAGS"]
+ , ["transition", {"type": "var", "name": "defaults-transition"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "list_provider"}
+ }
+ }
+, "default-LDFLAGS":
+ { "vars": ["defaults-transition"]
+ , "imports": {"list_provider": ["./", "../..", "field_list_provider"]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "proto-defaults"]
+ , ["provider", "LDFLAGS"]
+ , ["transition", {"type": "var", "name": "defaults-transition"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "list_provider"}
+ }
+ }
+, "default-GRPC_PLUGIN":
+ { "vars": ["defaults-transition"]
+ , "imports": {"list_provider": ["./", "../..", "field_list_provider"]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "proto-defaults"]
+ , ["provider", "GRPC_PLUGIN"]
+ , ["transition", {"type": "var", "name": "defaults-transition"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "list_provider"}
+ }
+ }
+, "default-ENV":
+ { "vars": ["defaults-transition"]
+ , "imports": {"map_provider": ["./", "../..", "field_map_provider"]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "proto-defaults"]
+ , ["provider", "ENV"]
+ , ["transition", {"type": "var", "name": "defaults-transition"}]
+ , ["default", {"type": "empty_map"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "map_provider"}
+ }
+ }
+, "default-PATH":
+ { "vars": ["defaults-transition"]
+ , "imports": {"list_provider": ["./", "../..", "field_list_provider"]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "proto-defaults"]
+ , ["provider", "PATH"]
+ , ["transition", {"type": "var", "name": "defaults-transition"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "list_provider"}
+ }
+ }
+, "default-TOOLCHAIN":
+ { "vars": ["defaults-transition"]
+ , "imports": {"map_provider": ["./", "../..", "field_map_provider"]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "proto-defaults"]
+ , ["provider", "TOOLCHAIN"]
+ , ["transition", {"type": "var", "name": "defaults-transition"}]
+ , ["default", {"type": "empty_map"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "map_provider"}
+ }
+ }
+, "default-NON_SYSTEM_TOOLS":
+ { "vars": ["defaults-transition"]
+ , "expression":
+ { "type": "map_union"
+ , "$1":
+ { "type": "foreach"
+ , "var": "x"
+ , "range": {"type": "FIELD", "name": "proto-defaults"}
+ , "body":
+ { "type": "DEP_PROVIDES"
+ , "dep": {"type": "var", "name": "x"}
+ , "provider": "NON_SYSTEM_TOOLS"
+ , "transition":
+ { "type": "var"
+ , "name": "defaults-transition"
+ , "default": {"type": "empty_map"}
+ }
+ , "default": {"type": "empty_map"}
+ }
+ }
+ }
+ }
+, "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"
+ , "DEBUG"
+ , "name"
+ , "stage"
+ , "service support"
+ , "public-fieldnames"
+ , "private-fieldnames"
+ ]
+ , "imports":
+ { "stage": ["", "stage_singleton_field"]
+ , "result": ["./", "..", "lib result"]
+ , "runfiles": ["./", "../..", "field_runfiles"]
+ , "artifacts_list": ["./", "../..", "field_artifacts_list"]
+ , "protoc-deps": "protoc-deps"
+ , "default-PROTOC": "default-PROTOC"
+ , "default-PROTOCFLAGS": "default-PROTOCFLAGS"
+ , "default-LDFLAGS": "default-LDFLAGS"
+ , "default-GRPC_PLUGIN": "default-GRPC_PLUGIN"
+ , "default-ENV": "default-ENV"
+ , "default-PATH": "default-PATH"
+ , "default-TOOLCHAIN": "default-TOOLCHAIN"
+ , "default-NON_SYSTEM_TOOLS": "default-NON_SYSTEM_TOOLS"
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["pure C", false]
+ , ["TOOLCHAIN_DIR", "toolchain"]
+ , ["TOOLCHAIN", {"type": "CALL_EXPRESSION", "name": "default-TOOLCHAIN"}]
+ , [ "TOOLCHAIN"
+ , { "type": "to_subdir"
+ , "subdir": {"type": "var", "name": "TOOLCHAIN_DIR"}
+ , "$1": {"type": "var", "name": "TOOLCHAIN"}
+ }
+ ]
+ , [ "NON_SYSTEM_TOOLS"
+ , {"type": "CALL_EXPRESSION", "name": "default-NON_SYSTEM_TOOLS"}
+ ]
+ , [ "PROTOC"
+ , { "type": "join"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ { "type": "if"
+ , "cond":
+ { "type": "lookup"
+ , "key": "PROTOC"
+ , "map": {"type": "var", "name": "NON_SYSTEM_TOOLS"}
+ }
+ , "then": ["./", {"type": "var", "name": "TOOLCHAIN_DIR"}, "/"]
+ }
+ , {"type": "CALL_EXPRESSION", "name": "default-PROTOC"}
+ ]
+ }
+ }
+ ]
+ , [ "GRPC_PLUGIN"
+ , { "type": "join"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ { "type": "if"
+ , "cond":
+ { "type": "lookup"
+ , "key": "GRPC_PLUGIN"
+ , "map": {"type": "var", "name": "NON_SYSTEM_TOOLS"}
+ }
+ , "then": ["./", {"type": "var", "name": "TOOLCHAIN_DIR"}, "/"]
+ }
+ , {"type": "CALL_EXPRESSION", "name": "default-GRPC_PLUGIN"}
+ ]
+ }
+ }
+ ]
+ , [ "ENV"
+ , { "type": "map_union"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "default-ENV"}
+ , {"type": "var", "name": "ENV", "default": {"type": "empty_map"}}
+ ]
+ }
+ ]
+ , [ "ENV_PATH"
+ , { "type": "lookup"
+ , "map": {"type": "var", "name": "ENV"}
+ , "key": "PATH"
+ }
+ ]
+ , [ "protoc-ENV"
+ , { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "ENV"}
+ , { "type": "singleton_map"
+ , "key": "PATH"
+ , "value":
+ { "type": "join"
+ , "separator": ":"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "default-PATH"}
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "ENV_PATH"}
+ , "then": [{"type": "var", "name": "ENV_PATH"}]
+ }
+ ]
+ }
+ }
+ }
+ ]
+ }
+ ]
+ , ["protoc-deps", {"type": "CALL_EXPRESSION", "name": "protoc-deps"}]
+ , [ "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":
+ [ [{"type": "var", "name": "PROTOC"}]
+ , {"type": "CALL_EXPRESSION", "name": "default-PROTOCFLAGS"}
+ , ["--proto_path=work", "--cpp_out=work"]
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "service support"}
+ , "then":
+ [ "--grpc_out=work"
+ , { "type": "join"
+ , "$1":
+ [ "--plugin=protoc-gen-grpc="
+ , {"type": "var", "name": "GRPC_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": "TOOLCHAIN"}
+ ]
+ }
+ , "outs": {"type": "var", "name": "outs"}
+ , "cmd": {"type": "var", "name": "cmd"}
+ , "env": {"type": "var", "name": "protoc-ENV"}
+ }
+ ]
+ , [ "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", []]
+ , [ "private-ldflags"
+ , {"type": "CALL_EXPRESSION", "name": "default-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..e7a2f46
--- /dev/null
+++ b/rules/CC/proto/RULES
@@ -0,0 +1,371 @@
+{ "defaults":
+ { "doc":
+ [ "A rule to provide protoc/GRPC defaults."
+ , "Used to implement [\"CC/proto\", \"defaults\"] for CC proto libraries"
+ , "and [\"CC/proto\", \"service defaults\"] for CC proto service libraries"
+ , "(GRPC)."
+ ]
+ , "target_fields": ["base", "toolchain", "deps"]
+ , "string_fields":
+ [ "PROTOC"
+ , "PROTOCFLAGS"
+ , "ADD_PROTOCFLAGS"
+ , "LDFLAGS"
+ , "ADD_LDFLAGS"
+ , "GRPC_PLUGIN"
+ , "PATH"
+ ]
+ , "config_vars": ["ARCH", "HOST_ARCH", "DEBUG"]
+ , "field_doc":
+ { "base":
+ [ "Other targets (using the same rule) to inherit values from. If"
+ , "multiple targets are specified, for values that are overwritten (see"
+ , "documentation of other fields) the last specified value wins."
+ ]
+ , "toolchain":
+ [ "Optional toolchain directory. A collection of artifacts that provide"
+ , "the protobuf compiler and the GRPC plugin (if needed). Note that only"
+ , "artifacts of the specified targets are considered (no runfiles etc.)."
+ , "Specifying this field extends artifacts from \"base\"."
+ ]
+ , "deps":
+ [ "Optional CC libraries the resulting CC proto libraries implicitly"
+ , "depend on. Those are typically \"libprotobuf\" for CC proto libraries"
+ , "and \"libgrpc++\" for CC proto service libraries. Specifying this"
+ , "field extends dependencies from \"base\"."
+ ]
+ , "PROTOC":
+ [ "The proto compiler. If \"toolchain\" is empty, this field's value is"
+ , "considered the proto compiler name that is looked up in \"PATH\". If"
+ , "\"toolchain\" is non-empty, this field's value is assumed to be the"
+ , "relative path to the proto compiler in \"toolchain\". Specifying this"
+ , "field overwrites values from \"base\"."
+ ]
+ , "GRPC_PLUGIN":
+ [ "The GRPC plugin for the proto compiler. If \"toolchain\" is empty,"
+ , "this field's value is considered to be the absolute system path to the"
+ , "plugin. If \"toolchain\" is non-empty, this field's value is assumed"
+ , "to be the relative path to the plugin in \"toolchain\". Specifying"
+ , "this field overwrites values from \"base\"."
+ ]
+ , "PROTOCFLAGS":
+ [ "Protobuf compiler flags. Specifying this field overwrites values from"
+ , "\"base\"."
+ ]
+ , "ADD_PROTOCFLAGS":
+ [ "Additional protobuf compiler flags. Specifying this field extends"
+ , "values from \"base\"."
+ ]
+ , "LDFLAGS":
+ [ "Linker flags for linking the final CC library. Specifying this field"
+ , "overwrites values from \"base\"."
+ ]
+ , "ADD_LDFLAGS":
+ [ "Additional linker flags for linking the final CC library. Specifying"
+ , "this field extends values from \"base\"."
+ ]
+ , "PATH":
+ [ "Path for looking up the proto compiler. Individual paths are joined"
+ , "with \":\". Specifying this field extends values from \"base\"."
+ ]
+ }
+ , "config_doc":
+ { "ARCH":
+ [ "The unqualified architecture. Is taken as a default for \"HOST_ARCH\""
+ , "and \"TARGET_ARCH\" if not set."
+ ]
+ , "HOST_ARCH":
+ ["The architecture on which the build actions are carried out."]
+ , "DEBUG": ["Compute the debug-stage, needed for local debugging."]
+ }
+ , "imports":
+ { "base-provides": ["./", "..", "defaults-base-provides"]
+ , "base-provides-++": ["./", "..", "defaults-base-provides-++"]
+ , "base-provides-list": ["./", "..", "defaults-base-provides-list"]
+ , "artifacts_list": ["", "field_artifacts_list"]
+ , "compile-deps": ["CC", "compile-deps"]
+ , "compile-args-deps": ["CC", "compile-args-deps"]
+ , "link-deps": ["CC", "link-deps"]
+ , "link-args-deps": ["CC", "link-args-deps"]
+ , "run-libs-deps": ["CC", "run-libs-deps"]
+ , "run-libs-args-deps": ["CC", "run-libs-args-deps"]
+ , "cflags-files-deps": ["CC", "cflags-files-deps"]
+ , "ldflags-files-deps": ["CC", "ldflags-files-deps"]
+ , "for host": ["transitions", "for host"]
+ , "debug-deps": ["CC", "debug-deps"]
+ }
+ , "config_transitions":
+ {"toolchain": [{"type": "CALL_EXPRESSION", "name": "for host"}]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["PROTOC", {"type": "FIELD", "name": "PROTOC"}]
+ , ["PROTOCFLAGS", {"type": "FIELD", "name": "PROTOCFLAGS"}]
+ , ["LDFLAGS", {"type": "FIELD", "name": "LDFLAGS"}]
+ , ["GRPC_PLUGIN", {"type": "FIELD", "name": "GRPC_PLUGIN"}]
+ , ["PATH", {"type": "FIELD", "name": "PATH"}]
+ , ["provider", "PROTOC"]
+ , [ "PROTOC"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "PROTOC"}
+ , "then": {"type": "var", "name": "PROTOC"}
+ , "else": {"type": "CALL_EXPRESSION", "name": "base-provides"}
+ }
+ ]
+ , ["provider", "PROTOCFLAGS"]
+ , [ "PROTOCFLAGS"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "PROTOCFLAGS"}
+ , "then": {"type": "var", "name": "PROTOCFLAGS"}
+ , "else": {"type": "CALL_EXPRESSION", "name": "base-provides-++"}
+ }
+ ]
+ , ["provider", "LDFLAGS"]
+ , [ "LDFLAGS"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "LDFLAGS"}
+ , "then": {"type": "var", "name": "LDFLAGS"}
+ , "else": {"type": "CALL_EXPRESSION", "name": "base-provides-++"}
+ }
+ ]
+ , ["provider", "GRPC_PLUGIN"]
+ , [ "GRPC_PLUGIN"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "GRPC_PLUGIN"}
+ , "then": {"type": "var", "name": "GRPC_PLUGIN"}
+ , "else": {"type": "CALL_EXPRESSION", "name": "base-provides"}
+ }
+ ]
+ , ["provider", "PATH"]
+ , [ "PATH"
+ , { "type": "nub_left"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "var", "name": "PATH"}
+ , {"type": "CALL_EXPRESSION", "name": "base-provides-++"}
+ ]
+ }
+ }
+ ]
+ , ["provider", "ENV"]
+ , ["default", {"type": "empty_map"}]
+ , ["ENV", {"type": "CALL_EXPRESSION", "name": "base-provides"}]
+ , ["provider", "NON_SYSTEM_TOOLS"]
+ , ["default", {"type": "empty_map"}]
+ , [ "NON_SYSTEM_TOOLS"
+ , { "type": "map_union"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ [{"type": "CALL_EXPRESSION", "name": "base-provides"}]
+ , { "type": "if"
+ , "cond": {"type": "FIELD", "name": "PROTOC"}
+ , "then":
+ [ { "type": "singleton_map"
+ , "key": "PROTOC"
+ , "value":
+ { "type": "if"
+ , "cond": {"type": "FIELD", "name": "toolchain"}
+ , "then": true
+ , "else": false
+ }
+ }
+ ]
+ }
+ , { "type": "if"
+ , "cond": {"type": "FIELD", "name": "GRPC_PLUGIN"}
+ , "then":
+ [ { "type": "singleton_map"
+ , "key": "GRPC_PLUGIN"
+ , "value":
+ { "type": "if"
+ , "cond": {"type": "FIELD", "name": "toolchain"}
+ , "then": true
+ , "else": false
+ }
+ }
+ ]
+ }
+ ]
+ }
+ }
+ ]
+ , ["provider", "TOOLCHAIN"]
+ , ["default", {"type": "empty_map"}]
+ , [ "TOOLCHAIN"
+ , { "type": "disjoint_map_union"
+ , "msg": "toolchain artifacts may not overlap"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "base-provides-list"}
+ , { "type": "if"
+ , "cond": {"type": "FIELD", "name": "toolchain"}
+ , "then":
+ { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "toolchain"]
+ , [ "transition"
+ , {"type": "CALL_EXPRESSION", "name": "for host"}
+ ]
+ ]
+ , "body":
+ {"type": "CALL_EXPRESSION", "name": "artifacts_list"}
+ }
+ }
+ ]
+ }
+ }
+ ]
+ , [ "PROTOCFLAGS"
+ , { "type": "++"
+ , "$1":
+ [ {"type": "var", "name": "PROTOCFLAGS"}
+ , {"type": "FIELD", "name": "ADD_PROTOCFLAGS"}
+ ]
+ }
+ ]
+ , [ "LDFLAGS"
+ , { "type": "++"
+ , "$1":
+ [ {"type": "var", "name": "LDFLAGS"}
+ , {"type": "FIELD", "name": "ADD_LDFLAGS"}
+ ]
+ }
+ ]
+ , ["deps-fieldnames", ["base", "deps"]]
+ , ["compile-deps", {"type": "CALL_EXPRESSION", "name": "compile-deps"}]
+ , [ "compile-args"
+ , {"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": "CALL_EXPRESSION", "name": "run-libs-args-deps"}
+ ]
+ , [ "cflags-files"
+ , {"type": "CALL_EXPRESSION", "name": "cflags-files-deps"}
+ ]
+ , [ "ldflags-files"
+ , {"type": "CALL_EXPRESSION", "name": "ldflags-files-deps"}
+ ]
+ , ["package", {"type": "env", "vars": ["cflags-files", "ldflags-files"]}]
+ , [ "debug-srcs"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "DEBUG"}
+ , "then":
+ { "type": "let*"
+ , "bindings": [["deps-provider", "debug-srcs"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "debug-deps"}
+ }
+ , "else": {"type": "empty_map"}
+ }
+ ]
+ , [ "debug-hdrs"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "DEBUG"}
+ , "then":
+ { "type": "map_union"
+ , "$1":
+ [ { "type": "let*"
+ , "bindings": [["deps-provider", "debug-hdrs"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "debug-deps"}
+ }
+ , {"type": "var", "name": "compile-deps"}
+ ]
+ }
+ , "else": {"type": "empty_map"}
+ }
+ ]
+ ]
+ , "body":
+ { "type": "RESULT"
+ , "provides":
+ { "type": "env"
+ , "vars":
+ [ "PROTOC"
+ , "PROTOCFLAGS"
+ , "LDFLAGS"
+ , "GRPC_PLUGIN"
+ , "PATH"
+ , "ENV"
+ , "TOOLCHAIN"
+ , "NON_SYSTEM_TOOLS"
+ , "compile-deps"
+ , "compile-args"
+ , "link-deps"
+ , "link-args"
+ , "run-libs"
+ , "run-libs-args"
+ , "package"
+ , "debug-srcs"
+ , "debug-hdrs"
+ ]
+ }
+ }
+ }
+ }
+, "library":
+ { "doc":
+ [ "A 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": ["CXX", "CXXFLAGS", "ADD_CXXFLAGS", "AR", "ENV", "DEBUG"]
+ , "implicit":
+ {"defaults": [["./", "..", "defaults"]], "proto-defaults": ["defaults"]}
+ , "imports": {"protoc-compile": "protoc-compile"}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["name", {"type": "join", "$1": {"type": "FIELD", "name": "name"}}]
+ , [ "stage"
+ , { "type": "join"
+ , "separator": "/"
+ , "$1": {"type": "FIELD", "name": "stage"}
+ }
+ ]
+ , ["public-fieldnames", ["deps", "proto-defaults", "defaults"]]
+ , ["private-fieldnames", ["deps", "proto-defaults", "defaults"]]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "protoc-compile"}
+ }
+ }
+, "service library":
+ { "doc":
+ [ "A service 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": ["CXX", "CXXFLAGS", "ADD_CXXFLAGS", "AR", "ENV", "DEBUG"]
+ , "implicit":
+ { "defaults": [["./", "..", "defaults"]]
+ , "proto-defaults": ["service defaults"]
+ }
+ , "imports": {"protoc-compile": "protoc-compile"}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["service support", true]
+ , ["name", {"type": "join", "$1": {"type": "FIELD", "name": "name"}}]
+ , [ "stage"
+ , { "type": "join"
+ , "separator": "/"
+ , "$1": {"type": "FIELD", "name": "stage"}
+ }
+ ]
+ , ["public-fieldnames", ["deps", "proto-defaults", "defaults"]]
+ , ["private-fieldnames", ["deps", "proto-defaults", "defaults"]]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "protoc-compile"}
+ }
+ }
+}
diff --git a/rules/CC/proto/TARGETS b/rules/CC/proto/TARGETS
new file mode 100644
index 0000000..87bebd0
--- /dev/null
+++ b/rules/CC/proto/TARGETS
@@ -0,0 +1,16 @@
+{ "defaults":
+ { "type": ["CC/proto", "defaults"]
+ , "PROTOC": ["protoc"]
+ , "PATH": ["/bin", "/usr/bin"]
+ , "deps": ["libprotobuf"]
+ }
+, "service defaults":
+ { "type": ["CC/proto", "defaults"]
+ , "base": ["defaults"]
+ , "GRPC_PLUGIN": ["/usr/bin/grpc_cpp_plugin"]
+ , "deps": ["libgrpc++"]
+ }
+, "libprotobuf":
+ {"type": ["CC/pkgconfig", "system_library"], "name": ["protobuf"]}
+, "libgrpc++": {"type": ["CC/pkgconfig", "system_library"], "name": ["grpc++"]}
+}
diff --git a/rules/CC/test/EXPRESSIONS b/rules/CC/test/EXPRESSIONS
new file mode 100644
index 0000000..1389bbc
--- /dev/null
+++ b/rules/CC/test/EXPRESSIONS
@@ -0,0 +1,410 @@
+{ "run_test":
+ { "doc":
+ [ "Build and run a CC test binary using the provided runner."
+ , ""
+ , "Note that if variable RUNS_PER_TEST contains a non-false value, a"
+ , "summarizer must be provided."
+ ]
+ , "vars":
+ [ "ARCH"
+ , "HOST_ARCH"
+ , "TARGET_ARCH"
+ , "ARCH_DISPATCH"
+ , "TEST_SUMMARY_EXECUTION_PROPERTIES"
+ , "CC"
+ , "CXX"
+ , "CFLAGS"
+ , "CXXFLAGS"
+ , "ADD_CFLAGS"
+ , "ADD_CXXFLAGS"
+ , "ENV"
+ , "TEST_ENV"
+ , "TIMEOUT_SCALE"
+ , "CC_TEST_LAUNCHER"
+ , "RUNS_PER_TEST"
+ , "name"
+ , "pure C"
+ , "stage"
+ , "srcs"
+ , "private-hdrs"
+ , "private-defines"
+ , "private-cflags"
+ , "private-ldflags"
+ , "defaults-transition"
+ , "deps-transition"
+ , "deps-fieldnames"
+ , "runner"
+ , "runner-data"
+ , "test-args"
+ , "test-data"
+ , "summarizer"
+ , "summary artifacts"
+ , "LINT"
+ ]
+ , "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"]
+ , "cflags-files-deps": ["./", "..", "cflags-files-deps"]
+ , "ldflags-files-deps": ["./", "..", "ldflags-files-deps"]
+ , "binary": ["./", "..", "bin artifact"]
+ , "host transition": ["transitions", "for host"]
+ , "target properties": ["transitions", "target properties"]
+ , "stage": ["./", "../..", "stage_singleton_field"]
+ , "list_provider": ["./", "../..", "field_list_provider"]
+ , "lint": ["./", "..", "lint information"]
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ [ "cflags-files"
+ , {"type": "CALL_EXPRESSION", "name": "cflags-files-deps"}
+ ]
+ , ["compile-deps", {"type": "CALL_EXPRESSION", "name": "compile-deps"}]
+ , [ "compile-args"
+ , { "type": "++"
+ , "$1":
+ [ { "type": "foreach"
+ , "var": "def"
+ , "range":
+ {"type": "var", "name": "private-defines", "default": []}
+ , "body":
+ {"type": "join", "$1": ["-D", {"type": "var", "name": "def"}]}
+ }
+ , {"type": "var", "name": "private-cflags", "default": []}
+ , {"type": "CALL_EXPRESSION", "name": "compile-args-deps"}
+ ]
+ }
+ ]
+ , [ "ldflags-files"
+ , {"type": "CALL_EXPRESSION", "name": "ldflags-files-deps"}
+ ]
+ , ["link-deps", {"type": "CALL_EXPRESSION", "name": "link-deps"}]
+ , [ "link-args"
+ , { "type": "++"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "link-args-deps"}
+ , {"type": "var", "name": "private-ldflags", "default": []}
+ ]
+ }
+ ]
+ , ["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"}]
+ , [ "lint"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "LINT"}
+ , "then":
+ { "type": "let*"
+ , "bindings":
+ [ ["hdrs", {"type": "empty_map"}]
+ , [ "lint-deps fieldnames"
+ , ["private-hdrs", "srcs", "private-deps"]
+ ]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "lint"}
+ }
+ }
+ ]
+ , [ "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"}
+ }
+ }
+ }
+ ]
+ , [ "test-args"
+ , { "type": "singleton_map"
+ , "key": "test-args.json"
+ , "value":
+ { "type": "BLOB"
+ , "data":
+ { "type": "json_encode"
+ , "$1": {"type": "var", "name": "test-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": []}
+ }
+ }
+ }
+ ]
+ , [ "test-name"
+ , { "type": "join"
+ , "separator": "/"
+ , "$1":
+ [{"type": "var", "name": "stage"}, {"type": "var", "name": "name"}]
+ }
+ ]
+ , [ "test input"
+ , { "type": "map_union"
+ , "$1":
+ [ { "type": "to_subdir"
+ , "subdir": "work"
+ , "$1": {"type": "var", "name": "test-data"}
+ }
+ , {"type": "var", "name": "runner"}
+ , { "type": "var"
+ , "name": "runner-data"
+ , "default": {"type": "empty_map"}
+ }
+ , {"type": "var", "name": "test-args"}
+ , {"type": "var", "name": "test-launcher"}
+ , {"type": "var", "name": "staged test binary"}
+ , {"type": "var", "name": "run-libs"}
+ ]
+ }
+ ]
+ , [ "target properties"
+ , {"type": "CALL_EXPRESSION", "name": "target properties"}
+ ]
+ ]
+ , "body":
+ { "type": "if"
+ , "cond": {"type": "var", "name": "RUNS_PER_TEST"}
+ , "else":
+ { "type": "let*"
+ , "bindings":
+ [ [ "test-results"
+ , { "type": "ACTION"
+ , "outs":
+ [ "result"
+ , "stdout"
+ , "stderr"
+ , "time-start"
+ , "time-stop"
+ , "pwd"
+ ]
+ , "inputs": {"type": "var", "name": "test input"}
+ , "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"]
+ }
+ , "timeout scaling":
+ {"type": "var", "name": "TIMEOUT_SCALE", "default": 1.0}
+ , "execution properties":
+ {"type": "var", "name": "target properties"}
+ }
+ ]
+ , [ "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"}
+ , "provides": {"type": "env", "vars": ["lint"]}
+ }
+ }
+ , "then":
+ { "type": "let*"
+ , "bindings":
+ [ [ "attempts (plain)"
+ , { "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": "ACTION"
+ , "outs":
+ ["result", "stdout", "stderr", "time-start", "time-stop"]
+ , "inputs":
+ { "type": "map_union"
+ , "$1":
+ [ { "type": "singleton_map"
+ , "key": "ATTEMPT"
+ , "value":
+ { "type": "BLOB"
+ , "data": {"type": "var", "name": "ATTEMPT"}
+ }
+ }
+ , {"type": "var", "name": "test input"}
+ ]
+ }
+ , "cmd": ["./runner"]
+ , "env":
+ { "type": "var"
+ , "name": "TEST_ENV"
+ , "default": {"type": "empty_map"}
+ }
+ , "may_fail": ["test"]
+ , "no_cache": ["test"]
+ , "fail_message":
+ { "type": "join"
+ , "$1":
+ [ "CC test "
+ , {"type": "var", "name": "test-name"}
+ , " failed (Run"
+ , {"type": "var", "name": "ATTEMPT"}
+ , ")"
+ ]
+ }
+ , "timeout scaling":
+ {"type": "var", "name": "TIMEOUT_SCALE", "default": 1.0}
+ , "execution properties":
+ {"type": "var", "name": "target properties"}
+ }
+ }
+ }
+ }
+ ]
+ , [ "attempts (for summary)"
+ , { "type": "map_union"
+ , "$1":
+ { "type": "foreach_map"
+ , "range": {"type": "var", "name": "attempts (plain)"}
+ , "body":
+ { "type": "singleton_map"
+ , "key": {"type": "var", "name": "_"}
+ , "value":
+ { "type": "TREE"
+ , "$1":
+ { "type": "map_union"
+ , "$1":
+ { "type": "foreach"
+ , "range": {"type": "var", "name": "summary artifacts"}
+ , "body":
+ { "type": "singleton_map"
+ , "key": {"type": "var", "name": "_"}
+ , "value":
+ { "type": "lookup"
+ , "map": {"type": "var", "name": "$_"}
+ , "key": {"type": "var", "name": "_"}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ]
+ , [ "summary PATH"
+ , { "type": "join"
+ , "separator": ":"
+ , "$1":
+ { "type": "let*"
+ , "bindings":
+ [["fieldname", "shell-defaults"], ["provider", "PATH"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "list_provider"}
+ }
+ }
+ ]
+ , [ "summary"
+ , { "type": "ACTION"
+ , "inputs":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "attempts (for summary)"}
+ , {"type": "var", "name": "summarizer"}
+ ]
+ }
+ , "outs":
+ ["stdout", "stderr", "result", "time-start", "time-stop"]
+ , "cmd": ["./summarizer"]
+ , "execution properties":
+ { "type": "var"
+ , "name": "TEST_SUMMARY_EXECUTION_PROPERTIES"
+ , "default": {"type": "empty_map"}
+ }
+ , "env":
+ { "type": "if"
+ , "cond": {"type": "var", "name": "summary PATH"}
+ , "then":
+ { "type": "singleton_map"
+ , "key": "PATH"
+ , "value": {"type": "var", "name": "summary PATH"}
+ }
+ , "else": {"type": "empty_map"}
+ }
+ }
+ ]
+ , [ "attempts"
+ , { "type": "map_union"
+ , "$1":
+ { "type": "foreach_map"
+ , "range": {"type": "var", "name": "attempts (plain)"}
+ , "body":
+ { "type": "singleton_map"
+ , "key": {"type": "var", "name": "_"}
+ , "value":
+ {"type": "TREE", "$1": {"type": "var", "name": "$_"}}
+ }
+ }
+ }
+ ]
+ , [ "artifacts"
+ , { "type": "`"
+ , "$1":
+ { "pwd":
+ {"type": ",", "$1": {"type": "BLOB", "data": "/summary"}}
+ , "work":
+ { "type": ","
+ , "$1":
+ {"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"}
+ , "provides": {"type": "env", "vars": ["lint"]}
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/rules/CC/test/RULES b/rules/CC/test/RULES
new file mode 100644
index 0000000..3401974
--- /dev/null
+++ b/rules/CC/test/RULES
@@ -0,0 +1,287 @@
+{ "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"
+ , "TARGET_ARCH"
+ , "CC"
+ , "CXX"
+ , "CFLAGS"
+ , "CXXFLAGS"
+ , "LDFLAGS"
+ , "ADD_CFLAGS"
+ , "ADD_CXXFLAGS"
+ , "ADD_LDFLAGS"
+ , "ENV"
+ , "BUILD_POSITION_INDEPENDENT"
+ , "TEST_ENV"
+ , "TIMEOUT_SCALE"
+ , "CC_TEST_LAUNCHER"
+ , "RUNS_PER_TEST"
+ , "ARCH_DISPATCH"
+ , "TEST_SUMMARY_EXECUTION_PROPERTIES"
+ , "LINT"
+ ]
+ , "implicit":
+ { "defaults": [["./", "..", "defaults"]]
+ , "shell-defaults": [["./", "../../shell", "defaults"]]
+ , "runner": ["runner"]
+ , "summarizer": [["./", "../../shell/test", "summarizer"]]
+ }
+ , "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"
+ , ""
+ , "The resulting test binary is run in an environment where it can assume"
+ , "that the environment variable TEST_TMPDIR points to a"
+ , "directory that may be used exclusively by this test."
+ , "For convenience, the environment variable TMPDIR is also set to TEST_TMPDIR."
+ , ""
+ , "This running of the test is carried out by the implicit dependency"
+ , "on the target \"runner\". By setting this target in the target layer"
+ , "of this rules repository (instead of letting it default to the"
+ , "respective file), the C/C++ test environment can be modified globally."
+ ]
+ , "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"]
+ , "defaults": ["The C/C++ toolchain to use"]
+ , "shell-defaults":
+ ["The shell toolchain to use PATH from for calling the summary action"]
+ , "runner":
+ [ "The test runner which starts the actual test binary after providing"
+ , "the respective environment. The runner also takes care of capturing"
+ , "stdout/stderr and timing information."
+ ]
+ , "summarizer":
+ [ "Tool to aggregate the results of individual test runs (for flakyness"
+ , "detection) to an overall test result. If more fields than the result"
+ , "itself is needed, those can be specified using the \"summarizer\" rule."
+ ]
+ }
+ , "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."]
+ , "TIMEOUT_SCALE":
+ ["Factor on how to scale the timeout for this test. Defaults to 1.0."]
+ , "CC_TEST_LAUNCHER":
+ [ "List of strings representing the launcher that is prepend to the"
+ , "command line for running the test binary."
+ ]
+ , "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 runs are summarized by the [\"shell/test\", \"summarizer\"] that"
+ , "is also used by shell tests."
+ ]
+ , "TARGET_ARCH":
+ [ "The architecture to build the test for."
+ , ""
+ , "Will only be honored, if that architecture is available in the"
+ , "ARCH_DISPATCH map. Otherwise, the test will be built for and run"
+ , "on the host architecture."
+ ]
+ , "ARCH_DISPATCH":
+ [ "Map of architectures to execution properties that ensure execution"
+ , "on that architecture. Only the actual test binary will be run with"
+ , "the specified execution properties (i.e., on the target architecture);"
+ , "all building will be done on the host architecture."
+ ]
+ , "TEST_SUMMARY_EXECUTION_PROPERTIES":
+ [ "Additional remote-execution properties for the test-summarizing action"
+ , "in case RUNS_PER_TEST is set; defaults to the empty map."
+ ]
+ , "LINT":
+ [ "Also provide nodes describing compile actions and header files;"
+ , "those can be used by lint rules (doing also the config transition)"
+ , "for additional checks."
+ ]
+ }
+ , "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."
+ , "pwd: the directory in which the test was carried out"
+ ]
+ , "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"]
+ , "host transition": ["transitions", "maybe for host"]
+ , "stage": ["./", "../..", "stage_singleton_field"]
+ , "run_test": "run_test"
+ , "field_list": ["", "field_list_provider"]
+ }
+ , "config_transitions":
+ { "defaults": [{"type": "CALL_EXPRESSION", "name": "host transition"}]
+ , "private-deps": [{"type": "CALL_EXPRESSION", "name": "host transition"}]
+ , "private-hdrs": [{"type": "CALL_EXPRESSION", "name": "host transition"}]
+ , "srcs": [{"type": "CALL_EXPRESSION", "name": "host transition"}]
+ , "data": [{"type": "CALL_EXPRESSION", "name": "host transition"}]
+ , "runner": [{"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"}
+ }
+ ]
+ , ["host-trans", {"type": "CALL_EXPRESSION", "name": "host transition"}]
+ , [ "srcs"
+ , { "type": "to_subdir"
+ , "subdir": {"type": "var", "name": "stage"}
+ , "$1":
+ { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "srcs"]
+ , ["transition", {"type": "var", "name": "host-trans"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "artifacts"}
+ }
+ }
+ ]
+ , [ "private-hdrs"
+ , { "type": "to_subdir"
+ , "subdir": {"type": "var", "name": "stage"}
+ , "$1":
+ { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "private-hdrs"]
+ , ["transition", {"type": "var", "name": "host-trans"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "artifacts"}
+ }
+ }
+ ]
+ , ["defaults-transition", {"type": "var", "name": "host-trans"}]
+ , ["deps-transition", {"type": "var", "name": "host-trans"}]
+ , ["deps-fieldnames", ["private-deps", "defaults"]]
+ , [ "runner"
+ , { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "runner"]
+ , ["location", "runner"]
+ , ["transition", {"type": "var", "name": "host-trans"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "stage"}
+ }
+ ]
+ , ["test-args", {"type": "FIELD", "name": "args", "default": []}]
+ , [ "test-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"}
+ ]
+ }
+ }
+ ]
+ , [ "summarizer"
+ , { "type": "let*"
+ , "bindings":
+ [["fieldname", "summarizer"], ["location", "summarizer"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "stage"}
+ }
+ ]
+ , [ "summary artifacts"
+ , { "type": "++"
+ , "$1":
+ [ ["result"]
+ , { "type": "let*"
+ , "bindings":
+ [["provider", "artifacts"], ["fieldname", "summarizer"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "field_list"}
+ }
+ ]
+ }
+ ]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "run_test"}
+ }
+ }
+}
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/runner b/rules/CC/test/runner
new file mode 100755
index 0000000..4984b17
--- /dev/null
+++ b/rules/CC/test/runner
@@ -0,0 +1,71 @@
+#!/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: float = time.time()
+time_stop: float = 0
+result: str = "UNKNOWN"
+stderr: str = ""
+stdout: str = ""
+
+
+def dump_results() -> None:
+ 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, ))
+ with open("pwd", "w") as f:
+ f.write("%s\n" % (os.getcwd(), ))
+
+
+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, 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..0c1f611
--- /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": "'", "$1": {"PATH": "/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/EXPRESSIONS b/rules/data/EXPRESSIONS
new file mode 100644
index 0000000..929eaf8
--- /dev/null
+++ b/rules/data/EXPRESSIONS
@@ -0,0 +1,113 @@
+{ "field_artifacts_without":
+ { "doc":
+ [ "Query and merge artifacts from target_field's targets,"
+ , "leaving out the specified logical paths."
+ ]
+ , "vars": ["fieldname", "transition", "exclude"]
+ , "vars_doc":
+ { "fieldname": ["The name of the target_field to query."]
+ , "transition": ["The optional configuration transition for the targets."]
+ , "exclude": ["The logical paths to exclude"]
+ }
+ , "expression":
+ { "type": "disjoint_map_union"
+ , "msg":
+ [ "artifacts"
+ , {"type": "var", "name": "fieldname"}
+ , "must not overlap after dropping paths"
+ , {"type": "var", "name": "exclude"}
+ ]
+ , "$1":
+ { "type": "foreach"
+ , "var": "x"
+ , "range":
+ {"type": "FIELD", "name": {"type": "var", "name": "fieldname"}}
+ , "body":
+ { "type": "map_union"
+ , "$1":
+ { "type": "foreach_map"
+ , "range":
+ { "type": "DEP_ARTIFACTS"
+ , "dep": {"type": "var", "name": "x"}
+ , "transition":
+ { "type": "var"
+ , "name": "transition"
+ , "default": {"type": "empty_map"}
+ }
+ }
+ , "body":
+ { "type": "if"
+ , "cond":
+ { "type": "lookup"
+ , "key": {"type": "var", "name": "_"}
+ , "map": {"type": "var", "name": "exclude"}
+ }
+ , "then": {"type": "empty_map"}
+ , "else":
+ { "type": "singleton_map"
+ , "key": {"type": "var", "name": "_"}
+ , "value": {"type": "var", "name": "$_"}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+, "field_runfiles_without":
+ { "doc":
+ [ "Query and merge runfiles from target_field's targets,"
+ , "leaving out the specified logical paths."
+ ]
+ , "vars": ["fieldname", "transition", "exclude"]
+ , "vars_doc":
+ { "fieldname": ["The name of the target_field to query."]
+ , "transition": ["The optional configuration transition for the targets."]
+ , "exclude": ["The logical paths to exclude"]
+ }
+ , "expression":
+ { "type": "disjoint_map_union"
+ , "msg":
+ [ "artifacts"
+ , {"type": "var", "name": "fieldname"}
+ , "must not overlap after dropping paths"
+ , {"type": "var", "name": "exclude"}
+ ]
+ , "$1":
+ { "type": "foreach"
+ , "var": "x"
+ , "range":
+ {"type": "FIELD", "name": {"type": "var", "name": "fieldname"}}
+ , "body":
+ { "type": "map_union"
+ , "$1":
+ { "type": "foreach_map"
+ , "range":
+ { "type": "DEP_RUNFILES"
+ , "dep": {"type": "var", "name": "x"}
+ , "transition":
+ { "type": "var"
+ , "name": "transition"
+ , "default": {"type": "empty_map"}
+ }
+ }
+ , "body":
+ { "type": "if"
+ , "cond":
+ { "type": "lookup"
+ , "key": {"type": "var", "name": "_"}
+ , "map": {"type": "var", "name": "exclude"}
+ }
+ , "then": {"type": "empty_map"}
+ , "else":
+ { "type": "singleton_map"
+ , "key": {"type": "var", "name": "_"}
+ , "value": {"type": "var", "name": "$_"}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/rules/data/RULES b/rules/data/RULES
new file mode 100644
index 0000000..ab5c92e
--- /dev/null
+++ b/rules/data/RULES
@@ -0,0 +1,138 @@
+{ "staged":
+ { "doc": ["Stage data to a logical subdirectory."]
+ , "target_fields": ["srcs", "deps"]
+ , "string_fields": ["stage", "drop"]
+ , "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."
+ ]
+ , "drop":
+ [ "List of paths to drop from (each of) the \"srcs\" targets"
+ , "before joining and staging. In this way, GLOB constructs can"
+ , "be used is \"srcs\"."
+ ]
+ }
+ , "artifacts_doc":
+ [ "The runfiles and artifacts of the \"srcs\" targets, leaving out"
+ , "the ones with logical path in \"drop\", 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"]
+ , "runfiles w/o": "field_runfiles_without"
+ , "artifacts w/o": "field_artifacts_without"
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ [ "stage"
+ , { "type": "join"
+ , "separator": "/"
+ , "$1": {"type": "FIELD", "name": "stage"}
+ }
+ ]
+ , [ "exclude"
+ , { "type": "map_union"
+ , "$1":
+ { "type": "foreach"
+ , "range": {"type": "FIELD", "name": "drop"}
+ , "body":
+ { "type": "singleton_map"
+ , "key": {"type": "var", "name": "_"}
+ , "value": true
+ }
+ }
+ }
+ ]
+ , [ "srcs"
+ , { "type": "let*"
+ , "bindings": [["fieldname", "srcs"]]
+ , "body":
+ { "type": "map_union"
+ , "$1":
+ { "type": "if"
+ , "cond": {"type": "var", "name": "exclude"}
+ , "then":
+ [ {"type": "CALL_EXPRESSION", "name": "runfiles w/o"}
+ , {"type": "CALL_EXPRESSION", "name": "artifacts w/o"}
+ ]
+ , "else":
+ [ {"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/lint/RULES b/rules/lint/RULES
new file mode 100644
index 0000000..6bdfba7
--- /dev/null
+++ b/rules/lint/RULES
@@ -0,0 +1,278 @@
+{ "defaults":
+ { "doc":
+ [ "A rule to provide default paths common to all lint targets."
+ , ""
+ , "While lint targets bring their own host directory via the"
+ , "field \"config\", it can still be necessary to bring some"
+ , "default paths, e.g., for finding the compiler, or the interpreter"
+ , "for the runner."
+ ]
+ , "string_fields": ["PATH"]
+ , "target_fields": ["base"]
+ , "field_doc":
+ { "base": ["Other targets to inherit values from."]
+ , "PATH":
+ [ "Paths for looking up system tools."
+ , "Specifying this field extends values from \"base\"."
+ ]
+ }
+ , "imports": {"base-provides-++": ["CC", "defaults-base-provides-++"]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ [ "PATH"
+ , { "type": "nub_left"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "FIELD", "name": "PATH"}
+ , { "type": "let*"
+ , "bindings": [["provider", "PATH"]]
+ , "body":
+ {"type": "CALL_EXPRESSION", "name": "base-provides-++"}
+ }
+ ]
+ }
+ }
+ ]
+ ]
+ , "body": {"type": "RESULT", "provides": {"type": "env", "vars": ["PATH"]}}
+ }
+ }
+, "targets":
+ { "doc":
+ [ "Run a given linter on the lint information provided by the given targets."
+ ]
+ , "target_fields": ["linter", "config", "summarizer", "targets"]
+ , "string_fields": ["name"]
+ , "tainted": ["lint"]
+ , "field_doc":
+ { "linter":
+ [ "Single artifact running the lint checks."
+ , ""
+ , "This program is invoked with"
+ , "- argv[1] the file to lint, and"
+ , "- argv[2:] the original command line."
+ , "This invocation happens in an environment with"
+ , "- CONFIG pointing to the directory with all the artifacts given"
+ , " by the field \"config\", and"
+ , "- OUT pointing to a directory to which files with the lint result"
+ , " can be written."
+ , "- META pointing to a json file contaning"
+ , " - at key \"direct deps artifact names\" a list of all input"
+ , " artifacts that come from the target itself or are runfiles of a"
+ , " direct dependency."
+ , "- TMPDIR pointing to a directory location that can be used to"
+ , " create additional temporary files."
+ , "It is supposed to indicate by the exit code whether the file to lint"
+ , "complies with the given linting policy, with 0 meaning"
+ , "compliant."
+ , "Stdout and stderr, as well as the directory ${OUT} can be used to"
+ , "provide additional information."
+ ]
+ , "config": ["Any configuration or other files needed by the linter."]
+ , "summarizer":
+ [ "Single artifact generating a summary of the individual lint results."
+ , "It will be called in a directory where all subdirectories"
+ , "except . and .. represent the results of the individual lint"
+ , "actions. Those are given as"
+ , " - a file \"result\" with content \"PASS\" if and only if the lint"
+ , " action exited 0,"
+ , " - files \"stdout\" and \"stderr\" with stdout and stderr of the lint"
+ , " action, and"
+ , " - a directory \"out\" with the additional information provided by the"
+ , " lint action."
+ , "The summarizer is required to indicate the overall result by the exit"
+ , "code, produce a human-readable summary on stdout, and optionally"
+ , "additional information in the directory ${OUT}."
+ ]
+ , "call_lint": ["Launcher for the linter"]
+ , "call_summary": ["Launcher for the summarizer"]
+ , "name":
+ [ "Name of the kind of lint check performed, to be reported"
+ , "when an action is failing."
+ ]
+ }
+ , "implicit":
+ { "defaults": ["defaults"]
+ , "call_lint": ["call_lint"]
+ , "call_summary": ["call_summary"]
+ }
+ , "config_transitions": {"targets": [{"type": "'", "$1": {"LINT": true}}]}
+ , "anonymous":
+ {"lint": {"target": "targets", "provider": "lint", "rule_map": {}}}
+ , "imports":
+ { "stage": ["", "stage_singleton_field"]
+ , "artifacts": ["", "field_artifacts"]
+ , "default-PATH": ["CC", "default-PATH"]
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ [ "linter"
+ , { "type": "let*"
+ , "bindings": [["fieldname", "linter"], ["location", "linter"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "stage"}
+ }
+ ]
+ , [ "runner"
+ , { "type": "let*"
+ , "bindings": [["fieldname", "call_lint"], ["location", "runner"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "stage"}
+ }
+ ]
+ , [ "config"
+ , { "type": "let*"
+ , "bindings": [["fieldname", "config"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "artifacts"}
+ }
+ ]
+ , [ "PATH"
+ , { "type": "join"
+ , "separator": ":"
+ , "$1": {"type": "CALL_EXPRESSION", "name": "default-PATH"}
+ }
+ ]
+ , ["name", {"type": "join", "$1": {"type": "FIELD", "name": "name"}}]
+ , [ "lint results"
+ , { "type": "foreach"
+ , "range": {"type": "FIELD", "name": "lint"}
+ , "body":
+ { "type": "let*"
+ , "bindings":
+ [ [ "src"
+ , { "type": "DEP_PROVIDES"
+ , "dep": {"type": "var", "name": "_"}
+ , "provider": "src"
+ }
+ ]
+ , [ "cmd"
+ , { "type": "DEP_PROVIDES"
+ , "dep": {"type": "var", "name": "_"}
+ , "provider": "cmd"
+ }
+ ]
+ , [ "src input"
+ , { "type": "DEP_ARTIFACTS"
+ , "dep": {"type": "var", "name": "_"}
+ }
+ ]
+ , [ "direct deps artifact names"
+ , { "type": "DEP_PROVIDES"
+ , "dep": {"type": "var", "name": "_"}
+ , "provider": "direct deps artifact names"
+ }
+ ]
+ ]
+ , "body":
+ { "type": "TREE"
+ , "$1":
+ { "type": "ACTION"
+ , "inputs":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "runner"}
+ , {"type": "var", "name": "linter"}
+ , { "type": "to_subdir"
+ , "subdir": "work"
+ , "$1": {"type": "var", "name": "src input"}
+ }
+ , { "type": "to_subdir"
+ , "subdir": "config"
+ , "$1": {"type": "var", "name": "config"}
+ }
+ , { "type": "singleton_map"
+ , "key": "meta.json"
+ , "value":
+ { "type": "BLOB"
+ , "data":
+ { "type": "json_encode"
+ , "$1":
+ { "type": "env"
+ , "vars": ["direct deps artifact names"]
+ }
+ }
+ }
+ }
+ ]
+ }
+ , "cmd":
+ { "type": "++"
+ , "$1":
+ [ ["./runner", {"type": "var", "name": "src"}]
+ , {"type": "var", "name": "cmd"}
+ ]
+ }
+ , "env": {"type": "env", "vars": ["PATH"]}
+ , "outs": ["stdout", "stderr", "result"]
+ , "out_dirs": ["out"]
+ , "may_fail": ["lint"]
+ , "fail_message":
+ { "type": "join"
+ , "$1":
+ [ "lint "
+ , {"type": "var", "name": "name"}
+ , " failed for "
+ , {"type": "var", "name": "src"}
+ ]
+ }
+ }
+ }
+ }
+ }
+ ]
+ , [ "lint results"
+ , {"type": "nub_right", "$1": {"type": "var", "name": "lint results"}}
+ ]
+ , [ "summary input"
+ , {"type": "enumerate", "$1": {"type": "var", "name": "lint results"}}
+ ]
+ , [ "summarizer"
+ , { "type": "let*"
+ , "bindings":
+ [["fieldname", "summarizer"], ["location", "summarizer"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "stage"}
+ }
+ ]
+ , [ "runner"
+ , { "type": "let*"
+ , "bindings": [["fieldname", "call_summary"], ["location", "runner"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "stage"}
+ }
+ ]
+ , [ "summary"
+ , { "type": "ACTION"
+ , "inputs":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "runner"}
+ , {"type": "var", "name": "summarizer"}
+ , { "type": "to_subdir"
+ , "subdir": "work"
+ , "$1": {"type": "var", "name": "summary input"}
+ }
+ ]
+ }
+ , "cmd": ["./runner"]
+ , "outs": ["report", "result"]
+ , "out_dirs": ["out"]
+ }
+ ]
+ ]
+ , "body":
+ { "type": "RESULT"
+ , "artifacts":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "summary"}
+ , { "type": "singleton_map"
+ , "key": "work"
+ , "value":
+ {"type": "TREE", "$1": {"type": "var", "name": "summary input"}}
+ }
+ ]
+ }
+ }
+ }
+ }
+}
diff --git a/rules/lint/TARGETS b/rules/lint/TARGETS
new file mode 100644
index 0000000..de52b00
--- /dev/null
+++ b/rules/lint/TARGETS
@@ -0,0 +1,3 @@
+{ "defaults":
+ {"type": "defaults", "base": [["CC", "defaults"], ["shell", "defaults"]]}
+}
diff --git a/rules/lint/call_lint b/rules/lint/call_lint
new file mode 100755
index 0000000..fd2a244
--- /dev/null
+++ b/rules/lint/call_lint
@@ -0,0 +1,44 @@
+#!/bin/sh
+# Copyright 2024 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
+
+export OUT="$(pwd)/out"
+mkdir -p config
+export CONFIG="$(pwd)/config"
+export META="$(pwd)/meta.json"
+mkdir scratch
+export TMPDIR=$(realpath scratch)
+
+cd work
+
+if ../linter "$@" > ../stdout 2> ../stderr
+then
+ RESULT=PASS
+else
+ RESULT=FAIL
+fi
+
+echo "${RESULT}" > ../result
+
+if [ "${RESULT}" '!=' PASS ]
+then
+ exit 1;
+fi
diff --git a/rules/lint/call_summary b/rules/lint/call_summary
new file mode 100755
index 0000000..d4aa8cb
--- /dev/null
+++ b/rules/lint/call_summary
@@ -0,0 +1,35 @@
+#!/bin/sh
+# Copyright 2024 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 report
+RESULT=UNKNOWN
+echo "${RESULT}" > result
+
+export OUT="$(pwd)/out"
+
+cd work
+
+if ../summarizer > ../report
+then
+ RESULT=PASS
+else
+ RESULT=FAIL
+fi
+
+echo "${RESULT}" > ../result
+
+exit 0
diff --git a/rules/patch/EXPRESSIONS b/rules/patch/EXPRESSIONS
new file mode 100644
index 0000000..7f8ce19
--- /dev/null
+++ b/rules/patch/EXPRESSIONS
@@ -0,0 +1,77 @@
+{ "default-PATCH":
+ { "vars": ["defaults-transition"]
+ , "imports": {"list_provider": ["./", "..", "field_list_provider"]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "patch-defaults"]
+ , ["provider", "PATCH"]
+ , ["transition", {"type": "var", "name": "defaults-transition"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "list_provider"}
+ }
+ }
+, "default-ENV":
+ { "vars": ["defaults-transition"]
+ , "imports": {"map_provider": ["./", "..", "field_map_provider"]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "patch-defaults"]
+ , ["provider", "ENV"]
+ , ["transition", {"type": "var", "name": "defaults-transition"}]
+ , ["default", {"type": "empty_map"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "map_provider"}
+ }
+ }
+, "default-PATH":
+ { "vars": ["defaults-transition"]
+ , "imports": {"list_provider": ["./", "..", "field_list_provider"]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "patch-defaults"]
+ , ["provider", "PATH"]
+ , ["transition", {"type": "var", "name": "defaults-transition"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "list_provider"}
+ }
+ }
+, "default-TOOLCHAIN":
+ { "vars": ["defaults-transition"]
+ , "imports": {"map_provider": ["./", "..", "field_map_provider"]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "patch-defaults"]
+ , ["provider", "TOOLCHAIN"]
+ , ["transition", {"type": "var", "name": "defaults-transition"}]
+ , ["default", {"type": "empty_map"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "map_provider"}
+ }
+ }
+, "default-NON_SYSTEM_TOOLS":
+ { "vars": ["defaults-transition"]
+ , "expression":
+ { "type": "map_union"
+ , "$1":
+ { "type": "foreach"
+ , "var": "x"
+ , "range": {"type": "FIELD", "name": "patch-defaults"}
+ , "body":
+ { "type": "DEP_PROVIDES"
+ , "dep": {"type": "var", "name": "x"}
+ , "provider": "NON_SYSTEM_TOOLS"
+ , "transition":
+ { "type": "var"
+ , "name": "defaults-transition"
+ , "default": {"type": "empty_map"}
+ }
+ , "default": {"type": "empty_map"}
+ }
+ }
+ }
+ }
+}
diff --git a/rules/patch/RULES b/rules/patch/RULES
new file mode 100644
index 0000000..ea495f0
--- /dev/null
+++ b/rules/patch/RULES
@@ -0,0 +1,351 @@
+{ "defaults":
+ { "doc":
+ [ "A rule to provide defaults."
+ , "All targets take their defaults for PATCH from the target"
+ , "[\"patch\", \"defaults\"]. This is probably the only sensible"
+ , "use of this rule. As targets form a different root, the defaults"
+ , "can be provided without changing this directory."
+ ]
+ , "target_fields": ["base", "toolchain"]
+ , "string_fields": ["PATCH", "PATH", "SYSTEM_TOOLS"]
+ , "field_doc":
+ { "base": ["Other targets (using the same rule) to inherit values from."]
+ , "toolchain":
+ [ "Optional toolchain directory. A collection of artifacts that provide"
+ , "the tool PATCH. Note that only artifacts of"
+ , "the specified targets are considered (no runfiles etc.). Specifying"
+ , "this field extends artifacts from \"base\"."
+ ]
+ , "PATCH": ["The patch binary to use"]
+ , "SYSTEM_TOOLS":
+ [ "List of tools (\"PATCH\") that should be taken from"
+ , "the system instead of from \"toolchain\" (if specified)."
+ ]
+ , "PATH":
+ [ "Path for looking up the compilers. Individual paths are joined"
+ , "with \":\". Specifying this field extends values from \"base\"."
+ ]
+ }
+ , "config_vars": ["ARCH", "HOST_ARCH"]
+ , "imports":
+ { "base-provides": ["CC", "defaults-base-provides"]
+ , "base-provides-++": ["CC", "defaults-base-provides-++"]
+ , "base-provides-list": ["CC", "defaults-base-provides-list"]
+ , "artifacts_list": ["", "field_artifacts_list"]
+ , "for host": ["transitions", "for host"]
+ }
+ , "config_transitions":
+ {"toolchain": [{"type": "CALL_EXPRESSION", "name": "for host"}]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["PATCH", {"type": "FIELD", "name": "PATCH"}]
+ , ["PATH", {"type": "FIELD", "name": "PATH"}]
+ , ["provider", "PATCH"]
+ , [ "PATCH"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "PATCH"}
+ , "then": {"type": "var", "name": "PATCH"}
+ , "else": {"type": "CALL_EXPRESSION", "name": "base-provides"}
+ }
+ ]
+ , ["provider", "PATH"]
+ , [ "PATH"
+ , { "type": "nub_left"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "var", "name": "PATH"}
+ , {"type": "CALL_EXPRESSION", "name": "base-provides-++"}
+ ]
+ }
+ }
+ ]
+ , ["provider", "ENV"]
+ , ["default", {"type": "empty_map"}]
+ , ["ENV", {"type": "CALL_EXPRESSION", "name": "base-provides"}]
+ , ["provider", "NON_SYSTEM_TOOLS"]
+ , ["default", {"type": "empty_map"}]
+ , [ "NON_SYSTEM_TOOLS"
+ , { "type": "map_union"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ [{"type": "CALL_EXPRESSION", "name": "base-provides"}]
+ , { "type": "if"
+ , "cond": {"type": "FIELD", "name": "PATCH"}
+ , "then":
+ [ { "type": "singleton_map"
+ , "key": "PATCH"
+ , "value":
+ { "type": "if"
+ , "cond": {"type": "FIELD", "name": "toolchain"}
+ , "then": true
+ , "else": false
+ }
+ }
+ ]
+ }
+ , { "type": "foreach"
+ , "range": {"type": "FIELD", "name": "SYSTEM_TOOLS"}
+ , "var": "tool"
+ , "body":
+ { "type": "singleton_map"
+ , "key": {"type": "var", "name": "tool"}
+ , "value": false
+ }
+ }
+ ]
+ }
+ }
+ ]
+ , ["provider", "TOOLCHAIN"]
+ , ["default", {"type": "empty_map"}]
+ , [ "TOOLCHAIN"
+ , { "type": "disjoint_map_union"
+ , "msg": "toolchain artifacts may not overlap"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "base-provides-list"}
+ , { "type": "if"
+ , "cond": {"type": "FIELD", "name": "toolchain"}
+ , "then":
+ { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "toolchain"]
+ , [ "transition"
+ , {"type": "CALL_EXPRESSION", "name": "for host"}
+ ]
+ ]
+ , "body":
+ {"type": "CALL_EXPRESSION", "name": "artifacts_list"}
+ }
+ }
+ ]
+ }
+ }
+ ]
+ ]
+ , "body":
+ { "type": "RESULT"
+ , "provides":
+ { "type": "env"
+ , "vars": ["PATCH", "PATH", "ENV", "TOOLCHAIN", "NON_SYSTEM_TOOLS"]
+ }
+ }
+ }
+ }
+, "file":
+ { "doc": ["Replace a file, logically in place, by a patched version"]
+ , "target_fields": ["src", "patch"]
+ , "config_vars": ["PATCH", "ENV"]
+ , "implicit":
+ {"patch-defaults": ["defaults"], "defaults": [["shell", "defaults"]]}
+ , "field_doc":
+ { "src":
+ [ "The single source file to patch, typically an explicit file reference."
+ ]
+ , "patch": ["The patch to apply."]
+ , "patch-defaults": ["The patch binary (and toolchain) to use"]
+ , "defaults": ["The shell toolchain to use"]
+ }
+ , "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"]
+ , "default-PATCH": "default-PATCH"
+ , "default-TOOLCHAIN": "default-TOOLCHAIN"
+ , "default-ENV": "default-ENV"
+ , "default-PATH": "default-PATH"
+ , "default-NON_SYSTEM_TOOLS": "default-NON_SYSTEM_TOOLS"
+ , "sh-TOOLCHAIN": ["CC", "default-TOOLCHAIN"]
+ , "sh-PATH": ["CC", "default-PATH"]
+ , "sh": ["shell", "sh"]
+ , "list_provider": ["./", "..", "field_list_provider"]
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["TOOLCHAIN_DIR", "toolchain"]
+ , [ "TOOLCHAIN"
+ , { "type": "disjoint_map_union"
+ , "msg": "Staging conflict between patch and sh toolchain"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "default-TOOLCHAIN"}
+ , {"type": "CALL_EXPRESSION", "name": "sh-TOOLCHAIN"}
+ ]
+ }
+ ]
+ , [ "TOOLCHAIN"
+ , { "type": "to_subdir"
+ , "subdir": {"type": "var", "name": "TOOLCHAIN_DIR"}
+ , "$1": {"type": "var", "name": "TOOLCHAIN"}
+ }
+ ]
+ , [ "bin dirs"
+ , { "type": "let*"
+ , "bindings": [["fieldname", "defaults"], ["provider", "bin dirs"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "list_provider"}
+ }
+ ]
+ , [ "bin dirs"
+ , { "type": "foreach"
+ , "range": {"type": "var", "name": "bin dirs"}
+ , "body":
+ { "type": "join"
+ , "$1":
+ [ "./"
+ , {"type": "var", "name": "TOOLCHAIN_DIR"}
+ , "/"
+ , {"type": "var", "name": "_"}
+ ]
+ }
+ }
+ ]
+ , [ "NON_SYSTEM_TOOLS"
+ , {"type": "CALL_EXPRESSION", "name": "default-NON_SYSTEM_TOOLS"}
+ ]
+ , [ "PATCH"
+ , { "type": "var"
+ , "name": "PATCH"
+ , "default":
+ { "type": "join"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ { "type": "if"
+ , "cond":
+ { "type": "lookup"
+ , "key": "PATCH"
+ , "map": {"type": "var", "name": "NON_SYSTEM_TOOLS"}
+ }
+ , "then":
+ ["./", {"type": "var", "name": "TOOLCHAIN_DIR"}, "/"]
+ }
+ , {"type": "CALL_EXPRESSION", "name": "default-PATCH"}
+ ]
+ }
+ }
+ }
+ ]
+ , [ "ENV"
+ , { "type": "map_union"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "default-ENV"}
+ , {"type": "var", "name": "ENV", "default": {"type": "empty_map"}}
+ ]
+ }
+ ]
+ , [ "ENV_PATH"
+ , { "type": "lookup"
+ , "map": {"type": "var", "name": "ENV"}
+ , "key": "PATH"
+ }
+ ]
+ , [ "ENV"
+ , { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "ENV"}
+ , { "type": "singleton_map"
+ , "key": "PATH"
+ , "value":
+ { "type": "join"
+ , "separator": ":"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "default-PATH"}
+ , {"type": "CALL_EXPRESSION", "name": "sh-PATH"}
+ , {"type": "var", "name": "bin dirs"}
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "ENV_PATH"}
+ , "then": [{"type": "var", "name": "ENV_PATH"}]
+ }
+ ]
+ }
+ }
+ }
+ ]
+ }
+ ]
+ , ["sh", {"type": "CALL_EXPRESSION", "name": "sh"}]
+ , [ "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"}
+ }
+ ]
+ , [ "script"
+ , { "type": "singleton_map"
+ , "key": "run_patch.sh"
+ , "value":
+ { "type": "BLOB"
+ , "data":
+ { "type": "join"
+ , "separator": "\n"
+ , "$1":
+ [ "set -e"
+ , "cp orig patched"
+ , "chmod +w patched"
+ , { "type": "join"
+ , "$1":
+ [ { "type": "join_cmd"
+ , "$1":
+ [ {"type": "var", "name": "PATCH", "default": "patch"}
+ , "patched"
+ , "patch"
+ ]
+ }
+ , " >log || (cat log && exit 1)"
+ ]
+ }
+ ]
+ }
+ }
+ }
+ ]
+ , [ "inputs"
+ , { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "orig"}
+ , {"type": "var", "name": "patch"}
+ , {"type": "var", "name": "TOOLCHAIN"}
+ , {"type": "var", "name": "script"}
+ ]
+ }
+ ]
+ , [ "patched"
+ , { "type": "ACTION"
+ , "inputs": {"type": "var", "name": "inputs"}
+ , "outs": ["patched"]
+ , "cmd": [{"type": "var", "name": "sh"}, "./run_patch.sh"]
+ , "env": {"type": "var", "name": "ENV"}
+ }
+ ]
+ , [ "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/patch/TARGETS b/rules/patch/TARGETS
new file mode 100644
index 0000000..9a0ad77
--- /dev/null
+++ b/rules/patch/TARGETS
@@ -0,0 +1,6 @@
+{ "defaults":
+ { "type": ["patch", "defaults"]
+ , "PATCH": ["patch"]
+ , "PATH": ["/bin", "/usr/bin"]
+ }
+}
diff --git a/rules/proto/RULES b/rules/proto/RULES
new file mode 100644
index 0000000..a9152dd
--- /dev/null
+++ b/rules/proto/RULES
@@ -0,0 +1,99 @@
+{ "library":
+ { "doc":
+ [ "A proto library as abstract data structure."
+ , ""
+ , "Such a library 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 access to \"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 definition 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/EXPRESSIONS b/rules/shell/EXPRESSIONS
new file mode 100644
index 0000000..34a5c92
--- /dev/null
+++ b/rules/shell/EXPRESSIONS
@@ -0,0 +1,171 @@
+{ "default-sh":
+ { "vars": ["defaults-transition", "fieldname"]
+ , "imports": {"list_provider": ["./", "..", "field_list_provider"]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ [ "fieldname"
+ , {"type": "var", "name": "fieldname", "default": "defaults"}
+ ]
+ , ["provider", "sh"]
+ , ["transition", {"type": "var", "name": "defaults-transition"}]
+ , [ "provided sh"
+ , { "type": "join"
+ , "$1": {"type": "CALL_EXPRESSION", "name": "list_provider"}
+ }
+ ]
+ , [ "sh"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "provided sh"}
+ , "then": {"type": "var", "name": "provided sh"}
+ , "else": "sh"
+ }
+ ]
+ ]
+ , "body": {"type": "var", "name": "sh"}
+ }
+ }
+, "NON_SYSTEM":
+ { "vars": ["defaults-transition", "fieldname"]
+ , "expression":
+ { "type": "map_union"
+ , "$1":
+ { "type": "foreach"
+ , "var": "x"
+ , "range":
+ { "type": "FIELD"
+ , "name": {"type": "var", "name": "fieldname", "default": "defaults"}
+ }
+ , "body":
+ { "type": "DEP_PROVIDES"
+ , "dep": {"type": "var", "name": "x"}
+ , "provider": "NON_SYSTEM_TOOLS"
+ , "transition":
+ { "type": "var"
+ , "name": "defaults-transition"
+ , "default": {"type": "empty_map"}
+ }
+ , "default": {"type": "empty_map"}
+ }
+ }
+ }
+ }
+, "sh":
+ { "vars": ["defaults-transition", "TOOLCHAIN_DIR", "fieldname"]
+ , "imports": {"default-sh": "default-sh", "NON_SYSTEM": "NON_SYSTEM"}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["sh", {"type": "CALL_EXPRESSION", "name": "default-sh"}]
+ , ["NON_SYSTEM", {"type": "CALL_EXPRESSION", "name": "NON_SYSTEM"}]
+ , [ "sh"
+ , { "type": "if"
+ , "cond":
+ { "type": "lookup"
+ , "key": "sh"
+ , "map": {"type": "var", "name": "NON_SYSTEM"}
+ }
+ , "then":
+ { "type": "join"
+ , "separator": "/"
+ , "$1":
+ [ "."
+ , { "type": "var"
+ , "name": "TOOLCHAIN_DIR"
+ , "default": "toolchain"
+ }
+ , {"type": "var", "name": "sh"}
+ ]
+ }
+ , "else": {"type": "var", "name": "sh"}
+ }
+ ]
+ ]
+ , "body": {"type": "var", "name": "sh"}
+ }
+ }
+, "PATH":
+ { "vars": ["fieldname", "defaults-transition"]
+ , "imports": {"list_provider": ["./", "..", "field_list_provider"]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ [ "fieldname"
+ , {"type": "var", "name": "fieldname", "default": "defaults"}
+ ]
+ , ["provider", "PATH"]
+ , ["transition", {"type": "var", "name": "defaults-transition"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "list_provider"}
+ }
+ }
+, "prolog":
+ { "vars": ["fieldname", "TOOLCHAIN_DIR"]
+ , "imports": {"list_provider": ["./", "..", "field_list_provider"]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["provider", "bin dirs"]
+ , ["bin dirs", {"type": "CALL_EXPRESSION", "name": "list_provider"}]
+ , [ "relative paths"
+ , { "type": "foreach"
+ , "range": {"type": "var", "name": "bin dirs"}
+ , "body":
+ { "type": "join"
+ , "separator": "/"
+ , "$1":
+ [ "."
+ , { "type": "var"
+ , "name": "TOOLCHAIN_DIR"
+ , "default": "toolchain"
+ }
+ , {"type": "var", "name": "_"}
+ ]
+ }
+ }
+ ]
+ , [ "pwd paths"
+ , { "type": "foreach"
+ , "range": {"type": "var", "name": "bin dirs"}
+ , "body":
+ { "type": "join"
+ , "separator": "/"
+ , "$1":
+ [ "$(pwd)"
+ , { "type": "var"
+ , "name": "TOOLCHAIN_DIR"
+ , "default": "toolchain"
+ }
+ , {"type": "var", "name": "_"}
+ ]
+ }
+ }
+ ]
+ ]
+ , "body":
+ [ "__PATH=$PATH"
+ , { "type": "join"
+ , "$1":
+ [ "export PATH="
+ , { "type": "join"
+ , "separator": ":"
+ , "$1": {"type": "var", "name": "relative paths"}
+ }
+ , "${PATH:+:}${PATH}"
+ ]
+ }
+ , { "type": "join"
+ , "$1":
+ [ "export PATH="
+ , { "type": "join"
+ , "separator": ":"
+ , "$1": {"type": "var", "name": "pwd paths"}
+ }
+ , "${__PATH:+:}${__PATH}"
+ ]
+ }
+ , "unset __PATH"
+ ]
+ }
+ }
+}
diff --git a/rules/shell/RULES b/rules/shell/RULES
new file mode 100644
index 0000000..7f53a4b
--- /dev/null
+++ b/rules/shell/RULES
@@ -0,0 +1,347 @@
+{ "defaults":
+ { "doc":
+ [ "A rule to provide defaults for the usage of the shell"
+ , ""
+ , "All targets using invocations of the shell use the target"
+ , "[\"shel\", \"defaults\"] to determine which shell to use and how to"
+ , "invoke it. The definition of this default target is probably the only"
+ , "meaningful use of this rule."
+ ]
+ , "target_fields": ["base", "toolchain"]
+ , "string_fields": ["sh", "PATH", "bin dirs"]
+ , "field_doc":
+ { "base": ["Other targets (using the same rule) to inherit values from."]
+ , "toolchain":
+ [ "Optional toolchain directory. A collection of artifacts that"
+ , "form the toolchain, in particular the shell itself, where not taken"
+ , "from the ambient host environment."
+ , "Values provided from base are extended."
+ , "This field is built for the host."
+ ]
+ , "sh":
+ [ "The name of the sh binary; if the the field \"toolchain\" is"
+ , "not empty, the value is interpreted as relative to the toolchain"
+ , "directory."
+ ]
+ , "PATH":
+ [ "Paths for looking up system tools."
+ , "Specifying this field extends values from \"base\"."
+ ]
+ , "bin dirs":
+ [ "Directories of the toolchain that contain additional binaries."
+ , "Shell-specific rules will add those into PATH."
+ ]
+ }
+ , "config_vars": ["ARCH", "HOST_ARCH", "TARGET_ARCH"]
+ , "imports":
+ { "for host": ["transitions", "for host"]
+ , "artifacts_list": ["", "field_artifacts_list"]
+ , "base-provides-list": ["CC", "defaults-base-provides-list"]
+ , "base-provides-++": ["CC", "defaults-base-provides-++"]
+ , "base-provides": ["CC", "defaults-base-provides"]
+ }
+ , "config_transitions":
+ {"toolchain": [{"type": "CALL_EXPRESSION", "name": "for host"}]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ [ "TOOLCHAIN"
+ , { "type": "disjoint_map_union"
+ , "msg": "toolchain artifacts must not overlap"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ { "type": "let*"
+ , "bindings":
+ [ ["provider", "TOOLCHAIN"]
+ , ["default", {"type": "empty_map"}]
+ ]
+ , "body":
+ {"type": "CALL_EXPRESSION", "name": "base-provides-list"}
+ }
+ , { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "toolchain"]
+ , [ "transition"
+ , {"type": "CALL_EXPRESSION", "name": "for host"}
+ ]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "artifacts_list"}
+ }
+ ]
+ }
+ }
+ ]
+ , [ "sh"
+ , { "type": "if"
+ , "cond": {"type": "FIELD", "name": "sh"}
+ , "then": {"type": "FIELD", "name": "sh"}
+ , "else":
+ { "type": "let*"
+ , "bindings": [["provider", "sh"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "base-provides"}
+ }
+ }
+ ]
+ , [ "NON_SYSTEM_TOOLS"
+ , { "type": "map_union"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ [ { "type": "let*"
+ , "bindings":
+ [ ["provider", "NON_SYSTEM_TOOLS"]
+ , ["default", {"type": "empty_map"}]
+ ]
+ , "body":
+ {"type": "CALL_EXPRESSION", "name": "base-provides"}
+ }
+ ]
+ , { "type": "if"
+ , "cond": {"type": "FIELD", "name": "sh"}
+ , "then":
+ [ { "type": "singleton_map"
+ , "key": "sh"
+ , "value":
+ { "type": "if"
+ , "cond": {"type": "FIELD", "name": "toolchain"}
+ , "then": true
+ , "else": false
+ }
+ }
+ ]
+ }
+ ]
+ }
+ }
+ ]
+ , [ "PATH"
+ , { "type": "nub_left"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "FIELD", "name": "PATH"}
+ , { "type": "let*"
+ , "bindings": [["provider", "PATH"]]
+ , "body":
+ {"type": "CALL_EXPRESSION", "name": "base-provides-++"}
+ }
+ ]
+ }
+ }
+ ]
+ , [ "bin dirs"
+ , { "type": "nub_left"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "FIELD", "name": "bin dirs"}
+ , { "type": "let*"
+ , "bindings": [["provider", "bin dirs"]]
+ , "body":
+ {"type": "CALL_EXPRESSION", "name": "base-provides-++"}
+ }
+ ]
+ }
+ }
+ ]
+ ]
+ , "body":
+ { "type": "RESULT"
+ , "provides":
+ { "type": "env"
+ , "vars": ["TOOLCHAIN", "sh", "NON_SYSTEM_TOOLS", "PATH", "bin dirs"]
+ }
+ }
+ }
+ }
+, "cmds":
+ { "doc":
+ [ "Execute comands using the shell"
+ , ""
+ , "This rule behaves similar to the built-in \"generic\" rule, however"
+ , "with the difference that the shell toolchain is honored."
+ ]
+ , "target_fields": ["deps"]
+ , "string_fields": ["cmds", "outs", "out_dirs"]
+ , "implicit": {"defaults": ["defaults"]}
+ , "field_doc":
+ { "deps":
+ [ "Any inputs to the argument."
+ , "Both, artifacts and rufiles of the dependecies are staged into"
+ , "the (effective) working directory of the action. Conflicts are"
+ , "resolved by giving artifacts priority to runfiles, and within"
+ , "each of those priority to ones brought by the latest dependency."
+ ]
+ , "cmds":
+ [ "The command to be executed."
+ , "Individual entries are joined by newline characters; the whole"
+ , "script is then prefixed by commands necessary to set up the"
+ , "work environment using the shell tool chain."
+ ]
+ , "defaults": ["The shell toolchain to use."]
+ , "outs": ["The expected file outputs"]
+ , "out_dirs": ["The expected output directories"]
+ }
+ , "imports":
+ { "artifacts_list": ["", "field_artifacts_list"]
+ , "runfiles_list": ["", "field_runfiles_list"]
+ , "map_provider": ["", "field_map_provider"]
+ , "prolog": "prolog"
+ , "sh": "sh"
+ , "PATH": "PATH"
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "deps"]
+ , [ "deps"
+ , { "type": "map_union"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "runfiles_list"}
+ , {"type": "CALL_EXPRESSION", "name": "artifacts_list"}
+ ]
+ }
+ }
+ ]
+ , ["fieldname", "defaults"]
+ , ["TOOLCHAIN_DIR", "toolchain"]
+ , [ "toolchain"
+ , { "type": "to_subdir"
+ , "subdir": {"type": "var", "name": "TOOLCHAIN_DIR"}
+ , "$1":
+ { "type": "let*"
+ , "bindings":
+ [["provider", "TOOLCHAIN"], ["default", {"type": "empty_map"}]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "map_provider"}
+ }
+ }
+ ]
+ , ["WRKDIR", "work"]
+ , [ "cmds"
+ , { "type": "++"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "prolog"}
+ , [ { "type": "join_cmd"
+ , "$1": ["cd", {"type": "var", "name": "WRKDIR"}]
+ }
+ ]
+ , {"type": "FIELD", "name": "cmds"}
+ ]
+ }
+ ]
+ , ["sh", {"type": "CALL_EXPRESSION", "name": "sh"}]
+ , [ "cmdfile"
+ , { "type": "singleton_map"
+ , "key": "cmd"
+ , "value":
+ { "type": "BLOB"
+ , "data":
+ { "type": "join"
+ , "separator": "\n"
+ , "$1": {"type": "var", "name": "cmds"}
+ }
+ }
+ }
+ ]
+ , ["PATH", {"type": "CALL_EXPRESSION", "name": "PATH"}]
+ , [ "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": "empty_map"}
+ }
+ ]
+ , [ "outs in WRKDIR"
+ , { "type": "foreach"
+ , "range": {"type": "FIELD", "name": "outs"}
+ , "body":
+ { "type": "join"
+ , "$1":
+ [ {"type": "var", "name": "WRKDIR"}
+ , "/"
+ , {"type": "var", "name": "_"}
+ ]
+ }
+ }
+ ]
+ , [ "out_dirs in WRKDIR"
+ , { "type": "foreach"
+ , "range": {"type": "FIELD", "name": "out_dirs"}
+ , "body":
+ { "type": "join"
+ , "$1":
+ [ {"type": "var", "name": "WRKDIR"}
+ , "/"
+ , {"type": "var", "name": "_"}
+ ]
+ }
+ }
+ ]
+ , [ "artifacts"
+ , { "type": "ACTION"
+ , "inputs":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "toolchain"}
+ , {"type": "var", "name": "cmdfile"}
+ , { "type": "to_subdir"
+ , "subdir": {"type": "var", "name": "WRKDIR"}
+ , "$1": {"type": "var", "name": "deps"}
+ }
+ ]
+ }
+ , "cmd": [{"type": "var", "name": "sh"}, "cmd"]
+ , "outs": {"type": "var", "name": "outs in WRKDIR"}
+ , "out_dirs": {"type": "var", "name": "out_dirs in WRKDIR"}
+ , "env": {"type": "var", "name": "env"}
+ }
+ ]
+ , [ "staged artifacts"
+ , { "type": "map_union"
+ , "$1":
+ { "type": "foreach"
+ , "range":
+ { "type": "++"
+ , "$1":
+ [ {"type": "FIELD", "name": "outs"}
+ , {"type": "FIELD", "name": "out_dirs"}
+ ]
+ }
+ , "body":
+ { "type": "singleton_map"
+ , "key": {"type": "var", "name": "_"}
+ , "value":
+ { "type": "lookup"
+ , "map": {"type": "var", "name": "artifacts"}
+ , "key":
+ { "type": "join"
+ , "$1":
+ [ {"type": "var", "name": "WRKDIR"}
+ , "/"
+ , {"type": "var", "name": "_"}
+ ]
+ }
+ }
+ }
+ }
+ }
+ ]
+ ]
+ , "body":
+ { "type": "RESULT"
+ , "artifacts": {"type": "var", "name": "staged artifacts"}
+ }
+ }
+ }
+}
diff --git a/rules/shell/TARGETS b/rules/shell/TARGETS
new file mode 100644
index 0000000..705d1d7
--- /dev/null
+++ b/rules/shell/TARGETS
@@ -0,0 +1 @@
+{"defaults": {"type": "defaults"}}
diff --git a/rules/shell/test/EXPRESSIONS b/rules/shell/test/EXPRESSIONS
new file mode 100644
index 0000000..9791911
--- /dev/null
+++ b/rules/shell/test/EXPRESSIONS
@@ -0,0 +1,380 @@
+{ "test-action":
+ { "vars":
+ [ "TEST_ENV"
+ , "TIMEOUT_SCALE"
+ , "ATTEMPT"
+ , "name"
+ , "test.sh"
+ , "keep"
+ , "keep-dirs"
+ , "runner"
+ , "deps-fieldname"
+ , "deps-transition"
+ , "target properties"
+ ]
+ , "imports":
+ { "artifacts_list": ["./", "../..", "field_artifacts_list"]
+ , "runfiles_list": ["./", "../..", "field_runfiles_list"]
+ , "map_provider": ["./", "../..", "field_map_provider"]
+ , "default-TOOLCHAIN": ["./", "../../CC", "default-TOOLCHAIN"]
+ , "default-NON_SYSTEM_TOOLS":
+ ["./", "../../CC", "default-NON_SYSTEM_TOOLS"]
+ , "default-PATH": ["./", "../../CC", "default-PATH"]
+ , "default-sh": ["./", "..", "default-sh"]
+ , "sh prolog": ["shell", "prolog"]
+ }
+ , "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"]}
+ }
+ }
+ }
+ }
+ ]
+ , ["toolchain dirname", "toolchain"]
+ , [ "toolchain"
+ , { "type": "to_subdir"
+ , "subdir": {"type": "var", "name": "toolchain dirname"}
+ , "$1": {"type": "CALL_EXPRESSION", "name": "default-TOOLCHAIN"}
+ }
+ ]
+ , ["sh", {"type": "CALL_EXPRESSION", "name": "default-sh"}]
+ , [ "NON_SYSTEM_TOOLS"
+ , {"type": "CALL_EXPRESSION", "name": "default-NON_SYSTEM_TOOLS"}
+ ]
+ , [ "sh from outside"
+ , { "type": "if"
+ , "cond":
+ { "type": "lookup"
+ , "key": "sh"
+ , "map": {"type": "var", "name": "NON_SYSTEM_TOOLS"}
+ }
+ , "then":
+ { "type": "join"
+ , "$1": ["./toolchain/", {"type": "var", "name": "sh"}]
+ }
+ , "else": {"type": "var", "name": "sh"}
+ }
+ ]
+ , [ "sh from workdir"
+ , { "type": "if"
+ , "cond":
+ { "type": "lookup"
+ , "key": "sh"
+ , "map": {"type": "var", "name": "NON_SYSTEM_TOOLS"}
+ }
+ , "then":
+ { "type": "join"
+ , "$1": ["../toolchain/", {"type": "var", "name": "sh"}]
+ }
+ , "else": {"type": "var", "name": "sh"}
+ }
+ ]
+ , [ "with-env"
+ , { "type": "singleton_map"
+ , "key": "with-env"
+ , "value":
+ { "type": "BLOB"
+ , "data":
+ { "type": "join"
+ , "separator": "\n"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ { "type": "let*"
+ , "bindings": [["fieldname", "defaults"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "sh prolog"}
+ }
+ , [ ""
+ , { "type": "join_cmd"
+ , "$1":
+ { "type": "++"
+ , "$1": [["./runner"], {"type": "var", "name": "keep"}]
+ }
+ }
+ , ""
+ ]
+ ]
+ }
+ }
+ }
+ }
+ ]
+ , [ "invocation cmd"
+ , [{"type": "var", "name": "sh from workdir"}, "../test.sh"]
+ ]
+ , [ "invocation"
+ , { "type": "singleton_map"
+ , "key": "invocation"
+ , "value":
+ { "type": "BLOB"
+ , "data":
+ { "type": "join_cmd"
+ , "$1": {"type": "var", "name": "invocation cmd"}
+ }
+ }
+ }
+ ]
+ , [ "test_env"
+ , {"type": "var", "name": "TEST_ENV", "default": {"type": "empty_map"}}
+ ]
+ , [ "test_env PATH"
+ , { "type": "lookup"
+ , "key": "PATH"
+ , "map": {"type": "var", "name": "test_env"}
+ }
+ ]
+ , [ "PATH"
+ , { "type": "join"
+ , "separator": ":"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ { "type": "if"
+ , "cond": {"type": "var", "name": "test_env PATH"}
+ , "then": [{"type": "var", "name": "test_env PATH"}]
+ }
+ , {"type": "CALL_EXPRESSION", "name": "default-PATH"}
+ ]
+ }
+ }
+ ]
+ , [ "test_env"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "PATH"}
+ , "then":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "test_env"}
+ , { "type": "singleton_map"
+ , "key": "PATH"
+ , "value": {"type": "var", "name": "PATH"}
+ }
+ ]
+ }
+ , "else": {"type": "var", "name": "test_env"}
+ }
+ ]
+ , [ "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", "pwd"]
+ , { "type": "foreach"
+ , "var": "filename"
+ , "range": {"type": "var", "name": "keep"}
+ , "body":
+ { "type": "join"
+ , "$1": ["work/", {"type": "var", "name": "filename"}]
+ }
+ }
+ ]
+ }
+ ]
+ , [ "out_dirs"
+ , { "type": "foreach"
+ , "var": "dir_path"
+ , "range": {"type": "var", "name": "keep-dirs"}
+ , "body":
+ { "type": "join"
+ , "$1": ["work/", {"type": "var", "name": "dir_path"}]
+ }
+ }
+ ]
+ , [ "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": "toolchain"}
+ , {"type": "var", "name": "with-env"}
+ , {"type": "var", "name": "runner"}
+ , {"type": "var", "name": "invocation"}
+ , {"type": "var", "name": "test.sh"}
+ , {"type": "var", "name": "attempt marker"}
+ ]
+ }
+ ]
+ , ["cmd", [{"type": "var", "name": "sh from outside"}, "with-env"]]
+ , [ "test_env"
+ , { "type": "map_union"
+ , "$1":
+ [ { "type": "if"
+ , "cond":
+ { "type": "=="
+ , "$1": {"type": "var", "name": "ATTEMPT"}
+ , "$2": null
+ }
+ , "then": {"type": "empty_map"}
+ , "else":
+ { "type": "singleton_map"
+ , "key": "TEST_RUN_NUMBER"
+ , "value": {"type": "var", "name": "ATTEMPT"}
+ }
+ }
+ , {"type": "var", "name": "test_env"}
+ ]
+ }
+ ]
+ ]
+ , "body":
+ { "type": "if"
+ , "cond":
+ {"type": "==", "$1": {"type": "var", "name": "ATTEMPT"}, "$2": null}
+ , "then":
+ { "type": "ACTION"
+ , "outs": {"type": "var", "name": "outs"}
+ , "out_dirs": {"type": "var", "name": "out_dirs"}
+ , "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"]
+ }
+ , "timeout scaling":
+ {"type": "var", "name": "TIMEOUT_SCALE", "default": 1.0}
+ , "execution properties": {"type": "var", "name": "target properties"}
+ }
+ , "else":
+ { "type": "ACTION"
+ , "outs": {"type": "var", "name": "outs"}
+ , "out_dirs": {"type": "var", "name": "out_dirs"}
+ , "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"}
+ , ")"
+ ]
+ }
+ , "timeout scaling":
+ {"type": "var", "name": "TIMEOUT_SCALE", "default": 1.0}
+ , "execution properties": {"type": "var", "name": "target properties"}
+ }
+ }
+ }
+ }
+, "test-result":
+ { "vars":
+ [ "TEST_ENV"
+ , "TIMEOUT_SCALE"
+ , "name"
+ , "test.sh"
+ , "keep"
+ , "keep-dirs"
+ , "runner"
+ , "deps-fieldname"
+ , "deps-transition"
+ , "target properties"
+ , "lint"
+ ]
+ , "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"}
+ , "provides": {"type": "env", "vars": ["lint"]}
+ }
+ }
+ }
+}
diff --git a/rules/shell/test/RULES b/rules/shell/test/RULES
new file mode 100644
index 0000000..bab1d8b
--- /dev/null
+++ b/rules/shell/test/RULES
@@ -0,0 +1,364 @@
+{ "summarizer":
+ { "doc":
+ ["Specify a test summarizer together with the required additional fields"]
+ , "target_fields": ["summarizer"]
+ , "string_fields": ["artifacts"]
+ , "imports": {"stage": ["./", "../..", "stage_singleton_field"]}
+ , "field_doc":
+ { "summarizer": ["The single artifact acting as summarizer"]
+ , "artifacts":
+ [ "Any additional artifacts, besides \"result\", the summaries needs from"
+ , "the individual test results"
+ ]
+ }
+ , "expression":
+ { "type": "RESULT"
+ , "artifacts":
+ { "type": "let*"
+ , "bindings": [["fieldname", "summarizer"], ["location", "summarizer"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "stage"}
+ }
+ , "provides":
+ { "type": "singleton_map"
+ , "key": "artifacts"
+ , "value": {"type": "FIELD", "name": "artifacts"}
+ }
+ }
+ }
+, "script":
+ { "doc": ["Shell test, given by a test script"]
+ , "target_fields": ["deps", "test"]
+ , "string_fields": ["keep", "keep-dirs", "name"]
+ , "config_vars":
+ [ "ARCH"
+ , "HOST_ARCH"
+ , "RUNS_PER_TEST"
+ , "TEST_ENV"
+ , "TIMEOUT_SCALE"
+ , "TARGET_ARCH"
+ , "ARCH_DISPATCH"
+ , "TEST_SUMMARY_EXECUTION_PROPERTIES"
+ , "LINT"
+ ]
+ , "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."
+ , ""
+ , "If the configuration variable RUNS_PER_TEST is set, the environment"
+ , "variable TEST_RUN_NUMBER will also be set to the number of the attempt,"
+ , "counting from 0."
+ , ""
+ , "This running of the test is carried out by the implicit dependency"
+ , "on the target \"runner\". By setting this target in the target layer"
+ , "of this rues repository (instead of letting it default to the"
+ , "respective file), the shell test environment can be modified globally."
+ ]
+ , "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"
+ ]
+ , "keep-dirs":
+ [ "List of names (relative to the test working directory) of directories"
+ , "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"
+ ]
+ , "runner":
+ [ "The test runner which starts the actual test script after providing"
+ , "the respective environment. The runner also takes care of capturing"
+ , "stdout/stderr, timing information, and ensure the presence of the"
+ , "files to keep even if the script failed to produce them."
+ ]
+ , "summarizer":
+ [ "Tool to aggregate the results of individual test runs (for flakyness"
+ , "detection) to an overall test result. If more fields than the result"
+ , "itself is needed, those can be specified using the \"summarizer\" rule."
+ ]
+ , "defaults": ["The shell toolcahin to use."]
+ }
+ , "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."
+ , ""
+ , "The individual test runs will be summarized by the implict dependency"
+ , "on the target \"summarizer\". By setting this target in the target"
+ , "in the target layer of this rues repository (instead of letting it"
+ , "default to the respective file) the layout of the summary can be"
+ , "changed globally."
+ ]
+ , "TEST_ENV": ["Additional environment for executing the test runner."]
+ , "TIMEOUT_SCALE":
+ ["Factor on how to scale the timeout for this test. Defaults to 1.0."]
+ , "TARGET_ARCH":
+ [ "The architecture to build the test for."
+ , ""
+ , "Will only be honored, if that architecture is available in the"
+ , "ARCH_DISPATCH map. Otherwise, the test will be built for and run"
+ , "on the host architecture."
+ ]
+ , "ARCH_DISPATCH":
+ [ "Map of architectures to execution properties that ensure execution"
+ , "on that architecture. Only the actual test binary will be run with"
+ , "the specified execution properties (i.e., on the target architecture);"
+ , "all building will be done on the host architecture."
+ ]
+ , "TEST_SUMMARY_EXECUTION_PROPERTIES":
+ [ "Additional remote-execution properties for the test-summarizing action"
+ , "in case RUNS_PER_TEST is set; defaults to the empty map."
+ ]
+ }
+ , "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\" and"
+ , " \"keep-dirs\" are staged"
+ , "time-start/time-stop: The time (decimally coded) in seconds since the"
+ , " epoch when the test invocation started and ended."
+ , "pwd: the directory in which the test was carried out"
+ ]
+ , "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": ["runner"]
+ , "summarizer": ["summarizer"]
+ , "defaults": [["./", "..", "defaults"]]
+ }
+ , "imports":
+ { "test-result": "test-result"
+ , "action": "test-action"
+ , "stage": ["./", "../..", "stage_singleton_field"]
+ , "host transition": ["transitions", "maybe for host"]
+ , "target properties": ["transitions", "target properties"]
+ , "default-PATH": ["./", "../../CC", "default-PATH"]
+ , "field_list": ["", "field_list_provider"]
+ }
+ , "config_transitions":
+ { "deps": [{"type": "CALL_EXPRESSION", "name": "host transition"}]
+ , "test": [{"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"]
+ , [ "transition"
+ , {"type": "CALL_EXPRESSION", "name": "host transition"}
+ ]
+ ]
+ , "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"}]
+ , ["keep-dirs", {"type": "FIELD", "name": "keep-dirs"}]
+ , ["runner", {"type": "FIELD", "name": "runner"}]
+ , ["deps-fieldname", "deps"]
+ , [ "deps-transition"
+ , {"type": "CALL_EXPRESSION", "name": "host transition"}
+ ]
+ , [ "target properties"
+ , {"type": "CALL_EXPRESSION", "name": "target properties"}
+ ]
+ , [ "lint"
+ , { "type": "if"
+ , "cond": {"type": "var", "name": "LINT"}
+ , "then":
+ { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "deps"]
+ , ["provider", "lint"]
+ , ["transition", {"type": "var", "name": "deps-transition"}]
+ ]
+ , "body": {"type": "CALL_EXPRESSION", "name": "field_list"}
+ }
+ }
+ ]
+ ]
+ , "body":
+ { "type": "if"
+ , "cond": {"type": "var", "name": "RUNS_PER_TEST"}
+ , "else": {"type": "CALL_EXPRESSION", "name": "test-result"}
+ , "then":
+ { "type": "let*"
+ , "bindings":
+ [ [ "attempts (plain)"
+ , { "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": "CALL_EXPRESSION", "name": "action"}
+ }
+ }
+ }
+ ]
+ , [ "summarizer"
+ , { "type": "let*"
+ , "bindings":
+ [["fieldname", "summarizer"], ["location", "summarizer"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "stage"}
+ }
+ ]
+ , [ "summary artifacts"
+ , { "type": "++"
+ , "$1":
+ [ ["result"]
+ , { "type": "let*"
+ , "bindings":
+ [["provider", "artifacts"], ["fieldname", "summarizer"]]
+ , "body": {"type": "CALL_EXPRESSION", "name": "field_list"}
+ }
+ ]
+ }
+ ]
+ , [ "attempts (for summary)"
+ , { "type": "map_union"
+ , "$1":
+ { "type": "foreach_map"
+ , "range": {"type": "var", "name": "attempts (plain)"}
+ , "body":
+ { "type": "singleton_map"
+ , "key": {"type": "var", "name": "_"}
+ , "value":
+ { "type": "TREE"
+ , "$1":
+ { "type": "map_union"
+ , "$1":
+ { "type": "foreach"
+ , "range": {"type": "var", "name": "summary artifacts"}
+ , "body":
+ { "type": "singleton_map"
+ , "key": {"type": "var", "name": "_"}
+ , "value":
+ { "type": "lookup"
+ , "map": {"type": "var", "name": "$_"}
+ , "key": {"type": "var", "name": "_"}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ]
+ , [ "summary PATH"
+ , { "type": "join"
+ , "separator": ":"
+ , "$1": {"type": "CALL_EXPRESSION", "name": "default-PATH"}
+ }
+ ]
+ , [ "summary"
+ , { "type": "ACTION"
+ , "inputs":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "attempts (for summary)"}
+ , {"type": "var", "name": "summarizer"}
+ ]
+ }
+ , "outs":
+ ["stdout", "stderr", "result", "time-start", "time-stop"]
+ , "cmd": ["./summarizer"]
+ , "execution properties":
+ { "type": "var"
+ , "name": "TEST_SUMMARY_EXECUTION_PROPERTIES"
+ , "default": {"type": "empty_map"}
+ }
+ , "env":
+ { "type": "if"
+ , "cond": {"type": "var", "name": "summary PATH"}
+ , "then":
+ { "type": "singleton_map"
+ , "key": "PATH"
+ , "value": {"type": "var", "name": "summary PATH"}
+ }
+ , "else": {"type": "empty_map"}
+ }
+ }
+ ]
+ , [ "attempts"
+ , { "type": "map_union"
+ , "$1":
+ { "type": "foreach_map"
+ , "range": {"type": "var", "name": "attempts (plain)"}
+ , "body":
+ { "type": "singleton_map"
+ , "key": {"type": "var", "name": "_"}
+ , "value":
+ {"type": "TREE", "$1": {"type": "var", "name": "$_"}}
+ }
+ }
+ }
+ ]
+ , [ "artifacts"
+ , { "type": "`"
+ , "$1":
+ { "pwd":
+ {"type": ",", "$1": {"type": "BLOB", "data": "/summary"}}
+ , "work":
+ { "type": ","
+ , "$1":
+ {"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"}
+ , "provides": {"type": "env", "vars": ["lint"]}
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/rules/shell/test/TARGETS b/rules/shell/test/TARGETS
new file mode 100644
index 0000000..5a4b849
--- /dev/null
+++ b/rules/shell/test/TARGETS
@@ -0,0 +1,6 @@
+{ "summarizer":
+ { "type": "summarizer"
+ , "summarizer": [["FILE", null, "summarizer"]]
+ , "artifacts": ["time-start", "time-stop"]
+ }
+}
diff --git a/rules/shell/test/runner b/rules/shell/test/runner
new file mode 100755
index 0000000..f2f5766
--- /dev/null
+++ b/rules/shell/test/runner
@@ -0,0 +1,60 @@
+#!/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
+pwd > pwd
+
+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 . ../invocation > ../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/summarizer b/rules/shell/test/summarizer
new file mode 100755
index 0000000..39b66be
--- /dev/null
+++ b/rules/shell/test/summarizer
@@ -0,0 +1,84 @@
+#!/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
+
+from typing import Any, Dict, List
+
+g_RESULTS: Dict[str, List[Any]] = {}
+g_COUNT: float = 0
+
+PASS_count: float = 0
+PASS_time: float = 0
+
+time_start: float = time.time()
+time_stop: float = 0
+
+for attempt in os.listdir("."):
+ if os.path.isdir(attempt):
+ g_COUNT += 1
+ with open(os.path.join(attempt, "result")) as f:
+ result = f.read().strip()
+ g_RESULTS[result] = g_RESULTS.get(result, []) + [int(attempt)]
+ try:
+ with open(os.path.join(attempt, "time-start")) as f:
+ start = float(f.read().strip())
+ time_start = min(time_start, start)
+ except:
+ pass
+ try:
+ with open(os.path.join(attempt, "time-stop")) as f:
+ stop = float(f.read().strip())
+ time_stop = max(time_start, stop)
+ except:
+ pass
+ if (start > 0) and (stop >= start) and result == "PASS":
+ PASS_count += 1
+ PASS_time += stop - start
+
+result: str = "UNKNOWN"
+if set(g_RESULTS.keys()) <= set(["PASS", "FAIL"]):
+ if not g_RESULTS.get("FAIL"):
+ result = "PASS"
+ elif not g_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(g_RESULTS.get("PASS", [])), ))
+ failures =sorted(g_RESULTS.get("FAIL", []))
+ f.write("FAIL: %s\n" % (failures, ))
+ g_RESULTS.pop("PASS", None)
+ g_RESULTS.pop("FAIL", None)
+ if g_RESULTS:
+ f.write("\nother results: %r\n" % (g_RESULTS, ))
+ if result == "FLAKY":
+ f.write("\nFailure rate %5.2f%%\n" % (100.0 * len(failures) / g_COUNT))
+ if PASS_count >= 2:
+ f.write("\nAverage time of a passed test instance: %.1fs\n"
+ % (PASS_time / PASS_count))
+
+with open("stderr", "w") as f:
+ pass
diff --git a/rules/test/RULES b/rules/test/RULES
new file mode 100644
index 0000000..b8d8116
--- /dev/null
+++ b/rules/test/RULES
@@ -0,0 +1,57 @@
+{ "suite":
+ { "doc":
+ [ "Form a compound target out of many test targets."
+ , ""
+ , "More precisely, take the runfiles of the given \"deps\", take their"
+ , "disjoint union and stage the result. Also propagate relevant"
+ , "providers."
+ ]
+ , "tainted": ["test"]
+ , "target_fields": ["deps"]
+ , "string_fields": ["stage"]
+ , "field_doc":
+ { "deps": ["The targets that suite is composed of."]
+ , "stage":
+ [ "The logical location this test suite is to be placed."
+ , "Individual entries will be joined with \"/\"."
+ ]
+ }
+ , "artifacts_doc":
+ [ "The disjoint union of the runfiles of the \"deps\" targets"
+ , "staged as the location given by \"stage\"."
+ ]
+ , "runfiles_doc": ["Same as artifacts."]
+ , "imports":
+ { "runfiles": ["", "field_runfiles"]
+ , "list_provider": ["", "field_list_provider"]
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ ["fieldname", "deps"]
+ , ["runfiles", {"type": "CALL_EXPRESSION", "name": "runfiles"}]
+ , [ "stage"
+ , { "type": "join"
+ , "separator": "/"
+ , "$1": {"type": "FIELD", "name": "stage"}
+ }
+ ]
+ , [ "staged results"
+ , { "type": "to_subdir"
+ , "subdir": {"type": "var", "name": "stage"}
+ , "$1": {"type": "var", "name": "runfiles"}
+ }
+ ]
+ , ["provider", "lint"]
+ , ["lint", {"type": "CALL_EXPRESSION", "name": "list_provider"}]
+ , ["lint", {"type": "nub_right", "$1": {"type": "var", "name": "lint"}}]
+ ]
+ , "body":
+ { "type": "RESULT"
+ , "artifacts": {"type": "var", "name": "staged results"}
+ , "runfiles": {"type": "var", "name": "staged results"}
+ , "provides": {"type": "env", "vars": ["lint"]}
+ }
+ }
+ }
+}
diff --git a/rules/transitions/EXPRESSIONS b/rules/transitions/EXPRESSIONS
new file mode 100644
index 0000000..d1ecefa
--- /dev/null
+++ b/rules/transitions/EXPRESSIONS
@@ -0,0 +1,122 @@
+{ "for host":
+ { "vars": ["ARCH", "HOST_ARCH", "TARGET_ARCH"]
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ [ "BUILD_ARCH"
+ , { "type": "var"
+ , "name": "TARGET_ARCH"
+ , "default": {"type": "var", "name": "ARCH"}
+ }
+ ]
+ , [ "TARGET_ARCH"
+ , { "type": "var"
+ , "name": "HOST_ARCH"
+ , "default": {"type": "var", "name": "ARCH"}
+ }
+ ]
+ ]
+ , "body": {"type": "env", "vars": ["BUILD_ARCH", "TARGET_ARCH"]}
+ }
+ }
+, "with fPIC":
+ { "doc":
+ [ "Transition that enables BUILD_POSITION_INDEPENDENT if config_field"
+ , "\"shared\" is not empty."
+ ]
+ , "var": ["BUILD_OBJECT_ONLY"]
+ , "expression":
+ { "type": "if"
+ , "cond":
+ { "type": "and"
+ , "$1":
+ [ {"type": "FIELD", "name": "shared"}
+ , {"type": "not", "$1": {"type": "var", "name": "BUILD_OBJECT_ONLY"}}
+ ]
+ }
+ , "then":
+ { "type": "singleton_map"
+ , "key": "BUILD_POSITION_INDEPENDENT"
+ , "value": true
+ }
+ , "else": {"type": "empty_map"}
+ }
+ }
+, "with fPIC, not object-only":
+ { "doc": ["Like \"with fPIC\", but also clearing BUILD_OBJECT_ONLY"]
+ , "var": ["BUILD_OBJECT_ONLY"]
+ , "imports": {"with fPIC": "with fPIC"}
+ , "expression":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "with fPIC"}
+ , {"type": "singleton_map", "key": "BUILD_OBJECT_ONLY", "value": null}
+ , { "type": "singleton_map"
+ , "key": "BUILD_OBJECT_ONLY_DROP_OBJECT_LINKING"
+ , "value": null
+ }
+ ]
+ }
+ }
+, "with fPIC, object-only":
+ { "doc":
+ ["Like \"with fPIC\", but also unconditionally setting BUILD_OBJECT_ONLY"]
+ , "var": ["BUILD_OBJECT_ONLY"]
+ , "imports": {"with fPIC": "with fPIC"}
+ , "expression":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "with fPIC"}
+ , {"type": "singleton_map", "key": "BUILD_OBJECT_ONLY", "value": true}
+ , { "type": "singleton_map"
+ , "key": "BUILD_OBJECT_ONLY_DROP_OBJECT_LINKING"
+ , "value": true
+ }
+ ]
+ }
+ }
+, "target properties":
+ { "vars": ["ARCH", "TARGET_ARCH", "ARCH_DISPATCH"]
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ [ "TARGET_ARCH"
+ , { "type": "var"
+ , "name": "TARGET_ARCH"
+ , "default": {"type": "var", "name": "ARCH"}
+ }
+ ]
+ ]
+ , "body":
+ { "type": "if"
+ , "cond":
+ { "type": "=="
+ , "$1": {"type": "var", "name": "TARGET_ARCH"}
+ , "$2": null
+ }
+ , "then": {"type": "empty_map"}
+ , "else":
+ { "type": "lookup"
+ , "map":
+ { "type": "var"
+ , "name": "ARCH_DISPATCH"
+ , "default": {"type": "empty_map"}
+ }
+ , "key": {"type": "var", "name": "TARGET_ARCH"}
+ , "default": {"type": "empty_map"}
+ }
+ }
+ }
+ }
+, "maybe for host":
+ { "vars": ["ARCH", "HOST_ARCH", "TARGET_ARCH", "ARCH_DISPATCH"]
+ , "imports":
+ {"target properties": "target properties", "for host": "for host"}
+ , "expression":
+ { "type": "if"
+ , "cond": {"type": "CALL_EXPRESSION", "name": "target properties"}
+ , "then": {"type": "empty_map"}
+ , "else": {"type": "CALL_EXPRESSION", "name": "for host"}
+ }
+ }
+}