Hello Max,

See feedback below

On 8/13/21 6:18 AM, Maximilian Blenk wrote:
> Add class to analyze binaries with checksec.py. checksec.py is a tool
> that checks if security features of a compiler have been used. To do
> so, it analyses the resulting binaries:
>  * NX Proctection is enabled
>  * Full RELRO is enabled
>  * RPATH and RUNPATH are not set
>  * Executables are compiled to be position independent
>  * FORTIFY_SOURCE is set (false-positives possible)
>  * Stack Canaries are enabled (false-positives possible)
>
> Signed-off-by: Maximilian Blenk <[email protected]>
> ---
> Hi guys,
>
> we are currently working on adding automatically checking the binaries
> we put into an image for the presence of certain recommended compiler
> features. To achieve this, we created a bbclass that wraps around the
> existing project checksec.py (https://github.com/Wenzel/checksec.py). In
> particular, checksec.py is used to check if
> * relro is enabled
> * executables are compiled to be position indipendet code
> * rpath and runpath are not set
> * stack canaries are enabled
> * fortify source is enabled
> I must however admit that the last two checks can suffer from
> false-positives which need manual analysis and whitelisting (check can
> also be completely disabled).
>
> Motivation:
> We've decided that such checks would be a nice thing to have because
> people might overwrite important compiler flags in their local recipe.
> Additionally there is always the possibility that components are shipped
> as binaries instead of code (so they are actually build outside the
> current build environment). Overall we've detected several cases where
> required compiler flags have not been applied to shipped components.
> After internal discussion we came to the conclusion that you guys would
> maybe also be interested in this kind of checks, so I'm offering this
> patch to you as well.
>
> I would really appreciate your feedback :-)

I used these against current master and found some duplicate recipes in
either Core or meta-python so I removed these.

 python3-asttokens_2.0.5.bb     
 python3-colorama_%.bbappend   
 python3-docopt_0.6.2.bb      
 python3-setuptools-scm_6.0.1.bb
 python3-toml_%.bbappend        

see:
https://gitlab.com/akuster/meta-security/-/commit/1332825d23eb8ff08e124422b3f25a030c032c0b

I needed to covert to the new overrides scheme before I could build.

see:
https://gitlab.com/akuster/meta-security/-/commit/847bd7551acd3a9ca539b9beccd83a149bdd417d

feel free to reuse those changes.

Regarding the selftest, is there test for failure?

I ran this against core-image-minimal and nothing was printed out. Does
that mean its fine?

You may want to remove the ".py" from
python3-checksec.py-native_0.6.1.bb, its not needed.

