summaryrefslogtreecommitdiff
path: root/rules
diff options
context:
space:
mode:
authorOliver Reiche <oliver.reiche@huawei.com>2023-04-11 18:53:05 +0200
committerKlaus Aehlig <klaus.aehlig@huawei.com>2023-04-18 12:44:10 +0200
commitbfd90d1607d9bbb88c24591be5dc252d2c2230df (patch)
treea231ab592047f495fb53503e8f81a58aeda5fe8d /rules
parentaba17c0a051ea76215de78906e61f62f5598e5dd (diff)
downloadjustbuild-bfd90d1607d9bbb88c24591be5dc252d2c2230df.tar.gz
rules: Support install-with-deps rule
Backport of commits a382b308b9011606e7d07376808812d51631d558 and 5ae5134804b6edaaffec593868f133dd840ef7df from the rules-cc repository.
Diffstat (limited to 'rules')
-rw-r--r--rules/CC/EXPRESSIONS187
-rw-r--r--rules/CC/RULES255
-rw-r--r--rules/EXPRESSIONS47
3 files changed, 488 insertions, 1 deletions
diff --git a/rules/CC/EXPRESSIONS b/rules/CC/EXPRESSIONS
index 7a8c531b..b33056e3 100644
--- a/rules/CC/EXPRESSIONS
+++ b/rules/CC/EXPRESSIONS
@@ -326,6 +326,182 @@
, "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"]
+ , "imports": {"contains": ["", "contains"]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [["list", {"type": "keys", "$1": {"type": "var", "name": "pkg-libs"}}]]
+ , "body":
+ { "type": "foreach"
+ , "var": "item"
+ , "range": {"type": "var", "name": "pkg-ldflags"}
+ , "body":
+ { "type": "if"
+ , "cond": {"type": "CALL_EXPRESSION", "name": "contains"}
+ , "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"]
+ , "imports": {"contains": ["", "contains"]}
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ [ "list"
+ , {"type": "keys", "$1": {"type": "var", "name": "pkg-flag-files"}}
+ ]
+ , ["list_prefix", "@"]
+ ]
+ , "body":
+ { "type": "foreach"
+ , "var": "item"
+ , "range": {"type": "var", "name": "flags"}
+ , "body":
+ { "type": "let*"
+ , "bindings":
+ [["flag-file", {"type": "CALL_EXPRESSION", "name": "contains"}]]
+ , "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"
@@ -661,6 +837,7 @@
, "private-cflags"
, "private-ldflags"
, "stage"
+ , "pkg-name"
, "extra-provides"
, "public-fieldnames"
, "private-fieldnames"
@@ -727,7 +904,13 @@
, [ "cflags-files"
, {"type": "CALL_EXPRESSION", "name": "cflags-files-deps"}
]
- , ["package", {"type": "env", "vars": ["cflags-files", "ldflags-files"]}]
+ , [ "package"
+ , { "type": "let*"
+ , "bindings": [["name", {"type": "var", "name": "pkg-name"}]]
+ , "body":
+ {"type": "env", "vars": ["name", "cflags-files", "ldflags-files"]}
+ }
+ ]
]
, "body":
{ "type": "RESULT"
@@ -932,10 +1115,12 @@
, [ "ldflags-files"
, {"type": "CALL_EXPRESSION", "name": "ldflags-files-deps"}
]
+ , ["package", {"type": "singleton_map", "key": "to_bin", "value": true}]
]
, "body":
{ "type": "RESULT"
, "artifacts": {"type": "CALL_EXPRESSION", "name": "binary"}
+ , "provides": {"type": "env", "vars": ["package"]}
}
}
}
diff --git a/rules/CC/RULES b/rules/CC/RULES
index 2b420fbc..45b9035a 100644
--- a/rules/CC/RULES
+++ b/rules/CC/RULES
@@ -122,6 +122,7 @@
, "cflags"
, "private-cflags"
, "private-ldflags"
+ , "pkg-name"
]
, "config_vars":
[ "CC"
@@ -181,6 +182,10 @@
, "duplicate work will be carried out, even if the same proto library"
, "is used at various places)."
]
+ , "pkg-name":
+ [ "Name to use for pkg-config files. If this field is empty, the field"
+ , "\"name\" is used instead."
+ ]
}
, "config_doc":
{ "CC":
@@ -318,6 +323,14 @@
}
]
, ["private-ldflags", {"type": "FIELD", "name": "private-ldflags"}]
+ , [ "pkg-name"
+ , { "type": "if"
+ , "cond": {"type": "FIELD", "name": "pkg-name"}
+ , "then":
+ {"type": "join", "$1": {"type": "FIELD", "name": "pkg-name"}}
+ , "else": {"type": "var", "name": "name"}
+ }
+ ]
, ["public-fieldnames", ["deps", "proto-deps"]]
, ["private-fieldnames", ["deps", "private-deps", "proto-deps"]]
]
@@ -462,4 +475,246 @@
, "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 \"share/pkgconfig\"."
+ ]
+ , "config_vars": ["PREFIX"]
+ , "target_fields": ["targets"]
+ , "string_fields": ["flat-libs", "prefix"]
+ , "imports":
+ { "compile-deps": "compile-deps"
+ , "compile-args-deps": "compile-args-deps"
+ , "link-deps": "link-deps"
+ , "link-args-deps": "link-args-deps"
+ , "pkg-config": "pkg-config"
+ }
+ , "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 \"/\"."
+ ]
+ }
+ , "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", "share/pkgconfig"]
+ , [ "install-stage"
+ , { "type": "disjoint_map_union"
+ , "msg": "install stages may not overlap"
+ , "$1":
+ { "type": "foreach"
+ , "var": "target"
+ , "range": {"type": "FIELD", "name": "targets"}
+ , "body":
+ { "type": "let*"
+ , "bindings":
+ [ [ "artifacts"
+ , { "type": "DEP_ARTIFACTS"
+ , "dep": {"type": "var", "name": "target"}
+ , "default": {"type": "empty_map"}
+ }
+ ]
+ , [ "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"}
+ }
+ ]
+ , [ "link-deps"
+ , { "type": "DEP_PROVIDES"
+ , "dep": {"type": "var", "name": "target"}
+ , "provider": "link-deps"
+ , "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"}
+ }
+ ]
+ , [ "headers"
+ , { "type": "disjoint_map_union"
+ , "msg": "headers may not overlap"
+ , "$1":
+ [ {"type": "var", "name": "runfiles"}
+ , {"type": "var", "name": "compile-deps"}
+ ]
+ }
+ ]
+ , [ "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"}]
+ ]
+ }
+ }
+ ]
+ , [ "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": "if"
+ , "cond": {"type": "FIELD", "name": "prefix"}
+ , "then":
+ { "type": "join"
+ , "separator": "/"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [[""], {"type": "FIELD", "name": "prefix"}]
+ }
+ }
+ , "else":
+ {"type": "var", "name": "PREFIX", "default": "/"}
+ }
+ ]
+ , [ "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": []
+ }
+ ]
+ }
+ ]
+ , [ "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": "FIELD", "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": "var", "name": "headers"}
+ }
+ , { "type": "to_subdir"
+ , "subdir": "lib"
+ , "flat": {"type": "FIELD", "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"}
+ }
+ ]
+ }
+ }
+ }
+ }
+ ]
+ ]
+ , "body":
+ {"type": "RESULT", "artifacts": {"type": "var", "name": "install-stage"}}
+ }
+ }
}
diff --git a/rules/EXPRESSIONS b/rules/EXPRESSIONS
index b974026e..c84ebf46 100644
--- a/rules/EXPRESSIONS
+++ b/rules/EXPRESSIONS
@@ -226,4 +226,51 @@
}
}
}
+, "contains":
+ { "doc": ["Returns the item if it is in the list or \"null\" otherwise."]
+ , "vars": ["list", "item", "list_prefix"]
+ , "vars_doc":
+ { "list": ["The list to look for the item."]
+ , "item": ["The item to look for in the list."]
+ , "list_prefix":
+ [ "An optional string, which every item in the list is prefixed with"
+ , "before comparison. Note that the returned item is not prefixed."
+ ]
+ }
+ , "expression":
+ { "type": "let*"
+ , "bindings":
+ [ [ "result"
+ , { "type": "++"
+ , "$1":
+ { "type": "foreach"
+ , "var": "entry"
+ , "range": {"type": "var", "name": "list"}
+ , "body":
+ { "type": "if"
+ , "cond":
+ { "type": "=="
+ , "$1":
+ { "type": "join"
+ , "$1":
+ [ {"type": "var", "name": "list_prefix", "default": ""}
+ , {"type": "var", "name": "entry"}
+ ]
+ }
+ , "$2": {"type": "var", "name": "item"}
+ }
+ , "then": [{"type": "var", "name": "entry"}]
+ }
+ }
+ }
+ ]
+ ]
+ , "body":
+ { "type": "if"
+ , "cond": {"type": "var", "name": "result"}
+ , "then": {"type": "join", "$1": {"type": "var", "name": "result"}}
+ , "else": null
+ }
+ }
+ }
}