summaryrefslogtreecommitdiff
path: root/CC
diff options
context:
space:
mode:
Diffstat (limited to 'CC')
-rw-r--r--CC/prebuilt/EXPRESSIONS186
-rw-r--r--CC/prebuilt/RULES31
-rwxr-xr-xCC/prebuilt/read_pkgconfig.py75
3 files changed, 288 insertions, 4 deletions
diff --git a/CC/prebuilt/EXPRESSIONS b/CC/prebuilt/EXPRESSIONS
index ca576f4..fc901d7 100644
--- a/CC/prebuilt/EXPRESSIONS
+++ b/CC/prebuilt/EXPRESSIONS
@@ -88,13 +88,16 @@
}
, "prebuilt result":
{ "vars":
- [ "name"
+ [ "ENV"
+ , "name"
, "version"
, "stage"
, "cflags"
, "ldflags"
, "libs"
, "hdrs"
+ , "config_reader"
+ , "pkg-configs"
, "deps-fieldnames"
]
, "imports":
@@ -105,6 +108,9 @@
, "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"]
}
, "expression":
{ "type": "let*"
@@ -225,6 +231,179 @@
}
}
]
+ , [ "ENV"
+ , { "type": "map_union"
+ , "$1":
+ { "type": "++"
+ , "$1":
+ [ {"type": "CALL_EXPRESSION", "name": "default-ENV"}
+ , [ { "type": "var"
+ , "name": "ENV"
+ , "default": {"type": "empty_map"}
+ }
+ ]
+ ]
+ }
+ }
+ ]
+ , [ "main-pkg-config"
+ , { "type": "foldl"
+ , "range": {"type": "var", "name": "pkg-configs", "default": []}
+ , "start": null
+ , "accum_var": "name"
+ , "var": "config"
+ , "body":
+ { "type": "if"
+ , "cond": {"type": "var", "name": "name"}
+ , "then": {"type": "var", "name": "name"}
+ , "else":
+ { "type": "join"
+ , "$1": {"type": "keys", "$1": {"type": "var", "name": "config"}}
+ }
+ }
+ }
+ ]
+ , [ "reader-inputs"
+ , { "type": "to_subdir"
+ , "subdir": "lib"
+ , "$1":
+ { "type": "map_union"
+ , "$1":
+ [ {"type": "var", "name": "libs"}
+ , { "type": "to_subdir"
+ , "subdir": "pkgconfig"
+ , "flat": true
+ , "$1":
+ { "type": "map_union"
+ , "$1": {"type": "var", "name": "pkg-configs", "default": []}
+ }
+ }
+ ]
+ }
+ }
+ ]
+ , [ "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":
+ [ "./config_reader"
+ , {"type": "var", "name": "cflags-filename"}
+ , {"type": "var", "name": "main-pkg-config"}
+ ]
+ , "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":
+ [ "./config_reader"
+ , {"type": "var", "name": "ldflags-filename"}
+ , {"type": "var", "name": "main-pkg-config"}
+ ]
+ , "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-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":
@@ -241,7 +420,10 @@
}
]
]
- , "body": {"type": "env", "vars": ["name", "version"]}
+ , "body":
+ { "type": "env"
+ , "vars": ["name", "version", "cflags-files", "ldflags-files"]
+ }
}
]
]
diff --git a/CC/prebuilt/RULES b/CC/prebuilt/RULES
index be2bacc..16f9f26 100644
--- a/CC/prebuilt/RULES
+++ b/CC/prebuilt/RULES
@@ -1,8 +1,13 @@
{ "library":
{ "doc": ["A prebuilt C++ library"]
- , "target_fields": ["lib", "hdrs", "deps"]
+ , "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"
@@ -32,6 +37,13 @@
["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"
@@ -67,7 +79,9 @@
]
}
, "imports":
- { "artifacts_list": ["./", "../..", "field_artifacts_list"]
+ { "artifacts": ["./", "../..", "field_artifacts"]
+ , "artifacts_list": ["./", "../..", "field_artifacts_list"]
+ , "stage_field": ["", "stage_singleton_field"]
, "prebuilt result": "prebuilt result"
}
, "expression":
@@ -112,6 +126,19 @@
, "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/CC/prebuilt/read_pkgconfig.py b/CC/prebuilt/read_pkgconfig.py
new file mode 100755
index 0000000..cb4154f
--- /dev/null
+++ b/CC/prebuilt/read_pkgconfig.py
@@ -0,0 +1,75 @@
+#!/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
+
+
+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, 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(["--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():
+ if len(sys.argv) < 3:
+ print(f"usage: read_pkgconfig OUT_NAME PC_FILE")
+ exit(1)
+
+ name = sys.argv[1]
+ pkg = Path(sys.argv[2]).stem
+ env = dict(os.environ, PKG_CONFIG_PATH="./lib/pkgconfig")
+
+ if name.endswith(".cflags"):
+ data = run_pkgconfig(["--cflags-only-other", pkg], env)
+ else:
+ data = read_ldflags(pkg, env)
+
+ with open(f"{name}", 'w') as f:
+ f.write(data)
+
+
+if __name__ == "__main__":
+ read_pkgconfig()