-armin
>
> BR Max
>
>  classes/image-with-hardened-binaries.bbclass  | 338 ++++++++++++++++++
>  ...1-main-Add-option-to-ignore-symlinks.patch |  81 +++++
>  .../0002-Elf-Fix-relro-detection.patch        |  51 +++
>  ...heck-Treat-binaries-with-0-fortifiab.patch |  33 ++
>  ...o-use-pre-compiled-version-of-spdlog.patch | 154 ++++++++
>  .../python/python3-asttokens_2.0.5.bb         |  15 +
>  .../python3-checksec.py-native_0.6.1.bb       |  31 ++
>  .../python/python3-colorama_%.bbappend        |   1 +
>  .../python/python3-commonmark_0.9.1.bb        |  14 +
>  .../python/python3-docopt_0.6.2.bb            |  18 +
>  .../python/python3-icontract_2.5.3.bb         |  14 +
>  .../python/python3-lief_0.11.5.bb             |  36 ++
>  .../python/python3-pylddwrap_1.0.1.bb         |  21 ++
>  recipes-devtools/python/python3-rich_7.1.0.bb |  16 +
>  .../python/python3-setuptools-scm_6.0.1.bb    |  17 +
>  .../python/python3-toml_%.bbappend            |   1 +
>  16 files changed, 841 insertions(+)
>  create mode 100644 classes/image-with-hardened-binaries.bbclass
>  create mode 100644 
> recipes-devtools/python/files/python3-checksec.py/0001-main-Add-option-to-ignore-symlinks.patch
>  create mode 100644 
> recipes-devtools/python/files/python3-checksec.py/0002-Elf-Fix-relro-detection.patch
>  create mode 100644 
> recipes-devtools/python/files/python3-checksec.py/0003-fortify-source-check-Treat-binaries-with-0-fortifiab.patch
>  create mode 100644 
> recipes-devtools/python/files/python3-lief/0001-Enable-to-use-pre-compiled-version-of-spdlog.patch
>  create mode 100644 recipes-devtools/python/python3-asttokens_2.0.5.bb
>  create mode 100644 
> recipes-devtools/python/python3-checksec.py-native_0.6.1.bb
>  create mode 100644 recipes-devtools/python/python3-colorama_%.bbappend
>  create mode 100644 recipes-devtools/python/python3-commonmark_0.9.1.bb
>  create mode 100644 recipes-devtools/python/python3-docopt_0.6.2.bb
>  create mode 100644 recipes-devtools/python/python3-icontract_2.5.3.bb
>  create mode 100644 recipes-devtools/python/python3-lief_0.11.5.bb
>  create mode 100644 recipes-devtools/python/python3-pylddwrap_1.0.1.bb
>  create mode 100644 recipes-devtools/python/python3-rich_7.1.0.bb
>  create mode 100644 recipes-devtools/python/python3-setuptools-scm_6.0.1.bb
>  create mode 100644 recipes-devtools/python/python3-toml_%.bbappend
>
> diff --git a/classes/image-with-hardened-binaries.bbclass 
> b/classes/image-with-hardened-binaries.bbclass
> new file mode 100644
> index 0000000..d7d3908
> --- /dev/null
> +++ b/classes/image-with-hardened-binaries.bbclass
> @@ -0,0 +1,338 @@
> +# Provide qa checks to ensure all applications and libraries shipped with 
> the image
> +# have common compiler security features enabled. In particular there are 
> checks that:
> +# * nx protection is enabled
> +# * relro is enabled
> +# * executables (except for static linked ones) are position independent
> +# * rpath and runpath are not set
> +
> +IMAGE_QA_COMMANDS += "image_check_binary_hardening"
> +
> +DEPENDS += "python3-checksec.py-native"
> +
> +inherit python3native
> +
> +# Add mappings to the path mappers (which determines if a binary is a 
> application or
> +# shared library). To add a mapping append " 
> /path/from/the/root/to/bin:{application,library,ignore}"
> +# to the list
> +HARDENED_BINARIES_EXTRA_MAPPING ?= ""
> +
> +# Config file in TOML format:
> +# [check]
> +# enabled = true
> +# whitelist = [
> +#   "path to some binary",
> +#   "path to some other binary"
> +# ]
> +# supported checks are: nx, relro, pie, rpath, runpath
> +HARDENED_BINARIES_CONFIG_FILE ?= ""
> +
> +# Custom message to show in case of a detected violation
> +# For instace if you want to add whom to contact for support
> +HARDENED_BINARIES_CUSTOM_ERROR_MESSAGE ?= ""
> +
> +# Path to libc used for foritfy source analysis. If fortify_source check is
> +# not enabled, this variable can be ignored.
> +HARDENED_BINARIES_LIBC_PATH ?= "${IMAGE_ROOTFS}${baselib}/libc.so.6"
> +
> +python image_check_binary_hardening () {
> +    import fnmatch
> +    import json
> +    import os
> +    import subprocess
> +    import toml
> +    from collections import defaultdict, OrderedDict
> +    from enum import Enum, auto
> +
> +    from oe.utils import ImageQAFailed
> +
> +    rootfs = d.getVar("IMAGE_ROOTFS")
> +
> +    #################################
> +    ## Data about supported checks ##
> +    #################################
> +
> +    class BinType(Enum):
> +        IGNORE = "ignore"
> +        APPLICATION = "application"
> +        LIBRARY = "library"
> +
> +    # Dict of checks to perform on the analysis result of checksec.py
> +    # Each entry needs to contain the following attributes:
> +    #  - allowed_value: Value in the analysis result that should be accepted
> +    #  - bintypes: List of types on which the check shall be enforced (e.g. 
> PIE check on libraries
> +    #              doesn't make much sense because PIE is only for 
> executables)
> +    #  - errormsg: Message that should be prompted in case violators have 
> been found
> +    #  - ignore_static: Indicates if statically linked applications should 
> be ignored for that check
> +    #  Notes specific checks:
> +    #  - NX: Needs to be enforced on applications and libraries. This is 
> because if only a single shared
> +    #        library doesn't use that, the whole process needs to have a 
> executable stack.
> +    #  - RELRO: Statically linked applications do not make use of 
> relocation, so this check would always
> +    #           fail for statically linked applications.
> +    #  - PIE: This check is only valid for applications (as in "position 
> independent executable" for
> +    #         applications vs. "position independent code" (PIC) for shared 
> libraries)
> +    CHECK_DATA = {
> +        "nx" : {
> +            "allowed_value": True,
> +            "bintypes": [BinType.APPLICATION, BinType.LIBRARY],
> +            "errormsg":
> +                "The following {} binaries do not use nx (not executable) 
> protection. This mechanism is used " \
> +                "to separate data from executable code. Disabling this 
> mechanism is a security issue because " \
> +                "this enables attackers to put code onto the stack. Please 
> also note, if the nx protection is " \
> +                "disabled in a shared library, all binary objects that link 
> against this library will not be " \
> +                "protected. This message usually appears if your binary is 
> linked using the \"-z execstack\" " \
> +                "flag.",
> +            "ignore_static": False,
> +        },
> +        "relro": {
> +            "allowed_value": "Full",
> +            "bintypes": [BinType.APPLICATION, BinType.LIBRARY],
> +            "errormsg":
> +                "The following {} binaries do not make use of the relro 
> (relocation read-only). This feature " \
> +                "prevents attackers from modifying addresses of functions 
> that are located in shared libraries " \
> +                "(which is a common technique to exploit vulnerabilities). 
> Due to this, not making use of this " \
> +                "feature is a security issue. Please make sure your 
> application is linked using " \
> +                "\"-Wl,-z,relro,-z,now\". ",
> +            "ignore_static": True,
> +        },
> +        "rpath": {
> +            "allowed_value": False,
> +            "bintypes": [BinType.APPLICATION, BinType.LIBRARY],
> +            "errormsg":
> +                "The following {} binaries are making use of the rpath 
> feature. This can easily enable an attacker " \
> +                "to get malicious code executed if there is some issue with 
> the file permissions at the specified " \
> +                "location. Due to this, the usage of this feature is 
> generally discouraged and needs approval " \
> +                "by the security team.",
> +            "ignore_static": False,
> +        },
> +        "runpath": {
> +            "allowed_value": False,
> +            "bintypes": [BinType.APPLICATION, BinType.LIBRARY],
> +            "errormsg":
> +                "The following {} binaries are making use of the runpath 
> feature. This can easily enable an attacker" \
> +                " to get malicious code executed if there is some issue with 
> the file permissions at the specified " \
> +                "location. Due to this, the usage of this feature is 
> generally discouraged and needs approval " \
> +                "by the security team.",
> +            "ignore_static": False,
> +        },
> +        "pie": {
> +            "allowed_value": "PIE",
> +            "bintypes": [BinType.APPLICATION],
> +            "errormsg":
> +                "The following {} applications are not compiled to be 
> position independent executables (pie). This " \
> +                "compiler feature compiles the code in a way that it can be 
> mapped to any location in the virtual " \
> +                "memory. Compiling the application this way is required to 
> make use of the Address Space Layout " \
> +                "Randomization (ASLR). This feature maps executable code to 
> a random location, which means an " \
> +                "attacker can not rely on the fact that a specific portion 
> of code is mapped to a specific address. " \
> +                "Please ensure that you application is compiled using 
> \"-fPIE\".",
> +            "ignore_static": True,
> +        },
> +        "canary": {
> +            "allowed_value": True,
> +            "bintypes": [BinType.APPLICATION, BinType.LIBRARY],
> +            "errormsg":
> +                "The following {} binaries seem to be not using stack 
> canaries. These canaries are used to mitigate " \
> +                "stack buffer overflows attacks. To do so the compiler adds 
> checks to the end of a function to " \
> +                "ensure that this function did not overwrite the stack 
> frames of another function. Not using " \
> +                "canaries may allow an attacker to exploit stack based 
> buffer overflows by modifying the stack frame " \
> +                "of other function calls (which simplifies exploiting such 
> vulnerabilities a lot). Please make sure " \
> +                "your components are compiled with the 
> \"-fstack-protector-strong\" compile flag. Please note that " \
> +                "there is a slight possibility for false-positives in this 
> check: The compiler checks if a function " \
> +                "needs canary protection or not. If there is no function 
> that needs proctedtion in your binary, this " \
> +                "check will fail anyway and the binary needs to be 
> whitelisted.",
> +            "ignore_static": False,
> +        },
> +        "fortify_source": {
> +            "allowed_value": True,
> +            "bintypes": [BinType.APPLICATION, BinType.LIBRARY],
> +            "errormsg":
> +                "The following {} binaries seem to be not using the fortify 
> source feature. This feature protects " \
> +                "(some, not all) calls to memory manipulations function like 
> memcpy, strcpy or strcat by adding " \
> +                "checks that prevent buffer overflows. These checks can 
> prevent attackers from exploiting such a " \
> +                "buffer overflow. Please make sure your component is 
> compiled with \"-D_FORTIFY_SOURCE=2\". In " \
> +                "addition the compiler optimizations need to be enabled with 
> \"-O1\" or higher. Please note that " \
> +                "there is a slight possibility for false positives here: Not 
> all occurences of these mentioned " \
> +                "memory calls that can not be protected they will appear as 
> if_FORTIFY_SOURCE has not been set. " \
> +                "In such a case the binary needs to be whitelisted.",
> +            "ignore_static": False,
> +        }
> +    }
> +
> +    #################################
> +    ## Parse data from config file ##
> +    #################################
> +
> +    config_file = d.getVar("HARDENED_BINARIES_CONFIG_FILE", True)
> +    if not config_file:
> +        msg = "Hardend Binary Check: No config file specifed. Please create 
> a config file and set " \
> +              "the variable \"HARDENED_BINARIES_CONFIG_FILE\" accordingly"
> +        raise ImageQAFailed(msg, image_check_binary_hardening)
> +
> +    CHECK_CONFIG_DATA = defaultdict(lambda: {"enabled": False})
> +    CHECK_CONFIG_DATA.update(toml.load(config_file))
> +
> +    # Expand whitelisted paths with rootfs
> +    for check, values in CHECK_CONFIG_DATA.items():
> +        values["whitelist"] = [rootfs + x for x in values["whitelist"]]
> +
> +    ###############################################
> +    ## Classes and functions to perform analysis ##
> +    ###############################################
> +
> +    class PathMapping:
> +        """ Class to map paths to BinTypes """
> +        def __init__(self, rootfs):
> +            self.rootfs = rootfs
> +            self.mapping = OrderedDict()
> +
> +            self.add("/bin/*", BinType.APPLICATION)
> +            self.add("/lib/firmware/*", BinType.IGNORE)
> +            self.add("/lib/modules/*", BinType.IGNORE)
> +            self.add("/lib/systemd/*.so", BinType.LIBRARY)
> +            self.add("/lib/systemd/*", BinType.APPLICATION)
> +            self.add("/lib/*", BinType.LIBRARY)
> +            self.add("/sbin/*", BinType.APPLICATION)
> +            self.add("/usr/bin/*", BinType.APPLICATION)
> +            self.add("/usr/libexec/*", BinType.APPLICATION)
> +            self.add("/usr/lib/firmware/*", BinType.IGNORE)
> +            self.add("/usr/lib/modules/*", BinType.IGNORE)
> +            self.add("/usr/lib/systemd/*.so", BinType.LIBRARY)
> +            self.add("/usr/lib/systemd/*", BinType.APPLICATION)
> +            self.add("/usr/lib/*", BinType.LIBRARY)
> +            self.add("/usr/sbin/*", BinType.APPLICATION)
> +
> +
> +        def add(self, path, bin_type):
> +            """ Add mapping of a path to a FileyType """
> +            self.mapping[self.rootfs + path] = bin_type
> +
> +        def map(self, path):
> +            """ Map a path to a FilesType. Returns None if path can not be 
> mapped. """
> +            for match_path, bin_type in self.mapping.items():
> +                if fnmatch.fnmatch(path, match_path):
> +                    return bin_type
> +            else:
> +                return None
> +
> +    def call_checksec(rootfs):
> +        """ Wrapper to call the checksec.py script
> +
> +            This function returns a list of result dicts, e.g.:
> +            [
> +                ...,
> +                "/bin/systemd-hwdb": {
> +                    "relro": "No",
> +                    "canary": true,
> +                    "nx": true,
> +                    "pie": "PIE",
> +                    "rpath": false,
> +                    "runpath": false,
> +                    "symbols": false,
> +                    "fortify_source": true,
> +                    "fortified": 5,
> +                    "fortify-able": 16,
> +                    "fortify_score": 31
> +                }
> +            ]
> +
> +        """
> +        parallel_make = d.getVar("PARALLEL_MAKE")
> +
> +        cmd = ["python3", "-m", "checksec", "--json", "--recursive", 
> "--ignore-symlinks"]
> +        if parallel_make:
> +            cmd.append(parallel_make.replace("-j", "--workers="))
> +        if CHECK_CONFIG_DATA["foritfy_source"]["enabled"]:
> +            libc_path = d.getVar("HARDENED_BINARIES_LIBC_PATH", True)
> +            cmd.append("--set-libc={}".format(libc_path))
> +        cmd.append(rootfs)
> +
> +        return json.loads(subprocess.check_output(cmd).decode('utf-8'))
> +
> +
> +    class ResultAnalyzer:
> +        """ Class to evaluate the results produced by checksec.py """
> +        def __init__(self, rootfs):
> +            self.rootfs = rootfs
> +            self.violators = defaultdict(list)
> +
> +        @staticmethod
> +        def __is_static(path):
> +            """ Checks if binary at given path is statically linked """
> +            return "statically linked" in subprocess.check_output(["file", 
> path], stderr=subprocess.STDOUT).decode('utf-8')
> +
> +        def check_result(self, path, result, bintype):
> +            """ Perfom checks specified in CHECK_DATA on the given analysis 
> result (of a specific binary) """
> +
> +            for check, values in CHECK_DATA.items():
> +                if CHECK_CONFIG_DATA[check]["enabled"] and bintype in 
> values["bintypes"]:
> +                    for whitelisted in CHECK_CONFIG_DATA[check]["whitelist"]:
> +                        if fnmatch.fnmatch(path, whitelisted):
> +                            break
> +                    else:
> +                        if result[check] != values["allowed_value"] and \
> +                                (not values["ignore_static"] or not 
> self.__is_static(path)):
> +                            self.violators[check].append(path)
> +
> +
> +    def perform_analysis(rootfs):
> +        """ Analyze all binaries in a given rootfs. In case a container 
> shall be analyzed the absolute path to the container_path
> +            rootfs needs to be passed.
> +        """
> +
> +        # Add custom path mapping (for bins in non-standard locations)
> +        path_mapping = PathMapping(rootfs)
> +        extra_mapping = d.getVar("HARDENED_BINARIES_EXTRA_MAPPING")
> +        if extra_mapping:
> +            for mapping in extra_mapping.split():
> +                try:
> +                    path, type = mapping.split(':')
> +                except:
> +                    bb.error("Hardened Binary Checks: Got misformated extra 
> mapping {}. Mapping needs to be " \
> +                             "in form: \"<path 
> regex>:{application,library,ignore}\"".format(mapping))
> +                    raise
> +                path_mapping.add(path, BinType(type))
> +
> +        # Perform analysis of complete rootfs
> +        analysis_result = call_checksec(rootfs)
> +
> +        # Check analysis results and ensure that all we can actually map all 
> binaries to a BinType
> +        result_analyzer = ResultAnalyzer(rootfs)
> +        unmapped_binaries = []
> +        for path, result in analysis_result.items():
> +            bintype = path_mapping.map(path)
> +            if bintype in [BinType.APPLICATION, BinType.LIBRARY]:
> +                result_analyzer.check_result(path, result, bintype)
> +            elif bintype != BinType.IGNORE:
> +                unmapped_binaries.append(path)
> +
> +        # To ensure that we analyze all the binaries lets break the build if 
> we can not map binaries
> +        if unmapped_binaries:
> +            msg = "Hardend Binary Check: Couldn't figure out if the 
> following files are applications " \
> +                  "or libraries. This is probably due to a non standard 
> location for applications or " \
> +                  "libraries. If you think this is required add the mapping 
> to " \
> +                  "HARDENED_BINARIES_EXTRA_MAPPING and/or contact 
> [email protected]" \
> +                  "\nUnmapped:\n{}".format("\n".join(unmapped_binaries),
> +                  image_check_binary_hardening)
> +            raise ImageQAFailed(msg, image_check_binary_hardening)
> +
> +        custom_error_message = 
> d.getVar('HARDENED_BINARIES_CUSTOM_ERROR_MESSAGE')
> +
> +        # Break the build and show error message if we detected violators 
> that are not whitelisted
> +        errors = []
> +        for check, violators in result_analyzer.violators.items():
> +            if violators:
> +                errormsg = 
> CHECK_DATA[check]["errormsg"].format(len(violators))
> +                errormsg += "\n{}".format("\n".join(violators))
> +                if custom_error_message:
> +                    errormsg += "\n" + custom_error_message
> +                errors.append(errormsg)
> +
> +        if errors:
> +            raise ImageQAFailed("\n".join(errors), 
> image_check_binary_hardening)
> +
> +    ##############################
> +    ## Start analysis on rootfs ##
> +    ##############################
> +
> +    perform_analysis(rootfs)
> +
> +}
> diff --git 
> a/recipes-devtools/python/files/python3-checksec.py/0001-main-Add-option-to-ignore-symlinks.patch
>  
> b/recipes-devtools/python/files/python3-checksec.py/0001-main-Add-option-to-ignore-symlinks.patch
> new file mode 100644
> index 0000000..ae434bc
> --- /dev/null
> +++ 
> b/recipes-devtools/python/files/python3-checksec.py/0001-main-Add-option-to-ignore-symlinks.patch
> @@ -0,0 +1,81 @@
> +From 182268203951750dcfb2c134354e801dea472e4c Mon Sep 17 00:00:00 2001
> +From: Maximilian Blenk <[email protected]>
> +Date: Fri, 2 Jul 2021 14:42:25 +0200
> +Subject: [PATCH 1/2] main: Add option to ignore symlinks
> +
> +When analyzing a complete rootfs (which might not be the rootfs of the
> +analyzing system) symlinks within that rootfs might be broken. In
> +particular absolute symlinks. However, if by chance such a symlink
> +currently points to a valid binary in your system, this binary pointed
> +to is analyzed. This commit adds the possibility to ignore symlinks to
> +files (symlinks to dirs are already ignored by default). This allows to
> +solve the issue described above, and if the whole rootfs is analyzed
> +there shouldn't be a loss of information (because all the binaries will
> +be analyzed anyway). Additionally, this also saves some time when
> +performing the analysis.
> +
> +Upstream-Status: Submitted https://github.com/Wenzel/checksec.py/pull/106
> +---
> + checksec/__main__.py | 12 +++++++-----
> + 1 file changed, 7 insertions(+), 5 deletions(-)
> +
> +diff --git a/checksec/__main__.py b/checksec/__main__.py
> +index 856d0b3..f1a3445 100644
> +--- a/checksec/__main__.py
> ++++ b/checksec/__main__.py
> +@@ -8,6 +8,7 @@ Options:
> +     -w WORKERS --workers=WORKERS    Specify the number of process pool 
> workers [default: 4]
> +     -j --json                       Display results as JSON
> +     -s LIBC --set-libc=LIBC         Specify LIBC library to use to check 
> for fortify scores (ELF)
> ++    -i --ignore-symlinks            Ignore symlinks to files
> +     -d --debug                      Enable debug output
> +     -h --help                       Display this message
> + """
> +@@ -27,15 +28,15 @@ from .pe import PEChecksecData, PESecurity, is_pe
> + from .utils import lief_set_logging
> + 
> + 
> +-def walk_filepath_list(filepath_list: List[Path], recursive: bool = False) 
> -> Iterator[Path]:
> ++def walk_filepath_list(filepath_list: List[Path], recursive: bool = False, 
> ignore_symlinks: bool = False) -> Iterator[Path]:
> +     for path in filepath_list:
> +         if path.is_dir() and not path.is_symlink():
> +             if recursive:
> +                 for f in os.scandir(path):
> +-                    yield from walk_filepath_list([Path(f)], recursive)
> ++                    yield from walk_filepath_list([Path(f)], recursive, 
> ignore_symlinks)
> +             else:
> +                 yield from (Path(f) for f in os.scandir(path))
> +-        elif path.is_file():
> ++        elif path.is_file() and (not ignore_symlinks or not 
> path.is_symlink()):
> +             yield path
> + 
> + 
> +@@ -72,6 +73,7 @@ def main(args):
> +     json = args["--json"]
> +     recursive = args["--recursive"]
> +     libc_path = args["--set-libc"]
> ++    ignore_symlinks = args["--ignore-symlinks"]
> + 
> +     # logging
> +     formatter = "%(asctime)s %(levelname)s:%(name)s:%(message)s"
> +@@ -107,7 +109,7 @@ def main(args):
> +             # we need to consume the iterator once to get the total
> +             # for the progress bar
> +             check_output.enumerating_tasks_start()
> +-            count = sum(1 for i in walk_filepath_list(filepath_list, 
> recursive))
> ++            count = sum(1 for i in walk_filepath_list(filepath_list, 
> recursive, ignore_symlinks))
> +             check_output.enumerating_tasks_stop(count)
> +             with ProcessPoolExecutor(
> +                 max_workers=workers, initializer=worker_initializer, 
> initargs=(libc_path,)
> +@@ -116,7 +118,7 @@ def main(args):
> +                     check_output.processing_tasks_start()
> +                     future_to_checksec = {
> +                         pool.submit(checksec_file, filepath): filepath
> +-                        for filepath in walk_filepath_list(filepath_list, 
> recursive)
> ++                        for filepath in walk_filepath_list(filepath_list, 
> recursive, ignore_symlinks)
> +                     }
> +                     for future in as_completed(future_to_checksec):
> +                         filepath = future_to_checksec[future]
> +-- 
> +2.31.1
> +
> diff --git 
> a/recipes-devtools/python/files/python3-checksec.py/0002-Elf-Fix-relro-detection.patch
>  
> b/recipes-devtools/python/files/python3-checksec.py/0002-Elf-Fix-relro-detection.patch
> new file mode 100644
> index 0000000..a891c2b
> --- /dev/null
> +++ 
> b/recipes-devtools/python/files/python3-checksec.py/0002-Elf-Fix-relro-detection.patch
> @@ -0,0 +1,51 @@
> +From f550777f35e178bc16a2ec612b2b39aa2c3946f2 Mon Sep 17 00:00:00 2001
> +From: Maximilian Blenk <[email protected]>
> +Date: Fri, 2 Jul 2021 16:16:47 +0200
> +Subject: [PATCH 2/2] Elf: Fix relro detection
> +
> +Currently, relro is only detected when the BIND_NOW is set. If however
> +the NOW flag in the FLAGS_1 section is set, relro is not detected (it
> +does not even tell that relro is enabled partially). With this commit
> +relro is detected correctly.
> +
> +Upstream-Status: Submitted https://github.com/Wenzel/checksec.py/pull/107
> +---
> + checksec/elf.py | 19 +++++++++++++++----
> + 1 file changed, 15 insertions(+), 4 deletions(-)
> +
> +diff --git a/checksec/elf.py b/checksec/elf.py
> +index 78ecacc..ef1850c 100644
> +--- a/checksec/elf.py
> ++++ b/checksec/elf.py
> +@@ -118,13 +118,24 @@ class ELFSecurity(BinarySecurity):
> +     def relro(self) -> RelroType:
> +         try:
> +             self.bin.get(lief.ELF.SEGMENT_TYPES.GNU_RELRO)
> +-            if lief.ELF.DYNAMIC_FLAGS.BIND_NOW in 
> self.bin.get(lief.ELF.DYNAMIC_TAGS.FLAGS):
> +-                return RelroType.Full
> +-            else:
> +-                return RelroType.Partial
> +         except lief.not_found:
> +             return RelroType.No
> + 
> ++        try:
> ++            bind_now = lief.ELF.DYNAMIC_FLAGS.BIND_NOW in 
> self.bin.get(lief.ELF.DYNAMIC_TAGS.FLAGS)
> ++        except lief.not_found:
> ++            bind_now = False
> ++
> ++        try:
> ++            now = lief.ELF.DYNAMIC_FLAGS_1.NOW in 
> self.bin.get(lief.ELF.DYNAMIC_TAGS.FLAGS_1)
> ++        except lief.not_found:
> ++            now = False
> ++
> ++        if bind_now or now:
> ++            return RelroType.Full
> ++        else:
> ++            return RelroType.Partial
> ++
> +     @property
> +     def has_canary(self) -> bool:
> +         canary_sections = ["__stack_chk_fail", "__intel_security_cookie"]
> +-- 
> +2.31.1
> +
> diff --git 
> a/recipes-devtools/python/files/python3-checksec.py/0003-fortify-source-check-Treat-binaries-with-0-fortifiab.patch
>  
> b/recipes-devtools/python/files/python3-checksec.py/0003-fortify-source-check-Treat-binaries-with-0-fortifiab.patch
> new file mode 100644
> index 0000000..0351f84
> --- /dev/null
> +++ 
> b/recipes-devtools/python/files/python3-checksec.py/0003-fortify-source-check-Treat-binaries-with-0-fortifiab.patch
> @@ -0,0 +1,33 @@
> +From 8de048c0065f8c5890d9e04ef2b32306e2ac4f8c Mon Sep 17 00:00:00 2001
> +From: Maximilian Blenk <[email protected]>
> +Date: Thu, 5 Aug 2021 15:21:58 +0200
> +Subject: [PATCH] fortify source check: Treat binaries with 0 fortifiable as
> + fortified
> +
> +Currently, if checksec.py detects 0 fortifiable instances it still
> +treats the binary as not fortified. Semtically it would make sense to
> +treat these binaries as fortified (because there is no evidence that it
> +is not)
> +
> +Upstream-Status: Submitted https://github.com/Wenzel/checksec.py/pull/109
> +---
> + checksec/elf.py | 3 +--
> + 1 file changed, 1 insertion(+), 2 deletions(-)
> +
> +diff --git a/checksec/elf.py b/checksec/elf.py
> +index ef1850c..5914135 100644
> +--- a/checksec/elf.py
> ++++ b/checksec/elf.py
> +@@ -229,8 +229,7 @@ class ELFSecurity(BinarySecurity):
> +                 else:
> +                     score = (fortified_count * 100) / fortifiable_count
> +                     score = round(score)
> +-
> +-            fortify_source = True if fortified_count != 0 else False
> ++            fortify_source = True if fortified_count != 0 or 
> fortifiable_count == 0 else False
> +         return ELFChecksecData(
> +             relro=self.relro,
> +             canary=self.has_canary,
> +-- 
> +2.31.1
> +
> diff --git 
> a/recipes-devtools/python/files/python3-lief/0001-Enable-to-use-pre-compiled-version-of-spdlog.patch
>  
> b/recipes-devtools/python/files/python3-lief/0001-Enable-to-use-pre-compiled-version-of-spdlog.patch
> new file mode 100644
> index 0000000..af94cfa
> --- /dev/null
> +++ 
> b/recipes-devtools/python/files/python3-lief/0001-Enable-to-use-pre-compiled-version-of-spdlog.patch
> @@ -0,0 +1,154 @@
> +From d2ad8f6108c750c3dbd33ee6d4e4c94ada748b8a Mon Sep 17 00:00:00 2001
> +From: Romain Thomas <[email protected]>
> +Date: Mon, 3 May 2021 11:25:49 +0200
> +Subject: [PATCH] Enable to use pre-compiled version of spdlog
> +
> +---
> + CMakeLists.txt               |  8 ++++----
> + cmake/LIEFDependencies.cmake | 36 +++++++++++++++++++++++-------------
> + cmake/LIEFOptions.cmake      |  4 ++++
> + setup.py                     | 17 +++++++++++++++++
> + 4 files changed, 48 insertions(+), 17 deletions(-)
> +
> +diff --git a/CMakeLists.txt b/CMakeLists.txt
> +index d1665cd..b92519a 100644
> +--- a/CMakeLists.txt
> ++++ b/CMakeLists.txt
> +@@ -307,8 +307,7 @@ source_group("mbedtls\\tls" FILES ${mbedtls_src_tls})
> + # Library definition
> + # ==================
> + target_include_directories(
> +-  LIB_LIEF SYSTEM PRIVATE "${SPDLOG_SOURCE_DIR}/include"
> +-                          "${MBEDTLS_INCLUDE_DIRS}")
> ++  LIB_LIEF SYSTEM PRIVATE "${MBEDTLS_INCLUDE_DIRS}")
> + 
> + target_include_directories(
> +   LIB_LIEF
> +@@ -355,7 +354,8 @@ target_sources(LIB_LIEF PRIVATE
> +   ${CMAKE_CURRENT_BINARY_DIR}/include/LIEF/third-party/utfcpp/utf8.h)
> + 
> + 
> +-add_dependencies(LIB_LIEF lief_spdlog lief_mbed_tls)
> ++add_dependencies(LIB_LIEF lief_mbed_tls)
> ++target_link_libraries(LIB_LIEF PRIVATE lief_spdlog)
> + 
> + # Flags definition
> + # ----------------
> +@@ -626,7 +626,7 @@ install(
> +   DESTINATION lib/pkgconfig
> +   COMPONENT libraries)
> + 
> +-export(TARGETS LIB_LIEF FILE LIEFExport.cmake)
> ++export(TARGETS LIB_LIEF lief_spdlog FILE LIEFExport.cmake)
> + 
> + # Package
> + # ======================
> +diff --git a/cmake/LIEFDependencies.cmake b/cmake/LIEFDependencies.cmake
> +index e75326f..37e6987 100644
> +--- a/cmake/LIEFDependencies.cmake
> ++++ b/cmake/LIEFDependencies.cmake
> +@@ -144,21 +144,31 @@ set(mbedtls_src_tls
> +   "${MBEDTLS_SOURCE_DIR}/library/ssl_tls13_keys.c"
> + )
> + 
> +-#set_source_files_properties("${MBEDTLS_SOURCE_DIR}/library/bignum.c" 
> PROPERTIES COMPILE_FLAGS -Wno-overlength-strings)
> ++add_library(lief_spdlog INTERFACE)
> + 
> +-set(SPDLOG_VERSION 1.8.2)
> +-set(SPDLOG_SHA256 
> SHA256=f0410b12b526065802b40db01304783550d3d20b4b6fe2f8da55f9d08ed2035d)
> +-set(SPDLOG_URL "${THIRD_PARTY_DIRECTORY}/spdlog-${SPDLOG_VERSION}.zip" 
> CACHE STRING "URL to the spdlog lib repo")
> +-ExternalProject_Add(lief_spdlog
> +-  URL               ${SPDLOG_URL}
> +-  URL_HASH          ${SPDLOG_SHA256}
> +-  CONFIGURE_COMMAND ""
> +-  BUILD_COMMAND     ""
> +-  UPDATE_COMMAND    ""
> +-  INSTALL_COMMAND   "")
> ++if(LIEF_EXTERNAL_SPDLOG)
> ++  find_package(spdlog REQUIRED)
> ++  list(APPEND CMAKE_MODULE_PATH "${SPDLOG_DIR}/cmake")
> ++  target_link_libraries(lief_spdlog INTERFACE spdlog::spdlog)
> ++  get_target_property(SPDLOG_INC_DIR spdlog::spdlog 
> INTERFACE_INCLUDE_DIRECTORIES)
> ++  target_include_directories(lief_spdlog SYSTEM INTERFACE ${SPDLOG_INC_DIR})
> ++else()
> ++  set(SPDLOG_VERSION 1.8.2)
> ++  set(SPDLOG_SHA256 
> SHA256=f0410b12b526065802b40db01304783550d3d20b4b6fe2f8da55f9d08ed2035d)
> ++  set(SPDLOG_URL "${THIRD_PARTY_DIRECTORY}/spdlog-${SPDLOG_VERSION}.zip" 
> CACHE STRING "URL to the spdlog source")
> ++  ExternalProject_Add(lief_spdlog_project
> ++    URL               ${SPDLOG_URL}
> ++    URL_HASH          ${SPDLOG_SHA256}
> ++    CONFIGURE_COMMAND ""
> ++    BUILD_COMMAND     ""
> ++    UPDATE_COMMAND    ""
> ++    INSTALL_COMMAND   "")
> + 
> +-ExternalProject_get_property(lief_spdlog SOURCE_DIR)
> +-set(SPDLOG_SOURCE_DIR "${SOURCE_DIR}")
> ++  ExternalProject_get_property(lief_spdlog_project SOURCE_DIR)
> ++  set(SPDLOG_SOURCE_DIR "${SOURCE_DIR}")
> ++  add_dependencies(lief_spdlog lief_spdlog_project)
> ++  target_include_directories(lief_spdlog SYSTEM INTERFACE 
> ${SPDLOG_SOURCE_DIR}/include)
> ++endif()
> + 
> + # Fuzzing
> + # ~~~~~~~
> +diff --git a/cmake/LIEFOptions.cmake b/cmake/LIEFOptions.cmake
> +index fd6df6c..3bb92c3 100644
> +--- a/cmake/LIEFOptions.cmake
> ++++ b/cmake/LIEFOptions.cmake
> +@@ -45,6 +45,10 @@ option(LIEF_PROFILING "Enable performance profiling" OFF)
> + cmake_dependent_option(LIEF_INSTALL_COMPILED_EXAMPLES "Install LIEF 
> Compiled examples" OFF
> +                        "LIEF_EXAMPLES" OFF)
> + 
> ++# Use a user-provided version of spdlog
> ++# It can be useful to reduce compile time
> ++option(LIEF_EXTERNAL_SPDLOG OFF)
> ++
> + set(LIEF_ELF_SUPPORT 0)
> + set(LIEF_PE_SUPPORT 0)
> + set(LIEF_MACHO_SUPPORT 0)
> +diff --git a/setup.py b/setup.py
> +index b915180..ad70bd8 100644
> +--- a/setup.py
> ++++ b/setup.py
> +@@ -45,6 +45,10 @@ class LiefDistribution(setuptools.Distribution):
> +         ('lief-no-vdex', None, 'Disable VDEX module'),
> +         ('lief-no-oat', None, 'Disable OAT module'),
> +         ('lief-no-dex', None, 'Disable DEX module'),
> ++
> ++        ('lief-no-cache', None, 'Do not use compiler cache (ccache)'),
> ++
> ++        ('spdlog-dir=', None, 'Path to the directory that contains 
> spdlogConfig.cmake'),
> +     ]
> + 
> +     def __init__(self, attrs=None):
> +@@ -66,6 +70,10 @@ class LiefDistribution(setuptools.Distribution):
> + 
> +         self.lief_no_android  = False
> +         self.doc = False
> ++
> ++        self.lief_no_cache  = False
> ++
> ++        self.spdlog_dir = None
> +         super().__init__(attrs)
> + 
> + 
> +@@ -154,6 +162,15 @@ class BuildLibrary(build_ext):
> +         else:
> +             cmake_args += ["-DLIEF_LOGGING_DEBUG=off"]
> + 
> ++        if self.distribution.lief_no_cache:
> ++            cmake_args += ["-DLIEF_USE_CCACHE=off"]
> ++
> ++        # Setup spdlog configuration flags if
> ++        # the user provides --spdlog-dir
> ++        if self.distribution.spdlog_dir is not None:
> ++            cmake_args.append("-DLIEF_EXTERNAL_SPDLOG=ON")
> ++            
> cmake_args.append("-Dspdlog_DIR={}".format(self.distribution.spdlog_dir))
> ++
> +         # Main formats
> +         # ============
> +         if self.distribution.lief_no_elf:
> +-- 
> +2.31.1
> +
> diff --git a/recipes-devtools/python/python3-asttokens_2.0.5.bb 
> b/recipes-devtools/python/python3-asttokens_2.0.5.bb
> new file mode 100644
> index 0000000..7ac2052
> --- /dev/null
> +++ b/recipes-devtools/python/python3-asttokens_2.0.5.bb
> @@ -0,0 +1,15 @@
> +SUMMARY = "Annotate AST trees with source code positions"
> +HOMEPAGE = "https://github.com/gristlabs/asttokens";
> +AUTHOR = "Dmitry Sagalovskiy, Grist Labs <[email protected]>"
> +LICENSE = "Apache-2.0"
> +LIC_FILES_CHKSUM = "file://LICENSE;md5=e3fc50a88d0a364313df4b21ef20c29e"
> +
> +SRC_URI[md5sum] = "0a2a057b9c9a220bffdb3e7512062f17"
> +SRC_URI[sha256sum] = 
> "9a54c114f02c7a9480d56550932546a3f1fe71d8a02f1bc7ccd0ee3ee35cf4d5"
> +
> +RDEPENDS_${PN} = "python3-six"
> +DEPENDS += "python3-setuptools-scm python3-toml"
> +
> +inherit pypi setuptools3
> +
> +BBCLASSEXTEND += "native"
> diff --git a/recipes-devtools/python/python3-checksec.py-native_0.6.1.bb 
> b/recipes-devtools/python/python3-checksec.py-native_0.6.1.bb
> new file mode 100644
> index 0000000..edce0a6
> --- /dev/null
> +++ b/recipes-devtools/python/python3-checksec.py-native_0.6.1.bb
> @@ -0,0 +1,31 @@
> +SUMMARY = "Tool to verify the security properties of binaries"
> +DESCRIPTION = "checksec.py is a tool verify if certain compiler flags \
> +               have been enabled on compield applications and libraries."
> +HOMEPAGE = "https://github.com/Wenzel/checksec.py";
> +BUGTRACKER = "https://github.com/Wenzel/checksec.py/issues";
> +SECTION = "devel/python"
> +
> +LICENSE = "GPL-3.0"
> +LIC_FILES_CHKSUM = "file://LICENSE;md5=1ebbd3e34237af26da5dc08a4e440464"
> +
> +RDEPENDS_${PN} += " \
> +    python3-docopt-native \
> +    python3-lief-native \
> +    python3-pylddwrap-native \
> +    python3-rich-native \
> +    "
> +
> +# Needs to be pulled from github becuase pypi package is currently broken
> +SRC_URI = " \
> +    git://github.com/Wenzel/checksec.py.git;protocol=https;branch=master \
> +    file://python3-checksec.py/0001-main-Add-option-to-ignore-symlinks.patch 
> \
> +    file://python3-checksec.py/0002-Elf-Fix-relro-detection.patch \
> +    
> file://python3-checksec.py/0003-fortify-source-check-Treat-binaries-with-0-fortifiab.patch
>  \
> +    "
> +
> +SRCREV = "4335ecd08f6ee13ff4ca9b01e83857ae6a8074e9"
> +
> +S="${WORKDIR}/git"
> +
> +inherit setuptools3 native
> +
> diff --git a/recipes-devtools/python/python3-colorama_%.bbappend 
> b/recipes-devtools/python/python3-colorama_%.bbappend
> new file mode 100644
> index 0000000..d6f5869
> --- /dev/null
> +++ b/recipes-devtools/python/python3-colorama_%.bbappend
> @@ -0,0 +1 @@
> +BBCLASSEXTEND += "native"
> diff --git a/recipes-devtools/python/python3-commonmark_0.9.1.bb 
> b/recipes-devtools/python/python3-commonmark_0.9.1.bb
> new file mode 100644
> index 0000000..a35abc3
> --- /dev/null
> +++ b/recipes-devtools/python/python3-commonmark_0.9.1.bb
> @@ -0,0 +1,14 @@
> +SUMMARY = "Python parser for the CommonMark Markdown spec"
> +HOMEPAGE = "https://github.com/rtfd/commonmark.py";
> +AUTHOR = "Bibek Kafle <[email protected]>, Roland Shoemaker 
> <[email protected]>"
> +LICENSE = "BSD-3-Clause"
> +LIC_FILES_CHKSUM = "file://LICENSE;md5=37e127eb75a030780aefcfc584e78523"
> +
> +SRC_URI[md5sum] = "cd1dc70c4714d9ed4117a40490c25e00"
> +SRC_URI[sha256sum] = 
> "452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60"
> +
> +S = "${WORKDIR}/commonmark-0.9.1"
> +
> +inherit pypi setuptools3
> +
> +BBCLASSEXTEND += "native"
> diff --git a/recipes-devtools/python/python3-docopt_0.6.2.bb 
> b/recipes-devtools/python/python3-docopt_0.6.2.bb
> new file mode 100644
> index 0000000..c1b111a
> --- /dev/null
> +++ b/recipes-devtools/python/python3-docopt_0.6.2.bb
> @@ -0,0 +1,18 @@
> +
> +SUMMARY = "Pythonic argument parser, that will make you smile"
> +HOMEPAGE = "http://docopt.org";
> +AUTHOR = "Vladimir Keleshev <[email protected]>"
> +LICENSE = "MIT"
> +LIC_FILES_CHKSUM = "file://LICENSE-MIT;md5=09b77fb74986791a3d4a0e746a37d88f"
> +
> +SRC_URI = "https://github.com/docopt/docopt/archive/refs/tags/${PV}.tar.gz";
> +SRC_URI[md5sum] = "a6c44155426fd0f7def8b2551d02fef6"
> +SRC_URI[sha256sum] = 
> "2113eed1e7fbbcd43fb7ee6a977fb02d0b482753586c9dc1a8e3b7d541426e99"
> +
> +S = "${WORKDIR}/docopt-0.6.2"
> +
> +RDEPENDS_${PN} = ""
> +
> +inherit setuptools3
> +
> +BBCLASSEXTEND += "native"
> diff --git a/recipes-devtools/python/python3-icontract_2.5.3.bb 
> b/recipes-devtools/python/python3-icontract_2.5.3.bb
> new file mode 100644
> index 0000000..88ac2ef
> --- /dev/null
> +++ b/recipes-devtools/python/python3-icontract_2.5.3.bb
> @@ -0,0 +1,14 @@
> +SUMMARY = "Provide design-by-contract with informative violation messages."
> +HOMEPAGE = "https://github.com/Parquery/icontract";
> +AUTHOR = "Marko Ristin <[email protected]>"
> +LICENSE = "MIT"
> +LIC_FILES_CHKSUM = "file://LICENSE.txt;md5=1d4a9b1f6b84bedf7a38843931e0dd57"
> +
> +SRC_URI[md5sum] = "6f41b9b84e4405374c160836587b3235"
> +SRC_URI[sha256sum] = 
> "b790101c8cc0d9df0105d852a645373c4d90d5049391b6e54db32a0acb4bccd7"
> +
> +inherit pypi setuptools3
> +
> +RDEPENDS_${PN} += "python3-asttokens"
> +
> +BBCLASSEXTEND += "native"
> diff --git a/recipes-devtools/python/python3-lief_0.11.5.bb 
> b/recipes-devtools/python/python3-lief_0.11.5.bb
> new file mode 100644
> index 0000000..5e4b422
> --- /dev/null
> +++ b/recipes-devtools/python/python3-lief_0.11.5.bb
> @@ -0,0 +1,36 @@
> +SUMMARY = "Library to instrument executable formats"
> +DESCRIPTION = " \
> +    This project provides a cross platform library which can parse, modify \
> +    and abstract ELF, PE and MachO formats. \
> +  "
> +SECTION = "devel/python"
> +HOMEPAGE = "https://github.com/lief-project/LIEF";
> +LICENSE = "APACHE-2.0"
> +LIC_FILES_CHKSUM = "file://LICENSE;md5=1809bd489c3dae63aa0cb70070dc308e"
> +
> +SRC_URI = " \
> +    
> https://github.com/lief-project/LIEF/releases/download/${PV}/lief-${PV}.zip \
> +    
> file://python3-lief/0001-Enable-to-use-pre-compiled-version-of-spdlog.patch \
> +    "
> +SRC_URI[sha256sum] = 
> "947825134d5dab91df218bb201fa4551814f1da0a47e4a890283716b800c8e8f"
> +
> +S = "${WORKDIR}/lief-${PV}"
> +
> +inherit setuptools3
> +
> +DEPENDS += "cmake-native"
> +
> +BBCLASSEXTEND += "native"
> +
> +DISTUTILS_BUILD_ARGS += " ${PARALLEL_MAKE} "
> +
> +do_compile() {
> +    # From distutils3.bbclass (needs to be modified here to avoid usage of 
> ccache)
> +    cd ${DISTUTILS_SETUP_PATH}
> +    NO_FETCH_BUILD=1 \
> +    STAGING_INCDIR=${STAGING_INCDIR} \
> +    STAGING_LIBDIR=${STAGING_LIBDIR} \
> +    ${STAGING_BINDIR_NATIVE}/${PYTHON_PN}-native/${PYTHON_PN} setup.py \
> +    --lief-no-cache build --build-base=${B} ${DISTUTILS_BUILD_ARGS} || \
> +    bbfatal_log "'${PYTHON_PN} setup.py --lief-no-cache build 
> ${DISTUTILS_BUILD_ARGS}' execution failed."
> +}
> diff --git a/recipes-devtools/python/python3-pylddwrap_1.0.1.bb 
> b/recipes-devtools/python/python3-pylddwrap_1.0.1.bb
> new file mode 100644
> index 0000000..985c424
> --- /dev/null
> +++ b/recipes-devtools/python/python3-pylddwrap_1.0.1.bb
> @@ -0,0 +1,21 @@
> +SUMMARY = "Python wrapper for ldd"
> +DESCRIPTION = " \
> +    Pylddwrap wraps ldd *nix utility to determine shared libraries required 
> by a program. \
> +  "
> +SECTION = "devel/python"
> +HOMEPAGE = "https://github.com/Parquery/pylddwrap";
> +LICENSE = "MIT"
> +LIC_FILES_CHKSUM = "file://LICENSE;md5=48fd6c978d39a38b3a04f45a1456d0fa"
> +
> +SRC_URI[sha256sum] = 
> "171a39fc7feb33e607706c57c08373ceb2f6fd4362af9241ccc65e80c948ccdf"
> +
> +inherit pypi setuptools3
> +
> +RDEPENDS_${PN} += "python3-icontract"
> +
> +do_install_append() {
> +    rm -f "${D}/${datadir}/requirements.txt"
> +    rm -f "${D}/${datadir}/README.rst"
> +}
> +
> +BBCLASSEXTEND += "native"
> diff --git a/recipes-devtools/python/python3-rich_7.1.0.bb 
> b/recipes-devtools/python/python3-rich_7.1.0.bb
> new file mode 100644
> index 0000000..59c26a4
> --- /dev/null
> +++ b/recipes-devtools/python/python3-rich_7.1.0.bb
> @@ -0,0 +1,16 @@
> +SUMMARY = "Render rich text, tables, progress bars, syntax highlighting, 
> markdown and more to the terminal"
> +HOMEPAGE = "https://github.com/willmcgugan/rich";
> +AUTHOR = "Will McGugan <[email protected]>"
> +LICENSE = "MIT"
> +LIC_FILES_CHKSUM = "file://LICENSE;md5=d0d35d5357392e5bfeb0d0a7e6ba4d83"
> +
> +SRC_URI[md5sum] = "25daeefa226770a84b98c591069b419c"
> +SRC_URI[sha256sum] = 
> "ff701be541be32bcf46e821487c00bf4fa560aa814fc3cc9b3d514fd9b19a6f6"
> +
> +S = "${WORKDIR}/rich-7.1.0"
> +
> +RDEPENDS_${PN} = "python3-typing-extensions python3-pygments 
> python3-commonmark python3-colorama"
> +
> +inherit pypi setuptools3
> +
> +BBCLASSEXTEND += "native"
> diff --git a/recipes-devtools/python/python3-setuptools-scm_6.0.1.bb 
> b/recipes-devtools/python/python3-setuptools-scm_6.0.1.bb
> new file mode 100644
> index 0000000..234694e
> --- /dev/null
> +++ b/recipes-devtools/python/python3-setuptools-scm_6.0.1.bb
> @@ -0,0 +1,17 @@
> +SUMMARY = "the blessed package to manage your versions by scm tags"
> +HOMEPAGE = "https://github.com/pypa/setuptools_scm/";
> +AUTHOR = "Ronny Pfannschmidt <[email protected]>"
> +LICENSE = "MIT"
> +LIC_FILES_CHKSUM = "file://LICENSE;md5=838c366f69b72c5df05c96dff79b35f2"
> +
> +SRC_URI = 
> "git://github.com/pypa/setuptools_scm.git;protocol=https;branch=main;tag=v${PV}"
> +
> +SRC_URI[sha256sum] = 
> "8f85bfc7272fb5c04df28f00bde9db8f862c586d25fa155eea90fe62ea6a3302"
> +
> +RDEPENDS_${PN} = "python3-setuptools"
> +
> +inherit setuptools3
> +
> +S = "${WORKDIR}/git"
> +
> +BBCLASSEXTEND += "native"
> diff --git a/recipes-devtools/python/python3-toml_%.bbappend 
> b/recipes-devtools/python/python3-toml_%.bbappend
> new file mode 100644
> index 0000000..d6f5869
> --- /dev/null
> +++ b/recipes-devtools/python/python3-toml_%.bbappend
> @@ -0,0 +1 @@
> +BBCLASSEXTEND += "native"
>
> 
>

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#54529): https://lists.yoctoproject.org/g/yocto/message/54529
Mute This Topic: https://lists.yoctoproject.org/mt/84968578/21656
Group Owner: [email protected]
Unsubscribe: https://lists.yoctoproject.org/g/yocto/unsub 
[[email protected]]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to