summaryrefslogtreecommitdiffstats
path: root/meta/classes-global/sanity.bbclass
diff options
context:
space:
mode:
Diffstat (limited to 'meta/classes-global/sanity.bbclass')
-rw-r--r--meta/classes-global/sanity.bbclass99
1 files changed, 82 insertions, 17 deletions
diff --git a/meta/classes-global/sanity.bbclass b/meta/classes-global/sanity.bbclass
index 180c6b77d8..1044ed9cc6 100644
--- a/meta/classes-global/sanity.bbclass
+++ b/meta/classes-global/sanity.bbclass
@@ -299,6 +299,11 @@ def check_path_length(filepath, pathname, limit):
299 return "The length of %s is longer than %s, this would cause unexpected errors, please use a shorter path.\n" % (pathname, limit) 299 return "The length of %s is longer than %s, this would cause unexpected errors, please use a shorter path.\n" % (pathname, limit)
300 return "" 300 return ""
301 301
302def check_non_ascii(filepath, pathname):
303 if(not filepath.isascii()):
304 return "Non-ASCII character(s) in %s path (\"%s\") detected. This would cause build failures as we build software that doesn't support this.\n" % (pathname, filepath)
305 return ""
306
302def get_filesystem_id(path): 307def get_filesystem_id(path):
303 import subprocess 308 import subprocess
304 try: 309 try:
@@ -475,6 +480,31 @@ def check_wsl(d):
475 bb.warn("You are running bitbake under WSLv2, this works properly but you should optimize your VHDX file eventually to avoid running out of storage space") 480 bb.warn("You are running bitbake under WSLv2, this works properly but you should optimize your VHDX file eventually to avoid running out of storage space")
476 return None 481 return None
477 482
483def check_userns():
484 """
485 Check that user namespaces are functional, as they're used for network isolation.
486 """
487
488 # There is a known failure case with AppAmrmor where the unshare() call
489 # succeeds (at which point the uid is nobody) but writing to the uid_map
490 # fails (so the uid isn't reset back to the user's uid). We can detect this.
491 parentuid = os.getuid()
492 if not bb.utils.is_local_uid(parentuid):
493 return None
494 pid = os.fork()
495 if not pid:
496 try:
497 bb.utils.disable_network()
498 except:
499 pass
500 os._exit(parentuid != os.getuid())
501
502 ret = os.waitpid(pid, 0)[1]
503 if ret:
504 bb.fatal("User namespaces are not usable by BitBake, possibly due to AppArmor.\n"
505 "See https://discourse.ubuntu.com/t/ubuntu-24-04-lts-noble-numbat-release-notes/39890#unprivileged-user-namespace-restrictions for more information.")
506
507
478# Require at least gcc version 8.0 508# Require at least gcc version 8.0
479# 509#
480# This can be fixed on CentOS-7 with devtoolset-6+ 510# This can be fixed on CentOS-7 with devtoolset-6+
@@ -484,23 +514,23 @@ def check_wsl(d):
484# built buildtools-extended-tarball) 514# built buildtools-extended-tarball)
485# 515#
486def check_gcc_version(sanity_data): 516def check_gcc_version(sanity_data):
487 import subprocess 517 version = oe.utils.get_host_gcc_version(sanity_data)
488 518 if bb.utils.vercmp_string_op(version, "8.0", "<"):
489 build_cc, version = oe.utils.get_host_compiler_version(sanity_data) 519 return "Your version of gcc is older than 8.0 and will break builds. Please install a newer version of gcc (you could use the project's buildtools-extended-tarball or use scripts/install-buildtools).\n"
490 if build_cc.strip() == "gcc":
491 if bb.utils.vercmp_string_op(version, "8.0", "<"):
492 return "Your version of gcc is older than 8.0 and will break builds. Please install a newer version of gcc (you could use the project's buildtools-extended-tarball or use scripts/install-buildtools).\n"
493 return None 520 return None
494 521
495# Tar version 1.24 and onwards handle overwriting symlinks correctly 522# Tar version 1.24 and onwards handle overwriting symlinks correctly
496# but earlier versions do not; this needs to work properly for sstate 523# but earlier versions do not; this needs to work properly for sstate
497# Version 1.28 is needed so opkg-build works correctly when reproducible builds are enabled 524# Version 1.28 is needed so opkg-build works correctly when reproducible builds are enabled
525# Gtar is assumed at to be used as tar in poky
498def check_tar_version(sanity_data): 526def check_tar_version(sanity_data):
499 import subprocess 527 import subprocess
500 try: 528 try:
501 result = subprocess.check_output(["tar", "--version"], stderr=subprocess.STDOUT).decode('utf-8') 529 result = subprocess.check_output(["tar", "--version"], stderr=subprocess.STDOUT).decode('utf-8')
502 except subprocess.CalledProcessError as e: 530 except subprocess.CalledProcessError as e:
503 return "Unable to execute tar --version, exit code %d\n%s\n" % (e.returncode, e.output) 531 return "Unable to execute tar --version, exit code %d\n%s\n" % (e.returncode, e.output)
532 if not "GNU" in result:
533 return "Your version of tar is not gtar. Please install gtar (you could use the project's buildtools-tarball from our last release or use scripts/install-buildtools).\n"
504 version = result.split()[3] 534 version = result.split()[3]
505 if bb.utils.vercmp_string_op(version, "1.28", "<"): 535 if bb.utils.vercmp_string_op(version, "1.28", "<"):
506 return "Your version of tar is older than 1.28 and does not have the support needed to enable reproducible builds. Please install a newer version of tar (you could use the project's buildtools-tarball from our last release or use scripts/install-buildtools).\n" 536 return "Your version of tar is older than 1.28 and does not have the support needed to enable reproducible builds. Please install a newer version of tar (you could use the project's buildtools-tarball from our last release or use scripts/install-buildtools).\n"
@@ -574,6 +604,28 @@ def drop_v14_cross_builds(d):
574 bb.utils.remove(stamp + "*") 604 bb.utils.remove(stamp + "*")
575 bb.utils.remove(workdir, recurse = True) 605 bb.utils.remove(workdir, recurse = True)
576 606
607def check_cpp_toolchain_flag(d, flag, error_message=None):
608 """
609 Checks if the g++ compiler supports the given flag
610 """
611 import shlex
612 import subprocess
613
614 cpp_code = """
615 #include <iostream>
616 int main() {
617 std::cout << "Hello, World!" << std::endl;
618 return 0;
619 }
620 """
621
622 cmd = ["g++", "-x", "c++","-", "-o", "/dev/null", flag]
623 try:
624 subprocess.run(cmd, input=cpp_code, capture_output=True, text=True, check=True)
625 return None
626 except subprocess.CalledProcessError as e:
627 return error_message or f"An unexpected issue occurred during the C++ toolchain check: {str(e)}"
628
577def sanity_handle_abichanges(status, d): 629def sanity_handle_abichanges(status, d):
578 # 630 #
579 # Check the 'ABI' of TMPDIR 631 # Check the 'ABI' of TMPDIR
@@ -638,17 +690,18 @@ def check_sanity_version_change(status, d):
638 status.addresult(check_git_version(d)) 690 status.addresult(check_git_version(d))
639 status.addresult(check_perl_modules(d)) 691 status.addresult(check_perl_modules(d))
640 status.addresult(check_wsl(d)) 692 status.addresult(check_wsl(d))
693 status.addresult(check_userns())
641 694
642 missing = "" 695 missing = ""
643 696
644 if not check_app_exists("${MAKE}", d): 697 if not check_app_exists("${MAKE}", d):
645 missing = missing + "GNU make," 698 missing = missing + "GNU make,"
646 699
647 if not check_app_exists('${BUILD_CC}', d): 700 if not check_app_exists('gcc', d):
648 missing = missing + "C Compiler (%s)," % d.getVar("BUILD_CC") 701 missing = missing + "C Compiler (gcc),"
649 702
650 if not check_app_exists('${BUILD_CXX}', d): 703 if not check_app_exists('g++', d):
651 missing = missing + "C++ Compiler (%s)," % d.getVar("BUILD_CXX") 704 missing = missing + "C++ Compiler (g++),"
652 705
653 required_utilities = d.getVar('SANITY_REQUIRED_UTILITIES') 706 required_utilities = d.getVar('SANITY_REQUIRED_UTILITIES')
654 707
@@ -668,6 +721,7 @@ def check_sanity_version_change(status, d):
668 # Check that TMPDIR isn't on a filesystem with limited filename length (eg. eCryptFS) 721 # Check that TMPDIR isn't on a filesystem with limited filename length (eg. eCryptFS)
669 import stat 722 import stat
670 tmpdir = d.getVar('TMPDIR') 723 tmpdir = d.getVar('TMPDIR')
724 topdir = d.getVar('TOPDIR')
671 status.addresult(check_create_long_filename(tmpdir, "TMPDIR")) 725 status.addresult(check_create_long_filename(tmpdir, "TMPDIR"))
672 tmpdirmode = os.stat(tmpdir).st_mode 726 tmpdirmode = os.stat(tmpdir).st_mode
673 if (tmpdirmode & stat.S_ISGID): 727 if (tmpdirmode & stat.S_ISGID):
@@ -676,14 +730,14 @@ def check_sanity_version_change(status, d):
676 status.addresult("TMPDIR is setuid, please don't build in a setuid directory") 730 status.addresult("TMPDIR is setuid, please don't build in a setuid directory")
677 731
678 # Check that a user isn't building in a path in PSEUDO_IGNORE_PATHS 732 # Check that a user isn't building in a path in PSEUDO_IGNORE_PATHS
679 pseudoignorepaths = d.getVar('PSEUDO_IGNORE_PATHS', expand=True).split(",") 733 pseudoignorepaths = (d.getVar('PSEUDO_IGNORE_PATHS', expand=True) or "").split(",")
680 workdir = d.getVar('WORKDIR', expand=True) 734 workdir = d.getVar('WORKDIR', expand=True)
681 for i in pseudoignorepaths: 735 for i in pseudoignorepaths:
682 if i and workdir.startswith(i): 736 if i and workdir.startswith(i):
683 status.addresult("You are building in a path included in PSEUDO_IGNORE_PATHS " + str(i) + " please locate the build outside this path.\n") 737 status.addresult("You are building in a path included in PSEUDO_IGNORE_PATHS " + str(i) + " please locate the build outside this path.\n")
684 738
685 # Check if PSEUDO_IGNORE_PATHS and paths under pseudo control overlap 739 # Check if PSEUDO_IGNORE_PATHS and paths under pseudo control overlap
686 pseudoignorepaths = d.getVar('PSEUDO_IGNORE_PATHS', expand=True).split(",") 740 pseudoignorepaths = (d.getVar('PSEUDO_IGNORE_PATHS', expand=True) or "").split(",")
687 pseudo_control_dir = "${D},${PKGD},${PKGDEST},${IMAGEROOTFS},${SDK_OUTPUT}" 741 pseudo_control_dir = "${D},${PKGD},${PKGDEST},${IMAGEROOTFS},${SDK_OUTPUT}"
688 pseudocontroldir = d.expand(pseudo_control_dir).split(",") 742 pseudocontroldir = d.expand(pseudo_control_dir).split(",")
689 for i in pseudoignorepaths: 743 for i in pseudoignorepaths:
@@ -731,8 +785,11 @@ def check_sanity_version_change(status, d):
731 if not oes_bb_conf: 785 if not oes_bb_conf:
732 status.addresult('You are not using the OpenEmbedded version of conf/bitbake.conf. This means your environment is misconfigured, in particular check BBPATH.\n') 786 status.addresult('You are not using the OpenEmbedded version of conf/bitbake.conf. This means your environment is misconfigured, in particular check BBPATH.\n')
733 787
734 # The length of TMPDIR can't be longer than 410 788 # The length of TMPDIR can't be longer than 400
735 status.addresult(check_path_length(tmpdir, "TMPDIR", 410)) 789 status.addresult(check_path_length(tmpdir, "TMPDIR", 400))
790
791 # Check that TOPDIR does not contain non ascii chars (perl_5.40.0, Perl-native and shadow-native build failures)
792 status.addresult(check_non_ascii(topdir, "TOPDIR"))
736 793
737 # Check that TMPDIR isn't located on nfs 794 # Check that TMPDIR isn't located on nfs
738 status.addresult(check_not_nfs(tmpdir, "TMPDIR")) 795 status.addresult(check_not_nfs(tmpdir, "TMPDIR"))
@@ -741,6 +798,14 @@ def check_sanity_version_change(status, d):
741 # macOS with default HFS+ file system) 798 # macOS with default HFS+ file system)
742 status.addresult(check_case_sensitive(tmpdir, "TMPDIR")) 799 status.addresult(check_case_sensitive(tmpdir, "TMPDIR"))
743 800
801 # Check if linking with lstdc++ is failing
802 status.addresult(check_cpp_toolchain_flag(d, "-lstdc++"))
803
804 # Check if the C++ toochain support the "--std=gnu++20" flag
805 status.addresult(check_cpp_toolchain_flag(d, "--std=gnu++20",
806 "An error occurred during checking the C++ toolchain for '--std=gnu++20' support. "
807 "Please use a g++ compiler that supports C++20 (e.g. g++ version 10 onwards)."))
808
744def sanity_check_locale(d): 809def sanity_check_locale(d):
745 """ 810 """
746 Currently bitbake switches locale to en_US.UTF-8 so check that this locale actually exists. 811 Currently bitbake switches locale to en_US.UTF-8 so check that this locale actually exists.
@@ -759,10 +824,10 @@ def check_sanity_everybuild(status, d):
759 if 0 == os.getuid(): 824 if 0 == os.getuid():
760 raise_sanity_error("Do not use Bitbake as root.", d) 825 raise_sanity_error("Do not use Bitbake as root.", d)
761 826
762 # Check the Python version, we now have a minimum of Python 3.8 827 # Check the Python version, we now have a minimum of Python 3.9
763 import sys 828 import sys
764 if sys.hexversion < 0x030800F0: 829 if sys.hexversion < 0x030900F0:
765 status.addresult('The system requires at least Python 3.8 to run. Please update your Python interpreter.\n') 830 status.addresult('The system requires at least Python 3.9 to run. Please update your Python interpreter.\n')
766 831
767 # Check the bitbake version meets minimum requirements 832 # Check the bitbake version meets minimum requirements
768 minversion = d.getVar('BB_MIN_VERSION') 833 minversion = d.getVar('BB_MIN_VERSION')