From e355328f3bdafc009be35b57aa9eab1c638ae1de Mon Sep 17 00:00:00 2001 From: Douglas Raillard Date: Mon, 21 Aug 2023 15:32:17 +0100 Subject: [PATCH 1/4] lisa._assets.kmodules.lisa: Allow C type introspection FEATURE For each type defined in vmlinux.h, allow compile-time introspection on struct/union/enum members from vmlinux.h using: * HAS_MEMBER(type, member), e.g. HAS_MEMBER(cfs_rq, avg) * HAS_TYPE(type), e.g. HAS_TYPE(cfs_rq) --- lisa/_assets/kmodules/lisa/Makefile | 12 +- .../kmodules/lisa/introspect_header.py | 137 ++++++++++++++++++ lisa/_assets/kmodules/lisa/introspection.h | 10 ++ lisa/_assets/kmodules/lisa/requirements.txt | 1 + lisa/_kmod.py | 1 + setup.py | 1 + tools/kmodules/lisa/introspect_header.py | 1 + tools/kmodules/lisa/introspection.h | 1 + tools/kmodules/lisa/requirements.txt | 1 + 9 files changed, 161 insertions(+), 4 deletions(-) create mode 100755 lisa/_assets/kmodules/lisa/introspect_header.py create mode 100644 lisa/_assets/kmodules/lisa/introspection.h create mode 100644 lisa/_assets/kmodules/lisa/requirements.txt create mode 120000 tools/kmodules/lisa/introspect_header.py create mode 120000 tools/kmodules/lisa/introspection.h create mode 120000 tools/kmodules/lisa/requirements.txt diff --git a/lisa/_assets/kmodules/lisa/Makefile b/lisa/_assets/kmodules/lisa/Makefile index ec765c253..03cc73003 100644 --- a/lisa/_assets/kmodules/lisa/Makefile +++ b/lisa/_assets/kmodules/lisa/Makefile @@ -82,7 +82,12 @@ endif VMLINUX_H_TYPE_PREFIX=KERNEL_PRIVATE_ -$(VMLINUX_H): $(GENERATED) $(VMLINUX_TXT) $(VMLINUX) +python_env: + python3 -m pip install -r $(MODULE_SRC)/requirements.txt + +.PHONY: python_env + +$(VMLINUX_H): $(GENERATED) $(VMLINUX_TXT) $(VMLINUX) python_env # Some options are not upstream (yet) but they have all be published on the # dwarves mailing list # @@ -112,9 +117,8 @@ $(VMLINUX_H): $(GENERATED) $(VMLINUX_TXT) $(VMLINUX) "$(CC)" -P -E - < _header > _header_no_comment # Create forward declaration of every type sed -r -n 's/.*(struct|union|enum) ([0-9a-zA-Z_]*) .*/\1 \2;/p' _header_no_comment | sort -u > _fwd_decl -# Create TYPED_DEFINED_struct_foo macros for every type, so the client code can -# check whether a given type exists before making use of it - sed -r -n 's/.*(struct|union|enum) ([0-9a-zA-Z_]*) .*/#define TYPE_DEFINED_\1_\2/p' _header_no_comment | sort -u >> _fwd_decl +# Create type introspection macros + python3 $(MODULE_SRC)/introspect_header.py _header >> _fwd_decl cat _fwd_decl _header > $@ # cat $@ diff --git a/lisa/_assets/kmodules/lisa/introspect_header.py b/lisa/_assets/kmodules/lisa/introspect_header.py new file mode 100755 index 000000000..3d5be1f42 --- /dev/null +++ b/lisa/_assets/kmodules/lisa/introspect_header.py @@ -0,0 +1,137 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (C) 2019, Arm Limited and contributors. +# +# 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 itertools +import argparse +import subprocess +from collections import namedtuple + +from pycparser import c_parser, c_ast + + +class TypeMember(namedtuple('TypeMember', ['type_name', 'member_name'])): + def make_define(self): + return f'#define _TYPE_HAS_MEMBER_{self.type_name}___{self.member_name}' + + @property + def printable(self): + return self.type_name and self.member_name + + +class TypeExists(namedtuple('TypeExists', ['type_name'])): + def make_define(self): + return f'#define _TYPE_EXISTS_{self.type_name}' + + @property + def printable(self): + return bool(self.type_name) + +def expand_typ(typ): + if isinstance(typ, c_ast.TypeDecl): + return expand_typ(typ.type) + else: + return [typ] + +def resolve_typ(typ): + if isinstance(typ, (c_ast.Struct, c_ast.Union)): + children = typ.decls or [] + children_typs = [ + child.type + for child in children + ] + name = typ.name + elif isinstance(typ, c_ast.Enum): + children = typ.values or [] + children_typs = [] + name = typ.name + elif isinstance(typ, c_ast.TypeDecl): + name = typ.declname + _, children, children_typs = resolve_typ(typ.type) + else: + raise ValueError('Unhandled type') + + return (name, children, children_typs) + + +def walk_type(typ): + try: + name, children, children_typs = resolve_typ(typ) + except ValueError: + return [] + else: + children_typs = itertools.chain.from_iterable(map(expand_typ, children_typs)) + + return itertools.chain( + [ + TypeExists(type_name=name) + ], + ( + TypeMember(type_name=name, member_name=child.name) + for child in children + ), + itertools.chain.from_iterable(map(walk_type, children_typs)) + ) + + +def main(): + parser = argparse.ArgumentParser(""" + Parse a header file and generate macros to allow compile-time introspection + of types. + """) + + parser.add_argument('header', help='C header file to parse') + + args = parser.parse_args() + with open(args.header, 'r') as f: + header = f.read() + + # Remove comments and the non-standard GNU C extensions that pycparser cannot + # process + cmd = ['cpp', '-P', '-D__attribute__(x)=', '-'] + res = subprocess.run(cmd, input=header, capture_output=True, text=True, check=True) + header = res.stdout + + parser = c_parser.CParser() + node = parser.parse(header, filename=args.header) + + assert isinstance(node, c_ast.FileAST) + + types = [ + _node.type + for _node in node + if isinstance(_node, (c_ast.Decl, c_ast.Typedef, c_ast.TypeDecl)) + ] + + records = set(itertools.chain.from_iterable(map(walk_type, types))) + records = sorted( + record + for record in records + if record.printable + ) + macros = '\n'.join( + record.make_define() + for record in records + ) + print('#define _TYPE_INTROSPECTION_INFO_AVAILABLE') + print(macros) + + + +main() diff --git a/lisa/_assets/kmodules/lisa/introspection.h b/lisa/_assets/kmodules/lisa/introspection.h new file mode 100644 index 000000000..84ac7c035 --- /dev/null +++ b/lisa/_assets/kmodules/lisa/introspection.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef INTROSPECTION_H +#define INTROSPECTION_H + +#include + +#define HAS_TYPE(typ) ((defined(_TYPE_INTROSPECTION_INFO_AVAILABLE) && defined(_TYPE_EXISTS_##typ)) || (!defined(_TYPE_INTROSPECTION_INFO_AVAILABLE))) +#define HAS_MEMBER(typ, member) ((defined(_TYPE_INTROSPECTION_INFO_AVAILABLE) && defined(_TYPE_HAS_MEMBER_##typ##___##member)) || (!defined(_TYPE_INTROSPECTION_INFO_AVAILABLE))) + +#endif /* INTROSPECTION_H */ diff --git a/lisa/_assets/kmodules/lisa/requirements.txt b/lisa/_assets/kmodules/lisa/requirements.txt new file mode 100644 index 000000000..dc1c9e101 --- /dev/null +++ b/lisa/_assets/kmodules/lisa/requirements.txt @@ -0,0 +1 @@ +pycparser diff --git a/lisa/_kmod.py b/lisa/_kmod.py index 4805a38c0..f382c68d6 100644 --- a/lisa/_kmod.py +++ b/lisa/_kmod.py @@ -255,6 +255,7 @@ def _make_build_chroot(cc, abi, bind_paths=None, version=None, overlay_backend=N 'bison', 'flex', 'python3', + 'py3-pip', ] if is_clang(cc): diff --git a/setup.py b/setup.py index 64aae32be..1b0dcdfd7 100755 --- a/setup.py +++ b/setup.py @@ -164,6 +164,7 @@ if __name__ == "__main__": "cffi", # unshare syscall "typeguard", + "pycparser", # For the kernel module build ], extras_require=extras_require, diff --git a/tools/kmodules/lisa/introspect_header.py b/tools/kmodules/lisa/introspect_header.py new file mode 120000 index 000000000..5ce079e31 --- /dev/null +++ b/tools/kmodules/lisa/introspect_header.py @@ -0,0 +1 @@ +../../../lisa/_assets/kmodules/lisa/introspect_header.py \ No newline at end of file diff --git a/tools/kmodules/lisa/introspection.h b/tools/kmodules/lisa/introspection.h new file mode 120000 index 000000000..87a8d4f3d --- /dev/null +++ b/tools/kmodules/lisa/introspection.h @@ -0,0 +1 @@ +../../../lisa/_assets/kmodules/lisa/introspection.h \ No newline at end of file diff --git a/tools/kmodules/lisa/requirements.txt b/tools/kmodules/lisa/requirements.txt new file mode 120000 index 000000000..6e79167a5 --- /dev/null +++ b/tools/kmodules/lisa/requirements.txt @@ -0,0 +1 @@ +../../../lisa/_assets/kmodules/lisa/requirements.txt \ No newline at end of file -- GitLab From 37c3769f574c1157ed889260fef596703165f2bd Mon Sep 17 00:00:00 2001 From: Douglas Raillard Date: Tue, 22 Aug 2023 14:47:58 +0100 Subject: [PATCH 2/4] lisa._assets.kmodules.lisa: Factor out the in-tree build detection --- lisa/_assets/kmodules/lisa/Makefile | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lisa/_assets/kmodules/lisa/Makefile b/lisa/_assets/kmodules/lisa/Makefile index 03cc73003..fc06078f2 100644 --- a/lisa/_assets/kmodules/lisa/Makefile +++ b/lisa/_assets/kmodules/lisa/Makefile @@ -15,12 +15,17 @@ # limitations under the License. # +ifeq ($(srctree),.) + IN_TREE_BUILD := 0 +else + IN_TREE_BUILD := 1 +endif + # Kbuild ifneq ($(KERNELRELEASE),) MODULE_OBJ := $(obj) KERNEL_SRC ?= $(srctree) -# Kbuild in-tree build -ifneq ($(srctree),.) +ifeq ($(IN_TREE_BUILD),1) MODULE_SRC ?= $(srctree)/$(src) # Kbuild out-of-tree build else @@ -54,7 +59,7 @@ SYMBOL_NAMESPACES_H = $(GENERATED)/symbol_namespaces.h MODULE_VERSION_H = $(GENERATED)/module_version.h # in-tree build -ifneq ($(srctree),.) +ifeq ($(IN_TREE_BUILD),1) ccflags-y += -I$(srctree) -D_IN_TREE_BUILD ldflags-y += -T $(srctree)/$(obj)/$(FEATURES_LDS) -- GitLab From a40cf66d1f867395b625764360f3bb2eceac9a06 Mon Sep 17 00:00:00 2001 From: Douglas Raillard Date: Tue, 22 Aug 2023 15:06:36 +0100 Subject: [PATCH 3/4] lisa._assets.kmodules.lisa: Make a synthetic vmlinux for in-tree builds FEATURE Instead of relying on direct inclusion of private headers for in-tree builds, include these headers in a separate compilation unit and use pahole on the object file to generate a vmlinux.h header. This has multiple advantages: * The overall code is the same regardless of the build method. In particular, internal scheduler helpers from the kernel do not leak in the module. * Since we control the creation of vmlinux.h using pahole, we can parse it to provide compile-time introspection. This would not be possible with kernel-provided headers. --- lisa/_assets/kmodules/lisa/Makefile | 49 +++++++++++++--------- lisa/_assets/kmodules/lisa/introspection.h | 2 +- lisa/_assets/kmodules/lisa/private_types.c | 14 +++++++ lisa/_assets/kmodules/lisa/sched_helpers.h | 11 +---- lisa/_assets/kmodules/lisa/tp.c | 7 +--- 5 files changed, 46 insertions(+), 37 deletions(-) create mode 100644 lisa/_assets/kmodules/lisa/private_types.c diff --git a/lisa/_assets/kmodules/lisa/Makefile b/lisa/_assets/kmodules/lisa/Makefile index fc06078f2..62f2cb793 100644 --- a/lisa/_assets/kmodules/lisa/Makefile +++ b/lisa/_assets/kmodules/lisa/Makefile @@ -44,19 +44,23 @@ ifneq ($(KERNELRELEASE),) LISA_KMOD_NAME ?= lisa obj-m := $(LISA_KMOD_NAME).o -$(LISA_KMOD_NAME)-y := main.o tp.o wq.o features.o pixel6.o +$(LISA_KMOD_NAME)-y := main.o tp.o wq.o features.o pixel6.o private_types.o # -fno-stack-protector is needed to possibly undefined __stack_chk_guard symbol -ccflags-y = "-I$(MODULE_SRC)" -std=gnu11 -fno-stack-protector -Wno-declaration-after-statement +ccflags-y := "-I$(MODULE_SRC)" -std=gnu11 -fno-stack-protector -Wno-declaration-after-statement + +# Ensure we get appropriate debug info so that pahole can work on the object +# file regardless of the kernel config. +CFLAGS_private_types.o := -g3 -gno-split-dwarf -gdwarf -fno-eliminate-unused-debug-types FEATURES_LDS := features.lds -GENERATED = $(MODULE_OBJ)/generated +GENERATED := $(MODULE_OBJ)/generated $(GENERATED): mkdir -p "$@" -SYMBOL_NAMESPACES_H = $(GENERATED)/symbol_namespaces.h -MODULE_VERSION_H = $(GENERATED)/module_version.h +SYMBOL_NAMESPACES_H := $(GENERATED)/symbol_namespaces.h +MODULE_VERSION_H := $(GENERATED)/module_version.h # in-tree build ifeq ($(IN_TREE_BUILD),1) @@ -67,32 +71,38 @@ ldflags-y += -T $(srctree)/$(obj)/$(FEATURES_LDS) # out-of-tree build else -VMLINUX_H = $(GENERATED)/vmlinux.h +PRIVATE_TYPES_H := $(GENERATED)/private_types.h ldflags-y += -T $(M)/$(FEATURES_LDS) -clean-files := $(VMLINUX_H) $(SYMBOL_NAMESPACES_H) $(MODULE_VERSION_H) +clean-files := $(PRIVATE_TYPES_H) $(SYMBOL_NAMESPACES_H) $(MODULE_VERSION_H) -VMLINUX_TXT = $(MODULE_SRC)/private_types.txt +PRIVATE_TYPES_TXT := $(MODULE_SRC)/private_types.txt # Can be either a kernel image built with DWARF debug info, or the BTF blob # found at /sys/kernel/btf/vmlinux -_BTF_VMLINUX = $(MODULE_SRC)/vmlinux -_DWARF_VMLINUX = $(KERNEL_SRC)/vmlinux -ifneq ("$(wildcard $(_BTF_VMLINUX))","") - VMLINUX := $(_BTF_VMLINUX) +_BTF_VMLINUX := $(MODULE_SRC)/vmlinux +_DWARF_VMLINUX := $(KERNEL_SRC)/vmlinux +_SYNTHETIC_VMLINUX := $(MODULE_OBJ)/private_types.o + +ifeq ("$(wildcard $(_BTF_VMLINUX))","") +ifeq ($(IN_TREE_BUILD),1) + VMLINUX := $(_SYNTHETIC_VMLINUX) else VMLINUX := $(_DWARF_VMLINUX) endif +else + VMLINUX := $(_BTF_VMLINUX) +endif -VMLINUX_H_TYPE_PREFIX=KERNEL_PRIVATE_ +PRIVATE_TYPES_H_TYPE_PREFIX := KERNEL_PRIVATE_ python_env: python3 -m pip install -r $(MODULE_SRC)/requirements.txt .PHONY: python_env -$(VMLINUX_H): $(GENERATED) $(VMLINUX_TXT) $(VMLINUX) python_env +$(PRIVATE_TYPES_H): $(GENERATED) $(PRIVATE_TYPES_TXT) $(VMLINUX) python_env # Some options are not upstream (yet) but they have all be published on the # dwarves mailing list # @@ -110,13 +120,12 @@ $(VMLINUX_H): $(GENERATED) $(VMLINUX_TXT) $(VMLINUX) python_env # that was not explicitly asked for. This avoids conflicting with type # definitions that would come from public kernel headers, while still allowing # easy attribute access. - - pahole -F btf,dwarf -E --suppress_force_paddings --show_only_data_members --skip_missing --expand_types_once -C "file://$(VMLINUX_TXT)" "$(VMLINUX)" > _header + pahole -F btf,dwarf -E --suppress_force_paddings --show_only_data_members --skip_missing --expand_types_once -C "file://$(PRIVATE_TYPES_TXT)" "$(VMLINUX)" > _header # Rename all defined types to include the prefix - sed "s/\(struct\|union\|enum\)\s*\([a-zA-Z0-9_]\+\)/\1 $(VMLINUX_H_TYPE_PREFIX)\2/g" -i _header + sed "s/\(struct\|union\|enum\)\s*\([a-zA-Z0-9_]\+\)/\1 $(PRIVATE_TYPES_H_TYPE_PREFIX)\2/g" -i _header # Create a sed script to rename back to initial state the types that we explicitly asked for - sed -n "s@\(.*\)@s/\\\(struct\\\|union\\\|enum\\\)\\\s*$(VMLINUX_H_TYPE_PREFIX)\1/\\\1 \\1/;@gp" "$(VMLINUX_TXT)" | sed -f - -i _header + sed -n "s@\(.*\)@s/\\\(struct\\\|union\\\|enum\\\)\\\s*$(PRIVATE_TYPES_H_TYPE_PREFIX)\1/\\\1 \\1/;@gp" "$(PRIVATE_TYPES_TXT)" | sed -f - -i _header # Strip comments to avoid matching them with the sed regex. "$(CC)" -P -E - < _header > _header_no_comment @@ -149,7 +158,7 @@ $(MODULE_VERSION_H): $(GENERATED) printf "\"\n#endif\n" >> $@ # Make all object files depend on the generated sources -$(addprefix $(MODULE_OBJ)/,$($(LISA_KMOD_NAME)-y)): $(VMLINUX_H) $(SYMBOL_NAMESPACES_H) $(MODULE_VERSION_H) +$(addprefix $(MODULE_OBJ)/,$($(LISA_KMOD_NAME)-y)): $(PRIVATE_TYPES_H) $(SYMBOL_NAMESPACES_H) $(MODULE_VERSION_H) # Non-Kbuild part else @@ -165,6 +174,6 @@ install: build "$(MAKE)" -C "$(KERNEL_SRC)" "M=$(MODULE_SRC)" modules_install clean: - rm -f "$(VMLINUX_H)" "$(SYMBOL_NAMESPACES_H)" + "$(MAKE)" -C "$(KERNEL_SRC)" "M=$(MODULE_SRC)" clean endif diff --git a/lisa/_assets/kmodules/lisa/introspection.h b/lisa/_assets/kmodules/lisa/introspection.h index 84ac7c035..d78f695d6 100644 --- a/lisa/_assets/kmodules/lisa/introspection.h +++ b/lisa/_assets/kmodules/lisa/introspection.h @@ -2,7 +2,7 @@ #ifndef INTROSPECTION_H #define INTROSPECTION_H -#include +#include #define HAS_TYPE(typ) ((defined(_TYPE_INTROSPECTION_INFO_AVAILABLE) && defined(_TYPE_EXISTS_##typ)) || (!defined(_TYPE_INTROSPECTION_INFO_AVAILABLE))) #define HAS_MEMBER(typ, member) ((defined(_TYPE_INTROSPECTION_INFO_AVAILABLE) && defined(_TYPE_HAS_MEMBER_##typ##___##member)) || (!defined(_TYPE_INTROSPECTION_INFO_AVAILABLE))) diff --git a/lisa/_assets/kmodules/lisa/private_types.c b/lisa/_assets/kmodules/lisa/private_types.c new file mode 100644 index 000000000..0d0639906 --- /dev/null +++ b/lisa/_assets/kmodules/lisa/private_types.c @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* Include here headers containing the types listed in private_types.txt. * We +process the debug info of the compiled object file like we would do * with the +BTF blob and generate the private_types.h header, which is then consumed the +exact * same way as an out-of-tree build. This allows controlling the format of +that * header for introspect_header.py. + */ + +#ifdef _IN_TREE_BUILD +#include +#include +#include +#endif diff --git a/lisa/_assets/kmodules/lisa/sched_helpers.h b/lisa/_assets/kmodules/lisa/sched_helpers.h index 4bbea9443..cc8b19ad9 100644 --- a/lisa/_assets/kmodules/lisa/sched_helpers.h +++ b/lisa/_assets/kmodules/lisa/sched_helpers.h @@ -7,15 +7,7 @@ #include -#ifdef _IN_TREE_BUILD - -#include -#include -#include - -#else - -#include "generated/vmlinux.h" +#include "generated/private_types.h" #ifdef CONFIG_FAIR_GROUP_SCHED static inline struct rq *rq_of(struct cfs_rq *cfs_rq) @@ -84,7 +76,6 @@ unsigned long uclamp_rq_util_with(struct rq *rq, unsigned long util, #endif } -#endif /* _IN_TREE_BUILD */ static inline void cfs_rq_tg_path(struct cfs_rq *cfs_rq, char *path, int len) { diff --git a/lisa/_assets/kmodules/lisa/tp.c b/lisa/_assets/kmodules/lisa/tp.c index fe0701880..240ab2998 100644 --- a/lisa/_assets/kmodules/lisa/tp.c +++ b/lisa/_assets/kmodules/lisa/tp.c @@ -1,18 +1,13 @@ /* SPDX-License-Identifier: GPL-2.0 */ #include - -#ifndef _IN_TREE_BUILD #include -#else -#include -#include -#endif #include #define CREATE_TRACE_POINTS #include "main.h" #include "ftrace_events.h" +#include "sched_helpers.h" #include "wq.h" #include "tp.h" -- GitLab From d1f161124a32fa1c572743f0332702687607671e Mon Sep 17 00:00:00 2001 From: Douglas Raillard Date: Tue, 22 Aug 2023 17:33:36 +0100 Subject: [PATCH 4/4] lisa._assets.kmodules.lisa: Create temp file in $(MODULE_OBJ) FIX Ensure we don't pollute the current working directory with temporary files. --- lisa/_assets/kmodules/lisa/Makefile | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lisa/_assets/kmodules/lisa/Makefile b/lisa/_assets/kmodules/lisa/Makefile index 62f2cb793..21393f6f5 100644 --- a/lisa/_assets/kmodules/lisa/Makefile +++ b/lisa/_assets/kmodules/lisa/Makefile @@ -120,20 +120,20 @@ $(PRIVATE_TYPES_H): $(GENERATED) $(PRIVATE_TYPES_TXT) $(VMLINUX) python_env # that was not explicitly asked for. This avoids conflicting with type # definitions that would come from public kernel headers, while still allowing # easy attribute access. - pahole -F btf,dwarf -E --suppress_force_paddings --show_only_data_members --skip_missing --expand_types_once -C "file://$(PRIVATE_TYPES_TXT)" "$(VMLINUX)" > _header + pahole -F btf,dwarf -E --suppress_force_paddings --show_only_data_members --skip_missing --expand_types_once -C "file://$(PRIVATE_TYPES_TXT)" "$(VMLINUX)" > $(MODULE_OBJ)/_header # Rename all defined types to include the prefix - sed "s/\(struct\|union\|enum\)\s*\([a-zA-Z0-9_]\+\)/\1 $(PRIVATE_TYPES_H_TYPE_PREFIX)\2/g" -i _header + sed "s/\(struct\|union\|enum\)\s*\([a-zA-Z0-9_]\+\)/\1 $(PRIVATE_TYPES_H_TYPE_PREFIX)\2/g" -i $(MODULE_OBJ)/_header # Create a sed script to rename back to initial state the types that we explicitly asked for - sed -n "s@\(.*\)@s/\\\(struct\\\|union\\\|enum\\\)\\\s*$(PRIVATE_TYPES_H_TYPE_PREFIX)\1/\\\1 \\1/;@gp" "$(PRIVATE_TYPES_TXT)" | sed -f - -i _header + sed -n "s@\(.*\)@s/\\\(struct\\\|union\\\|enum\\\)\\\s*$(PRIVATE_TYPES_H_TYPE_PREFIX)\1/\\\1 \\1/;@gp" "$(PRIVATE_TYPES_TXT)" | sed -f - -i $(MODULE_OBJ)/_header # Strip comments to avoid matching them with the sed regex. - "$(CC)" -P -E - < _header > _header_no_comment + "$(CC)" -P -E - < $(MODULE_OBJ)/_header > $(MODULE_OBJ)/_header_no_comment # Create forward declaration of every type - sed -r -n 's/.*(struct|union|enum) ([0-9a-zA-Z_]*) .*/\1 \2;/p' _header_no_comment | sort -u > _fwd_decl + sed -r -n 's/.*(struct|union|enum) ([0-9a-zA-Z_]*) .*/\1 \2;/p' $(MODULE_OBJ)/_header_no_comment | sort -u > $(MODULE_OBJ)/_fwd_decl # Create type introspection macros - python3 $(MODULE_SRC)/introspect_header.py _header >> _fwd_decl - cat _fwd_decl _header > $@ + python3 $(MODULE_SRC)/introspect_header.py $(MODULE_OBJ)/_header >> $(MODULE_OBJ)/_fwd_decl + cat $(MODULE_OBJ)/_fwd_decl $(MODULE_OBJ)/_header > $@ # cat $@ # out-of-tree build -- GitLab