Compare commits

..

33 Commits

Author SHA1 Message Date
Daniel Turull
167f714a72 linux/cve-exclusion: Execute the script after changing to the new data source
Execute new script generate-cve-exclusions.py
./generate-cve-exclusions.py ~/cvelistV5/ 6.12.19 > cve-exclusion_6.12.inc

After using the database from CVEproject, some old
CVEs did not have correct metadata, therefore moving missing ones
from old cve-exclusions_6.12.inc into cve-exclusion.inc

Comparing output from cve_check before and after, two CVEs are removed:
CVE-2023-52904 and CVE-2024-38381

(From OE-Core rev: 02a8d5d255397e85d32879b178dd6dd559a34a05)

Signed-off-by: Daniel Turull <daniel.turull@ericsson.com>
Signed-off-by: Mathieu Dubois-Briand <mathieu.dubois-briand@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2025-04-23 19:50:57 +01:00
Daniel Turull
13f4119ccf linux/generate-cve-exclusions: use data from CVEProject
The old script was relying on linuxkernelcves.com that was archived in
May 2024 when kernel.org became a CNA.

The new script reads CVE json files from the datadir that can be either
from the official kernel.org CNA [1] or CVEProject [2]

[1] https://git.kernel.org/pub/scm/linux/security/vulns.git
[2] https://github.com/CVEProject/cvelistV5

(From OE-Core rev: 96ef76d88851a5a397d9fc04e37baa285d9f4074)

Signed-off-by: Daniel Turull <daniel.turull@ericsson.com>
Signed-off-by: Mathieu Dubois-Briand <mathieu.dubois-briand@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2025-04-23 19:50:57 +01:00
Antonin Godard
9b96fdbb0c migration-guides/release-notes-5.2.rst: add missing cves
Add missing fixed CVEs to the release note as reported here:
https://lore.kernel.org/r/5fc0d33e-4ba5-4f8d-80c2-c5c87be79680@gmail.com

Additions can be verified at the following links:
- https://gstreamer.freedesktop.org/security/
- https://www.openssh.com/txt/release-9.9p2
- http://www.dest-unreach.org/socat/

libssh2 CVE-2023-48795 was already fixed in previous releases so remove
it. See the previous migration guides.

Otherwise the CVE entries have been sorted.

Reported-by: Takayasu Ito <ypa.takayasu.ito@gmail.com>
(From yocto-docs rev: b8d9cf79d299b2e553e6bc962527d835206022ec)

Signed-off-by: Antonin Godard <antonin.godard@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2025-04-23 19:50:52 +01:00
Antonin Godard
81c9c4f6d4 migration-guides/release-notes-5.2.rst: fix badly formatted gstreamer entries
Reviewed-by: Quentin Schulz <quentin.schulz@cherry.de>
(From yocto-docs rev: 22babeaa9ef4c0e6706c6de8f16fbd0e8d505818)

Signed-off-by: Antonin Godard <antonin.godard@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2025-04-23 19:50:52 +01:00
Antonin Godard
51d1210367 migration-guides/{migration,release-notes}-5.2.rst: notes for systemd pni-names
Add a note to the migration guide regarding the pni-names behavior
change.

Suggested-by: Enrico Jörns <ejo@pengutronix.de>
(From yocto-docs rev: 9a1b9778c296351a575501a4abc5317e9be954bc)

Signed-off-by: Antonin Godard <antonin.godard@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2025-04-23 19:50:52 +01:00
Ross Burton
43909a9870 genericarm64: add ttyPS1 for KV260
The AMD KV260 has a serial console on ttyPS1, so until we can dynamically
detect the console under sysvinit we can add it to SERIAL_CONSOLES so
this platform has a working console when not running systemd.

(From meta-yocto rev: 467b6d77e50f92bee3c8f7ca928bd70758bab457)

Signed-off-by: Ross Burton <ross.burton@arm.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2025-04-23 19:49:06 +01:00
Ross Burton
185a87256e systemd: always depend on the explicit serial console units
The systemd-serialgetty recipe generates explicit units for consoles
that are defined in SERIAL_CONSOLES, and if that variable is not defined
then just produces an empty package.

Even when systemd has been configured to use the getty generator, if
there are explicit consoles defined then we should respect them.  Don't
conditionalise the dependency on systemd-serialgetty so that we always
pull in the explicit consoles.

(From OE-Core rev: 6ec2c52b938302b894f119f701ffcf0a847eee85)

Signed-off-by: Ross Burton <ross.burton@arm.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2025-04-23 19:49:06 +01:00
Ross Burton
22f3616aad systemd: enable getty generator by default
Until recently, even when the getty generator was disabled in the
systemd recipe it was actually still active.  This was because the old
behaviour was to delete the serial-getty template unit if the generator
was disabled, but the systemd-serialgetty package shipped then shipped
the same files so the generator continued to run.  This was a bug in the
original commit[1] so this behaviour has been present since 2016.

My recent fixes[2] changed this: if the getty generator was disabled
then the generator itself is deleted. This makes the actual behaviour
match the intention, but the consequence was to demonstrate that some
modern platforms were relying on this unexpected behaviour: specifically
the genericarm64 BSP which intends to support a number of virtual and
physical boards with a number of serial console ports that are not
really suitable to be hardcoded into SERIAL_CONSOLES:

- ttyS0
- ttyAMA0 (AMBA PL011 uart)
- ttyS2 (BeagleBone Play, S0 and S1 are internal)
- hvc0 (KVM)
- ttyPS1 (AMD KV260)
- And most likely more

Restore the existing behaviour by explicitly enabling the serial getty
generator: this means that systemd will automatically bring up a getty
on the first serial console it finds.

In the future we should extend some level of dynamic console-finding to
sysvinit-based systems by searching for a console device in inittab, but
for now this reverts the unintentional regression.

[1] oe-core 2a8d0df47c9 ("systemd: make systemd-serialgetty optional")
[2] oe-core 2beb3170af6 ("systemd: if getty generator is disabled remove
    the generator, not the units")

(From OE-Core rev: 87136e18b70c0fb66d7268b30e8bc0da9268aa31)

Signed-off-by: Ross Burton <ross.burton@arm.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2025-04-23 19:49:06 +01:00
Ross Burton
58776612f0 mesa-demos: fix detection of GLX headers
Backport a patch from upstream to fix the build when glx.pc isn't found,
but the glx headers are available. As libglvnd is the only provider of
glx.pc and by default we build without libglvnd, this is common.

This solves the problem where mesa-demo is missing the GLX demos, such
as glxgears.

[ YOCTO #15825 ]

(From OE-Core rev: 466c01cb1ec9ad2a13dc12b5fa7276b9b450266e)

Signed-off-by: Ross Burton <ross.burton@arm.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2025-04-23 19:48:04 +01:00
Ross Burton
62689ff1fb mesa: remove obsolete deletion of .la files
As Mesa is built with Meson now, there's no need to delete the .la files
as they're not installed in the first place.

(From OE-Core rev: 7cc1288c0121268b02ab26d0b032cee6cb9eacb4)

Signed-off-by: Ross Burton <ross.burton@arm.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2025-04-23 19:48:04 +01:00
Bruce Ashfield
528b36636b linux-yocto/6.12: cfg: fix iommu configuration for -tiny kernel
Integrating the following commit(s) to linux-yocto/.:

1/1 [
    Author: Bruce Ashfield
    Email: bruce.ashfield@gmail.com
    Subject: iommu: add config dependencies
    Date: Sun, 20 Apr 2025 22:28:21 -0400

    commit [cfg/intel.scc: Include iommu.scc for Arrowlake boot support]
    moves the iommu configuration to a location that is included by more
    BSPs and kernel types.

    One of those kernel types is the -tiny kernel, which uses a allnoconfig
    base. Due to the allnoconfig, there are missing dependencies to allow
    the desired options to be enabled in the final .config

    Those missing options throw configuration audit warnings

    By adding the required dependencies to the fragment, it is now
    standalone and can be included from anywhere without configuration
    audit warnings being triggered.

    Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
]

(From OE-Core rev: 795594476c6fabd5391dc35f254de8028f7c47d6)

Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2025-04-23 19:48:04 +01:00
Bruce Ashfield
5f6a1c9838 linux-yocto/6.12: cfg: Include iommu.scc for Arrowlake boot support
Integrating the following commit(s) to linux-yocto/.:

1/1 [
    Author: Yogesh Tyagi
    Email: yogesh.tyagi@intel.com
    Subject: cfg/intel.scc: Include iommu.scc for Arrowlake boot support
    Date: Mon, 14 Apr 2025 11:55:45 +0530

    Move features/iommu/iommu.scc from bsp/intel-common/intel-corei7-64.scc and
    bsp/intel-x86/intel-x86.scc to cfg/intel.scc to eliminate redundancy and ensure
    IOMMU support (CONFIG_INTEL_IOMMU=y, etc.) is enabled for genericx86-64
    on Intel Arrowlake, resolving boot issues.

    This changes is needed in 6.12 as well as master branch.

    https://bugzilla.yoctoproject.org/show_bug.cgi?id=15802

    Signed-off-by: Yogesh Tyagi <yogesh.tyagi@intel.com>
    Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
]

(From OE-Core rev: ff91efc2ab25880967b82cc709954d10d62b8cbe)

Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2025-04-23 19:48:04 +01:00
Bruce Ashfield
17b2110721 kern-tools: allow comments after configuration options
Bumping the kern-tools SRCREV to allow comments after configuration
options.

Without this update of the regex, symbol_why will incorrectly detect
that options are not in the final .config during audit.

(From OE-Core rev: 79135df956b536d3be1ca86d28d5c77d59c672c4)

Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2025-04-23 19:48:04 +01:00
Bruce Ashfield
542eec1b1c linux-yocto/6.12: update to v6.12.23
Updating linux-yocto/6.12 to the latest korg -stable release that comprises
the following commits:

    83b4161a63b8 Linux 6.12.23
    e70b4b8f93d7 platform/x86/amd/pmf: fix cleanup in amd_pmf_init_smart_pc()
    625e9b91eb13 tracing: Do not use PERF enums when perf is not defined
    59fc42318305 ARM: 9443/1: Require linker to support KEEP within OVERLAY for DCE
    c6f2a8146da1 NFSD: Skip sending CB_RECALL_ANY when the backchannel isn't up
    afec5b5010de NFSD: Never return NFS4ERR_FILE_OPEN when removing a directory
    101fd0aa0d7d NFSD: nfsd_unlink() clobbers non-zero status returned from fh_fill_pre_attrs()
    a84c80515ca8 nfsd: fix management of listener transports
    cad3479b6366 nfsd: put dl_stid if fail to queue dl_recall
    52e209203c35 nfsd: allow SC_STATUS_FREEABLE when searching via nfs4_lookup_stateid()
    adf0ddb914c9 media: streamzap: fix race between device disconnection and urb callback
    845e9286ff99 media: vimc: skip .s_stream() for stopped entities
    e2d8e7bd3314 exec: fix the racy usage of fs_struct->in_exec
    747e3eec1d7d mm: zswap: fix crypto_free_acomp() deadlock in zswap_cpu_comp_dead()
    2d9709690f31 jfs: add index corruption check to DT_GETPAGE()
    0beddc2a3f9b jfs: fix slab-out-of-bounds read in ea_get()
    b47584c55644 ext4: fix OOB read when checking dotdot dir
    13d6f8ba5074 ext4: don't over-report free space or inodes in statvfs
    0cfea60966e4 wifi: mt76: mt7921: fix kernel panic due to null pointer dereference
    2df8ee605eb6 arm64: Don't call NULL in do_compat_alignment_fixup()
    2e877ff34922 mm/gup: reject FOLL_SPLIT_PMD with hugetlb VMAs
    1abca855ea9f tracing/osnoise: Fix possible recursive locking for cpus_read_lock()
    33052e7f52c5 tracing: Fix synth event printk format for str fields
    cffc2a6718e4 tracing: Ensure module defining synth event cannot be unloaded while tracing
    c85efe6e1374 tracing: Fix use-after-free in print_graph_function_flags during tracer switching
    37c9875c178f exfat: fix potential wrong error return from get_block
    49b0a6ab8e52 exfat: fix random stack corruption after get_block
    ca8bed31edf7 ksmbd: fix null pointer dereference in alloc_preauth_hash()
    56de7778a485 ksmbd: validate zero num_subauth before sub_auth is accessed
    6a9cd9ff0fa2 ksmbd: fix overflow in dacloffset bounds check
    9069939d7621 ksmbd: fix session use-after-free in multichannel connection
    ca042cc0e4f9 ksmbd: fix use-after-free in ksmbd_sessions_deregister()
    800c482c9ef5 ksmbd: add bounds check for create lease context
    29b946714d6a ksmbd: add bounds check for durable handle context
    9bc3299039d2 KVM: SVM: Don't change target vCPU state on AP Creation VMGEXIT error
    a31fa24813a7 mmc: sdhci-omap: Disable MMC_CAP_AGGRESSIVE_PM for eMMC/SD
    1209241a6b40 mmc: sdhci-pxav3: set NEED_RSP_BUSY capability
    b548a448993a mmc: omap: Fix memory leak in mmc_omap_new_slot
    0c121f2065e4 Remove unnecessary firmware version check for gc v9_4_2
    6b9ddc4f5f2e media: omap3isp: Handle ARM dma_iommu_mapping
    9f7ae45f0c61 ARM: 9444/1: add KEEP() keyword to ARM_VECTORS
    498edda23f7e ACPI: resource: Skip IRQ override on ASUS Vivobook 14 X1404VAP
    e71a57c5aaa3 acpi: nfit: fix narrowing conversion in acpi_nfit_ctl
    339d6c965f20 wifi: mt76: mt7925: remove unused acpi function for clc
    93224deb50a8 x86/mm: Fix flush_tlb_range() when used for zapping normal PMDs
    70a2fa13d4a9 x86/tsc: Always save/restore TSC sched_clock() on suspend/resume
    e3d54decc75c x86/Kconfig: Add cmpxchg8b support back to Geode CPUs
    e8bba7ced03e idpf: Don't hard code napi_struct size
    c35771342e47 uprobes/x86: Harden uretprobe syscall trampoline check
    3a8bec6583e5 perf/x86/intel: Avoid disable PMU if !cpuc->enabled in sample read
    e853bb7d6aec perf/x86/intel: Apply static call for drain_pebs
    854b6764be33 ntb_perf: Delete duplicate dmaengine_unmap_put() call in perf_copy_chunk()
    1a85281415fb platform/x86: ISST: Correct command storage data length
    48792ab44552 platform/x86: thinkpad_acpi: disable ACPI fan access for T495* and E560
    35c1834dd630 ACPI: x86: Extend Lenovo Yoga Tab 3 quirk with skip GPIO event-handlers
    805e3ce5e0e3 x86/tdx: Fix arch_safe_halt() execution for TDX VMs
    3e3d8169c095 x86/mce: use is_copy_from_user() to determine copy-from-user context
    ada88219d531 x86/microcode/AMD: Fix __apply_microcode_amd()'s return value
    d39838da59bd KVM: x86: block KVM_CAP_SYNC_REGS if guest state is protected
    a54247efbc73 x86/hyperv: Fix check of return value from snp_set_vmsa()
    add72c418d0a LoongArch: BPF: Use move_addr() for BPF_PSEUDO_FUNC
    223d565d8892 LoongArch: BPF: Don't override subprog's return value
    205a2182c51f LoongArch: BPF: Fix off-by-one error in build_prologue()
    0aa5d4370b5b LoongArch: Increase MAX_IO_PICS up to 8
    1d0def2d1658 LoongArch: Increase ARCH_DMA_MINALIGN up to 16
    dc07c4698587 rust: Fix enabling Rust and building with GCC for LoongArch
    d689645cd159 usbnet:fix NPE during rx_complete
    86f327305ed4 wifi: mac80211: Fix sparse warning for monitor_sdata
    96fa2608296d tty: serial: lpuart: only disable CTS instead of overwriting the whole UARTMODIR register
    b09ff334c168 tty: serial: fsl_lpuart: Fix unused variable 'sport' build warning
    ac08fa36d8cb tty: serial: fsl_lpuart: use port struct directly to simply code
    82719d0e7584 tty: serial: fsl_lpuart: Use u32 and u8 for register variables
    3501677651ca cgroup/rstat: Fix forceidle time in cpu.stat
    39bc1484eb06 cgroup/rstat: Tracking cgroup-level niced CPU time
    ef79f2dec7a9 tracing: Correct the refcount if the hist/hist_debug file fails to open
    eecb62a24b23 tracing/hist: Support POLLPRI event for poll on histogram
    fe87f8d3a5b4 tracing/hist: Add poll(POLLIN) support on hist file
    387dc88c2c27 tracing: Switch trace_events_hist.c code over to use guard()
    7de8290a66df tools/power turbostat: report CoreThr per measurement interval
    e9c928807239 perf/core: Fix child_total_time_enabled accounting bug at task exit
    d3f0a68b2914 drm/amdgpu/gfx12: fix num_mec
    2ac69453e9e5 drm/amdgpu/gfx11: fix num_mec
    528287815ee5 kbuild: deb-pkg: don't set KBUILD_BUILD_VERSION unconditionally
    8a88bb092f42 net: ibmveth: make veth_pool_store stop hanging
    ebebeb58d48e arcnet: Add NULL check in com20020pci_probe()
    f4fea25f5c7f ipv6: Do not consider link down nexthops in path selection
    1eb36a2cdf63 ipv6: Start path selection from the first nexthop
    2952776c69a1 net: fix geneve_opt length integer overflow
    9dec9dacaeed net: dsa: mv88e6xxx: propperly shutdown PPU re-enable timer on destroy
    de579015d132 ipv6: fix omitted netlink attributes when using RTEXT_FILTER_SKIP_STATS
    0a93a710d6df netfilter: nft_tunnel: fix geneve_opt type confusion addition
    92a5c1851311 net: decrease cached dst counters in dst_release
    9539c1721a36 tunnels: Accept PACKET_HOST in skb_tunnel_check_pmtu().
    47744d0d5f3b vsock: avoid timeout during connect() if the socket is closing
    a116b271bf3c udp: Fix memory accounting leak.
    94d5ad7b4112 udp: Fix multiple wraparounds of sk->sk_rmem_alloc.
    fcbfb54a0269 net: mvpp2: Prevent parser TCAM memory corruption
    e5178bfc55b3 sctp: add mutual exclusion in proc_sctp_do_udp_port()
    2f35b7673a3a net_sched: skbprio: Remove overly strict queue assertions
    3ba9cf69de50 netlabel: Fix NULL pointer exception caused by CALIPSO on IPv4 sockets
    feb1fa2a03a2 netfilter: nf_tables: don't unregister hook when table is dormant
    86bd9609fd3e netfilter: nft_set_hash: GC reaps elements with conncount for dynamic sets only
    79618e952ef4 idpf: fix adapter NULL pointer dereference on reboot
    d11d0ce887f4 e1000e: change k1 configuration on MTP and later platforms
    40d187b247b3 spi: bcm2835: Restore native CS probing when pinctrl-bcm2835 is absent
    174954911f1c ALSA: hda/realtek: Fix built-in mic on another ASUS VivoBook model
    48b175aa4677 spi: bcm2835: Do not call gpiod_put() on invalid descriptor
    4d8458e48ff1 ASoC: imx-card: Add NULL check in imx_card_probe()
    a3800b64f866 nvme/ioctl: don't warn on vectorized uring_cmd with fixed buffer
    c35ec5e046ba riscv/purgatory: 4B align purgatory_start
    4c6b1d08e614 riscv/kexec_file: Handle R_RISCV_64 in purgatory relocator
    be85b932b578 riscv: Fix hugetlb retrieval of number of ptes in case of !present pte
    e50781bf7acc spi: cadence: Fix out-of-bounds array access in cdns_mrvl_xspi_setup_clock()
    d3b862658669 ASoC: codecs: rt5665: Fix some error handling paths in rt5665_probe()
    c76bb2d0aa54 s390/entry: Fix setting _CIF_MCCK_GUEST with lowcore relocation
    7e3497d7dacb ublk: make sure ubq->canceling is set when queue is frozen
    efd101b1f0f5 x86/uaccess: Improve performance by aligning writes to 8 bytes in copy_user_generic(), on non-FSRM/ERMS CPUs
    0751db851374 RISC-V: errata: Use medany for relocatable builds
    92a25feb4546 ALSA: hda/realtek: Fix built-in mic breakage on ASUS VivoBook X515JA
    26d14768c4ba firmware: cs_dsp: Ensure cs_dsp_load[_coeff]() returns 0 on success
    3dbb73a07579 ntb: intel: Fix using link status DB's
    cb153bdc1812 ntb_hw_switchtec: Fix shift-out-of-bounds in switchtec_ntb_mw_set_trans
    4119e80ce22d riscv: ftrace: Add parentheses in macro definitions of make_call_t0 and make_call_ra
    8522051c58d6 fs/9p: fix NULL pointer dereference on mkdir
    d04600f43569 spufs: fix a leak in spufs_create_context()
    029d8c711f5e spufs: fix gang directory lifetimes
    35f789ccebd6 spufs: fix a leak on spufs_new_file() failure
    7a95b4887348 netfs: Fix netfs_unbuffered_read() to return ssize_t rather than int
    8a2cc9ffd13c hwmon: (nct6775-core) Fix out of bounds access for NCT679{8,9}
    bc08c087118e memory: omap-gpmc: drop no compatible check
    d840c84cdddd can: statistics: use atomic access in hot path
    54c198d672ca ALSA: hda/realtek: Add mute LED quirk for HP Pavilion x360 14-dy1xxx
    a3612053b2e7 selftests: netfilter: skip br_netfilter queue tests if kernel is tainted
    93c59b5548ee net: devmem: do not WARN conditionally after netdev_rx_queue_restart()
    cf1b90486748 drm/amd: Keep display off while going into S4
    3e6ce0d9ec79 nvme-pci: fix stuck reset on concurrent DPC and HP
    5e194e0f77ee x86/sgx: Warn explicitly if X86_FEATURE_SGX_LC is not enabled
    eafd7ec55b1d x86/hyperv: Fix output argument to hypercall that changes page visibility
    ddf40162ac79 locking/semaphore: Use wake_q to wake up processes outside lock critical section
    e401fa5b953e wifi: mac80211: fix SA Query processing in MLO
    9465e09b74eb wifi: mac80211: flush the station before moving it to UN-AUTHORIZED state
    56e6d4a8877f ASoC: rt1320: set wake_capable = 0 explicitly
    f8dfd7c50170 ASoC: codecs: wsa884x: report temps to hwmon in millidegree of Celsius
    e1fc76b2bbf3 x86/hyperv/vtl: Stop kernel from probing VTL0 low memory
    ecc08c460866 sched/deadline: Use online cpus for validating runtime
    c730833bc025 ALSA: hda/realtek: Add support for ASUS Zenbook UM3406KA Laptops using CS35L41 HDA
    01a27b2dd07f ALSA: hda/realtek: Add support for ASUS B5405 and B5605 Laptops using CS35L41 HDA
    2e2626d1e8db ALSA: hda/realtek: Add support for ASUS B3405 and B3605 Laptops using CS35L41 HDA
    f57ca98c65cd ALSA: hda/realtek: Add support for various ASUS Laptops using CS35L41 HDA
    ff8ebaf47dce ALSA: hda/realtek: Add support for ASUS ROG Strix G614 Laptops using CS35L41 HDA
    9dcf970c5c38 ALSA: hda/realtek: Add support for ASUS ROG Strix GA603 Laptops using CS35L41 HDA
    c7943f0677d6 ALSA: hda/realtek: Add support for ASUS ROG Strix G814 Laptop using CS35L41 HDA
    92075758782c exfat: add a check for invalid data size
    77a5ed6b0349 platform/x86/amd/pmf: Update PMF Driver for Compatibility with new PMF-TA
    5dd021991430 platform/x86/amd/pmf: Propagate PMF-TA return codes
    f7038ea68fc0 HID: i2c-hid: improve i2c_hid_get_report error message
    95459156b366 net: dsa: rtl8366rb: don't prompt users for LED control
    64eb31d872fe platform/x86/intel/vsec: Add Diamond Rapids support
    10ac73318c3a platform/x86: intel-hid: fix volume buttons on Microsoft Surface Go 4 tablet
    6edee7c63b93 cifs: fix incorrect validation for num_aces field of smb_acl
    da087905e327 smb: common: change the data type of num_aces to le16
    7364420090ac perf/core: Fix perf_pmu_register() vs. perf_init_event()
    fbd3a04bd86f ALSA: hda: Fix speakers on ASUS EXPERTBOOK P5405CSA 1.0
    64c707d24ccc ALSA: hda/realtek: Fix Asus Z13 2025 audio
    83d888b69310 affs: don't write overlarge OFS data block size fields
    4fbfb003bba4 affs: generate OFS sequence numbers starting at 1
    d8575bdcf820 wifi: brcmfmac: keep power during suspend if board requires it
    5eb8c8fee726 nvme-pci: skip CMB blocks incompatible with PCI P2P DMA
    63bd235de242 nvme-pci: clean up CMBMSC when registering CMB fails
    c2fa1deeb4b8 nvme-tcp: fix possible UAF in nvme_tcp_poll
    12622cb7b1d8 wifi: iwlwifi: mvm: use the right version of the rate API
    bd888d67c7ce wifi: iwlwifi: fw: allocate chained SG tables for dump
    e0862a6d3dab wifi: mac80211: remove debugfs dir for virtual monitor
    5d42a3413724 wifi: mac80211: Cleanup sta TXQs on flush
    eb532ac40dc8 nfs: Add missing release on error in nfs_lock_and_join_requests()
    26bf086ebd70 objtool/loongarch: Add unwind hints in prepare_frametrace()
    d80168db5e0c rcu-tasks: Always inline rcu_irq_work_resched()
    00911b416ad7 context_tracking: Always inline ct_{nmi,irq}_{enter,exit}()
    8e49f912ae14 sched/smt: Always inline sched_smt_active()
    22e1e4e11af5 objtool: Fix verbose disassembly if CROSS_COMPILE isn't set
    10856c530de3 octeontx2-af: Free NIX_AF_INT_VEC_GEN irq
    d2e60c3b8a62 octeontx2-af: Fix mbox INTR handler when num VFs > 64
    a436e1434317 net: phy: broadcom: Correct BCM5221 PHY model detection
    d3561dc471ac ACPI: processor: idle: Return an error if both P_LVL{2,3} idle states are invalid
    00c22ab0614a LoongArch: Rework the arch_kgdb_breakpoint() implementation
    035a4a852ee8 LoongArch: Fix device node refcount leak in fdt_cpu_clk_init()
    396cdb580e2e LoongArch: Fix help text of CMDLINE_EXTEND in Kconfig
    11d479dffde5 objtool: Fix segfault in ignore_unreachable_insn()
    2a6f8823ff60 ring-buffer: Fix bytes_dropped calculation issue
    5923492ba353 net/mlx5e: SHAMPO, Make reserved size independent of page size
    457db486203c ksmbd: fix r_count dec/increment mismatch
    e0b32b6f0f13 ksmbd: fix multichannel connection failure
    3e341dbd5f5a ksmbd: use aead_request_free to match aead_request_alloc
    3f17af46cfc7 rndis_host: Flag RNDIS modems as WWAN devices
    28b21ee8e8fb rtnetlink: Allocate vfinfo size for VF GUIDs when supported
    4a9595eb024b exfat: fix missing shutdown check
    6a1407532500 exfat: fix the infinite loop in exfat_find_last_cluster()
    7d8dfc27d90d smb: client: Fix netns refcount imbalance causing leaks and use-after-free
    81270dd79606 NFS: Shut down the nfs_client only after all the superblocks
    cd80277f6521 objtool, media: dib8000: Prevent divide-by-zero in dib8000_set_dds()
    1adc93a525fd objtool, nvmet: Fix out-of-bounds stack access in nvmet_ctrl_state_show()
    456300be232e thermal: core: Remove duplicate struct declaration
    8f178998af67 perf bpf-filter: Fix a parsing error with comma
    2c3dea5d1776 perf tools: annotate asm_pure_loop.S
    aba918999252 fs/procfs: fix the comment above proc_pid_wchan()
    819685fcebdf perf vendor events arm64 AmpereOneX: Fix frontend_bound calculation
    5b2b692804ce tty: n_tty: use uint for space returned by tty_write_room()
    1817c4b85011 staging: vchiq_arm: Fix possible NPR of keep-alive thread
    f3fafa188d96 staging: vchiq_arm: Register debugfs after cdev
    f14dd4025975 staging: rtl8723bs: select CONFIG_CRYPTO_LIB_AES
    ed1d004a5af0 perf: intel-tpebs: Fix incorrect usage of zfree()
    70afdf771171 perf dso: fix dso__is_kallsyms() check
    18ea76a747ac perf python: Check if there is space to copy all the event
    9816424d65a2 perf python: Don't keep a raw_data pointer to consumed ring buffer space
    4608d15a43fb perf python: Decrement the refcount of just created event on failure
    f0343969111f perf python: Fixup description of sample.id event member
    e1c900e078d5 i3c: master: svc: Fix missing the IBI rules
    a8edfc206ed1 um: hostfs: avoid issues on inode number reuse by host
    5b37d2370d0c um: remove copy_from_kernel_nofault_allowed
    2b0328c5f0f9 um: Pass the correct Rust target and options with gcc
    0d8ba0ed03c3 selftests/mm/cow: fix the incorrect error handling
    eafb4e3a82aa fuse: fix dax truncate/punch_hole fault path
    ca27c16539a3 NFS: fix open_owner_id_maxsz and related fields.
    46117472a279 NFSv4: Avoid unnecessary scans of filesystems for delayed delegations
    8765bc2638ce NFSv4: Avoid unnecessary scans of filesystems for expired delegations
    ac8be75a7deb NFSv4: Avoid unnecessary scans of filesystems for returning delegations
    4595beb5fee9 NFSv4: Don't trigger uneccessary scans for return-on-close delegations
    d04bea49c806 arch/powerpc: drop GENERIC_PTDUMP from mpc885_ads_defconfig
    49d2a2ea9d30 ocfs2: validate l_tree_depth to avoid out-of-bounds access
    c6338b0d56f0 kexec: initialize ELF lowest address to ULONG_MAX
    c42282a07832 kernel/events/uprobes: handle device-exclusive entries correctly in __replace_page()
    32222c0fd242 perf units: Fix insufficient array space
    b18056f753bf perf evlist: Add success path to evlist__create_syswide_maps
    7cd1096d3bea perf debug: Avoid stack overflow in recursive error message
    7a40b52d4442 iio: light: Add check for array bounds in veml6075_read_int_time_ms
    967570b52826 iio: adc: ad7768-1: set MOSI idle state to prevent accidental reset
    dd6391006379 iio: adc: ad7173: Fix comparison of channel configs
    12eeec2fe012 iio: adc: ad7124: Fix comparison of channel configs
    0c13dc967e07 iio: adc: ad4130: Fix comparison of channel setups
    55e2dbe2ba78 dmaengine: fsl-edma: free irq correctly in remove path
    bcd00d044346 dmaengine: fsl-edma: cleanup chan after dma_async_device_unregister
    201a2bdda13b fs/ntfs3: Prevent integer overflow in hdr_first_de()
    284c9549386e fs/ntfs3: Fix a couple integer overflows on 32bit systems
    8109f57613a0 usb: xhci: correct debug message page size calculation
    fc1b20f16897 perf bench: Fix perf bench syscall loop count
    8e901e95bedc perf arm-spe: Fix load-store operation checking
    df3892e5e861 iio: backend: make sure to NULL terminate stack buffer
    91cc7dca2a69 iio: accel: msa311: Fix failure to release runtime pm if direct mode claim fails.
    7c640dd70e63 iio: accel: mma8452: Ensure error return on failure to matching oversampling ratio
    a17a3db6d411 ucsi_ccg: Don't show failed to get FW build information error
    d72a8585043b perf build: Fix in-tree build due to symbolic link
    a7b29a28d1e4 tools/x86: Fix linux/unaligned.h include path in lib/insn.c
    72a149792714 perf pmu: Don't double count common sysfs and json events
    1315b08f609e coresight-etm4x: add isb() before reading the TRCSTATR
    3a19eb3d9818 vhost-scsi: Fix handling of multiple calls to vhost_scsi_set_endpoint
    e90a5776e105 coresight: catu: Fix number of pages while using 64k pages
    6f774f82a7fa greybus: gb-beagleplay: Add error handling for gb_greybus_init
    372a144dbb96 perf report: Switch data file correctly in TUI
    0e344b67bf26 soundwire: slave: fix an OF node reference leak in soundwire slave device
    82d0586c3592 isofs: fix KMSAN uninit-value bug in do_isofs_readdir()
    f9b0819e8b10 phy: phy-rockchip-samsung-hdptx: Don't use dt aliases to determine phy-id
    641394fbb5a5 fs/ntfs3: Update inode->i_mapping->a_ops on compression state
    4f750b846280 w1: fix NULL pointer dereference in probe
    4baed8d7452b perf: Always feature test reallocarray
    de9c71274735 perf stat: Fix find_stat for mixed legacy/non-legacy events
    165b155dfedb clk: qcom: mmcc-sdm660: fix stuck video_subcore0 clock
    bf233124d398 pinctrl: intel: Fix wrong bypass assignment in intel_pinctrl_probe_pwm()
    5416777d568a crypto: hisilicon/sec2 - fix for aead auth key length
    0d6460b9d2a3 RDMA/core: Fix use-after-free when rename device name
    782526a40149 x86/dumpstack: Fix inaccurate unwinding from exception stacks due to misplaced assignment
    c2ddf2f5760b leds: Fix LED_OFF brightness race
    a1fab9e64948 mfd: sm501: Switch to BIT() to mitigate integer overflows
    7ee71ef057b1 pinctrl: renesas: rzv2m: Fix missing of_node_put() call
    cad677085274 RDMA/mlx5: Fix mlx5_poll_one() cur_qp update flow
    19e6817f8400 bpf: Fix array bounds error with may_goto
    cff6b3c8085d clk: qcom: gcc-sm8650: Do not turn off USB GDSCs during gdsc_disable()
    4fdbccc738af crypto: nx - Fix uninitialised hv_nxc on error
    ac9e52aca2cb power: supply: max77693: Fix wrong conversion of charge input threshold value
    b6542ef0d4dd x86/entry: Fix ORC unwinder for PUSH_REGS with save_ret=1
    cd0e4789f870 clk: amlogic: g12a: fix mmc A peripheral clock
    f29760cdca4b clk: clk-imx8mp-audiomix: fix dsp/ocram_a clock parents
    64bb7efb0c4c crypto: qat - remove access to parity register for QAT GEN4
    4409e87cdc8b pinctrl: npcm8xx: Fix incorrect struct npcm8xx_pincfg assignment
    8ba426f170f1 rust: fix signature of rust_fmt_argument
    c9fad5ce1ef9 selftests/bpf: Select NUMA_NO_NODE to create map
    4d32504f7ae9 clk: amlogic: gxbb: drop non existing 32k clock parent
    dc8477444ac6 clk: amlogic: g12b: fix cluster A parent data
    52f3ef292b7b pinctrl: tegra: Set SFIO mode to Mux Register
    2aec4d9a79a7 IB/mad: Check available slots before posting receive WRs
    6d4e56e4c581 crypto: api - Fix larval relookup type and mask
    eae034cdcee9 power: supply: bq27xxx_battery: do not update cached flags prematurely
    005d8de09c71 remoteproc: qcom_q6v5_mss: Handle platforms with one power domain
    a114d25d584c RDMA/erdma: Prevent use-after-free in erdma_accept_newconn()
    257f0bdd5a4b RDMA/mlx5: Fix calculation of total invalidated pages
    df45ae2a4f1c RDMA/core: Don't expose hw_counters outside of init net namespace
    c9c2582c4cd1 clk: rockchip: rk3328: fix wrong clk_ref_usb3otg parent
    dcb5997ead6d selftests/bpf: Fix freplace_link segfault in tailcalls prog test
    25aa4fe297a5 RDMA/mlx5: Fix MR cache initialization error flow
    fb4206c76b99 pinctrl: renesas: rzg2l: Fix missing of_node_put() call
    3980e3741a8c pinctrl: renesas: rza2: Fix missing of_node_put() call
    e7b7f5a170d3 lib: 842: Improve error handling in sw842_compress()
    8ed5381756de bpf: Use preempt_count() directly in bpf_send_signal_common()
    42efddee037b clk: qcom: gcc-x1e80100: Unregister GCC_GPU_CFG_AHB_CLK/GCC_DISP_XO_CLK
    82484764ea90 remoteproc: qcom_q6v5_pas: Use resource with CX PD for MSM8226
    4a7e28e3523f crypto: tegra - Set IV to NULL explicitly for AES ECB
    7d25febb0e03 RDMA/mana_ib: Ensure variable err is initialized
    088a200ebf46 s390: Remove ioremap_wt() and pgprot_writethrough()
    bd717b4dea87 clk: qcom: gcc-msm8953: fix stuck venus0_core0 clock
    13a2312c5352 crypto: tegra - Fix CMAC intermediate result handling
    241d9965109b pinctrl: nuvoton: npcm8xx: Fix error handling in npcm8xx_gpio_fw()
    24307866e0ac clk: samsung: Fix UBSAN panic in samsung_clk_init()
    81d4e03116d3 remoteproc: qcom: pas: add minidump_id to SC7280 WPSS
    b5d1970003cc clk: renesas: r8a08g045: Check the source of the CPU PLL settings
    8d6373f83f36 x86/mm/pat: Fix VM_PAT handling when fork() fails in copy_page_range()
    919206201aac selftests/bpf: Fix string read in strncmp benchmark
    652a3dfd8c2b libbpf: Fix hypothetical STT_SECTION extern NULL deref case
    73fd28b12d78 remoteproc: qcom_q6v5_pas: Make single-PD handling more robust
    26c0229b604e pinctrl: renesas: rzg2l: Suppress binding attributes
    bfcca46f01ac of: property: Increase NR_FWNODE_REFERENCE_ARGS
    2df19f5f6f72 remoteproc: core: Clear table_sz when rproc_shutdown
    01fd737776ca RDMA/mlx5: Fix page_size variable overflow
    51bcbe6cdaf0 crypto: hisilicon/sec2 - fix for sec spec check
    71f4581c464b crypto: hisilicon/sec2 - fix for aead authsize alignment
    0069c0e671ab clk: amlogic: gxbb: drop incorrect flag on 32k clock
    46ea02988bb9 crypto: tegra - Use HMAC fallback when keyslots are full
    057298d19334 crypto: bpf - Add MODULE_DESCRIPTION for skcipher
    3e0d61cf588f crypto: tegra - check return value for hash do_one_req
    5d9147db00d3 crypto: tegra - Use separate buffer for setkey
    f23dfee54b57 crypto: qat - set parity error mask for qat_420xx
    92936d50c5b8 crypto: iaa - Test the correct request flag
    238ece4937aa fbdev: sm501fb: Add some geometry checks.
    8356f4570082 mdacon: rework dependency list
    d3ea050c153d dummycon: fix default rows/cols
    9a14cacaf527 fbdev: au1100fb: Move a variable assignment behind a null pointer check
    b1c4bd166771 PCI: pciehp: Don't enable HPIE when resuming in poll mode
    e23dfb926f5b PCI: Fix BAR resizing when VF BARs are assigned
    a1855c2ebb88 PCI: histb: Fix an error handling path in histb_pcie_probe()
    b004cf517d8e PCI: dwc: ep: Return -ENOMEM for allocation failures
    3453bcaf2ca9 drm/amd/display: avoid NPD when ASIC does not support DMUB
    d877bf6eb39c drm/mediatek: dsi: fix error codes in mtk_dsi_host_transfer()
    57a9fb47551b drm/mediatek: dp: drm_err => dev_err in HPD path to avoid NULL ptr
    e5838a2bf16f drm/mediatek: Fix config_updating flag never false when no mbox channel
    02e94069c3e9 PCI: xilinx-cpm: Fix IRQ domain leak in error path of probe
    362b5879a7f3 PCI: Remove stray put_device() in pci_register_host_bridge()
    7b40c5b938e9 powerpc/kexec: fix physical address calculation in clear_utlb_entry()
    7e754aa0daaf crypto: powerpc: Mark ghashp8-ppc.o as an OBJECT_FILES_NON_STANDARD
    a3030fcba3c8 drm/msm/a6xx: Fix a6xx indexed-regs in devcoreduump
    f42a78df8894 drm/amd/display: fix type mismatch in CalculateDynamicMetadataParameters()
    b8b5e2e77083 drm/panthor: Update CS_STATUS_ defines to correct values
    bcb484200441 PCI: Avoid reset when disabled via sysfs
    2a54a1a9c6c9 PCI/portdrv: Only disable pciehp interrupts early when needed
    2cf276e501c4 PCI: brcmstb: Fix potential premature regulator disabling
    df63321a40cc PCI: brcmstb: Fix error path after a call to regulator_bulk_get()
    0fe63272c43c PCI: brcmstb: Use internal register to change link capability
    4557922dbfca PCI: brcmstb: Set generation limit before PCIe link up
    b23b73ea4c21 PCI: cadence-ep: Fix the driver to send MSG TLP for INTx without data payload
    c0ef1c8ef70b drm/amdkfd: Fix Circular Locking Dependency in 'svm_range_cpu_invalidate_pagetables'
    70f1dcc21779 drm/msm/dsi: Set PHY usescase (and mode) before registering DSI host
    2af52e4d2e19 drm/msm/dsi: Use existing per-interface slice count in DSC timing
    a47ee1884c5b drm/msm/dsi/phy: Program clock inverters in correct register
    47a025046640 drm/msm/dpu: don't use active in atomic_check()
    a99219bbd69a drm/amd/display: fix an indent issue in DML21
    8ba27aa51286 PCI/ACS: Fix 'pci=config_acs=' parameter
    91b0ab875128 drm/panel: ilitek-ili9882t: fix GPIO name in error message
    f556b6ba0ac5 PCI/ASPM: Fix link state exit during switch upstream function removal
    4f997843de78 drm/mediatek: mtk_hdmi: Fix typo for aud_sampe_size member
    0fe9a58fa5d0 drm/mediatek: mtk_hdmi: Unregister audio platform device on failure
    372e387c4f1c PCI: Remove add_align overwrite unrelated to size0
    254f771c7067 PCI: Use downstream bridges for distributing resources
    f2b099e945ee drm/amdgpu/umsch: fix ucode check
    2dbf9e3efcc0 drm/amdgpu: refine smu send msg debug log format
    2a07eab05d9d gpu: cdns-mhdp8546: fix call balance of mhdp->clk handling routines
    d5eb8e347905 drm/vkms: Fix use after free and double free on init error
    b84d743c2393 drm: xlnx: zynqmp: Fix max dma segment size
    dd8e6445e4e3 drm/bridge: it6505: fix HDCP V match check is not performed correctly
    69e90c1e3391 drm/dp_mst: Fix drm RAD print
    5ffb6b9a1a04 drm/ssd130x: ensure ssd132x pitch is correct
    5a3461ca54db drm/ssd130x: fix ssd132x encoding
    a9c4366566e6 drm/ssd130x: Set SPI .id_table to prevent an SPI core warning
    950513eba9cb drm/bridge: ti-sn65dsi86: Fix multiple instances
    15291b561d8c ALSA: timer: Don't take register_mutex with copy_from/to_user()
    11242f4b9baa ASoC: ti: j721e-evm: Fix clock configuration for ti,j7200-cpb-audio compatible
    f751361b3a15 ALSA: hda/realtek: Always honor no_shutup_pins
    2050247d5ebf dt-bindings: vendor-prefixes: add GOcontroll
    7fdca6c0b12c HID: remove superfluous (and wrong) Makefile entry for CONFIG_INTEL_ISH_FIRMWARE_DOWNLOADER
    da3ac4cf7f13 ASoC: amd: acp: Fix for enabling DMIC on acp platforms via _DSD entry
    748a1118d20d ASoC: cs35l41: check the return value from spi_setup()
    5b6739341500 platform/x86: dell-ddv: Fix temperature calculation
    0654ea13976c platform/x86: dell-uart-backlight: Make dell_uart_bl_serdev_driver static
    a4f38bc600f3 platform/x86: lenovo-yoga-tab2-pro-1380-fastcharger: Make symbol static
    4f42478af663 auxdisplay: panel: Fix an API misuse in panel.c
    f0a72629ccec media: platform: allgro-dvt: unregister v4l2_device on the error path
    d34100049923 media: verisilicon: HEVC: Initialize start_bit field
    e161533964de auxdisplay: MAX6959 should select BITREVERSE
    d026245063d2 regulator: pca9450: Fix enable register for LDO5
    f5852872eb29 x86/entry: Add __init to ia32_emulation_override_cmdline()
    52e513a8850c x86/fpu/xstate: Fix inconsistencies in guest FPU xfeatures
    b86500597089 x86/traps: Make exc_double_fault() consistently noreturn
    5108828fecfc perf/ring_buffer: Allow the EPOLLRDNORM flag for poll
    345957c1cfb8 lockdep: Don't disable interrupts on RT in disable_irq_nosync_lockdep.*()
    c3a4c91a409e PM: sleep: Fix handling devices with direct_complete set on errors
    953d28a4f459 thermal: int340x: Add NULL check for adev
    a8a1bcc27d46 x86/resctrl: Fix allocation of cleanest CLOSID on platforms with no monitors
    385a0265295f EDAC/ie31200: Fix the error path order of ie31200_init()
    4294e94f43c7 EDAC/ie31200: Fix the DIMM size mask for several SoCs
    67d079c0f29e EDAC/ie31200: Fix the size of EDAC_MC_LAYER_CHIP_SELECT layer
    96b4f2e97408 selinux: Chain up tool resolving errors in install_policy.sh
    864750968d71 watchdog/hardlockup/perf: Fix perf_event memory leak
    b471631fa19a kunit/stackinit: Use fill byte different from Clang i386 pattern
    ff435a627342 RISC-V: KVM: Disable the kernel perf counter during configure
    e2bda794d381 cpufreq: tegra194: Allow building for Tegra234
    31d5665172b3 PM: sleep: Adjust check before setting power.must_resume
    4d28c2ab2af5 lockdep/mm: Fix might_fault() lockdep check of current->mm->mmap_lock
    9807270d7399 x86/sev: Add missing RIP_REL_REF() invocations during sme_enable()
    3e14d9a4eb74 x86/platform: Only allow CONFIG_EISA for 32-bit
    a086e7cde509 x86/fpu: Avoid copying dynamic FP state from init_task in arch_dup_task_struct()
    568aa554e760 x86/fpu: Fix guest FPU state buffer allocation size
    2c27c9e1d18a EDAC/{skx_common,i10nm}: Fix some missing error reports on Emerald Rapids
    f381c92ab4ec cpufreq: governor: Fix negative 'idle_time' handling in dbs_update()
    b576c4834d5a sched/eevdf: Force propagating min_slice of cfs_rq when {en,de}queue tasks
    7b1d2454d0b6 sched: Cancel the slice protection of the idle entity
    2d5c37dff4b0 smack: ipv4/ipv6: tcp/dccp/sctp: fix incorrect child socket label
    9d93922280f9 smack: dont compile ipv6 code unless ipv6 is configured
    40426fc0970e cpufreq: scpi: compare kHz instead of Hz
    bc4d689a231d x86/mm/pat: cpa-test: fix length for CPA_ARRAY test
    56ec918e6c86 watch_queue: fix pipe accounting mismatch
    2ee7ebed771b mips: Add '-std=gnu11' to vdso CFLAGS
    b2c792d89ac5 yaffs2: switch from readlink_copy() to vfs_readlink()
    807165b1ec1c tools/power/x86/intel-speed-select: Prefix header search path with sysroot
    e97df805b938 drm/tilcdc: Set preferred depth
    7160a4379dcc arch/arm64/configs: remove CONFIG_SM_DISPCC_8650
    6d8ac5ebe6e8 aufs6: core
    587abc1b64c4 aufs6: standalone
    1af41d30ef42 aufs6: mmap
    6ee2464d2e9d aufs6: base
    103b676505f7 aufs6: kbuild
    67281562943f qemux86: add configuration symbol to select values
    73f315ca0823 sched/isolation: really align nohz_full with rcu_nocbs
    1e4e7f8ab622 clear_warn_once: add a clear_warn_once= boot parameter
    918e7a825e8b clear_warn_once: bind a timer to written reset value
    f533f87c3758 clear_warn_once: expand debugfs to include read support
    f149ca27cba9 tools: Remove some options from CLANG_CROSS_FLAGS
    e633abe9c44e libbpf: Fix build warning on ref_ctr_off
    ec0916a4cfc1 perf: perf can not parser the backtrace of app in the 32bit system and 64bit kernel.
    03721ceb5626 perf: x86-32: explicitly include <errno.h>
    4c36c5295bb0 perf: mips64: Convert __u64 to unsigned long long
    b0200449610d perf: fix bench numa compilation
    aff0940b2212 perf: add SLANG_INC for slang.h
    ef912018d28c perf: add sgidefs.h to for mips builds
    d8860f858b87 perf: change --root to --prefix for python install
    dc38a0eee6e5 perf: add 'libperl not found' warning
    6ed51f8786da perf: force include of <stdbool.h>
    c538d4c4ac65 fat: Replace prandom_u32() with get_random_u32()
    63d94846f0c5 fat: don't use obsolete random32 call in namei_vfat
    7816667451ef FAT: Added FAT_NO_83NAME
    f81dbd60f0d5 FAT: Add CONFIG_VFAT_NO_CREATE_WITH_LONGNAMES option
    771cdefba44b FAT: Add CONFIG_VFAT_FS_NO_DUALNAMES option
    a24784fd8f88 yaffs2: update to v6.12 folio changes
    d0a48fd46db8 yaffs2: adapt to v6.10 i_time changes
    d097e4d4115a yaffs: fix mtime/itime field access
    4411e0d49fe3 yaffs2: update VFS ctime operations to 6.6+
    1b6619086e8b yaffs2: v6.5 fixups
    25b261ee3c54 yaffs2: Fix miscalculation of devname buffer length
    5c07936a5d1c yaffs2: convert user_namespace to mnt_idmap
    55986a1284b3 yaffs2: replace bdevname call with sprintf
    6f5508f8db8f yaffs2: convert read_page -> readfolio
    fd179a5df5d5 yaffs: replace IS_ERR with IS_ERR_OR_NULL to check both ERR and NULL
    c9a620dacdd1 yaffs: fix -Wstringop-overread compile warning in yaffs_fix_null_name
    78588208ed17 yaffs2: v5.12+ build fixups (not runtime tested)
    8d2dddba272c yaffs: include blkdev.h
    8c1ca9ef9712 yaffs: Fix build failure by handling inode i_version with proper atomic API
    27005cbac2ed yaffs2: v5.6 build fixups
    668211c9f9b7 yaffs2: fix memory leak when /proc/yaffs is read
    285f911dcc1c yaffs: add strict check when call yaffs_internal_read_super
    ffc2ed489ccf yaffs: repair yaffs_get_mtd_device
    6dce4b70a5e3 yaffs: Fix build failure by handling inode i_version with proper atomic API
    19f283abc5d1 yaffs2: fix memory leak in mount/umount
    04e84672b571 yaffs: Avoid setting any ACL releated xattr
    4f221d6a32e2 Yaffs:check oob size before auto selecting Yaffs1
    81f36004e56b fs: yaffs2: replace CURRENT_TIME by other appropriate apis
    26d7a3dd0054 yaffs2: adjust to proper location of MS_RDONLY
    a7016eac4540 yaffs2: import git revision b4ce1bb (jan, 2020)
    feb240bbb91e initramfs: allow an optional wrapper script around initramfs generation
    874746eaa341 drivers: gpu: drm: msm: registers: improve reproducibility
    1d42508faee8 tools: use basename to identify file in gen-mach-types
    4b055eca593d iwlwifi: select MAC80211_LEDS conditionally
    97e20e275ac0 net/dccp: make it depend on CONFIG_BROKEN (CVE-2020-16119)
    6dec58319165 defconfigs: drop obselete options
    a416ccb5b6c9 linux-yocto: Handle /bin/awk issues
    7efe8a1e5158 uvesafb: provide option to specify timeout for task completion
    78d10ae07eca uvesafb: print error message when task timeout occurs
    80473b7eb8ca compiler.h: Undef before redefining __attribute_const__
    ddeff2f1a9a7 vmware: include jiffies.h
    3dcdda8912b4 Resolve jiffies wrapping about arp
    3b1507db6735 nfs: Allow default io size to be configured.
    c2fedad05f77 check console device file on fs when booting
    208d6fbada3f mount_root: clarify error messages for when no rootfs found
    dbe9454c8ea0 mconf: fix output of cflags and libraries
    7c7b224f5cce menuconfig,mconf-cfg: Allow specification of ncurses location
    b6c189c81397 modpost: mask trivial warnings
    a5cc21325ba9 kbuild: exclude meta directory from distclean processing
    361ec143c23f powerpc: serialize image targets
    605e6ccb304c arm: serialize build targets
    e94b04fcb7d2 mtd_blkdevs: add mtd_table_mutex lock back to blktrans_{open, release} to avoid race condition
    44cc7f69a0a0 cpu/amd: inhibit SMP check for qemux86
    a08cb65331e6 x86_64_defconfig: Fix warnings
    8ad332ef777b mips: make current_cpu_data preempt safe
    754f05ddce3f mips: vdso: fix 'jalr $t9' crash in vdso code
    325ff78ff44d mips: Kconfig: add QEMUMIPS64 option
    99ae0eadcf11 4kc cache tlb hazard: tlbp cache coherency
    c6894c66a534 malta uhci quirks: make allowance for slow 4k(e)c
    8b52c01f3294 arm64: defconfig: remove CONFIG_IPQ_APSS_5018
    16c7629f035e drm/fb-helper: move zeroing code to drm_fb_helper_fill_var
    6b60c874cbb0 arm64: defconfig: cleanup config options
    8e44673ecd89 vexpress: Pass LOADADDR to Makefile
    f34e6805aad5 arm: ARM EABI socketcall
    94dec9b88de4 ARM: LPAE: Invalidate the TLB for module addresses during translation fault

(From OE-Core rev: 054457a772df0e7866fa4ff0f22d79622ff419bd)

Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2025-04-23 19:48:04 +01:00
Bruce Ashfield
a472092f33 linux-yocto/6.12: update to v6.12.22
Updating linux-yocto/6.12 to the latest korg -stable release that comprises
the following commits:

    55767d6e74ef Linux 6.12.22
    9e6e83e1e2d0 bcachefs: bch2_ioctl_subvolume_destroy() fixes
    a964484a3537 serial: 8250_dma: terminate correct DMA in tx_dma_flush()
    5f9176f82ec7 serial: stm32: do not deassert RS485 RTS GPIO prematurely
    f86907583000 perf tools: Fix up some comments and code to properly use the event_source bus
    b094e8e3988e memstick: rtsx_usb_ms: Fix slab-use-after-free in rtsx_usb_ms_drv_remove
    a4931d9fb99e usb: xhci: Apply the link chain quirk on NEC isoc endpoints
    6af20ac254cb usb: xhci: Don't skip on Stopped - Length Invalid
    ed5760db3d8a net: usb: usbnet: restore usb%d name exception for local mac addresses
    52e05bea53c2 net: usb: qmi_wwan: add Telit Cinterion FE990B composition
    666e78b47713 net: usb: qmi_wwan: add Telit Cinterion FN990B composition
    53a005d3019f tty: serial: fsl_lpuart: disable transmitter before changing RS485 related registers
    27bd86d139ce tty: serial: 8250: Add Brainboxes XC devices
    54f9a8dcab90 tty: serial: 8250: Add some more device IDs
    0fac51a2d143 counter: microchip-tcb-capture: Fix undefined counter channel state on probe
    181a2ab650f7 counter: stm32-lptimer-cnt: fix error handling when enabling
    3ed38d0297fa ALSA: hda/realtek: Support mute LED on HP Laptop 15s-du3xxx
    2bb139e483f8 netfilter: socket: Lookup orig tuple for IPv6 SNAT
    2c1674fb52b2 drm/amd/display: Don't write DP_MSTM_CTRL after LT
    95407304253a nfsd: fix legacy client tracking initialization
    09691f367df4 atm: Fix NULL pointer dereference
    dddd13f7f167 HID: hid-plantronics: Add mic mute mapping and generalize quirks
    a532e7680878 ALSA: usb-audio: Add quirk for Plantronics headsets to fix control names
    2ee7ebed771b mips: Add '-std=gnu11' to vdso CFLAGS
    3423cae69078 Linux 6.12.21
    2fa52cd829c1 mptcp: Fix data stream corruption in the address announcement
    86368616a9ce mm/huge_memory: drop beyond-EOF folios with the right number of refs
    e7940c5794c3 arm64: dts: rockchip: fix u2phy1_host status for NanoPi R4S
    9aaffd371829 libsubcmd: Silence compiler warning
    8ece5abd7490 Revert "sched/core: Reduce cost of sched_move_task when config autogroup"
    c7762348038b KVM: arm64: Eagerly switch ZCR_EL{1,2}
    4a397bf077e7 KVM: arm64: Mark some header functions as inline
    2e4f2c20db53 KVM: arm64: Refactor exit handlers
    cb53828d6911 KVM: arm64: Remove VHE host restore of CPACR_EL1.SMEN
    d547b363f16a KVM: arm64: Remove VHE host restore of CPACR_EL1.ZEN
    f19a46cb5373 KVM: arm64: Remove host FPSIMD saving for non-protected KVM
    79e140bba70b KVM: arm64: Unconditionally save+flush host FPSIMD/SVE/SME state
    e6cd28bbbf90 KVM: arm64: Calculate cptr_el2 traps on activating traps
    73ef4f6e379b io_uring/net: fix sendzc double notif flush
    a4cb17797a5d ksmbd: fix incorrect validation for num_aces field of smb_acl
    731eccbd65aa drm/amdkfd: Fix user queue validation on Gfx7/8
    3aa8e00fefca drm/amdgpu: Fix JPEG video caps max size for navi1x and raven
    a0a43a133371 drm/amdgpu: Fix MPEG2, MPEG4 and VC1 video caps max size
    499d1adcac3e drm/amdgpu: Remove JPEG from vega and carrizo video caps
    97c2a78d2995 drm/amdgpu/pm: wire up hwmon fan speed for smu 14.0.2
    4b8b7026fc3b drm/amdgpu/pm: Handle SCLK offset correctly in overdrive for smu 14.0.2
    8201c17e986e drm/amdgpu: Restore uncached behaviour on GFX12
    eacbc9d28391 drm/amd/pm: add unique_id for gfx12
    c58726d64d08 drm/amd/display: Use HW lock mgr for PSR1 when only one eDP
    1992e216fd3c drm/amd/display: Fix message for support_edp0_on_dp1
    7341e36e6513 drm/amdgpu/gfx12: correct cleanup of 'me' field with gfx_v12_0_me_fini()
    1135a9431160 drm/sched: Fix fence reference count leak
    dd1801aa01bb drm/radeon: fix uninitialized size issue in radeon_vce_cs_parse()
    b2ab8c713bad pmdomain: amlogic: fix T7 ISP secpower
    f4489260f571 soc: qcom: pdr: Fix the potential deadlock
    91176c193417 batman-adv: Ignore own maximum aggregation size during RX
    130290f44bce xsk: fix an integer overflow in xp_create_and_assign_umem()
    6afe2ea2daec keys: Fix UAF in key_put()
    8332847875f7 efi/libstub: Avoid physical address 0x0 when doing random allocation
    c4e37b381a7a firmware: qcom: uefisecapp: fix efivars registration race
    54ccfef43773 ARM: shmobile: smp: Enforce shmobile_smp_* alignment
    0b1d48698ed9 ARM: dts: imx6qdl-apalis: Fix poweroff on Apalis iMX6
    2e1dfe3105ab memcg: drain obj stock on cpu hotplug teardown
    ede3e8ac90ae proc: fix UAF in proc_get_inode()
    4b84c6437f4b mm/page_alloc: fix memory accept before watermarks gets initialized
    c057ee03f751 mm/migrate: fix shmem xarray update during migration
    abc2677d167d mm: fix error handling in __filemap_get_folio() with FGP_NOWAIT
    baa37829052f selftests/mm: run_vmtests.sh: fix half_ufd_size_MB calculation
    8f8eb5afa2cb mmc: atmel-mci: Add missing clk_disable_unprepare()
    e96500b7d695 mmc: sdhci-brcmstb: add cqhci suspend/resume to PM ops
    838c916e6d66 arm64: dts: rockchip: fix pinmux of UART5 for PX30 Ringneck on Haikou
    f8ec8036e7e0 arm64: dts: rockchip: fix pinmux of UART0 for PX30 Ringneck on Haikou
    200517d82b4c arm64: dts: freescale: imx8mm-verdin-dahlia: add Microphone Jack to sound card
    16f1b7dc28a4 arm64: dts: freescale: imx8mp-verdin-dahlia: add Microphone Jack to sound card
    b362fc904d26 accel/qaic: Fix integer overflow in qaic_validate_req()
    a99f1254b11e regulator: check that dummy regulator has been probed before using it
    d3b83a1442a0 regulator: dummy: force synchronous probing
    0def1a40c3e7 netfs: Call `invalidate_cache` only if implemented
    adb7325362c7 riscv: dts: starfive: Fix a typo in StarFive JH7110 pin function definitions
    66e3cc3885e8 io_uring/net: don't clear REQ_F_NEED_CLEANUP unconditionally
    4b4d2527840f drm/v3d: Don't run jobs that have errors flagged in its fence
    c76a537ca228 drm/xe: Fix exporting xe buffers multiple times
    dc55ba5f6dd5 can: flexcan: disable transceiver during system PM
    7072723e0534 can: flexcan: only change CAN state when link up in system PM
    8cec9e314d33 can: ucan: fix out of bound read in strscpy() source
    eb14937ece4f can: rcar_canfd: Fix page entries in the AFL list
    76a13fad5a3f dt-bindings: can: renesas,rcar-canfd: Fix typo in pattern properties for R-Car V4M
    15cc669513d6 net: mana: Support holes in device list reply msg
    bb83e6e7b56e i2c: omap: fix IRQ storms
    71c9cf87776e tracing: tprobe-events: Fix leakage of module refcount
    a3ff812d68f6 Revert "gre: Fix IPv6 link-local address generation."
    250793874f91 net/neighbor: add missing policy for NDTPA_QUEUE_LENBYTES
    176d0333aae4 libfs: Fix duplicate directory entry in offset_dir_lookup
    0d8a8179fa52 net: ipv6: ioam6: fix lwtunnel_output() loop
    49a009135042 net: lwtunnel: fix recursion loops
    1344df9a981c net: ti: icssg-prueth: Add lock to stats
    326223182e47 net: atm: fix use after free in lec_send()
    99918fb674d2 gpu: host1x: Do not assume that a NULL domain means no DMA IOMMU
    58ed057dcdb3 phy: fix xa_alloc_cyclic() error handling
    cb2f8a5c1fd9 dpll: fix xa_alloc_cyclic() error handling
    f8aaa38cfaf6 devlink: fix xa_alloc_cyclic() error handling
    cfbde06fda15 ipv6: Set errno after ip_fib_metrics_init() in ip6_route_info_create().
    29d91820184d ipv6: Fix memleak of nhc_pcpu_rth_output in fib_check_nh_v6_gw().
    8940e6168bb3 net: ipv6: fix TCP GSO segmentation with NAT
    d4bf956547c3 net: ethernet: ti: am65-cpsw: Fix NAPI registration sequence
    8bf2f1ba2729 ata: libata-core: Add ATA_QUIRK_NO_LPM_ON_ATI for certain Samsung SSDs
    5ba4f58ec2de tracing: tprobe-events: Fix to clean up tprobe correctly when module unload
    dfc80ed249b6 ARM: davinci: da850: fix selecting ARCH_DAVINCI_DA8XX
    1be40f79d36d accel/qaic: Fix possible data corruption in BOs > 2G
    e8f50474037f Bluetooth: hci_event: Fix connection regression between LE and non-LE adapters
    761b7c36addd Bluetooth: Fix error code in chan_alloc_skb_cb()
    bc6824b3aaff RDMA/hns: Fix wrong value of max_sge_rd
    abf7f5be159a RDMA/hns: Fix missing xa_destroy()
    0fa35d93d50a RDMA/hns: Fix a missing rollback in error path of hns_roce_create_qp_common()
    7912097c9304 RDMA/hns: Fix invalid sq params not being blocked
    4e4c2571aac4 RDMA/hns: Fix unmatched condition in error path of alloc_user_qp_db()
    13a52f6c9ff9 RDMA/hns: Fix soft lockup during bt pages loop
    d7b8dc4a0dce RDMA/bnxt_re: Avoid clearing VLAN_ID mask in modify qp path
    ca3c033a4fe1 dma-mapping: fix missing clear bdr in check_ram_in_range_map()
    db7dd032eeb2 ARM: dts: BCM5301X: Fix switch port labels of ASUS RT-AC3200
    2c74f29eaa0d ARM: dts: BCM5301X: Fix switch port labels of ASUS RT-AC5300
    d4ebdbbd4603 ARM: dts: bcm2711: Don't mark timer regs unconfigured
    49d3178ea54a ARM: OMAP1: select CONFIG_GENERIC_IRQ_CHIP
    7c2a5a535cbd RDMA/mlx5: Handle errors returned from mlx5r_ib_rate()
    adeba5b0d120 RDMA/bnxt_re: Add missing paranthesis in map_qp_id_to_tbl_indx
    2776978d2fac RDMA/rxe: Fix the failure of ibv_query_device() and ibv_query_device_ex() tests
    9d22afe499d0 arm64: dts: rockchip: Remove undocumented sdmmc property from lubancat-1
    be96850f9ed2 arm64: dts: bcm2712: PL011 UARTs are actually r1p5
    98c175b8eb2b ARM: dts: bcm2711: PL011 UARTs are actually r1p5
    b8a47aa0b3df ARM: dts: bcm2711: Fix xHCI power-domain
    11ae21f1b926 soc: imx8m: Unregister cpufreq and soc dev in cleanup path
    224d8bf798fb soc: imx8m: Use devm_* to simplify probe failure handling
    4d709816638d soc: imx8m: Remove global soc_uid
    25e4700489cf xfrm_output: Force software GSO only in tunnel mode
    a0395e96831a xfrm: fix tunnel mode TX datapath in packet offload mode
    a64df69c9718 arm64: dts: rockchip: remove supports-cqe from rk3588 tiger
    02396956ad89 arm64: dts: rockchip: remove supports-cqe from rk3588 jaguar
    5e203693ebf2 arm64: dts: freescale: tqma8mpql: Fix vqmmc-supply
    ea835113e5d0 firmware: imx-scu: fix OF node leak in .probe()
    d78510d151b5 firmware: qcom: scm: Fix error code in probe()
    f491dd2afe1c Linux 6.12.20
    62b9ad7e52d4 fs/netfs/read_collect: add to next->prev_donated
    8f324d99306b HID: apple: disable Fn key handling on the Omoton KB066
    888bcd6c5832 nvme-fc: rely on state transitions to handle connectivity loss
    f87271d21dd4 Bluetooth: L2CAP: Fix corrupted list in hci_chan_del
    ee06d5c81041 tools/sched_ext: Add helper to check task migration state
    46db29a2c8b1 sched_ext: selftests/dsp_local_on: Fix selftest on UP systems
    9d9d87e44dd7 smb: client: Fix match_session bug preventing session reuse
    beb97eba4cd8 smb3: add support for IAKerb
    f41514828296 mm/hugetlb: wait for hugetlb folios to be freed
    3b699bcc2667 i2c: sis630: Fix an error handling path in sis630_probe()
    ee2ae325f78e i2c: ali15x3: Fix an error handling path in ali15x3_probe()
    be05097610f0 i2c: ali1535: Fix an error handling path in ali1535_probe()
    9233b85afb47 x86/vmware: Parse MP tables for SEV-SNP enabled guests under VMware hypervisors
    1c46673be93d cifs: Fix integer overflow while processing closetimeo mount option
    4740cef2a9d0 cifs: Fix integer overflow while processing actimeo mount option
    2809a79bc649 cifs: Fix integer overflow while processing acdirmax mount option
    833f2903eb8b cifs: Fix integer overflow while processing acregmax mount option
    527bde0d9cac block: change blk_mq_add_to_batch() third argument type to bool
    0dfe4a7957a5 scripts: generate_rust_analyzer: add uapi crate
    4614939363bb scripts: generate_rust_analyzer: add missing include_dirs
    657f5e3eeceb scripts: generate_rust_analyzer: add missing macros deps
    7c29e8fd1f0e drm/i915: Increase I915_PARAM_MMAP_GTT_VERSION version to indicate support for partial mmaps
    e72a52a5cf18 ASoC: codecs: wm0010: Fix error handling path in wm0010_spi_probe()
    77213a424a48 nvme: move error logging from nvme_end_req() to __nvme_end_req()
    6f33bb8664b8 drm/xe/pm: Temporarily disable D3Cold on BMG
    b99b5c254442 drm/xe/userptr: Fix an incorrect assert
    0e9989bea707 drm/xe: Release guc ids before cancelling work
    084c46a133c1 drm/xe: cancel pending job timer before freeing scheduler
    90d1cf2fad80 ASoC: rt722-sdca: add missing readable registers
    9dcd2b72ea05 rust: init: add missing newline to pr_info! calls
    c79a462560d0 ASoC: cs42l43: Fix maximum ADC Volume
    cebcc1f336a6 drm/gma500: Add NULL check for pci_gfx_root in mid_get_vbt_data()
    4ec50b0cead5 rust: error: add missing newline to pr_warn! calls
    a46a9371f8b9 ASoC: ops: Consistently treat platform_max as control value
    752b56bb76e2 sched_ext: Validate prev_cpu in scx_bpf_select_cpu_dfl()
    72833a339f1f net: phy: nxp-c45-tja11xx: add TJA112XB SGMII PCS restart errata
    d52d624f3d70 net: phy: nxp-c45-tja11xx: add TJA112X PHY configuration errata
    b9004fe68878 smb: client: fix regression with guest option
    9721f3a79345 qlcnic: fix memory leak issues in qlcnic_sriov_common.c
    608bbf7ff5a5 Fix mmu notifiers for range-based invalidates
    f6bbea2ffea7 arm64: mm: Populate vmemmap at the page level if not section aligned
    5a87e46da241 dm-flakey: Fix memory corruption in optional corrupt_bio_byte feature
    454825019d2f netmem: prevent TX of unreadable skbs
    e2c89427e08b ASoC: amd: yc: Support mic on another Lenovo ThinkPad E16 Gen 2 model
    ac4b32cb59ff ASoC: Intel: sof_sdw: Fix unlikely uninitialized variable use in create_sdw_dailinks()
    0a024f992500 clk: samsung: gs101: fix synchronous external abort in samsung_clk_save()
    d14ef11b1d1e clk: samsung: update PLL locktime for PLL142XX used on FSD platform
    a4261bbc33fb ksmbd: prevent connection release during oplock break notification
    62746ae3f541 ksmbd: fix use-after-free in ksmbd_free_work_struct
    bac7b8b1a3f1 drm/amd/display: Fix slab-use-after-free on hdcp_work
    04f90b505ad3 drm/amd/display: Assign normalized_pix_clk when color depth = 14
    6d669a3b031a drm/amd/display: Restore correct backlight brightness after a GPU reset
    fefa811e616b drm/amd/display: fix missing .is_two_pixels_per_container
    9826fd36ff20 drm/amd/display: fix default brightness
    d1227b94d75c drm/amd/display: Disable unneeded hpd interrupts during dm_init
    60ae74e367ae drm/amdgpu/display: Allow DCC for video formats on GFX12
    c5c5e76aea80 drm/amd/amdkfd: Evict all queues even HWS remove queue failed
    72235808eabe drm/amdgpu: NULL-check BO's backing store when determining GFX12 PTE flags
    beb47bc67363 drm/dp_mst: Fix locking when skipping CSN before topology probing
    962912aaf8d1 drm/atomic: Filter out redundant DPMS calls
    e487d35964fb drm/panic: fix overindented list items in documentation
    8232ec53bcdd drm/panic: use `div_ceil` to clean Clippy warning
    8f55d4414d55 drm/i915/cdclk: Do cdclk post plane programming later
    220e26960ef4 spi: microchip-core: prevent RX overflows when transmit size > FIFO size
    488ffc0cac38 x86/microcode/AMD: Fix out-of-bounds on systems with CPU-less NUMA nodes
    677088b7fa88 rust: init: fix `Zeroable` implementation for `Option<NonNull<T>>` and `Option<KBox<T>>`
    514d35a745b8 rust: Disallow BTF generation with Rust + LTO
    28d472f153f9 rust: alloc: satisfy POSIX alignment requirement
    6db379b34a06 rust: remove leftover mentions of the `alloc` crate
    2ef7bdb84620 rust: lockdep: Remove support for dynamically allocated LockClassKeys
    ccffb475c133 USB: serial: option: match on interface class for Telit FN990B
    d233dbf101b1 USB: serial: option: fix Telit Cinterion FE990A name
    3bfa629f4516 USB: serial: option: add Telit Cinterion FE990B compositions
    87ede08ef245 USB: serial: ftdi_sio: add support for Altera USB Blaster 3
    1a7493a2b899 Input: i8042 - swap old quirk combination with new quirk for more devices
    64c6abf1b427 Input: i8042 - swap old quirk combination with new quirk for several devices
    ee554ffa3731 Input: i8042 - add required quirks for missing old boardnames
    3d6fa8c56bb1 Input: i8042 - swap old quirk combination with new quirk for NHxxRZQ
    0ff93d895619 Input: xpad - rename QH controller to Legion Go S
    f7ccf4eb4bac Input: xpad - add support for TECNO Pocket Go
    d91dd818f1fc Input: xpad - add support for ZOTAC Gaming Zone
    e2304bbf8789 Input: xpad - add multiple supported devices
    1936b189fa7d Input: xpad - add 8BitDo SN30 Pro, Hyperkin X91 and Gamesir G7 SE controllers
    84f7b6f1d63a Input: iqs7222 - preserve system status register
    2daccd3b50dd Input: ads7846 - fix gpiod allocation
    eff502828bb4 Input: goodix-berlin - fix vddio regulator references
    fef9d44b24be cifs: Throw -EOPNOTSUPP error on unsupported reparse point type from parse_reparse_point()
    b2bccc729b93 cifs: Validate content of WSL reparse point buffers
    061ea46c56f6 vhost: return task creation error instead of NULL
    7184e996107c block: fix 'kmem_cache of name 'bio-108' already exists'
    d1ceef54b239 net: Handle napi_schedule() calls from non-interrupt
    1cf295ac531c drm/nouveau: Do not override forced connector status
    27fcaf0afe16 mptcp: safety check before fallback
    d7e94211d12d perf/x86/rapl: Add support for Intel Arrow Lake U
    2d2b4bdf083d x86/irq: Define trace events conditionally
    c481ada21a72 x86/of: Don't use DTB for SMP setup if ACPI is enabled
    b1d5a2c0501f perf/x86/intel: Use better start period for frequency mode
    665de082f3cb drm/vkms: Round fixp2int conversion in lerp_u16
    7b67d2671481 ASoC: SOF: Intel: don't check number of sdw links when set dmic_fixup
    e5c9f8d2202d ASoC: dapm-graph: set fill colour of turned on nodes
    df2ae00d9605 fuse: don't truncate cached, mutated symlink
    c54e42985189 ASoC: tas2764: Set the SDOUT polarity correctly
    1769f5cb5395 ASoC: tas2764: Fix power control mask
    e43334e1dc09 ASoC: tas2770: Fix volume scale
    06d7337799dc phy: ti: gmii-sel: Do not use syscon helper to build regmap
    bfe7f298eedc nvme: only allow entering LIVE from CONNECTING state
    94e7476fa7c5 sctp: Fix undefined behavior in left shift operation
    7ece63c977c1 cifs: Treat unhandled directory name surrogate reparse points as mount directory nodes
    317fb015fe58 apple-nvme: Release power domains when probe fails
    1f07456a5a66 nvmet-rdma: recheck queue state is LIVE in state lock in recv done
    fd903dd30122 nvme-pci: quirk Acer FA100 for non-uniqueue identifiers
    b349a3d1b15e io-wq: backoff when retrying worker creation
    4fd9f51368a2 net: wwan: mhi_wwan_mbim: Silence sequence number glitch errors
    a14be80a82c8 ASoC: SOF: amd: Handle IPC replies before FW_BOOT_COMPLETE
    985c2c69a5e4 ASoC: SOF: amd: Add post_fw_run_delay ACP quirk
    eb49f80b8a6f ALSA: hda: hda-intel: add Panther Lake-H support
    458173e86d77 ASoC: SOF: Intel: pci-ptl: Add support for PTL-H
    c51c8ec76cfc ALSA: hda: intel-dsp-config: Add PTL-H support
    4ed43c26b7dc PCI: pci_ids: add INTEL_HDA_PTL_H
    8aac6256919d ASoC: SOF: Intel: hda: add softdep pre to snd-hda-codec-hdmi module
    5b27776a2beb ASoC: arizona/madera: use fsleep() in up/down DAPM event delays.
    f6eaaf1f5bcf ASoC: rsnd: adjust convert rate limitation
    6ff121ffe87c ASoC: rsnd: don't indicate warning on rsnd_kctrl_accept_runtime()
    e96e1000be20 ASoC: rsnd: indicate unsupported clock rate
    d44418f5024f ALSA: hda/realtek: Limit mic boost on Positivo ARN50
    a402f90da448 ASoC: simple-card-utils.c: add missing dlc->of_node
    c18fc7e6bbd0 ASoC: Intel: soc-acpi-intel-mtl-match: declare adr as ull
    ed05ae9a27c9 ASoC: Intel: sof_sdw: Add quirk for Asus Zenbook S14
    d5742c484f52 ASoC: Intel: sof_sdw: Add lookup of quirk using PCI subsystem ID
    45fb7e0d0cab selftests/bpf: Fix invalid flag of recv()
    02a12760d7c9 drm/tests: hdmi: Fix recursive locking
    b0f9bb67869d drm/tests: hdmi: Reorder DRM entities variables assignment
    9828d2f2a6ee drm/tests: hdmi: Remove redundant assignments
    f8094625a591 Bluetooth: L2CAP: Fix slab-use-after-free Read in l2cap_send_cmd
    2139811c3f79 Xen/swiotlb: mark xen_swiotlb_fixup() __init
    aa3b0ea4742a arm64: amu: Delay allocating cpumask for AMU FIE support
    8aa4c89378ed LoongArch: KVM: Set host with kernel mode when switch to VM mode
    f30b7b949ed8 LoongArch: Fix kernel_page_present() for KPRANGE/XKPRANGE
    a91922e9eab5 thermal/cpufreq_cooling: Remove structure member documentation
    e129f7291506 s390/cio: Fix CHPID "configure" attribute caching
    7e759fb01512 platform/x86: int3472: Call "reset" GPIO "enable" for INT347E
    515b17dcd4cf platform/x86: int3472: Use correct type for "polarity", call it gpio_flags
    f6ee81371e70 platform/x86: thinkpad_acpi: Support for V9 DYTC platform profiles
    f92324135f09 platform/x86: thinkpad_acpi: Fix invalid fan speed on ThinkPad X120e
    30a40b592594 sched: Clarify wake_up_q()'s write to task->wake_q.next
    c39bd0df25b4 objtool: Ignore dangling jump table entries
    d5ca39d3369a btrfs: fix two misuses of folio_shift()
    3ceaafa26f30 HID: apple: fix up the F6 key on the Omoton KB066 keyboard
    024d7e006aa4 HID: hid-apple: Apple Magic Keyboard a3203 USB-C support
    08fde0878480 selftests/cgroup: use bash in test_cpuset_v1_hp.sh
    fb019cf04211 HID: topre: Fix n-key rollover on Realforce R3S TKL boards
    2501c9ce2da7 HID: intel-ish-hid: ipc: Add Panther Lake PCI device IDs
    25736fe5893d usb: phy: generic: Use proper helper for property detection
    705f2515189c HID: hid-steam: Fix issues with disabling both gamepad mode and lizard mode
    6ca3d4d87af4 HID: ignore non-functional sensor in HP 5MP Camera
    3cef11955f29 HID: intel-ish-hid: Send clock sync message immediately after reset
    e9275a19e271 HID: intel-ish-hid: fix the length of MNG_SYNC_FW_CLOCK in doorbell
    05db4968d4bb sched_ext: selftests/dsp_local_on: Fix sporadic failures
    7963b379a37c selftests: always check mask returned by statmount(2)
    37e638d4cae4 vboxsf: fix building with GCC 15
    3b477a0296f4 alpha/elf: Fix misc/setarch test of util-linux by removing 32bit support
    ef35c36fb4f1 smb: client: fix noisy when tree connecting to DFS interlink targets
    61699cb2534f ACPI: resource: IRQ override for Eluktronics MECH-17
    af71ba921d08 scsi: qla1280: Fix kernel oops when debug level > 2
    3be04084517e scsi: ufs: core: Fix error return with query response
    1207e5d1a268 scsi: core: Use GFP_NOIO to avoid circular locking dependency
    36793d90d76f drm/amd/display: Fix out-of-bound accesses
    8bf1b5eeaf94 platform/x86/intel: pmc: fix ltr decode in pmc_core_ltr_show()
    20d6994b6f1f sched/debug: Provide slice length for fair tasks
    b253660fac5e iscsi_ibft: Fix UBSAN shift-out-of-bounds warning in ibft_attr_show_nic()
    aa189c394168 futex: Pass in task to futex_queue()
    fb51a7209398 btrfs: avoid starting new transaction when cleaning qgroup during subvolume drop
    ccdec7ea9a3d powercap: call put_device() on an error path in powercap_register_control_type()
    ae5716b4631f hrtimers: Mark is_migration_base() with __always_inline
    18bee525aa9a nvme-fc: do not ignore connectivity loss during connecting
    50ef04270048 nvme-fc: go straight to connecting state when initializing
    d6402fb37720 net/mlx5e: Prevent bridge link show failure for non-eswitch-allowed devices
    f7bf259a0427 net/mlx5: Bridge, fix the crash caused by LAG state check
    b22fae6a7aaf net/mlx5: Lag, Check shared fdb before creating MultiPort E-Switch
    4251e73182c3 net/mlx5: Fix incorrect IRQ pool usage when releasing IRQs
    5f634c972be8 net/mlx5: HWS, Rightsize bwc matcher priority
    9e79fdabd52c Revert "openvswitch: switch to per-action label counting in conntrack"
    e6610f9c08b4 net: openvswitch: remove misbehaving actions length check
    a4d42b590115 gre: Fix IPv6 link-local address generation.
    931681bc821f netfilter: nft_exthdr: fix offset with ipv4_find_option()
    5c3ca9cb48b5 net_sched: Prevent creation of classes with TC_H_ROOT
    e6cb63fac7fd ipvs: prevent integer overflow in do_ip_vs_get_ctl()
    db1e0c085682 netfilter: nf_conncount: Fully initialize struct nf_conncount_tuple in insert_tree()
    992a60cdfd9f rtase: Fix improper release of ring list entries in rtase_sw_reset
    247347fe0cdd selftests: bonding: fix incorrect mac address
    4cf224c45fe7 bonding: fix incorrect MAC address setting to receive NS messages
    5c47d5bfa7b0 net: mctp: unshare packets when reassembling
    a597d4b75669 net: switchdev: Convert blocking notification chain to a raw one
    187ef72a8438 eth: bnxt: fix memory leak in queue reset
    0997443906b9 bnxt_en: handle tpa_info in queue API implementation
    fa36f457eec3 bnxt_en: refactor tpa_info alloc/free into helpers
    f49bc4d7ff3d eth: bnxt: use page pool for head frags
    f059a0fd7330 eth: bnxt: fix kernel panic in the bnxt_get_queue_stats{rx | tx}
    5b57ed14a1b8 eth: bnxt: do not update checksum in bnxt_xdp_build_skb()
    a6604717850e eth: bnxt: do not use BNXT_VNIC_NTUPLE unconditionally in queue restart logic
    14eb5f0d6554 eth: bnxt: return fail if interface is down in bnxt_queue_mem_alloc()
    19107e71be33 eth: bnxt: fix truesize for mb-xdp-pass case
    1d34296409a5 net/mlx5: handle errors in mlx5_chains_create_table()
    102d02874911 Drivers: hv: vmbus: Don't release fb_mmio resource in vmbus_free_mmio()
    4545e2aa121a fbdev: hyperv_fb: Allow graceful removal of framebuffer
    ae833890703c fbdev: hyperv_fb: Simplify hvfb_putmem
    cfffe46a994a fbdev: hyperv_fb: Fix hang in kdump kernel when on Hyper-V Gen 2 VMs
    24f1bbfb2be7 drm/hyperv: Fix address space leak when Hyper-V DRM device is removed
    be7188d7f1f6 netpoll: hold rcu read lock in __netpoll_send_skb()
    caff87addf19 net: mctp i2c: Copy headers if cloned
    370dacb7edc2 net: mctp i3c: Copy headers if cloned
    956d8ef54a42 net: dsa: mv88e6xxx: Verify after ATU Load ops
    251841a71c4f net/mlx5: Fill out devlink dev info only for PFs
    55b098a2beec Revert "Bluetooth: hci_core: Fix sleeping function called from invalid context"
    0677a4f3c067 Bluetooth: hci_event: Fix enabling passive scanning
    a5158d67bff0 wifi: cfg80211: cancel wiphy_work before freeing wiphy
    83a73cb88f1d wifi: mac80211: don't queue sdata::work for a non-running sdata
    6114d2e6efda wifi: iwlwifi: mvm: fix PNVM timeout for non-MSI-X platforms
    68896dd50180 sched: address a potential NULL pointer dereference in the GRED scheduler.
    0befa32ac3f9 netfilter: nf_tables: make destruction work queue pernet
    a5396ee0f541 netfilter: nf_conncount: garbage collection is not skipped when jiffies wrap around
    198907fa1444 ice: Fix switchdev slow-path in LAG
    3b27e6e10a32 ice: fix memory leak in aRFS after reset
    44386eb2d9b7 ice: do not configure destination override for switchdev
    2231d7c821f3 netfilter: nft_ct: Use __refcount_inc() for per-CPU nft_ct_pcpu_template.
    a585f6ea42ec pinctrl: nuvoton: npcm8xx: Add NULL check in npcm8xx_gpio_fw
    319900a10835 pinctrl: bcm281xx: Fix incorrect regmap max_registers value
    ea8411db9fba fbdev: hyperv_fb: iounmap() the correct memory when removing a device
    99012b24ca23 userfaultfd: fix PTE unmapping stack-allocated PTE copies
    4e9507246298 mm: fix kernel BUG when userfaultfd_move encounters swapcache
    a74979dce9e9 mm/slab/kvfree_rcu: Switch to WQ_MEM_RECLAIM wq
    b2c792d89ac5 yaffs2: switch from readlink_copy() to vfs_readlink()
    807165b1ec1c tools/power/x86/intel-speed-select: Prefix header search path with sysroot
    e97df805b938 drm/tilcdc: Set preferred depth
    7160a4379dcc arch/arm64/configs: remove CONFIG_SM_DISPCC_8650
    6d8ac5ebe6e8 aufs6: core
    587abc1b64c4 aufs6: standalone
    1af41d30ef42 aufs6: mmap
    6ee2464d2e9d aufs6: base
    103b676505f7 aufs6: kbuild
    67281562943f qemux86: add configuration symbol to select values
    73f315ca0823 sched/isolation: really align nohz_full with rcu_nocbs
    1e4e7f8ab622 clear_warn_once: add a clear_warn_once= boot parameter
    918e7a825e8b clear_warn_once: bind a timer to written reset value
    f533f87c3758 clear_warn_once: expand debugfs to include read support
    f149ca27cba9 tools: Remove some options from CLANG_CROSS_FLAGS
    e633abe9c44e libbpf: Fix build warning on ref_ctr_off
    ec0916a4cfc1 perf: perf can not parser the backtrace of app in the 32bit system and 64bit kernel.
    03721ceb5626 perf: x86-32: explicitly include <errno.h>
    4c36c5295bb0 perf: mips64: Convert __u64 to unsigned long long
    b0200449610d perf: fix bench numa compilation
    aff0940b2212 perf: add SLANG_INC for slang.h
    ef912018d28c perf: add sgidefs.h to for mips builds
    d8860f858b87 perf: change --root to --prefix for python install
    dc38a0eee6e5 perf: add 'libperl not found' warning
    6ed51f8786da perf: force include of <stdbool.h>
    c538d4c4ac65 fat: Replace prandom_u32() with get_random_u32()
    63d94846f0c5 fat: don't use obsolete random32 call in namei_vfat
    7816667451ef FAT: Added FAT_NO_83NAME
    f81dbd60f0d5 FAT: Add CONFIG_VFAT_NO_CREATE_WITH_LONGNAMES option
    771cdefba44b FAT: Add CONFIG_VFAT_FS_NO_DUALNAMES option
    a24784fd8f88 yaffs2: update to v6.12 folio changes
    d0a48fd46db8 yaffs2: adapt to v6.10 i_time changes
    d097e4d4115a yaffs: fix mtime/itime field access
    4411e0d49fe3 yaffs2: update VFS ctime operations to 6.6+
    1b6619086e8b yaffs2: v6.5 fixups
    25b261ee3c54 yaffs2: Fix miscalculation of devname buffer length
    5c07936a5d1c yaffs2: convert user_namespace to mnt_idmap
    55986a1284b3 yaffs2: replace bdevname call with sprintf
    6f5508f8db8f yaffs2: convert read_page -> readfolio
    fd179a5df5d5 yaffs: replace IS_ERR with IS_ERR_OR_NULL to check both ERR and NULL
    c9a620dacdd1 yaffs: fix -Wstringop-overread compile warning in yaffs_fix_null_name
    78588208ed17 yaffs2: v5.12+ build fixups (not runtime tested)
    8d2dddba272c yaffs: include blkdev.h
    8c1ca9ef9712 yaffs: Fix build failure by handling inode i_version with proper atomic API
    27005cbac2ed yaffs2: v5.6 build fixups
    668211c9f9b7 yaffs2: fix memory leak when /proc/yaffs is read
    285f911dcc1c yaffs: add strict check when call yaffs_internal_read_super
    ffc2ed489ccf yaffs: repair yaffs_get_mtd_device
    6dce4b70a5e3 yaffs: Fix build failure by handling inode i_version with proper atomic API
    19f283abc5d1 yaffs2: fix memory leak in mount/umount
    04e84672b571 yaffs: Avoid setting any ACL releated xattr
    4f221d6a32e2 Yaffs:check oob size before auto selecting Yaffs1
    81f36004e56b fs: yaffs2: replace CURRENT_TIME by other appropriate apis
    26d7a3dd0054 yaffs2: adjust to proper location of MS_RDONLY
    a7016eac4540 yaffs2: import git revision b4ce1bb (jan, 2020)
    feb240bbb91e initramfs: allow an optional wrapper script around initramfs generation
    874746eaa341 drivers: gpu: drm: msm: registers: improve reproducibility
    1d42508faee8 tools: use basename to identify file in gen-mach-types
    4b055eca593d iwlwifi: select MAC80211_LEDS conditionally
    97e20e275ac0 net/dccp: make it depend on CONFIG_BROKEN (CVE-2020-16119)
    6dec58319165 defconfigs: drop obselete options
    a416ccb5b6c9 linux-yocto: Handle /bin/awk issues
    7efe8a1e5158 uvesafb: provide option to specify timeout for task completion
    78d10ae07eca uvesafb: print error message when task timeout occurs
    80473b7eb8ca compiler.h: Undef before redefining __attribute_const__
    ddeff2f1a9a7 vmware: include jiffies.h
    3dcdda8912b4 Resolve jiffies wrapping about arp
    3b1507db6735 nfs: Allow default io size to be configured.
    c2fedad05f77 check console device file on fs when booting
    208d6fbada3f mount_root: clarify error messages for when no rootfs found
    dbe9454c8ea0 mconf: fix output of cflags and libraries
    7c7b224f5cce menuconfig,mconf-cfg: Allow specification of ncurses location
    b6c189c81397 modpost: mask trivial warnings
    a5cc21325ba9 kbuild: exclude meta directory from distclean processing
    361ec143c23f powerpc: serialize image targets
    605e6ccb304c arm: serialize build targets
    e94b04fcb7d2 mtd_blkdevs: add mtd_table_mutex lock back to blktrans_{open, release} to avoid race condition
    44cc7f69a0a0 cpu/amd: inhibit SMP check for qemux86
    a08cb65331e6 x86_64_defconfig: Fix warnings
    8ad332ef777b mips: make current_cpu_data preempt safe
    754f05ddce3f mips: vdso: fix 'jalr $t9' crash in vdso code
    325ff78ff44d mips: Kconfig: add QEMUMIPS64 option
    99ae0eadcf11 4kc cache tlb hazard: tlbp cache coherency
    c6894c66a534 malta uhci quirks: make allowance for slow 4k(e)c
    8b52c01f3294 arm64: defconfig: remove CONFIG_IPQ_APSS_5018
    16c7629f035e drm/fb-helper: move zeroing code to drm_fb_helper_fill_var
    6b60c874cbb0 arm64: defconfig: cleanup config options
    8e44673ecd89 vexpress: Pass LOADADDR to Makefile
    f34e6805aad5 arm: ARM EABI socketcall
    94dec9b88de4 ARM: LPAE: Invalidate the TLB for module addresses during translation fault

(From OE-Core rev: dc1f7b326cd2aa8b074158e24af4ee41614cd459)

Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2025-04-23 19:48:04 +01:00
Bruce Ashfield
3408d70d2c linux-yocto/6.12: config: add pmem to genericarm64
Integrating the following commit(s) to linux-yocto/.:

1/1 [
    Author: Mikko Rapeli
    Email: mikko.rapeli@linaro.org
    Subject: genericarm64: add pmem feature and enable on genericarm64
    Date: Fri, 14 Mar 2025 11:48:34 +0200

    PMEM enables firmware to provide large memory block devices
    to the kernel. The firmware can download e.g. installer
    rootfs images to memory which kernel can then boot into.

    u-boot support has been added in
    https://lore.kernel.org/u-boot/20241203163605.1482152-2-sughosh.ganu@linaro.org/

    Signed-off-by: Mikko Rapeli <mikko.rapeli@linaro.org>
    Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
]

(From OE-Core rev: 15269f4ef08a5aa40e1794025a294ae66784a9e4)

Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2025-04-23 19:48:03 +01:00
Bruce Ashfield
8df460977d mips: Add '-std=gnu11' to vdso CFLAGS
Integrating the following commit(s) to linux-yocto/6.12:

1/1 [
    Author: Khem Raj
    Email: raj.khem@gmail.com
    Subject: mips: Add '-std=gnu11' to vdso CFLAGS
    Date: Wed, 26 Mar 2025 20:24:36 -0700

    GCC 15 changed the default C standard dialect from gnu17 to gnu23,
    which should not have impacted the kernel because it explicitly requests
    the gnu11 standard in the main Makefile. However, mips/vdso code uses
    its own CFLAGS without a '-std=' value, which break with this dialect
    change because of the kernel's own definitions of bool, false, and true
    conflicting with the C23 reserved keywords.

      include/linux/stddef.h:11:9: error: cannot use keyword 'false' as enumeration constant
         11 |         false   = 0,
            |         ^~~~~
      include/linux/stddef.h:11:9: note: 'false' is a keyword with '-std=c23' onwards
      include/linux/types.h:35:33: error: 'bool' cannot be defined via 'typedef'
         35 | typedef _Bool                   bool;
            |                                 ^~~~
      include/linux/types.h:35:33: note: 'bool' is a keyword with '-std=c23' onwards

    Add '-std=gnu11' to the decompressor and purgatory CFLAGS to eliminate
    these errors and make the C standard version of these areas match the
    rest of the kernel.

    Signed-off-by: Khem Raj <raj.khem@gmail.com>
    Cc: stable@vger.kernel.org
    Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
]

(From OE-Core rev: 832657740c76c63b2e2e9229eb3934c04a5d5ca1)

Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2025-04-23 19:48:03 +01:00
Antonin Godard
fdf0ab1370 Fix dead links that use the DISTRO macro
After introducing the DISTRO_LATEST_TAG and DISTRO_REL_LATEST_TAG
macros, use them in links that currently use DISTRO/DISTRO_REL_TAG. When
building for the tip of a branch, this will replace the current A.B.999
in links to the latest existing tag.

The links were found across the documentation by running 'grep -r
"http.*5\.2\.999"' inside the _build/html output after building the
docs.

[YOCTO #14802]

(From yocto-docs rev: 29be069ebbf2c55d72fc51d99ed5a558af37c05e)

Signed-off-by: Antonin Godard <antonin.godard@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2025-04-21 21:17:02 +01:00
Antonin Godard
5c4cf4b573 poky.yaml: introduce DISTRO_LATEST_TAG
Introduce the DISTRO_LATEST_TAG macro, which should always point to the
latest existing tag in the documentation, unlike DISTRO which may point
to A.B.999 to represent the tip of a branch.

This variable is needed to fix dead links in the documentation that
currently use the DISTRO macro.

Also, make DISTRO_REL_TAG use the DISTRO macro directly, to avoid
repetition, and add a DISTRO_REL_LATEST_TAG macro that has the same role
as DISTRO_LATEST_TAG but with "yocto-" prepended to it.

In set_versions.py, run the "git describe --abbrev=0 --tags
--match='yocto-*'" command to get the latest existing tag on the
currently checked out commit. Fallback to ourversion in case we didn't
find any.

(From yocto-docs rev: a85b0e500c94921f77fa7b7dbb877e4945f96d1e)

Signed-off-by: Antonin Godard <antonin.godard@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2025-04-21 21:17:02 +01:00
Andrew Kreimer
e5577538c3 manuals: remove repeated word
The word "modern" appears twice, remove the extra one.

(From yocto-docs rev: 8a2169431551ea29bf45b2eb120a13f0e444e1ea)

Signed-off-by: Andrew Kreimer <algonell@gmail.com>
Signed-off-by: Antonin Godard <antonin.godard@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2025-04-21 21:17:02 +01:00
Antonin Godard
90e4af3eff migration-guides/{migration,release-note}-5.2: update for 5.2 release
Document changes between 1c3020f173 ("expat: Upgrade 2.7.0 -> 2.7.1")
up to e894acce6e ("build-appliance-image: Update to master head
revision") in Poky:

- Add a note on the devtool upgrade-status change.
- Be more precise about the usage of multiple repositories in SRC_URI,
  mention that it makes sense for bare clones only.

As the walnascar branch has now frozen and is up for QA, these should be
the one of the last changes to these documents.

(From yocto-docs rev: 322355ead2be9e267368ca47d805f41ae10ad6cc)

Signed-off-by: Antonin Godard <antonin.godard@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2025-04-21 21:17:02 +01:00
Antonin Godard
15a7d7b881 ref-manual/variables.rst: improve the PKGV documentation
It may be confusing for users that source control information is not
present in the BitBake environment. Document it as a warning block.

(From yocto-docs rev: 39967b9cc87cf216c4658598806fd7a68db5053a)

Signed-off-by: Antonin Godard <antonin.godard@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2025-04-21 21:17:02 +01:00
Peter Marko
39cbc37918 cve-update-nvd2-native: add workaround for json5 style list
NVD responses changed to an invalid json between:
* April 5, 2025 at 3:03:44 AM GMT+2
* April 5, 2025 at 4:19:48 AM GMT+2

The last response is since then in format
{
  "resultsPerPage": 625,
  "startIndex": 288000,
  "totalResults": 288625,
  "format": "NVD_CVE",
  "version": "2.0",
  "timestamp": "2025-04-07T07:17:17.534",
  "vulnerabilities": [
    {...},
    ...
    {...},
  ]
}

Json does not allow trailing , in responses, that is json5 format.
So cve-update-nvd2-native do_Fetch task fails with log backtrace ending:

...
File: '/builds/ccp/meta-siemens/projects/ccp/../../poky/meta/recipes-core/meta/cve-update-nvd2-native.bb', lineno: 234, function: update_db_file
     0230:            if raw_data is None:
     0231:                # We haven't managed to download data
     0232:                return False
     0233:
 *** 0234:            data = json.loads(raw_data)
     0235:
     0236:            index = data["startIndex"]
     0237:            total = data["totalResults"]
     0238:            per_page = data["resultsPerPage"]
...
File: '/usr/lib/python3.11/json/decoder.py', lineno: 355, function: raw_decode
     0351:        """
     0352:        try:
     0353:            obj, end = self.scan_once(s, idx)
     0354:        except StopIteration as err:
 *** 0355:            raise JSONDecodeError("Expecting value", s, err.value) from None
     0356:        return obj, end
Exception: json.decoder.JSONDecodeError: Expecting value: line 1 column 1442633 (char 1442632)
...

There was no announcement about json format of API v2.0 by nvd.
Also this happens only if whole database is queried (database update is
fine, even when multiple pages as queried).
And lastly it's only the cve list, all other lists inside are fine.
So this looks like a bug in NVD 2.0 introduced with some update.

Patch this with simple character deletion for now and let's monitor the
situation and possibly switch to json5 in the future.
Note that there is no native json5 support in python, we'd have to use
one of external libraries for it.

(From OE-Core rev: 131d983dd19ae12bf0746f772b7d7a058e549fb1)

Signed-off-by: Peter Marko <peter.marko@siemens.com>
Signed-off-by: Mathieu Dubois-Briand <mathieu.dubois-briand@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2025-04-10 11:53:36 +01:00
Lee Chee Yang
9f9e7bbace migration-guides: add release notes for 5.0.8
(From yocto-docs rev: 3b50193fa0c9acf4a601aeae6e1c78d0e4a05aef)

Signed-off-by: Lee Chee Yang <chee.yang.lee@intel.com>
Signed-off-by: Antonin Godard <antonin.godard@bootlin.com>
(cherry picked from commit 7494df521ed9c70e877dbdef1adfe38ad717682f)
Signed-off-by: Antonin Godard <antonin.godard@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2025-04-03 16:29:51 +01:00
Lee Chee Yang
539ce63c81 migration-guides: add release notes for 5.1.4
(From yocto-docs rev: 4602e6b42118e7fbd3b6aa07782779047d209bb0)

Signed-off-by: Lee Chee Yang <chee.yang.lee@intel.com>
Signed-off-by: Antonin Godard <antonin.godard@bootlin.com>
(cherry picked from commit f7c8fdfdfef0cac529594af5bdb72e53b29262fe)
Signed-off-by: Antonin Godard <antonin.godard@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2025-04-03 16:29:51 +01:00
Antonin Godard
43d807650a ref-manual/variables.rst: HOST_CC_ARCH: fix wrong SDK reference
When building for nativesdk recipes, HOST_CC_ARCH equals SDK_CC_ARCH,
not BUILDSDK_CC_ARCH which doesn't exist.

Reviewed-by: Quentin Schulz <quentin.schulz@cherry.de>
(From yocto-docs rev: a4a8aca22bb854756eb2ed1e652331bec3c7c68e)

Signed-off-by: Antonin Godard <antonin.godard@bootlin.com>
(cherry picked from commit 08fc3446cb13b5bd8781874d2d996899ce12b082)
Signed-off-by: Antonin Godard <antonin.godard@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2025-04-03 16:29:51 +01:00
Antonin Godard
949c0bb2f5 ref-manual/variables.rst: document HOST_*_ARCH variables
These variables control the flags for the assembler, compiler and
linker, but depend on the context.

Reviewed-by: Quentin Schulz <quentin.schulz@cherry.de>
(From yocto-docs rev: 8f070b788c9cd6cc16e03505d978177b4c82de03)

Signed-off-by: Antonin Godard <antonin.godard@bootlin.com>
(cherry picked from commit f8eb33569a5e8cadc036855e2d95eee77e627cb4)
Signed-off-by: Antonin Godard <antonin.godard@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2025-04-03 16:29:51 +01:00
Antonin Godard
0c32303252 ref-manual/variables.rst: document missing SDK_*_ARCH variables
These variables control the flags for the assembler, compiler and linker
when building for nativesdk recipes.

Reviewed-by: Quentin Schulz <quentin.schulz@cherry.de>
(From yocto-docs rev: 978300e5f14874f2586efa3474c6f3803e3d9031)

Signed-off-by: Antonin Godard <antonin.godard@bootlin.com>
(cherry picked from commit c08f6d3c8aee86264c069b7c30850cb02de76076)
Signed-off-by: Antonin Godard <antonin.godard@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2025-04-03 16:29:51 +01:00
Antonin Godard
ecacb6015a ref-manual/variables.rst: add missing documentation for BUILD_* variables
These toolchain variables are used in a native context. Some of the
BUILD_* variables missed documentation. Also, some of the base commands
were also not there so document them.

Some of existing BUILD_* variable documentation were missing the note
about their usage in a native context, so add it too so that all BUILD_*
variables are documented the same way.

[YOCTO #15719]

Reviewed-by: Quentin Schulz <quentin.schulz@cherry.de>
(From yocto-docs rev: e42d49218945a030f300dbb608e7cfb0611f5733)

Signed-off-by: Antonin Godard <antonin.godard@bootlin.com>
(cherry picked from commit 87103afa1cb6690e9aaa87ca1f23e45eaaa359ac)
Signed-off-by: Antonin Godard <antonin.godard@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2025-04-03 16:29:51 +01:00
Antonin Godard
0990fceebe ref-manual/variables.rst: add manpage links for toolchain variables
Use the :manpage: role to provide links to common toolchain utilities.

Reviewed-by: Quentin Schulz <quentin.schulz@cherry.de>
(From yocto-docs rev: 8a25963c8dfc36482582294f0d2e7c7555d96399)

Signed-off-by: Antonin Godard <antonin.godard@bootlin.com>
(cherry picked from commit 7023e5f176efde05a6798476712c8a4e006a6b0d)
Signed-off-by: Antonin Godard <antonin.godard@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2025-04-03 16:29:51 +01:00
Antonin Godard
6b2bc1e4cb documentation/conf.py: define a manpage url
By defining the manpages_url we can use the :manpage: role in the
documentation for providing links to manpages. See:
https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-manpages_url

Replace existing manpages links to use this role.

Reviewed-by: Quentin Schulz <quentin.schulz@cherry.de>
(From yocto-docs rev: 0d0115cb2d96960837678f775cf5c2297494c51c)

Signed-off-by: Antonin Godard <antonin.godard@bootlin.com>
(cherry picked from commit 4e63cd74cd1a330ea5e96bb04243a90f607b2857)
Signed-off-by: Antonin Godard <antonin.godard@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2025-04-03 16:29:51 +01:00
Antonin Godard
5ec826fa2e migration-guides/{migration,release-note}-5.2: improvements and fixes
Address some of the reviews received on the release notes and migration
guide for 5.2:

- Remove the wget fetcher addition, I misread commit 0a9f90ff658e
  ("tests/fetch: support setting PV in the wget fetcher") from BitBake,
  and it actually affects the tests for the wget fetcher, not the
  fetcher itself.
- Add a way to transition from the branch=nameX,nameY syntax. From what
  I have tested, I achieve the same behavior when using one or the other
  syntax.
- Remove the default value for SPDX_PACKAGE_VERSION in the release note.
- Fix a couple of typos.

Suggested-by: Quentin Schulz <quentin.schulz@cherry.de>
(From yocto-docs rev: 39bf43a6009a46d4979337d7401eb46ece618f67)

Signed-off-by: Antonin Godard <antonin.godard@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2025-04-03 16:29:51 +01:00
Antonin Godard
a287584563 ref-manual/classes: ptest-python-pytest: improve the current documentation
Improve the current ptest-python-pytest documentation and
PTEST_PYTEST_DIR variable definition. Namely remove the default value
that may evolve over time.

Suggested-by: Quentin Schulz <quentin.schulz@cherry.de>
(From yocto-docs rev: a83406103ca73d84fc8f5c50a8968faf91276a62)

Signed-off-by: Antonin Godard <antonin.godard@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2025-04-03 16:29:51 +01:00
5829 changed files with 736095 additions and 114 deletions

4
.b4-config Normal file
View File

@@ -0,0 +1,4 @@
[b4]
prep-perpatch-check-cmd = ./scripts/b4-wrapper-poky.py prep-perpatch-check-cmd
send-auto-cc-cmd = ./scripts/b4-wrapper-poky.py send-auto-cc-cmd
send-auto-to-cmd = ./scripts/b4-wrapper-poky.py send-auto-to-cmd

2
.templateconf Normal file
View File

@@ -0,0 +1,2 @@
# Template settings
TEMPLATECONF=${TEMPLATECONF:-meta-poky/conf/templates/default}

20
LICENSE Normal file
View File

@@ -0,0 +1,20 @@
Different components of OpenEmbedded are under different licenses (a mix
of MIT and GPLv2). See LICENSE.GPL-2.0-only and LICENSE.MIT for further
details of the individual licenses.
All metadata is MIT licensed unless otherwise stated. Source code
included in tree for individual recipes (e.g. patches) are under
the LICENSE stated in the associated recipe (.bb file) unless
otherwise stated.
License information for any other files is either explicitly stated
or defaults to GPL version 2 only.
Individual files contain the following style tags instead of the full license
text to identify their license:
SPDX-License-Identifier: GPL-2.0-only
SPDX-License-Identifier: MIT
This enables machine processing of license information based on the SPDX
License Identifiers that are here available: http://spdx.org/licenses/

288
LICENSE.GPL-2.0-only Normal file
View File

@@ -0,0 +1,288 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Note:
Individual files contain the following tag instead of the full license text.
SPDX-License-Identifier: GPL-2.0-only
This enables machine processing of license information based on the SPDX
License Identifiers that are here available: http://spdx.org/licenses/

25
LICENSE.MIT Normal file
View File

@@ -0,0 +1,25 @@
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Note:
Individual files contain the following tag instead of the full license text.
SPDX-License-Identifier: MIT
This enables machine processing of license information based on the SPDX
License Identifiers that are here available: http://spdx.org/licenses/

69
MAINTAINERS.md Normal file
View File

@@ -0,0 +1,69 @@
OpenEmbedded-Core and Yocto Project Maintainer Information
==========================================================
OpenEmbedded and Yocto Project work jointly together to maintain the metadata,
layers, tools and sub-projects that make up their ecosystems.
The projects operate through collaborative development. This currently takes
place on mailing lists for many components as the "pull request on github"
workflow works well for single or small numbers of maintainers but we have
a large number, all with different specialisms and benefit from the mailing
list review process. Changes therefore undergo peer review through mailing
lists in many cases.
This file aims to acknowledge people with specific skills/knowledge/interest
both to recognise their contributions but also empower them to help lead and
curate those components. Where we have people with specialist knowledge in
particular areas, during review patches/feedback from these people in these
areas would generally carry weight.
This file is maintained in OE-Core but may refer to components that are separate
to it if that makes sense in the context of maintainership. The README of specific
layers and components should ultimately be definitive about the patch process and
maintainership for the component.
Recipe Maintainers
------------------
See meta/conf/distro/include/maintainers.inc
Component/Subsystem Maintainers
-------------------------------
* Kernel (inc. linux-yocto, perf): Bruce Ashfield
* Reproducible Builds: Joshua Watt
* Toaster: David Reyna
* Hash-Equivalence: Joshua Watt
* Recipe upgrade infrastructure: Alex Kanavin
* Toolchain: Khem Raj
* ptest-runner: Aníbal Limón
* opkg: Alex Stewart
* devtool: Saul Wold
* eSDK: Saul Wold
* overlayfs: Vyacheslav Yurkov
* Patchtest: Trevor Gamblin
Maintainers needed
------------------
* Pseudo
* Layer Index
* recipetool
* QA framework/automated testing
* error reporting system/web UI
* wic
* Patchwork
* Matchbox
* Sato
* Autobuilder
Layer Maintainers needed
------------------------
* meta-gplv2 (ideally new strategy but active maintainer welcome)
Shadow maintainers/development needed
--------------------------------------
* toaster
* bitbake

5
MEMORIAM Normal file
View File

@@ -0,0 +1,5 @@
Some project contributors who are sadly no longer with us:
Greg Gilbert (treke) - Ahead of his time with licensing
Thomas Wood (thos) - Creator of the original sato
Scott Rifenbark (scottrif) - Our long standing techwriter whose words live on

114
README
View File

@@ -1,114 +0,0 @@
The poky repository master branch is no longer being updated.
You can either:
a) switch to individual clones of bitbake, openembedded-core, meta-yocto and yocto-docs
https://docs.yoctoproject.org/dev/dev-manual/poky-manual-setup.html
b) use the new bitbake-setup
https://docs.yoctoproject.org/bitbake/dev/bitbake-user-manual/bitbake-user-manual-environment-setup.html
You can find more information in our documentation: https://docs.yoctoproject.org/
Note that "poky" the distro setting is still available in meta-yocto as
before and we continue to use and maintain that.
Long live Poky!
Some further information on the background of this change follows. The
details are taken from:
https://lists.openembedded.org/g/openembedded-architecture/message/2179
TLDR: People have complained about the combo-layer built poky
repository for years. It was meant to be a temporary thing, we now have
an alternative and I'm therefore doing what I promised I'd do. Change
is tough, things may break but this is the right point to at least try
it.
I'd like to note that:
* setting up builds with a separate oe-core and bitbake clone
works as it always has done
* you can change your CI just to use those two repos instead of poky
* bitbake-setup isn't mandatory, it will just be what the yocto-
docs presents to users
* we don't have to stop maintaining the poky repository
however nobody will test the new approach/code unless we do
* we are optionally exposing sstate mirrors in the new config
* we are also exposing config fragments to users
* poky as a DISTRO in meta-yocto remains
A bit more about the history and background for those who are
interested and then some FAQs:
Back around 2010 when we split up openembedded-classic and started
developing layers, we made the artificial "poky" repository construct
as a way to let people easily and quickly get started with the project.
without cloning and managing multiple repositories. Layers were a new
idea with lots of rough edges. kas didn't exist, I think repo was only
just created and it was a different world. For us, it meant hacking up
a quick tool, "combo-layer" and it was really a temporary solution to
fill a gap and it was at least as functional as repo of the era. It was
assumed we'd work it out properly in the future.
At developer meetings there are inevitable questions about why
poky/combo-layer exist and few seem to actually like/support it. There
are continual questions about why a tool doesn't exist or why we don't
adopt one too.
15 years later, a bit longer than we might have thought, we are finally
in a position where there may be a viable way forward to change.
It has taken us a bit of time to get to this point. I wrote the
original description of something like bitbake-setup about 7-8 years
ago. I shared it privately with a few people, the review feedback
stopped me pushing it further as I simply did not have the bandwidth.
We were fortunate to get funding from the Sovereign Tech Fund to start
the work and whilst I'd probably prefer to avoid the issue, the time
had come to start. Since then, Alexander Kanavin has put a lot of work
into getting it to the point where it would be possible to switch. A
huge thanks to him for getting this to the current point.
Why not use kas/submodules/repo?
This topic has been discussed in depth several times. Very roughly,
these are either difficult to focus on our use cases or have specific
designs and intent which we as a project would struggle to influence.
We are taking significant influence from some of them but also trying
to build something where we can benefit from tight direct integration
with bitbake and the metadata. For example fragment support is generic
and hopefully something other approaches can also benefit from. We want
to provide something we can switch the projects docs and autobuilder to
which we can control and develop as we need it to. We are not aiming to
force anyone to switch, you can use whichever tool you want.
Can we not keep poky [repository master branch] around?
If we do that, nobody will use the new tooling and it will be a
disaster as issues won't get resolved. We need our CI to use the same
thing we promote to our new and experienced users. We need this new
tooling to be usable by our experienced developers too. We have tried
for months to get people to try it and they simply don't. Making a
release with it won't change much either. It needs people using it and
for that, poky has to stop being updated.
What happens to poky [repository]?
The LTS branches continue their lifetime as planned. For master, I'll
probably put a final commit in changing to just a README which points
people at the bitbake-setup changes and explains what happened.
What are the timelines? Why now?
If we're going to make a change, we really want this in the next LTS
release, which is April 2026. We only have one release before that
which is now, October 2025. We therefore need to switch now, and then
give us time to update docs, fix issues that arise and so on and have
it in a release cycle. Whilst it means delaying the Oct 2025 release
slightly, that is the right thing to do in the context of the bigger
picture.

32
README.OE-Core.md Normal file
View File

@@ -0,0 +1,32 @@
OpenEmbedded-Core
=================
OpenEmbedded-Core is a layer containing the core metadata for current versions
of OpenEmbedded. It is distro-less (can build a functional image with
DISTRO = "nodistro") and contains only emulated machine support.
For information about OpenEmbedded, see the OpenEmbedded website:
<https://www.openembedded.org/>
The Yocto Project has extensive documentation about OE including a reference manual
which can be found at:
<https://docs.yoctoproject.org/>
Contributing
------------
Please refer to our contributor guide here: <https://docs.yoctoproject.org/dev/contributor-guide/>
for full details on how to submit changes.
As a quick guide, patches should be sent to openembedded-core@lists.openembedded.org
The git command to do that would be:
```
git send-email -M -1 --to openembedded-core@lists.openembedded.org
```
Mailing list:
<https://lists.openembedded.org/g/openembedded-core>
Source code:
<https://git.openembedded.org/openembedded-core/>

1
README.hardware.md Symbolic link
View File

@@ -0,0 +1 @@
meta-yocto-bsp/README.hardware.md

1
README.md Symbolic link
View File

@@ -0,0 +1 @@
README.poky.md

1
README.poky.md Symbolic link
View File

@@ -0,0 +1 @@
meta-poky/README.poky.md

15
README.qemu.md Normal file
View File

@@ -0,0 +1,15 @@
QEMU Emulation Targets
======================
To simplify development, the build system supports building images to
work with the QEMU emulator in system emulation mode. Several architectures
are currently supported in 32 and 64 bit variants:
* ARM (qemuarm + qemuarm64)
* x86 (qemux86 + qemux86-64)
* PowerPC (qemuppc only)
* MIPS (qemumips + qemumips64)
Use of the QEMU images is covered in the Yocto Project Reference Manual.
The appropriate MACHINE variable value corresponding to the target is given
in brackets.

22
SECURITY.md Normal file
View File

@@ -0,0 +1,22 @@
How to Report a Potential Vulnerability
=======================================
If you would like to report a public issue (for example, one with a released
CVE number), please report it using the
[Security Bugzilla](https://bugzilla.yoctoproject.org/enter_bug.cgi?product=Security)
If you are dealing with a not-yet released or urgent issue, please send a
message to security AT yoctoproject DOT org, including as many details as
possible: the layer or software module affected, the recipe and its version,
and any example code, if available.
Branches maintained with security fixes
---------------------------------------
See [Stable release and LTS](https://wiki.yoctoproject.org/wiki/Stable_Release_and_LTS)
for detailed info regarding the policies and maintenance of Stable branches.
The [Release page](https://wiki.yoctoproject.org/wiki/Releases) contains
a list of all releases of the Yocto Project. Versions in grey are no longer
actively maintained with security patches, but well-tested patches may still
be accepted for them for significant issues.

4
bitbake/.b4-config Normal file
View File

@@ -0,0 +1,4 @@
[b4]
send-series-to = bitbake-devel@lists.openembedded.org
send-auto-cc-cmd = ./contrib/b4-wrapper-bitbake.py send-auto-cc-cmd
prep-pre-flight-checks = disable-needs-checking

2
bitbake/.gitattributes vendored Normal file
View File

@@ -0,0 +1,2 @@
*min.js binary
*min.css binary

10
bitbake/AUTHORS Normal file
View File

@@ -0,0 +1,10 @@
Tim Ansell <mithro@mithis.net>
Phil Blundell <pb@handhelds.org>
Seb Frankengul <seb@frankengul.org>
Holger Freyther <holger@moiji-mobile.com>
Marcin Juszkiewicz <marcin@juszkiewicz.com.pl>
Chris Larson <kergoth@handhelds.org>
Ulrich Luckas <luckas@musoft.de>
Mickey Lauer <mickey@Vanille.de>
Richard Purdie <rpurdie@rpsys.net>
Holger Schurig <holgerschurig@gmx.de>

317
bitbake/ChangeLog Normal file
View File

@@ -0,0 +1,317 @@
Changes in Bitbake 1.9.x:
- Add PE (Package Epoch) support from Philipp Zabel (pH5)
- Treat python functions the same as shell functions for logging
- Use TMPDIR/anonfunc as a __anonfunc temp directory (T)
- Catch truncated cache file errors
- Allow operations other than assignment on flag variables
- Add code to handle inter-task dependencies
- Fix cache errors when generation dotGraphs
- Make sure __inherit_cache is updated before calling include() (from Michael Krelin)
- Fix bug when target was in ASSUME_PROVIDED (#2236)
- Raise ParseError for filenames with multiple underscores instead of infinitely looping (#2062)
- Fix invalid regexp in BBMASK error handling (missing import) (#1124)
- Promote certain warnings from debug to note 2 level
- Update manual
- Correctly redirect stdin when forking
- If parsing errors are found, exit, too many users miss the errors
- Remove supriours PREFERRED_PROVIDER warnings
- svn fetcher: Add _buildsvncommand function
- Improve certain error messages
- Rewrite svn fetcher to make adding extra operations easier
as part of future SRCDATE="now" fixes
(requires new FETCHCMD_svn definition in bitbake.conf)
- Change SVNDIR layout to be more unique (fixes #2644 and #2624)
- Add ConfigParsed Event after configuration parsing is complete
- Add SRCREV support for svn fetcher
- data.emit_var() - only call getVar if we need the variable
- Stop generating the A variable (seems to be legacy code)
- Make sure intertask depends get processed correcting in recursive depends
- Add pn-PN to overrides when evaluating PREFERRED_VERSION
- Improve the progress indicator by skipping tasks that have
already run before starting the build rather than during it
- Add profiling option (-P)
- Add BB_SRCREV_POLICY variable (clear or cache) to control SRCREV cache
- Add SRCREV_FORMAT support
- Fix local fetcher's localpath return values
- Apply OVERRIDES before performing immediate expansions
- Allow the -b -e option combination to take regular expressions
- Fix handling of variables with expansion in the name using _append/_prepend
e.g. RRECOMMENDS_${PN}_append_xyz = "abc"
- Add plain message function to bb.msg
- Sort the list of providers before processing so dependency problems are
reproducible rather than effectively random
- Fix/improve bitbake -s output
- Add locking for fetchers so only one tries to fetch a given file at a given time
- Fix int(0)/None confusion in runqueue.py which causes random gaps in dependency chains
- Expand data in addtasks
- Print the list of missing DEPENDS,RDEPENDS for the "No buildable providers available for required...."
error message.
- Rework add_task to be more efficient (6% speedup, 7% number of function calls reduction)
- Sort digraph output to make builds more reproducible
- Split expandKeys into two for loops to benefit from the expand_cache (12% speedup)
- runqueue.py: Fix idepends handling to avoid dependency errors
- Clear the terminal TOSTOP flag if set (and warn the user)
- Fix regression from r653 and make SRCDATE/CVSDATE work for packages again
- Fix a bug in bb.decodeurl where http://some.where.com/somefile.tgz decoded to host="" (#1530)
- Warn about malformed PREFERRED_PROVIDERS (#1072)
- Add support for BB_NICE_LEVEL option (#1627)
- Psyco is used only on x86 as there is no support for other architectures.
- Sort initial providers list by default preference (#1145, #2024)
- Improve provider sorting so prefered versions have preference over latest versions (#768)
- Detect builds of tasks with overlapping providers and warn (will become a fatal error) (#1359)
- Add MULTI_PROVIDER_WHITELIST variable to allow known safe multiple providers to be listed
- Handle paths in svn fetcher module parameter
- Support the syntax "export VARIABLE"
- Add bzr fetcher
- Add support for cleaning directories before a task in the form:
do_taskname[cleandirs] = "dir"
- bzr fetcher tweaks from Robert Schuster (#2913)
- Add mercurial (hg) fetcher from Robert Schuster (#2913)
- Don't add duplicates to BBPATH
- Fix preferred_version return values (providers.py)
- Fix 'depends' flag splitting
- Fix unexport handling (#3135)
- Add bb.copyfile function similar to bb.movefile (and improve movefile error reporting)
- Allow multiple options for deptask flag
- Use git-fetch instead of git-pull removing any need for merges when
fetching (we don't care about the index). Fixes fetch errors.
- Add BB_GENERATE_MIRROR_TARBALLS option, set to 0 to make git fetches
faster at the expense of not creating mirror tarballs.
- SRCREV handling updates, improvements and fixes from Poky
- Add bb.utils.lockfile() and bb.utils.unlockfile() from Poky
- Add support for task selfstamp and lockfiles flags
- Disable task number acceleration since it can allow the tasks to run
out of sequence
- Improve runqueue code comments
- Add task scheduler abstraction and some example schedulers
- Improve circular dependency chain debugging code and user feedback
- Don't give a stacktrace for invalid tasks, have a user friendly message (#3431)
- Add support for "-e target" (#3432)
- Fix shell showdata command (#3259)
- Fix shell data updating problems (#1880)
- Properly raise errors for invalid source URI protocols
- Change the wget fetcher failure handling to avoid lockfile problems
- Add support for branches in git fetcher (Otavio Salvador, Michael Lauer)
- Make taskdata and runqueue errors more user friendly
- Add norecurse and fullpath options to cvs fetcher
- Fix exit code for build failures in --continue mode
- Fix git branch tags fetching
- Change parseConfigurationFile so it works on real data, not a copy
- Handle 'base' inherit and all other INHERITs from parseConfigurationFile
instead of BBHandler
- Fix getVarFlags bug in data_smart
- Optmise cache handling by more quickly detecting an invalid cache, only
saving the cache when its changed, moving the cache validity check into
the parsing loop and factoring some getVar calls outside a for loop
- Cooker: Remove a debug message from the parsing loop to lower overhead
- Convert build.py exec_task to use getVarFlags
- Update shell to use cooker.buildFile
- Add StampUpdate event
- Convert -b option to use taskdata/runqueue
- Remove digraph and switch to new stamp checking code. exec_task no longer
honours dependencies
- Make fetcher timestamp updating non-fatal when permissions don't allow
updates
- Add BB_SCHEDULER variable/option ("completion" or "speed") controlling
the way bitbake schedules tasks
- Add BB_STAMP_POLICY variable/option ("perfile" or "full") controlling
how extensively stamps are looked at for validity
- When handling build target failures make sure idepends are checked and
failed where needed. Fixes --continue mode crashes.
- Fix -f (force) in conjunction with -b
- Fix problems with recrdeptask handling where some idepends weren't handled
correctly.
- Handle exit codes correctly (from pH5)
- Work around refs/HEAD issues with git over http (#3410)
- Add proxy support to the CVS fetcher (from Cyril Chemparathy)
- Improve runfetchcmd so errors are seen and various GIT variables are exported
- Add ability to fetchers to check URL validity without downloading
- Improve runtime PREFERRED_PROVIDERS warning message
- Add BB_STAMP_WHITELIST option which contains a list of stamps to ignore when
checking stamp dependencies and using a BB_STAMP_POLICY of "whitelist"
- No longer weight providers on the basis of a package being "already staged". This
leads to builds being non-deterministic.
- Flush stdout/stderr before forking to fix duplicate console output
- Make sure recrdeps tasks include all inter-task dependencies of a given fn
- Add bb.runqueue.check_stamp_fn() for use by packaged-staging
- Add PERSISTENT_DIR to store the PersistData in a persistent
directory != the cache dir.
- Add md5 and sha256 checksum generation functions to utils.py
- Correctly handle '-' characters in class names (#2958)
- Make sure expandKeys has been called on the data dictionary before running tasks
- Correctly add a task override in the form task-TASKNAME.
- Revert the '-' character fix in class names since it breaks things
- When a regexp fails to compile for PACKAGES_DYNAMIC, print a more useful error (#4444)
- Allow to checkout CVS by Date and Time. Just add HHmm to the SRCDATE.
- Move prunedir function to utils.py and add explode_dep_versions function
- Raise an exception if SRCREV == 'INVALID'
- Fix hg fetcher username/password handling and fix crash
- Fix PACKAGES_DYNAMIC handling of packages with '++' in the name
- Rename __depends to __base_depends after configuration parsing so we don't
recheck the validity of the config files time after time
- Add better environmental variable handling. By default it will now only pass certain
whitelisted variables into the data store. If BB_PRESERVE_ENV is set bitbake will use
all variable from the environment. If BB_ENV_WHITELIST is set, that whitelist will be
used instead of the internal bitbake one. Alternatively, BB_ENV_EXTRAWHITE can be used
to extend the internal whitelist.
- Perforce fetcher fix to use commandline options instead of being overriden by the environment
- bb.utils.prunedir can cope with symlinks to directoriees without exceptions
- use @rev when doing a svn checkout
- Add osc fetcher (from Joshua Lock in Poky)
- When SRCREV autorevisioning for a recipe is in use, don't cache the recipe
- Add tryaltconfigs option to control whether bitbake trys using alternative providers
to fulfil failed dependencies. It defaults to off, changing the default since this
behaviour confuses many users and isn't often useful.
- Improve lock file function error handling
- Add username handling to the git fetcher (Robert Bragg)
- Add support for HTTP_PROXY and HTTP_PROXY_IGNORE variables to the wget fetcher
- Export more variables to the fetcher commands to allow ssh checkouts and checkouts through
proxies to work better. (from Poky)
- Also allow user and pswd options in SRC_URIs globally (from Poky)
- Improve proxy handling when using mirrors (from Poky)
- Add bb.utils.prune_suffix function
- Fix hg checkouts of specific revisions (from Poky)
- Fix wget fetching of urls with parameters specified (from Poky)
- Add username handling to git fetcher (from Poky)
- Set HOME environmental variable when running fetcher commands (from Poky)
- Make sure allowed variables inherited from the environment are exported again (from Poky)
- When running a stage task in bbshell, run populate_staging, not the stage task (from Poky)
- Fix + character escaping from PACKAGES_DYNAMIC (thanks Otavio Salvador)
- Addition of BBCLASSEXTEND support for allowing one recipe to provide multiple targets (from Poky)
Changes in Bitbake 1.8.0:
- Release 1.7.x as a stable series
Changes in BitBake 1.7.x:
- Major updates of the dependency handling and execution
of tasks. Code from bin/bitbake replaced with runqueue.py
and taskdata.py
- New task execution code supports multithreading with a simplistic
threading algorithm controlled by BB_NUMBER_THREADS
- Change of the SVN Fetcher to keep the checkout around
courtsey of Paul Sokolovsky (#1367)
- PATH fix to bbimage (#1108)
- Allow debug domains to be specified on the commandline (-l)
- Allow 'interactive' tasks
- Logging message improvements
- Drop now uneeded BUILD_ALL_DEPS variable
- Add support for wildcards to -b option
- Major overhaul of the fetchers making a large amount of code common
including mirroring code
- Fetchers now touch md5 stamps upon access (to show activity)
- Fix -f force option when used without -b (long standing bug)
- Add expand_cache to data_cache.py, caching expanded data (speedup)
- Allow version field in DEPENDS (ignored for now)
- Add abort flag support to the shell
- Make inherit fail if the class doesn't exist (#1478)
- Fix data.emit_env() to expand keynames as well as values
- Add ssh fetcher
- Add perforce fetcher
- Make PREFERRED_PROVIDER_foobar defaults to foobar if available
- Share the parser's mtime_cache, reducing the number of stat syscalls
- Compile all anonfuncs at once!
*** Anonfuncs must now use common spacing format ***
- Memorise the list of handlers in __BBHANDLERS and tasks in __BBTASKS
This removes 2 million function calls resulting in a 5-10% speedup
- Add manpage
- Update generateDotGraph to use taskData/runQueue improving accuracy
and also adding a task dependency graph
- Fix/standardise on GPLv2 licence
- Move most functionality from bin/bitbake to cooker.py and split into
separate funcitons
- CVS fetcher: Added support for non-default port
- Add BBINCLUDELOGS_LINES, the number of lines to read from any logfile
- Drop shebangs from lib/bb scripts
Changes in Bitbake 1.6.0:
- Better msg handling
- COW dict implementation from Tim Ansell (mithro) leading
to better performance
- Speed up of -s
Changes in Bitbake 1.4.4:
- SRCDATE now handling courtsey Justin Patrin
- #1017 fix to work with rm_work
Changes in BitBake 1.4.2:
- Send logs to oe.pastebin.com instead of pastebin.com
fixes #856
- Copy the internal bitbake data before building the
dependency graph. This fixes nano not having a
virtual/libc dependency
- Allow multiple TARBALL_STASH entries
- Cache, check if the directory exists before changing
into it
- git speedup cloning by not doing a checkout
- allow to have spaces in filenames (.conf, .bb, .bbclass)
Changes in BitBake 1.4.0:
- Fix to check both RDEPENDS and RDEPENDS_${PN}
- Fix a RDEPENDS parsing bug in utils:explode_deps()
- Update git fetcher behaviour to match git changes
- ASSUME_PROVIDED allowed to include runtime packages
- git fetcher cleanup and efficency improvements
- Change the format of the cache
- Update usermanual to document the Fetchers
- Major changes to caching with a new strategy
giving a major performance increase when reparsing
with few data changes
Changes in BitBake 1.3.3:
- Create a new Fetcher module to ease the
development of new Fetchers.
Issue #438 fixed by rpurdie@openedhand.com
- Make the Subversion fetcher honor the SRC Date
(CVSDATE).
Issue #555 fixed by chris@openedhand.com
- Expand PREFERRED_PROVIDER properly
Issue #436 fixed by rprudie@openedhand.com
- Typo fix for Issue #531 by Philipp Zabel for the
BitBake Shell
- Introduce a new special variable SRCDATE as
a generic naming to replace CVSDATE.
- Introduce a new keyword 'required'. In contrast
to 'include' parsing will fail if a to be included
file can not be found.
- Remove hardcoding of the STAMP directory. Patch
courtsey pHilipp Zabel
- Track the RDEPENDS of each package (rpurdie@openedhand.com)
- Introduce BUILD_ALL_DEPS to build all RDEPENDS. E.g
this is used by the OpenEmbedded Meta Packages.
(rpurdie@openedhand.com).
Changes in BitBake 1.3.2:
- reintegration of make.py into BitBake
- bbread is gone, use bitbake -e
- lots of shell updates and bugfixes
- Introduction of the .= and =. operator
- Sort variables, keys and groups in bitdoc
- Fix regression in the handling of BBCOLLECTIONS
- Update the bitbake usermanual
Changes in BitBake 1.3.0:
- add bitbake interactive shell (bitbake -i)
- refactor bitbake utility in OO style
- kill default arguments in methods in the bb.data module
- kill default arguments in methods in the bb.fetch module
- the http/https/ftp fetcher will fail if the to be
downloaded file was not found in DL_DIR (this is needed
to avoid unpacking the sourceforge mirror page)
- Switch to a cow like data instance for persistent and non
persisting mode (called data_smart.py)
- Changed the callback of bb.make.collect_bbfiles to carry
additional parameters
- Drastically reduced the amount of needed RAM by not holding
each data instance in memory when using a cache/persistent
storage
Changes in BitBake 1.2.1:
The 1.2.1 release is meant as a intermediate release to lay the
ground for more radical changes. The most notable changes are:
- Do not hardcode {}, use bb.data.init() instead if you want to
get a instance of a data class
- bb.data.init() is a factory and the old bb.data methods are delegates
- Do not use deepcopy use bb.data.createCopy() instead.
- Removed default arguments in bb.fetch

29
bitbake/LICENSE Normal file
View File

@@ -0,0 +1,29 @@
BitBake is licensed under the GNU General Public License version 2.0. See
LICENSE.GPL-2.0-only for further details.
Individual files contain the following style tags instead of the full license text:
SPDX-License-Identifier: GPL-2.0-only
This enables machine processing of license information based on the SPDX
License Identifiers that are here available: http://spdx.org/licenses/
The following external components are distributed with this software:
* The Toaster Simple UI application is based upon the Django project template, the files of which are covered by the BSD license and are copyright (c) Django Software
Foundation and individual contributors.
* Twitter Bootstrap (including Glyphicons), redistributed under the MIT license
* jQuery is redistributed under the MIT license.
* Twitter typeahead.js redistributed under the MIT license. Note that the JS source has one small modification, so the full unminified file is currently included to make it obvious where this is.
* jsrender is redistributed under the MIT license.
* QUnit is redistributed under the MIT license.
* Font Awesome fonts redistributed under the SIL Open Font License 1.1
* simplediff is distributed under the zlib license.

View File

@@ -0,0 +1,288 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Note:
Individual files contain the following tag instead of the full license text.
SPDX-License-Identifier: GPL-2.0-only
This enables machine processing of license information based on the SPDX
License Identifiers that are here available: http://spdx.org/licenses/

25
bitbake/LICENSE.MIT Normal file
View File

@@ -0,0 +1,25 @@
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Note:
Individual files contain the following tag instead of the full license text.
SPDX-License-Identifier: MIT
This enables machine processing of license information based on the SPDX
License Identifiers that are here available: http://spdx.org/licenses/

63
bitbake/README Normal file
View File

@@ -0,0 +1,63 @@
Bitbake
=======
BitBake is a generic task execution engine that allows shell and Python tasks to be run
efficiently and in parallel while working within complex inter-task dependency constraints.
One of BitBake's main users, OpenEmbedded, takes this core and builds embedded Linux software
stacks using a task-oriented approach.
For information about Bitbake, see the OpenEmbedded website:
https://www.openembedded.org/
Bitbake plain documentation can be found under the doc directory or its integrated
html version at the Yocto Project website:
https://docs.yoctoproject.org
Bitbake requires Python version 3.8 or newer.
Contributing
------------
Please refer to our contributor guide here: https://docs.yoctoproject.org/contributor-guide/
for full details on how to submit changes.
As a quick guide, patches should be sent to bitbake-devel@lists.openembedded.org
The git command to do that would be:
git send-email -M -1 --to bitbake-devel@lists.openembedded.org
If you're sending a patch related to the BitBake manual, make sure you copy
the Yocto Project documentation mailing list:
git send-email -M -1 --to bitbake-devel@lists.openembedded.org --cc docs@lists.yoctoproject.org
Mailing list:
https://lists.openembedded.org/g/bitbake-devel
Source code:
https://git.openembedded.org/bitbake/
Testing
-------
Bitbake has a testsuite located in lib/bb/tests/ whichs aim to try and prevent regressions.
You can run this with "bitbake-selftest". In particular the fetcher is well covered since
it has so many corner cases. The datastore has many tests too. Testing with the testsuite is
recommended before submitting patches, particularly to the fetcher and datastore. We also
appreciate new test cases and may require them for more obscure issues.
To run the tests "zstd" and "git" must be installed.
The assumption is made that this testsuite is run from an initialized OpenEmbedded build
environment (i.e. `source oe-init-build-env` is used). If this is not the case, run the
testsuite as follows:
export PATH=$(pwd)/bin:$PATH
bin/bitbake-selftest
The testsuite can alternatively be executed using pytest, e.g. obtained from PyPI (in this
case, the PATH is configured automatically):
pytest

24
bitbake/SECURITY.md Normal file
View File

@@ -0,0 +1,24 @@
How to Report a Potential Vulnerability?
========================================
If you would like to report a public issue (for example, one with a released
CVE number), please report it using the
[https://bugzilla.yoctoproject.org/enter_bug.cgi?product=Security Security Bugzilla].
If you have a patch ready, submit it following the same procedure as any other
patch as described in README.md.
If you are dealing with a not-yet released or urgent issue, please send a
message to security AT yoctoproject DOT org, including as many details as
possible: the layer or software module affected, the recipe and its version,
and any example code, if available.
Branches maintained with security fixes
---------------------------------------
See [https://wiki.yoctoproject.org/wiki/Stable_Release_and_LTS Stable release and LTS]
for detailed info regarding the policies and maintenance of Stable branches.
The [https://wiki.yoctoproject.org/wiki/Releases Release page] contains a list of all
releases of the Yocto Project. Versions in grey are no longer actively maintained with
security patches, but well-tested patches may still be accepted for them for
significant issues.

45
bitbake/bin/bitbake Executable file
View File

@@ -0,0 +1,45 @@
#!/usr/bin/env python3
#
# Copyright (C) 2003, 2004 Chris Larson
# Copyright (C) 2003, 2004 Phil Blundell
# Copyright (C) 2003 - 2005 Michael 'Mickey' Lauer
# Copyright (C) 2005 Holger Hans Peter Freyther
# Copyright (C) 2005 ROAD GmbH
# Copyright (C) 2006 Richard Purdie
#
# SPDX-License-Identifier: GPL-2.0-only
#
import os
import sys
import warnings
warnings.simplefilter("default")
sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(__file__)),
'lib'))
try:
import bb
except RuntimeError as exc:
sys.exit(str(exc))
from bb import cookerdata
from bb.main import bitbake_main, BitBakeConfigParameters, BBMainException
bb.utils.check_system_locale()
__version__ = "2.12.0"
if __name__ == "__main__":
if __version__ != bb.__version__:
sys.exit("Bitbake core version and program version mismatch!")
try:
sys.exit(bitbake_main(BitBakeConfigParameters(sys.argv),
cookerdata.CookerConfiguration()))
except BBMainException as err:
sys.exit(err)
except bb.BBHandledException:
sys.exit(1)
except Exception:
import traceback
traceback.print_exc()
sys.exit(1)

View File

@@ -0,0 +1 @@
bitbake-layers

208
bitbake/bin/bitbake-diffsigs Executable file
View File

@@ -0,0 +1,208 @@
#!/usr/bin/env python3
# bitbake-diffsigs / bitbake-dumpsig
# BitBake task signature data dump and comparison utility
#
# Copyright (C) 2012-2013, 2017 Intel Corporation
#
# SPDX-License-Identifier: GPL-2.0-only
#
import os
import sys
import warnings
warnings.simplefilter("default")
import argparse
import logging
import pickle
sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(sys.argv[0])), 'lib'))
import bb.tinfoil
import bb.siggen
import bb.msg
myname = os.path.basename(sys.argv[0])
logger = bb.msg.logger_create(myname)
is_dump = myname == 'bitbake-dumpsig'
def find_siginfo(tinfoil, pn, taskname, sigs=None):
result = None
tinfoil.set_event_mask(['bb.event.FindSigInfoResult',
'logging.LogRecord',
'bb.command.CommandCompleted',
'bb.command.CommandFailed'])
ret = tinfoil.run_command('findSigInfo', pn, taskname, sigs)
if ret:
while True:
event = tinfoil.wait_event(1)
if event:
if isinstance(event, bb.command.CommandCompleted):
break
elif isinstance(event, bb.command.CommandFailed):
logger.error(str(event))
sys.exit(2)
elif isinstance(event, bb.event.FindSigInfoResult):
result = event.result
elif isinstance(event, logging.LogRecord):
logger.handle(event)
else:
logger.error('No result returned from findSigInfo command')
sys.exit(2)
return result
def find_siginfo_task(bbhandler, pn, taskname, sig1=None, sig2=None):
""" Find the most recent signature files for the specified PN/task """
if not taskname.startswith('do_'):
taskname = 'do_%s' % taskname
if sig1 and sig2:
sigfiles = find_siginfo(bbhandler, pn, taskname, [sig1, sig2])
if not sigfiles:
logger.error('No sigdata files found matching %s %s matching either %s or %s' % (pn, taskname, sig1, sig2))
sys.exit(1)
elif sig1 not in sigfiles:
logger.error('No sigdata files found matching %s %s with signature %s' % (pn, taskname, sig1))
sys.exit(1)
elif sig2 not in sigfiles:
logger.error('No sigdata files found matching %s %s with signature %s' % (pn, taskname, sig2))
sys.exit(1)
latestfiles = [sigfiles[sig1]['path'], sigfiles[sig2]['path']]
else:
sigfiles = find_siginfo(bbhandler, pn, taskname)
latestsigs = sorted(sigfiles.keys(), key=lambda h: sigfiles[h]['time'])[-2:]
if not latestsigs:
logger.error('No sigdata files found matching %s %s' % (pn, taskname))
sys.exit(1)
latestfiles = [sigfiles[latestsigs[0]]['path']]
if len(latestsigs) > 1:
latestfiles.append(sigfiles[latestsigs[1]]['path'])
return latestfiles
# Define recursion callback
def recursecb(key, hash1, hash2):
hashes = [hash1, hash2]
hashfiles = find_siginfo(tinfoil, key, None, hashes)
recout = []
if not hashfiles:
recout.append("Unable to find matching sigdata for %s with hashes %s or %s" % (key, hash1, hash2))
elif hash1 not in hashfiles:
recout.append("Unable to find matching sigdata for %s with hash %s" % (key, hash1))
elif hash2 not in hashfiles:
recout.append("Unable to find matching sigdata for %s with hash %s" % (key, hash2))
else:
out2 = bb.siggen.compare_sigfiles(hashfiles[hash1]['path'], hashfiles[hash2]['path'], recursecb, color=color)
for change in out2:
for line in change.splitlines():
recout.append(' ' + line)
return recout
parser = argparse.ArgumentParser(
description=("Dumps" if is_dump else "Compares") + " siginfo/sigdata files written out by BitBake")
parser.add_argument('-D', '--debug',
help='Enable debug output',
action='store_true')
if is_dump:
parser.add_argument("-t", "--task",
help="find the signature data file for the last run of the specified task",
action="store", dest="taskargs", nargs=2, metavar=('recipename', 'taskname'))
parser.add_argument("sigdatafile1",
help="Signature file to dump. Not used when using -t/--task.",
action="store", nargs='?', metavar="sigdatafile")
else:
parser.add_argument('-c', '--color',
help='Colorize the output (where %(metavar)s is %(choices)s)',
choices=['auto', 'always', 'never'], default='auto', metavar='color')
parser.add_argument('-d', '--dump',
help='Dump the last signature data instead of comparing (equivalent to using bitbake-dumpsig)',
action='store_true')
parser.add_argument("-t", "--task",
help="find the signature data files for the last two runs of the specified task and compare them",
action="store", dest="taskargs", nargs=2, metavar=('recipename', 'taskname'))
parser.add_argument("-s", "--signature",
help="With -t/--task, specify the signatures to look for instead of taking the last two",
action="store", dest="sigargs", nargs=2, metavar=('fromsig', 'tosig'))
parser.add_argument("sigdatafile1",
help="First signature file to compare (or signature file to dump, if second not specified). Not used when using -t/--task.",
action="store", nargs='?')
parser.add_argument("sigdatafile2",
help="Second signature file to compare",
action="store", nargs='?')
options = parser.parse_args()
if is_dump:
options.color = 'never'
options.dump = True
options.sigdatafile2 = None
options.sigargs = None
if options.debug:
logger.setLevel(logging.DEBUG)
color = (options.color == 'always' or (options.color == 'auto' and sys.stdout.isatty()))
if options.taskargs:
with bb.tinfoil.Tinfoil() as tinfoil:
tinfoil.prepare(config_only=True)
if not options.dump and options.sigargs:
files = find_siginfo_task(tinfoil, options.taskargs[0], options.taskargs[1], options.sigargs[0],
options.sigargs[1])
else:
files = find_siginfo_task(tinfoil, options.taskargs[0], options.taskargs[1])
if options.dump:
logger.debug("Signature file: %s" % files[-1])
output = bb.siggen.dump_sigfile(files[-1])
else:
if len(files) < 2:
logger.error('Only one matching sigdata file found for the specified task (%s %s)' % (
options.taskargs[0], options.taskargs[1]))
sys.exit(1)
# Recurse into signature comparison
logger.debug("Signature file (previous): %s" % files[-2])
logger.debug("Signature file (latest): %s" % files[-1])
output = bb.siggen.compare_sigfiles(files[-2], files[-1], recursecb, color=color)
else:
if options.sigargs:
logger.error('-s/--signature can only be used together with -t/--task')
sys.exit(1)
try:
if not options.dump and options.sigdatafile1 and options.sigdatafile2:
with bb.tinfoil.Tinfoil() as tinfoil:
tinfoil.prepare(config_only=True)
output = bb.siggen.compare_sigfiles(options.sigdatafile1, options.sigdatafile2, recursecb, color=color)
elif options.sigdatafile1:
output = bb.siggen.dump_sigfile(options.sigdatafile1)
else:
logger.error('Must specify signature file(s) or -t/--task')
parser.print_help()
sys.exit(1)
except IOError as e:
logger.error(str(e))
sys.exit(1)
except (pickle.UnpicklingError, EOFError):
logger.error('Invalid signature data - ensure you are specifying sigdata/siginfo files')
sys.exit(1)
if output:
print('\n'.join(output))

1
bitbake/bin/bitbake-dumpsig Symbolic link
View File

@@ -0,0 +1 @@
bitbake-diffsigs

66
bitbake/bin/bitbake-getvar Executable file
View File

@@ -0,0 +1,66 @@
#! /usr/bin/env python3
#
# Copyright (C) 2021 Richard Purdie
#
# SPDX-License-Identifier: GPL-2.0-only
#
import argparse
import io
import os
import sys
import warnings
warnings.simplefilter("default")
bindir = os.path.dirname(__file__)
topdir = os.path.dirname(bindir)
sys.path[0:0] = [os.path.join(topdir, 'lib')]
import bb.providers
import bb.tinfoil
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Bitbake Query Variable")
parser.add_argument("variable", help="variable name to query")
parser.add_argument("-r", "--recipe", help="Recipe name to query", default=None, required=False)
parser.add_argument('-u', '--unexpand', help='Do not expand the value (with --value)', action="store_true")
parser.add_argument('-f', '--flag', help='Specify a variable flag to query (with --value)', default=None)
parser.add_argument('--value', help='Only report the value, no history and no variable name', action="store_true")
parser.add_argument('-q', '--quiet', help='Silence bitbake server logging', action="store_true")
parser.add_argument('--ignore-undefined', help='Suppress any errors related to undefined variables', action="store_true")
args = parser.parse_args()
if not args.value:
if args.unexpand:
sys.exit("--unexpand only makes sense with --value")
if args.flag:
sys.exit("--flag only makes sense with --value")
quiet = args.quiet or args.value
with bb.tinfoil.Tinfoil(tracking=True, setup_logging=not quiet) as tinfoil:
if args.recipe:
tinfoil.prepare(quiet=3 if quiet else 2)
try:
d = tinfoil.parse_recipe(args.recipe)
except bb.providers.NoProvider as e:
sys.exit(str(e))
else:
tinfoil.prepare(quiet=2, config_only=True)
# Expand keys and run anonymous functions to get identical result to
# "bitbake -e"
d = tinfoil.finalizeData()
value = None
if args.flag:
value = d.getVarFlag(args.variable, args.flag, expand=not args.unexpand)
if value is None and not args.ignore_undefined:
sys.exit(f"The flag '{args.flag}' is not defined for variable '{args.variable}'")
else:
value = d.getVar(args.variable, expand=not args.unexpand)
if value is None and not args.ignore_undefined:
sys.exit(f"The variable '{args.variable}' is not defined")
if args.value:
print(str(value if value is not None else ""))
else:
bb.data.emit_var(args.variable, d=d, all=True)

462
bitbake/bin/bitbake-hashclient Executable file
View File

@@ -0,0 +1,462 @@
#! /usr/bin/env python3
#
# Copyright (C) 2019 Garmin Ltd.
#
# SPDX-License-Identifier: GPL-2.0-only
#
import argparse
import hashlib
import logging
import os
import pprint
import sys
import threading
import time
import warnings
import netrc
import json
import statistics
import textwrap
warnings.simplefilter("default")
try:
import tqdm
ProgressBar = tqdm.tqdm
except ImportError:
class ProgressBar(object):
def __init__(self, *args, **kwargs):
pass
def __enter__(self):
return self
def __exit__(self, *args, **kwargs):
pass
def update(self):
pass
sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(__file__)), 'lib'))
import hashserv
import bb.asyncrpc
DEFAULT_ADDRESS = 'unix://./hashserve.sock'
METHOD = 'stress.test.method'
def print_user(u):
print(f"Username: {u['username']}")
if "permissions" in u:
print("Permissions: " + " ".join(u["permissions"]))
if "token" in u:
print(f"Token: {u['token']}")
def main():
def handle_get(args, client):
result = client.get_taskhash(args.method, args.taskhash, all_properties=True)
if not result:
return 0
print(json.dumps(result, sort_keys=True, indent=4))
return 0
def handle_get_outhash(args, client):
result = client.get_outhash(args.method, args.outhash, args.taskhash)
if not result:
return 0
print(json.dumps(result, sort_keys=True, indent=4))
return 0
def handle_stats(args, client):
if args.reset:
s = client.reset_stats()
else:
s = client.get_stats()
print(json.dumps(s, sort_keys=True, indent=4))
return 0
def handle_stress(args, client):
def thread_main(pbar, lock):
nonlocal found_hashes
nonlocal missed_hashes
nonlocal max_time
nonlocal times
with hashserv.create_client(args.address) as client:
for i in range(args.requests):
taskhash = hashlib.sha256()
taskhash.update(args.taskhash_seed.encode('utf-8'))
taskhash.update(str(i).encode('utf-8'))
start_time = time.perf_counter()
l = client.get_unihash(METHOD, taskhash.hexdigest())
elapsed = time.perf_counter() - start_time
with lock:
if l:
found_hashes += 1
else:
missed_hashes += 1
times.append(elapsed)
pbar.update()
max_time = 0
found_hashes = 0
missed_hashes = 0
lock = threading.Lock()
times = []
start_time = time.perf_counter()
with ProgressBar(total=args.clients * args.requests) as pbar:
threads = [threading.Thread(target=thread_main, args=(pbar, lock), daemon=False) for _ in range(args.clients)]
for t in threads:
t.start()
for t in threads:
t.join()
total_elapsed = time.perf_counter() - start_time
with lock:
mean = statistics.mean(times)
median = statistics.median(times)
stddev = statistics.pstdev(times)
print(f"Number of clients: {args.clients}")
print(f"Requests per client: {args.requests}")
print(f"Number of requests: {len(times)}")
print(f"Total elapsed time: {total_elapsed:.3f}s")
print(f"Total request rate: {len(times)/total_elapsed:.3f} req/s")
print(f"Average request time: {mean:.3f}s")
print(f"Median request time: {median:.3f}s")
print(f"Request time std dev: {stddev:.3f}s")
print(f"Maximum request time: {max(times):.3f}s")
print(f"Minimum request time: {min(times):.3f}s")
print(f"Hashes found: {found_hashes}")
print(f"Hashes missed: {missed_hashes}")
if args.report:
with ProgressBar(total=args.requests) as pbar:
for i in range(args.requests):
taskhash = hashlib.sha256()
taskhash.update(args.taskhash_seed.encode('utf-8'))
taskhash.update(str(i).encode('utf-8'))
outhash = hashlib.sha256()
outhash.update(args.outhash_seed.encode('utf-8'))
outhash.update(str(i).encode('utf-8'))
client.report_unihash(taskhash.hexdigest(), METHOD, outhash.hexdigest(), taskhash.hexdigest())
with lock:
pbar.update()
def handle_remove(args, client):
where = {k: v for k, v in args.where}
if where:
result = client.remove(where)
print("Removed %d row(s)" % (result["count"]))
else:
print("No query specified")
def handle_clean_unused(args, client):
result = client.clean_unused(args.max_age)
print("Removed %d rows" % (result["count"]))
return 0
def handle_refresh_token(args, client):
r = client.refresh_token(args.username)
print_user(r)
def handle_set_user_permissions(args, client):
r = client.set_user_perms(args.username, args.permissions)
print_user(r)
def handle_get_user(args, client):
r = client.get_user(args.username)
print_user(r)
def handle_get_all_users(args, client):
users = client.get_all_users()
print("{username:20}| {permissions}".format(username="Username", permissions="Permissions"))
print(("-" * 20) + "+" + ("-" * 20))
for u in users:
print("{username:20}| {permissions}".format(username=u["username"], permissions=" ".join(u["permissions"])))
def handle_new_user(args, client):
r = client.new_user(args.username, args.permissions)
print_user(r)
def handle_delete_user(args, client):
r = client.delete_user(args.username)
print_user(r)
def handle_get_db_usage(args, client):
usage = client.get_db_usage()
print(usage)
tables = sorted(usage.keys())
print("{name:20}| {rows:20}".format(name="Table name", rows="Rows"))
print(("-" * 20) + "+" + ("-" * 20))
for t in tables:
print("{name:20}| {rows:<20}".format(name=t, rows=usage[t]["rows"]))
print()
total_rows = sum(t["rows"] for t in usage.values())
print(f"Total rows: {total_rows}")
def handle_get_db_query_columns(args, client):
columns = client.get_db_query_columns()
print("\n".join(sorted(columns)))
def handle_gc_status(args, client):
result = client.gc_status()
if not result["mark"]:
print("No Garbage collection in progress")
return 0
print("Current Mark: %s" % result["mark"])
print("Total hashes to keep: %d" % result["keep"])
print("Total hashes to remove: %s" % result["remove"])
return 0
def handle_gc_mark(args, client):
where = {k: v for k, v in args.where}
result = client.gc_mark(args.mark, where)
print("New hashes marked: %d" % result["count"])
return 0
def handle_gc_mark_stream(args, client):
stdin = (l.strip() for l in sys.stdin)
marked_hashes = 0
try:
result = client.gc_mark_stream(args.mark, stdin)
marked_hashes = result["count"]
except ConnectionError:
logger.warning(
"Server doesn't seem to support `gc-mark-stream`. Sending "
"hashes sequentially using `gc-mark` API."
)
for line in stdin:
pairs = line.split()
condition = dict(zip(pairs[::2], pairs[1::2]))
result = client.gc_mark(args.mark, condition)
marked_hashes += result["count"]
print("New hashes marked: %d" % marked_hashes)
return 0
def handle_gc_sweep(args, client):
result = client.gc_sweep(args.mark)
print("Removed %d rows" % result["count"])
return 0
def handle_unihash_exists(args, client):
result = client.unihash_exists(args.unihash)
if args.quiet:
return 0 if result else 1
print("true" if result else "false")
return 0
def handle_ping(args, client):
times = []
for i in range(1, args.count + 1):
if not args.quiet:
print(f"Ping {i} of {args.count}... ", end="")
start_time = time.perf_counter()
client.ping()
elapsed = time.perf_counter() - start_time
times.append(elapsed)
if not args.quiet:
print(f"{elapsed:.3f}s")
mean = statistics.mean(times)
median = statistics.median(times)
std_dev = statistics.pstdev(times)
if not args.quiet:
print("------------------------")
print(f"Number of pings: {len(times)}")
print(f"Average round trip time: {mean:.3f}s")
print(f"Median round trip time: {median:.3f}s")
print(f"Round trip time std dev: {std_dev:.3f}s")
print(f"Min time is: {min(times):.3f}s")
print(f"Max time is: {max(times):.3f}s")
return 0
parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
description='Hash Equivalence Client',
epilog=textwrap.dedent(
"""
Possible ADDRESS options are:
unix://PATH Connect to UNIX domain socket at PATH
ws://HOST[:PORT] Connect to websocket at HOST:PORT (default port is 80)
wss://HOST[:PORT] Connect to secure websocket at HOST:PORT (default port is 443)
HOST:PORT Connect to TCP server at HOST:PORT
"""
),
)
parser.add_argument('--address', default=DEFAULT_ADDRESS, help='Server address (default "%(default)s")')
parser.add_argument('--log', default='WARNING', help='Set logging level')
parser.add_argument('--login', '-l', metavar="USERNAME", help="Authenticate as USERNAME")
parser.add_argument('--password', '-p', metavar="TOKEN", help="Authenticate using token TOKEN")
parser.add_argument('--become', '-b', metavar="USERNAME", help="Impersonate user USERNAME (if allowed) when performing actions")
parser.add_argument('--no-netrc', '-n', action="store_false", dest="netrc", help="Do not use .netrc")
subparsers = parser.add_subparsers()
get_parser = subparsers.add_parser('get', help="Get the unihash for a taskhash")
get_parser.add_argument("method", help="Method to query")
get_parser.add_argument("taskhash", help="Task hash to query")
get_parser.set_defaults(func=handle_get)
get_outhash_parser = subparsers.add_parser('get-outhash', help="Get output hash information")
get_outhash_parser.add_argument("method", help="Method to query")
get_outhash_parser.add_argument("outhash", help="Output hash to query")
get_outhash_parser.add_argument("taskhash", help="Task hash to query")
get_outhash_parser.set_defaults(func=handle_get_outhash)
stats_parser = subparsers.add_parser('stats', help='Show server stats')
stats_parser.add_argument('--reset', action='store_true',
help='Reset server stats')
stats_parser.set_defaults(func=handle_stats)
stress_parser = subparsers.add_parser('stress', help='Run stress test')
stress_parser.add_argument('--clients', type=int, default=10,
help='Number of simultaneous clients')
stress_parser.add_argument('--requests', type=int, default=1000,
help='Number of requests each client will perform')
stress_parser.add_argument('--report', action='store_true',
help='Report new hashes')
stress_parser.add_argument('--taskhash-seed', default='',
help='Include string in taskhash')
stress_parser.add_argument('--outhash-seed', default='',
help='Include string in outhash')
stress_parser.set_defaults(func=handle_stress)
remove_parser = subparsers.add_parser('remove', help="Remove hash entries")
remove_parser.add_argument("--where", "-w", metavar="KEY VALUE", nargs=2, action="append", default=[],
help="Remove entries from table where KEY == VALUE")
remove_parser.set_defaults(func=handle_remove)
clean_unused_parser = subparsers.add_parser('clean-unused', help="Remove unused database entries")
clean_unused_parser.add_argument("max_age", metavar="SECONDS", type=int, help="Remove unused entries older than SECONDS old")
clean_unused_parser.set_defaults(func=handle_clean_unused)
refresh_token_parser = subparsers.add_parser('refresh-token', help="Refresh auth token")
refresh_token_parser.add_argument("--username", "-u", help="Refresh the token for another user (if authorized)")
refresh_token_parser.set_defaults(func=handle_refresh_token)
set_user_perms_parser = subparsers.add_parser('set-user-perms', help="Set new permissions for user")
set_user_perms_parser.add_argument("--username", "-u", help="Username", required=True)
set_user_perms_parser.add_argument("permissions", metavar="PERM", nargs="*", default=[], help="New permissions")
set_user_perms_parser.set_defaults(func=handle_set_user_permissions)
get_user_parser = subparsers.add_parser('get-user', help="Get user")
get_user_parser.add_argument("--username", "-u", help="Username")
get_user_parser.set_defaults(func=handle_get_user)
get_all_users_parser = subparsers.add_parser('get-all-users', help="List all users")
get_all_users_parser.set_defaults(func=handle_get_all_users)
new_user_parser = subparsers.add_parser('new-user', help="Create new user")
new_user_parser.add_argument("--username", "-u", help="Username", required=True)
new_user_parser.add_argument("permissions", metavar="PERM", nargs="*", default=[], help="New permissions")
new_user_parser.set_defaults(func=handle_new_user)
delete_user_parser = subparsers.add_parser('delete-user', help="Delete user")
delete_user_parser.add_argument("--username", "-u", help="Username", required=True)
delete_user_parser.set_defaults(func=handle_delete_user)
db_usage_parser = subparsers.add_parser('get-db-usage', help="Database Usage")
db_usage_parser.set_defaults(func=handle_get_db_usage)
db_query_columns_parser = subparsers.add_parser('get-db-query-columns', help="Show columns that can be used in database queries")
db_query_columns_parser.set_defaults(func=handle_get_db_query_columns)
gc_status_parser = subparsers.add_parser("gc-status", help="Show garbage collection status")
gc_status_parser.set_defaults(func=handle_gc_status)
gc_mark_parser = subparsers.add_parser('gc-mark', help="Mark hashes to be kept for garbage collection")
gc_mark_parser.add_argument("mark", help="Mark for this garbage collection operation")
gc_mark_parser.add_argument("--where", "-w", metavar="KEY VALUE", nargs=2, action="append", default=[],
help="Keep entries in table where KEY == VALUE")
gc_mark_parser.set_defaults(func=handle_gc_mark)
gc_mark_parser_stream = subparsers.add_parser(
'gc-mark-stream',
help=(
"Mark multiple hashes to be retained for garbage collection. Input should be provided via stdin, "
"with each line formatted as key-value pairs separated by spaces, for example 'column1 foo column2 bar'."
)
)
gc_mark_parser_stream.add_argument("mark", help="Mark for this garbage collection operation")
gc_mark_parser_stream.set_defaults(func=handle_gc_mark_stream)
gc_sweep_parser = subparsers.add_parser('gc-sweep', help="Perform garbage collection and delete any entries that are not marked")
gc_sweep_parser.add_argument("mark", help="Mark for this garbage collection operation")
gc_sweep_parser.set_defaults(func=handle_gc_sweep)
unihash_exists_parser = subparsers.add_parser('unihash-exists', help="Check if a unihash is known to the server")
unihash_exists_parser.add_argument("--quiet", action="store_true", help="Don't print status. Instead, exit with 0 if unihash exists and 1 if it does not")
unihash_exists_parser.add_argument("unihash", help="Unihash to check")
unihash_exists_parser.set_defaults(func=handle_unihash_exists)
ping_parser = subparsers.add_parser('ping', help="Ping server")
ping_parser.add_argument("-n", "--count", type=int, help="Number of pings. Default is %(default)s", default=10)
ping_parser.add_argument("-q", "--quiet", action="store_true", help="Don't print each ping; only print results")
ping_parser.set_defaults(func=handle_ping)
args = parser.parse_args()
logger = logging.getLogger('hashserv')
level = getattr(logging, args.log.upper(), None)
if not isinstance(level, int):
raise ValueError('Invalid log level: %s' % args.log)
logger.setLevel(level)
console = logging.StreamHandler()
console.setLevel(level)
logger.addHandler(console)
login = args.login
password = args.password
if login is None and args.netrc:
try:
n = netrc.netrc()
auth = n.authenticators(args.address)
if auth is not None:
login, _, password = auth
except FileNotFoundError:
pass
except netrc.NetrcParseError as e:
sys.stderr.write(f"Error parsing {e.filename}:{e.lineno}: {e.msg}\n")
func = getattr(args, 'func', None)
if func:
try:
with hashserv.create_client(args.address, login, password) as client:
if args.become:
client.become_user(args.become)
return func(args, client)
except bb.asyncrpc.InvokeError as e:
print(f"ERROR: {e}")
return 1
return 0
if __name__ == '__main__':
try:
ret = main()
except Exception:
ret = 1
import traceback
traceback.print_exc()
sys.exit(ret)

179
bitbake/bin/bitbake-hashserv Executable file
View File

@@ -0,0 +1,179 @@
#! /usr/bin/env python3
#
# Copyright (C) 2018 Garmin Ltd.
#
# SPDX-License-Identifier: GPL-2.0-only
#
import os
import sys
import logging
import argparse
import sqlite3
import warnings
warnings.simplefilter("default")
sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(__file__)), "lib"))
import hashserv
from hashserv.server import DEFAULT_ANON_PERMS
VERSION = "1.0.0"
DEFAULT_BIND = "unix://./hashserve.sock"
def main():
parser = argparse.ArgumentParser(
description="Hash Equivalence Reference Server. Version=%s" % VERSION,
formatter_class=argparse.RawTextHelpFormatter,
epilog="""
The bind address may take one of the following formats:
unix://PATH - Bind to unix domain socket at PATH
ws://ADDRESS:PORT - Bind to websocket on ADDRESS:PORT
ADDRESS:PORT - Bind to raw TCP socket on ADDRESS:PORT
To bind to all addresses, leave the ADDRESS empty, e.g. "--bind :8686" or
"--bind ws://:8686". To bind to a specific IPv6 address, enclose the address in
"[]", e.g. "--bind [::1]:8686" or "--bind ws://[::1]:8686"
Note that the default Anonymous permissions are designed to not break existing
server instances when upgrading, but are not particularly secure defaults. If
you want to use authentication, it is recommended that you use "--anon-perms
@read" to only give anonymous users read access, or "--anon-perms @none" to
give un-authenticated users no access at all.
Setting "--anon-perms @all" or "--anon-perms @user-admin" is not allowed, since
this would allow anonymous users to manage all users accounts, which is a bad
idea.
If you are using user authentication, you should run your server in websockets
mode with an SSL terminating load balancer in front of it (as this server does
not implement SSL). Otherwise all usernames and passwords will be transmitted
in the clear. When configured this way, clients can connect using a secure
websocket, as in "wss://SERVER:PORT"
The following permissions are supported by the server:
@none - No permissions
@read - The ability to read equivalent hashes from the server
@report - The ability to report equivalent hashes to the server
@db-admin - Manage the hash database(s). This includes cleaning the
database, removing hashes, etc.
@user-admin - The ability to manage user accounts. This includes, creating
users, deleting users, resetting login tokens, and assigning
permissions.
@all - All possible permissions, including any that may be added
in the future
""",
)
parser.add_argument(
"-b",
"--bind",
default=os.environ.get("HASHSERVER_BIND", DEFAULT_BIND),
help='Bind address (default $HASHSERVER_BIND, "%(default)s")',
)
parser.add_argument(
"-d",
"--database",
default=os.environ.get("HASHSERVER_DB", "./hashserv.db"),
help='Database file (default $HASHSERVER_DB, "%(default)s")',
)
parser.add_argument(
"-l",
"--log",
default=os.environ.get("HASHSERVER_LOG_LEVEL", "WARNING"),
help='Set logging level (default $HASHSERVER_LOG_LEVEL, "%(default)s")',
)
parser.add_argument(
"-u",
"--upstream",
default=os.environ.get("HASHSERVER_UPSTREAM", None),
help="Upstream hashserv to pull hashes from ($HASHSERVER_UPSTREAM)",
)
parser.add_argument(
"-r",
"--read-only",
action="store_true",
help="Disallow write operations from clients ($HASHSERVER_READ_ONLY)",
)
parser.add_argument(
"--db-username",
default=os.environ.get("HASHSERVER_DB_USERNAME", None),
help="Database username ($HASHSERVER_DB_USERNAME)",
)
parser.add_argument(
"--db-password",
default=os.environ.get("HASHSERVER_DB_PASSWORD", None),
help="Database password ($HASHSERVER_DB_PASSWORD)",
)
parser.add_argument(
"--anon-perms",
metavar="PERM[,PERM[,...]]",
default=os.environ.get("HASHSERVER_ANON_PERMS", ",".join(DEFAULT_ANON_PERMS)),
help='Permissions to give anonymous users (default $HASHSERVER_ANON_PERMS, "%(default)s")',
)
parser.add_argument(
"--admin-user",
default=os.environ.get("HASHSERVER_ADMIN_USER", None),
help="Create default admin user with name ADMIN_USER ($HASHSERVER_ADMIN_USER)",
)
parser.add_argument(
"--admin-password",
default=os.environ.get("HASHSERVER_ADMIN_PASSWORD", None),
help="Create default admin user with password ADMIN_PASSWORD ($HASHSERVER_ADMIN_PASSWORD)",
)
parser.add_argument(
"--reuseport",
action="store_true",
help="Enable SO_REUSEPORT, allowing multiple servers to bind to the same port for load balancing",
)
args = parser.parse_args()
logger = logging.getLogger("hashserv")
level = getattr(logging, args.log.upper(), None)
if not isinstance(level, int):
raise ValueError(
"Invalid log level: %s (Try ERROR/WARNING/INFO/DEBUG)" % args.log
)
logger.setLevel(level)
console = logging.StreamHandler()
console.setLevel(level)
logger.addHandler(console)
read_only = (os.environ.get("HASHSERVER_READ_ONLY", "0") == "1") or args.read_only
if "," in args.anon_perms:
anon_perms = args.anon_perms.split(",")
else:
anon_perms = args.anon_perms.split()
server = hashserv.create_server(
args.bind,
args.database,
upstream=args.upstream,
read_only=read_only,
db_username=args.db_username,
db_password=args.db_password,
anon_perms=anon_perms,
admin_username=args.admin_user,
admin_password=args.admin_password,
reuseport=args.reuseport,
)
server.serve_forever()
return 0
if __name__ == "__main__":
try:
ret = main()
except Exception:
ret = 1
import traceback
traceback.print_exc()
sys.exit(ret)

106
bitbake/bin/bitbake-layers Executable file
View File

@@ -0,0 +1,106 @@
#!/usr/bin/env python3
# This script has subcommands which operate against your bitbake layers, either
# displaying useful information, or acting against them.
# See the help output for details on available commands.
# Copyright (C) 2011 Mentor Graphics Corporation
# Copyright (C) 2011-2015 Intel Corporation
#
# SPDX-License-Identifier: GPL-2.0-only
#
import logging
import os
import sys
import argparse
import warnings
warnings.simplefilter("default")
bindir = os.path.dirname(__file__)
toolname = os.path.basename(__file__).split(".")[0]
topdir = os.path.dirname(bindir)
sys.path[0:0] = [os.path.join(topdir, 'lib')]
import bb.tinfoil
import bb.msg
logger = bb.msg.logger_create(toolname, sys.stdout)
def main():
parser = argparse.ArgumentParser(
description="BitBake layers utility",
epilog="Use %(prog)s <subcommand> --help to get help on a specific command",
add_help=False)
parser.add_argument('-d', '--debug', help='Enable debug output', action='store_true')
parser.add_argument('-q', '--quiet', help='Print only errors', action='store_true')
parser.add_argument('-F', '--force', help='Forced execution: can be specified multiple times. -F will force add without recipe parse verification and -FF will additionally force the run withput layer parsing.', action='count', default=0)
parser.add_argument('--color', choices=['auto', 'always', 'never'], default='auto', help='Colorize output (where %(metavar)s is %(choices)s)', metavar='COLOR')
global_args, unparsed_args = parser.parse_known_args()
# Help is added here rather than via add_help=True, as we don't want it to
# be handled by parse_known_args()
parser.add_argument('-h', '--help', action='help', default=argparse.SUPPRESS,
help='show this help message and exit')
subparsers = parser.add_subparsers(title='subcommands', metavar='<subcommand>')
subparsers.required = True
if global_args.debug:
logger.setLevel(logging.DEBUG)
elif global_args.quiet:
logger.setLevel(logging.ERROR)
# Need to re-run logger_create with color argument
# (will be the same logger since it has the same name)
bb.msg.logger_create('bitbake-layers', output=sys.stdout,
color=global_args.color,
level=logger.getEffectiveLevel())
plugins = []
with bb.tinfoil.Tinfoil(tracking=True) as tinfoil:
tinfoil.logger.setLevel(logger.getEffectiveLevel())
if global_args.force > 1:
bbpaths = []
else:
tinfoil.prepare(True)
bbpaths = tinfoil.config_data.getVar('BBPATH').split(':')
for path in ([topdir] + bbpaths):
pluginbasepath = {"bitbake-layers":'bblayers', 'bitbake-config-build':'bbconfigbuild'}[toolname]
pluginpath = os.path.join(path, 'lib', pluginbasepath)
bb.utils.load_plugins(logger, plugins, pluginpath)
registered = False
for plugin in plugins:
if hasattr(plugin, 'tinfoil_init') and global_args.force <= 1:
plugin.tinfoil_init(tinfoil)
if hasattr(plugin, 'register_commands'):
registered = True
plugin.register_commands(subparsers)
if not registered:
logger.error("No commands registered - missing plugins?")
sys.exit(1)
args = parser.parse_args(unparsed_args, namespace=global_args)
if getattr(args, 'parserecipes', False):
tinfoil.config_data.disableTracking()
tinfoil.parse_recipes()
tinfoil.config_data.enableTracking()
return args.func(args)
if __name__ == "__main__":
try:
ret = main()
except bb.BBHandledException:
ret = 1
except Exception:
ret = 1
import traceback
traceback.print_exc()
sys.exit(ret)

113
bitbake/bin/bitbake-prserv Executable file
View File

@@ -0,0 +1,113 @@
#!/usr/bin/env python3
#
# Copyright BitBake Contributors
#
# SPDX-License-Identifier: GPL-2.0-only
#
import os
import sys,logging
import argparse
import warnings
warnings.simplefilter("default")
sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(__file__)), "lib"))
import prserv
import prserv.serv
VERSION = "2.0.0"
PRHOST_DEFAULT="0.0.0.0"
PRPORT_DEFAULT=8585
def init_logger(logfile, loglevel):
numeric_level = getattr(logging, loglevel.upper(), None)
if not isinstance(numeric_level, int):
raise ValueError("Invalid log level: %s" % loglevel)
FORMAT = "%(asctime)-15s %(message)s"
logging.basicConfig(level=numeric_level, filename=logfile, format=FORMAT)
def main():
parser = argparse.ArgumentParser(
description="BitBake PR Server. Version=%s" % VERSION,
formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument(
"-f",
"--file",
default="prserv.sqlite3",
help="database filename (default: prserv.sqlite3)",
)
parser.add_argument(
"-l",
"--log",
default="prserv.log",
help="log filename(default: prserv.log)",
)
parser.add_argument(
"--loglevel",
default="INFO",
help="logging level, i.e. CRITICAL, ERROR, WARNING, INFO, DEBUG",
)
parser.add_argument(
"--start",
action="store_true",
help="start daemon",
)
parser.add_argument(
"--stop",
action="store_true",
help="stop daemon",
)
parser.add_argument(
"--host",
help="ip address to bind",
default=PRHOST_DEFAULT,
)
parser.add_argument(
"--port",
type=int,
default=PRPORT_DEFAULT,
help="port number (default: 8585)",
)
parser.add_argument(
"-r",
"--read-only",
action="store_true",
help="open database in read-only mode",
)
parser.add_argument(
"-u",
"--upstream",
default=os.environ.get("PRSERV_UPSTREAM", None),
help="Upstream PR service (host:port)",
)
args = parser.parse_args()
init_logger(os.path.abspath(args.log), args.loglevel)
if args.start:
ret=prserv.serv.start_daemon(
args.file,
args.host,
args.port,
os.path.abspath(args.log),
args.read_only,
args.upstream
)
elif args.stop:
ret=prserv.serv.stop_daemon(args.host, args.port)
else:
ret=parser.print_help()
return ret
if __name__ == "__main__":
try:
ret = main()
except Exception:
ret = 1
import traceback
traceback.print_exc()
sys.exit(ret)

78
bitbake/bin/bitbake-selftest Executable file
View File

@@ -0,0 +1,78 @@
#!/usr/bin/env python3
#
# Copyright (C) 2012 Richard Purdie
#
# SPDX-License-Identifier: GPL-2.0-only
#
import os
import sys, logging
import warnings
warnings.simplefilter("default")
sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(__file__)), 'lib'))
import unittest
try:
import bb
import hashserv
import prserv
import layerindexlib
except RuntimeError as exc:
sys.exit(str(exc))
tests = ["bb.tests.codeparser",
"bb.tests.color",
"bb.tests.cooker",
"bb.tests.cow",
"bb.tests.data",
"bb.tests.event",
"bb.tests.fetch",
"bb.tests.parse",
"bb.tests.runqueue",
"bb.tests.siggen",
"bb.tests.utils",
"bb.tests.compression",
"hashserv.tests",
"prserv.tests",
"layerindexlib.tests.layerindexobj",
"layerindexlib.tests.restapi",
"layerindexlib.tests.cooker"]
for t in tests:
t = '.'.join(t.split('.')[:3])
__import__(t)
# Set-up logging
class StdoutStreamHandler(logging.StreamHandler):
"""Special handler so that unittest is able to capture stdout"""
def __init__(self):
# Override __init__() because we don't want to set self.stream here
logging.Handler.__init__(self)
@property
def stream(self):
# We want to dynamically write wherever sys.stdout is pointing to
return sys.stdout
handler = StdoutStreamHandler()
bb.logger.addHandler(handler)
bb.logger.setLevel(logging.DEBUG)
ENV_HELP = """\
Environment variables:
BB_SKIP_NETTESTS set to 'yes' in order to skip tests using network
connection
BB_TMPDIR_NOCLEAN set to 'yes' to preserve test tmp directories
"""
class main(unittest.main):
def _print_help(self, *args, **kwargs):
super(main, self)._print_help(*args, **kwargs)
print(ENV_HELP)
if __name__ == '__main__':
main(defaultTest=tests, buffer=True)

56
bitbake/bin/bitbake-server Executable file
View File

@@ -0,0 +1,56 @@
#!/usr/bin/env python3
#
# SPDX-License-Identifier: GPL-2.0-only
#
# Copyright (C) 2020 Richard Purdie
#
import os
import sys
import warnings
warnings.simplefilter("default")
warnings.filterwarnings("ignore", category=DeprecationWarning, message=".*use.of.fork.*may.lead.to.deadlocks.in.the.child.*")
import logging
sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(sys.argv[0])), 'lib'))
import bb
bb.utils.check_system_locale()
# Users shouldn't be running this code directly
if len(sys.argv) != 11 or not sys.argv[1].startswith("decafbad"):
print("bitbake-server is meant for internal execution by bitbake itself, please don't use it standalone.")
sys.exit(1)
import bb.server.process
lockfd = int(sys.argv[2])
readypipeinfd = int(sys.argv[3])
logfile = sys.argv[4]
lockname = sys.argv[5]
sockname = sys.argv[6]
timeout = float(sys.argv[7])
profile = bool(int(sys.argv[8]))
xmlrpcinterface = (sys.argv[9], int(sys.argv[10]))
if xmlrpcinterface[0] == "None":
xmlrpcinterface = (None, xmlrpcinterface[1])
# Replace standard fds with our own
with open('/dev/null', 'r') as si:
os.dup2(si.fileno(), sys.stdin.fileno())
with open(logfile, 'a+') as so:
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(so.fileno(), sys.stderr.fileno())
# Have stdout and stderr be the same so log output matches chronologically
# and there aren't two seperate buffers
sys.stderr = sys.stdout
logger = logging.getLogger("BitBake")
# Ensure logging messages get sent to the UI as events
handler = bb.event.LogHandler()
logger.addHandler(handler)
bb.server.process.execServer(lockfd, readypipeinfd, lockname, sockname, timeout, xmlrpcinterface, profile)

593
bitbake/bin/bitbake-worker Executable file
View File

@@ -0,0 +1,593 @@
#!/usr/bin/env python3
#
# Copyright BitBake Contributors
#
# SPDX-License-Identifier: GPL-2.0-only
#
import os
import sys
import warnings
warnings.simplefilter("default")
warnings.filterwarnings("ignore", category=DeprecationWarning, message=".*use.of.fork.*may.lead.to.deadlocks.in.the.child.*")
sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(sys.argv[0])), 'lib'))
from bb import fetch2
import logging
import bb
import select
import errno
import signal
import pickle
import traceback
import queue
import shlex
import subprocess
import fcntl
from multiprocessing import Lock
from threading import Thread
# Remove when we have a minimum of python 3.10
if not hasattr(fcntl, 'F_SETPIPE_SZ'):
fcntl.F_SETPIPE_SZ = 1031
bb.utils.check_system_locale()
# Users shouldn't be running this code directly
if len(sys.argv) != 2 or not sys.argv[1].startswith("decafbad"):
print("bitbake-worker is meant for internal execution by bitbake itself, please don't use it standalone.")
sys.exit(1)
profiling = False
if sys.argv[1].startswith("decafbadbad"):
profiling = True
try:
import cProfile as profile
except:
import profile
# Unbuffer stdout to avoid log truncation in the event
# of an unorderly exit as well as to provide timely
# updates to log files for use with tail
try:
if sys.stdout.name == '<stdout>':
fl = fcntl.fcntl(sys.stdout.fileno(), fcntl.F_GETFL)
fl |= os.O_SYNC
fcntl.fcntl(sys.stdout.fileno(), fcntl.F_SETFL, fl)
#sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
except:
pass
logger = logging.getLogger("BitBake")
worker_pipe = sys.stdout.fileno()
bb.utils.nonblockingfd(worker_pipe)
# Try to make the pipe buffers larger as it is much more efficient. If we can't
# e.g. out of buffer space (/proc/sys/fs/pipe-user-pages-soft) then just pass over.
try:
fcntl.fcntl(worker_pipe, fcntl.F_SETPIPE_SZ, 512 * 1024)
except:
pass
# Need to guard against multiprocessing being used in child processes
# and multiple processes trying to write to the parent at the same time
worker_pipe_lock = None
handler = bb.event.LogHandler()
logger.addHandler(handler)
if 0:
# Code to write out a log file of all events passing through the worker
logfilename = "/tmp/workerlogfile"
format_str = "%(levelname)s: %(message)s"
conlogformat = bb.msg.BBLogFormatter(format_str)
consolelog = logging.FileHandler(logfilename)
consolelog.setFormatter(conlogformat)
logger.addHandler(consolelog)
worker_queue = queue.Queue()
def worker_fire(event, d):
data = b"<event>" + pickle.dumps(event) + b"</event>"
worker_fire_prepickled(data)
def worker_fire_prepickled(event):
global worker_queue
worker_queue.put(event)
#
# We can end up with write contention with the cooker, it can be trying to send commands
# and we can be trying to send event data back. Therefore use a separate thread for writing
# back data to cooker.
#
worker_thread_exit = False
def worker_flush(worker_queue):
worker_queue_int = bytearray()
global worker_pipe, worker_thread_exit
while True:
try:
worker_queue_int.extend(worker_queue.get(True, 1))
except queue.Empty:
pass
while (worker_queue_int or not worker_queue.empty()):
try:
(_, ready, _) = select.select([], [worker_pipe], [], 1)
if not worker_queue.empty():
worker_queue_int.extend(worker_queue.get())
written = os.write(worker_pipe, worker_queue_int)
del worker_queue_int[0:written]
except (IOError, OSError) as e:
if e.errno != errno.EAGAIN and e.errno != errno.EPIPE:
raise
if worker_thread_exit and worker_queue.empty() and not worker_queue_int:
return
worker_thread = Thread(target=worker_flush, args=(worker_queue,))
worker_thread.start()
def worker_child_fire(event, d):
global worker_pipe
global worker_pipe_lock
data = b"<event>" + pickle.dumps(event) + b"</event>"
try:
with bb.utils.lock_timeout(worker_pipe_lock):
while(len(data)):
written = worker_pipe.write(data)
data = data[written:]
except IOError:
sigterm_handler(None, None)
raise
bb.event.worker_fire = worker_fire
lf = None
#lf = open("/tmp/workercommandlog", "w+")
def workerlog_write(msg):
if lf:
lf.write(msg)
lf.flush()
def sigterm_handler(signum, frame):
signal.signal(signal.SIGTERM, signal.SIG_DFL)
os.killpg(0, signal.SIGTERM)
sys.exit()
def fork_off_task(cfg, data, databuilder, workerdata, extraconfigdata, runtask):
fn = runtask['fn']
task = runtask['task']
taskname = runtask['taskname']
taskhash = runtask['taskhash']
unihash = runtask['unihash']
appends = runtask['appends']
layername = runtask['layername']
taskdepdata = runtask['taskdepdata']
quieterrors = runtask['quieterrors']
# We need to setup the environment BEFORE the fork, since
# a fork() or exec*() activates PSEUDO...
envbackup = {}
fakeroot = False
fakeenv = {}
umask = None
uid = os.getuid()
gid = os.getgid()
taskdep = runtask['taskdep']
if 'umask' in taskdep and taskname in taskdep['umask']:
umask = taskdep['umask'][taskname]
elif workerdata["umask"]:
umask = workerdata["umask"]
if umask:
# umask might come in as a number or text string..
try:
umask = int(umask, 8)
except TypeError:
pass
dry_run = cfg.dry_run or runtask['dry_run']
# We can't use the fakeroot environment in a dry run as it possibly hasn't been built
if 'fakeroot' in taskdep and taskname in taskdep['fakeroot'] and not dry_run:
fakeroot = True
envvars = (runtask['fakerootenv'] or "").split()
for key, value in (var.split('=',1) for var in envvars):
envbackup[key] = os.environ.get(key)
os.environ[key] = value
fakeenv[key] = value
fakedirs = (runtask['fakerootdirs'] or "").split()
for p in fakedirs:
bb.utils.mkdirhier(p)
logger.debug2('Running %s:%s under fakeroot, fakedirs: %s' %
(fn, taskname, ', '.join(fakedirs)))
else:
envvars = (runtask['fakerootnoenv'] or "").split()
for key, value in (var.split('=',1) for var in envvars):
envbackup[key] = os.environ.get(key)
os.environ[key] = value
fakeenv[key] = value
sys.stdout.flush()
sys.stderr.flush()
try:
pipein, pipeout = os.pipe()
pipein = os.fdopen(pipein, 'rb', 4096)
pipeout = os.fdopen(pipeout, 'wb', 0)
pid = os.fork()
except OSError as e:
logger.critical("fork failed: %d (%s)" % (e.errno, e.strerror))
sys.exit(1)
if pid == 0:
def child():
global worker_pipe
global worker_pipe_lock
pipein.close()
bb.utils.signal_on_parent_exit("SIGTERM")
# Save out the PID so that the event can include it the
# events
bb.event.worker_pid = os.getpid()
bb.event.worker_fire = worker_child_fire
worker_pipe = pipeout
worker_pipe_lock = Lock()
# Make the child the process group leader and ensure no
# child process will be controlled by the current terminal
# This ensures signals sent to the controlling terminal like Ctrl+C
# don't stop the child processes.
os.setsid()
signal.signal(signal.SIGTERM, sigterm_handler)
# Let SIGHUP exit as SIGTERM
signal.signal(signal.SIGHUP, sigterm_handler)
# No stdin & stdout
# stdout is used as a status report channel and must not be used by child processes.
dumbio = os.open(os.devnull, os.O_RDWR)
os.dup2(dumbio, sys.stdin.fileno())
os.dup2(dumbio, sys.stdout.fileno())
if umask is not None:
os.umask(umask)
try:
(realfn, virtual, mc) = bb.cache.virtualfn2realfn(fn)
the_data = databuilder.mcdata[mc]
the_data.setVar("BB_WORKERCONTEXT", "1")
the_data.setVar("BB_TASKDEPDATA", taskdepdata)
the_data.setVar('BB_CURRENTTASK', taskname.replace("do_", ""))
if cfg.limited_deps:
the_data.setVar("BB_LIMITEDDEPS", "1")
the_data.setVar("BUILDNAME", workerdata["buildname"])
the_data.setVar("DATE", workerdata["date"])
the_data.setVar("TIME", workerdata["time"])
for varname, value in extraconfigdata.items():
the_data.setVar(varname, value)
bb.parse.siggen.set_taskdata(workerdata["sigdata"])
if "newhashes" in workerdata:
bb.parse.siggen.set_taskhashes(workerdata["newhashes"])
ret = 0
the_data = databuilder.parseRecipe(fn, appends, layername)
the_data.setVar('BB_TASKHASH', taskhash)
the_data.setVar('BB_UNIHASH', unihash)
bb.parse.siggen.setup_datacache_from_datastore(fn, the_data)
bb.utils.set_process_name("%s:%s" % (the_data.getVar("PN"), taskname.replace("do_", "")))
if not bb.utils.to_boolean(the_data.getVarFlag(taskname, 'network')):
if bb.utils.is_local_uid(uid):
logger.debug("Attempting to disable network for %s" % taskname)
bb.utils.disable_network(uid, gid)
else:
logger.debug("Skipping disable network for %s since %s is not a local uid." % (taskname, uid))
# exported_vars() returns a generator which *cannot* be passed to os.environ.update()
# successfully. We also need to unset anything from the environment which shouldn't be there
exports = bb.data.exported_vars(the_data)
bb.utils.empty_environment()
for e, v in exports:
os.environ[e] = v
for e in fakeenv:
os.environ[e] = fakeenv[e]
the_data.setVar(e, fakeenv[e])
the_data.setVarFlag(e, 'export', "1")
task_exports = the_data.getVarFlag(taskname, 'exports')
if task_exports:
for e in task_exports.split():
the_data.setVarFlag(e, 'export', '1')
v = the_data.getVar(e)
if v is not None:
os.environ[e] = v
if quieterrors:
the_data.setVarFlag(taskname, "quieterrors", "1")
except Exception:
if not quieterrors:
logger.critical(traceback.format_exc())
os._exit(1)
sys.stdout.flush()
sys.stderr.flush()
try:
if dry_run:
return 0
try:
ret = bb.build.exec_task(fn, taskname, the_data, cfg.profile)
finally:
if fakeroot:
fakerootcmd = shlex.split(the_data.getVar("FAKEROOTCMD"))
subprocess.run(fakerootcmd + ['-S'], check=True, stdout=subprocess.PIPE)
return ret
except:
os._exit(1)
if not profiling:
os._exit(child())
else:
profname = "profile-%s.log" % (fn.replace("/", "-") + "-" + taskname)
prof = profile.Profile()
try:
ret = profile.Profile.runcall(prof, child)
finally:
prof.dump_stats(profname)
bb.utils.process_profilelog(profname)
os._exit(ret)
else:
for key, value in iter(envbackup.items()):
if value is None:
del os.environ[key]
else:
os.environ[key] = value
return pid, pipein, pipeout
class runQueueWorkerPipe():
"""
Abstraction for a pipe between a worker thread and the worker server
"""
def __init__(self, pipein, pipeout):
self.input = pipein
if pipeout:
pipeout.close()
bb.utils.nonblockingfd(self.input)
self.queue = bytearray()
def read(self):
start = len(self.queue)
try:
self.queue.extend(self.input.read(512*1024) or b"")
except (OSError, IOError) as e:
if e.errno != errno.EAGAIN:
raise
end = len(self.queue)
index = self.queue.find(b"</event>")
while index != -1:
msg = self.queue[:index+8]
assert msg.startswith(b"<event>") and msg.count(b"<event>") == 1
worker_fire_prepickled(msg)
self.queue = self.queue[index+8:]
index = self.queue.find(b"</event>")
return (end > start)
def close(self):
while self.read():
continue
if len(self.queue) > 0:
print("Warning, worker child left partial message: %s" % self.queue)
self.input.close()
normalexit = False
class BitbakeWorker(object):
def __init__(self, din):
self.input = din
bb.utils.nonblockingfd(self.input)
self.queue = bytearray()
self.cookercfg = None
self.databuilder = None
self.data = None
self.extraconfigdata = None
self.build_pids = {}
self.build_pipes = {}
signal.signal(signal.SIGTERM, self.sigterm_exception)
# Let SIGHUP exit as SIGTERM
signal.signal(signal.SIGHUP, self.sigterm_exception)
if "beef" in sys.argv[1]:
bb.utils.set_process_name("Worker (Fakeroot)")
else:
bb.utils.set_process_name("Worker")
def sigterm_exception(self, signum, stackframe):
if signum == signal.SIGTERM:
bb.warn("Worker received SIGTERM, shutting down...")
elif signum == signal.SIGHUP:
bb.warn("Worker received SIGHUP, shutting down...")
self.handle_finishnow(None)
signal.signal(signal.SIGTERM, signal.SIG_DFL)
os.kill(os.getpid(), signal.SIGTERM)
def serve(self):
while True:
(ready, _, _) = select.select([self.input] + [i.input for i in self.build_pipes.values()], [] , [], 1)
if self.input in ready:
try:
r = self.input.read()
if len(r) == 0:
# EOF on pipe, server must have terminated
self.sigterm_exception(signal.SIGTERM, None)
self.queue.extend(r)
except (OSError, IOError):
pass
if len(self.queue):
self.handle_item(b"cookerconfig", self.handle_cookercfg)
self.handle_item(b"extraconfigdata", self.handle_extraconfigdata)
self.handle_item(b"workerdata", self.handle_workerdata)
self.handle_item(b"newtaskhashes", self.handle_newtaskhashes)
self.handle_item(b"runtask", self.handle_runtask)
self.handle_item(b"finishnow", self.handle_finishnow)
self.handle_item(b"ping", self.handle_ping)
self.handle_item(b"quit", self.handle_quit)
for pipe in self.build_pipes:
if self.build_pipes[pipe].input in ready:
self.build_pipes[pipe].read()
if len(self.build_pids):
while self.process_waitpid():
continue
def handle_item(self, item, func):
opening_tag = b"<" + item + b">"
if not self.queue.startswith(opening_tag):
return
tag_len = len(opening_tag)
if len(self.queue) < tag_len + 4:
# we need to receive more data
return
header = self.queue[tag_len:tag_len + 4]
payload_len = int.from_bytes(header, 'big')
# closing tag has length (tag_len + 1)
if len(self.queue) < tag_len * 2 + 1 + payload_len:
# we need to receive more data
return
index = self.queue.find(b"</" + item + b">")
if index != -1:
try:
func(self.queue[(tag_len + 4):index])
except pickle.UnpicklingError:
workerlog_write("Unable to unpickle data: %s\n" % ":".join("{:02x}".format(c) for c in self.queue))
raise
self.queue = self.queue[(index + len(b"</") + len(item) + len(b">")):]
def handle_cookercfg(self, data):
self.cookercfg = pickle.loads(data)
self.databuilder = bb.cookerdata.CookerDataBuilder(self.cookercfg, worker=True)
self.databuilder.parseBaseConfiguration(worker=True)
self.data = self.databuilder.data
def handle_extraconfigdata(self, data):
self.extraconfigdata = pickle.loads(data)
def handle_workerdata(self, data):
self.workerdata = pickle.loads(data)
bb.build.verboseShellLogging = self.workerdata["build_verbose_shell"]
bb.build.verboseStdoutLogging = self.workerdata["build_verbose_stdout"]
bb.msg.loggerDefaultLogLevel = self.workerdata["logdefaultlevel"]
bb.msg.loggerDefaultDomains = self.workerdata["logdefaultdomain"]
for mc in self.databuilder.mcdata:
self.databuilder.mcdata[mc].setVar("PRSERV_HOST", self.workerdata["prhost"])
self.databuilder.mcdata[mc].setVar("BB_HASHSERVE", self.workerdata["hashservaddr"])
self.databuilder.mcdata[mc].setVar("__bbclasstype", "recipe")
def handle_newtaskhashes(self, data):
self.workerdata["newhashes"] = pickle.loads(data)
def handle_ping(self, _):
workerlog_write("Handling ping\n")
logger.warning("Pong from bitbake-worker!")
def handle_quit(self, data):
workerlog_write("Handling quit\n")
global normalexit
normalexit = True
sys.exit(0)
def handle_runtask(self, data):
runtask = pickle.loads(data)
fn = runtask['fn']
task = runtask['task']
taskname = runtask['taskname']
workerlog_write("Handling runtask %s %s %s\n" % (task, fn, taskname))
pid, pipein, pipeout = fork_off_task(self.cookercfg, self.data, self.databuilder, self.workerdata, self.extraconfigdata, runtask)
self.build_pids[pid] = task
self.build_pipes[pid] = runQueueWorkerPipe(pipein, pipeout)
def process_waitpid(self):
"""
Return none is there are no processes awaiting result collection, otherwise
collect the process exit codes and close the information pipe.
"""
try:
pid, status = os.waitpid(-1, os.WNOHANG)
if pid == 0 or os.WIFSTOPPED(status):
return False
except OSError:
return False
workerlog_write("Exit code of %s for pid %s\n" % (status, pid))
if os.WIFEXITED(status):
status = os.WEXITSTATUS(status)
elif os.WIFSIGNALED(status):
# Per shell conventions for $?, when a process exits due to
# a signal, we return an exit code of 128 + SIGNUM
status = 128 + os.WTERMSIG(status)
task = self.build_pids[pid]
del self.build_pids[pid]
self.build_pipes[pid].close()
del self.build_pipes[pid]
worker_fire_prepickled(b"<exitcode>" + pickle.dumps((task, status)) + b"</exitcode>")
return True
def handle_finishnow(self, _):
if self.build_pids:
logger.info("Sending SIGTERM to remaining %s tasks", len(self.build_pids))
for k, v in iter(self.build_pids.items()):
try:
os.kill(-k, signal.SIGTERM)
os.waitpid(-1, 0)
except:
pass
for pipe in self.build_pipes:
self.build_pipes[pipe].read()
try:
worker = BitbakeWorker(os.fdopen(sys.stdin.fileno(), 'rb'))
if not profiling:
worker.serve()
else:
profname = "profile-worker.log"
prof = profile.Profile()
try:
profile.Profile.runcall(prof, worker.serve)
finally:
prof.dump_stats(profname)
bb.utils.process_profilelog(profname)
except BaseException as e:
if not normalexit:
import traceback
sys.stderr.write(traceback.format_exc())
sys.stderr.write(str(e))
finally:
worker_thread_exit = True
worker_thread.join()
workerlog_write("exiting")
if not normalexit:
sys.exit(1)
sys.exit(0)

175
bitbake/bin/git-make-shallow Executable file
View File

@@ -0,0 +1,175 @@
#!/usr/bin/env python3
#
# Copyright BitBake Contributors
#
# SPDX-License-Identifier: GPL-2.0-only
#
"""git-make-shallow: make the current git repository shallow
Remove the history of the specified revisions, then optionally filter the
available refs to those specified.
"""
import argparse
import collections
import errno
import itertools
import os
import subprocess
import sys
import warnings
warnings.simplefilter("default")
version = 1.0
git_cmd = ['git', '-c', 'safe.bareRepository=all']
def main():
if sys.version_info < (3, 4, 0):
sys.exit('Python 3.4 or greater is required')
git_dir = check_output(git_cmd + ['rev-parse', '--git-dir']).rstrip()
shallow_file = os.path.join(git_dir, 'shallow')
if os.path.exists(shallow_file):
try:
check_output(git_cmd + ['fetch', '--unshallow'])
except subprocess.CalledProcessError:
try:
os.unlink(shallow_file)
except OSError as exc:
if exc.errno != errno.ENOENT:
raise
args = process_args()
revs = check_output(git_cmd + ['rev-list'] + args.revisions).splitlines()
make_shallow(shallow_file, args.revisions, args.refs)
ref_revs = check_output(git_cmd + ['rev-list'] + args.refs).splitlines()
remaining_history = set(revs) & set(ref_revs)
for rev in remaining_history:
if check_output(git_cmd + ['rev-parse', '{}^@'.format(rev)]):
sys.exit('Error: %s was not made shallow' % rev)
filter_refs(args.refs)
if args.shrink:
shrink_repo(git_dir)
subprocess.check_call(git_cmd + ['fsck', '--unreachable'])
def process_args():
# TODO: add argument to automatically keep local-only refs, since they
# can't be easily restored with a git fetch.
parser = argparse.ArgumentParser(description='Remove the history of the specified revisions, then optionally filter the available refs to those specified.')
parser.add_argument('--ref', '-r', metavar='REF', action='append', dest='refs', help='remove all but the specified refs (cumulative)')
parser.add_argument('--shrink', '-s', action='store_true', help='shrink the git repository by repacking and pruning')
parser.add_argument('revisions', metavar='REVISION', nargs='+', help='a git revision/commit')
if len(sys.argv) < 2:
parser.print_help()
sys.exit(2)
args = parser.parse_args()
if args.refs:
args.refs = check_output(git_cmd + ['rev-parse', '--symbolic-full-name'] + args.refs).splitlines()
else:
args.refs = get_all_refs(lambda r, t, tt: t == 'commit' or tt == 'commit')
args.refs = list(filter(lambda r: not r.endswith('/HEAD'), args.refs))
args.revisions = check_output(git_cmd + ['rev-parse'] + ['%s^{}' % i for i in args.revisions]).splitlines()
return args
def check_output(cmd, input=None):
return subprocess.check_output(cmd, universal_newlines=True, input=input)
def make_shallow(shallow_file, revisions, refs):
"""Remove the history of the specified revisions."""
for rev in follow_history_intersections(revisions, refs):
print("Processing %s" % rev)
with open(shallow_file, 'a') as f:
f.write(rev + '\n')
def get_all_refs(ref_filter=None):
"""Return all the existing refs in this repository, optionally filtering the refs."""
ref_output = check_output(git_cmd + ['for-each-ref', '--format=%(refname)\t%(objecttype)\t%(*objecttype)'])
ref_split = [tuple(iter_extend(l.rsplit('\t'), 3)) for l in ref_output.splitlines()]
if ref_filter:
ref_split = (e for e in ref_split if ref_filter(*e))
refs = [r[0] for r in ref_split]
return refs
def iter_extend(iterable, length, obj=None):
"""Ensure that iterable is the specified length by extending with obj."""
return itertools.islice(itertools.chain(iterable, itertools.repeat(obj)), length)
def filter_refs(refs):
"""Remove all but the specified refs from the git repository."""
all_refs = get_all_refs()
to_remove = set(all_refs) - set(refs)
if to_remove:
check_output(git_cmd + ['update-ref', '--no-deref', '--stdin', '-z'],
input=''.join('delete ' + l + '\0\0' for l in to_remove))
def follow_history_intersections(revisions, refs):
"""Determine all the points where the history of the specified revisions intersects the specified refs."""
queue = collections.deque(revisions)
seen = set()
for rev in iter_except(queue.popleft, IndexError):
if rev in seen:
continue
parents = check_output(git_cmd + ['rev-parse', '%s^@' % rev]).splitlines()
yield rev
seen.add(rev)
if not parents:
continue
check_refs = check_output(git_cmd + ['merge-base', '--independent'] + sorted(refs)).splitlines()
for parent in parents:
for ref in check_refs:
print("Checking %s vs %s" % (parent, ref))
try:
merge_base = check_output(git_cmd + ['merge-base', parent, ref]).rstrip()
except subprocess.CalledProcessError:
continue
else:
queue.append(merge_base)
def iter_except(func, exception, start=None):
"""Yield a function repeatedly until it raises an exception."""
try:
if start is not None:
yield start()
while True:
yield func()
except exception:
pass
def shrink_repo(git_dir):
"""Shrink the newly shallow repository, removing the unreachable objects."""
subprocess.check_call(git_cmd + ['reflog', 'expire', '--expire-unreachable=now', '--all'])
subprocess.check_call(git_cmd + ['repack', '-ad'])
try:
os.unlink(os.path.join(git_dir, 'objects', 'info', 'alternates'))
except OSError as exc:
if exc.errno != errno.ENOENT:
raise
subprocess.check_call(git_cmd + ['prune', '--expire', 'now'])
if __name__ == '__main__':
main()

332
bitbake/bin/toaster Executable file
View File

@@ -0,0 +1,332 @@
#!/bin/echo ERROR: This script needs to be sourced. Please run as .
# toaster - shell script to start Toaster
# Copyright (C) 2013-2015 Intel Corp.
#
# SPDX-License-Identifier: GPL-2.0-or-later
#
HELP="
Usage 1: source toaster start|stop [webport=<address:port>] [noweb] [nobuild] [toasterdir]
Optional arguments:
[nobuild] Setup the environment for capturing builds with toaster but disable managed builds
[noweb] Setup the environment for capturing builds with toaster but don't start the web server
[webport] Set the development server (default: localhost:8000)
[toasterdir] Set absolute path to be used as TOASTER_DIR (default: BUILDDIR/../)
Usage 2: source toaster manage [createsuperuser|lsupdates|migrate|makemigrations|checksettings|collectstatic|...]
"
custom_extention()
{
custom_extension=$BBBASEDIR/lib/toaster/orm/fixtures/custom_toaster_append.sh
if [ -f $custom_extension ] ; then
$custom_extension $*
fi
}
databaseCheck()
{
retval=0
# you can always add a superuser later via
# ../bitbake/lib/toaster/manage.py createsuperuser --username=<ME>
$MANAGE migrate --noinput || retval=1
if [ $retval -eq 1 ]; then
echo "Failed migrations, halting system start" 1>&2
return $retval
fi
# Make sure that checksettings can pick up any value for TEMPLATECONF
export TEMPLATECONF
$MANAGE checksettings --traceback || retval=1
if [ $retval -eq 1 ]; then
printf "\nError while checking settings; exiting\n"
return $retval
fi
return $retval
}
webserverKillAll()
{
local pidfile
if [ -f ${BUILDDIR}/.toastermain.pid ] ; then
custom_extention web_stop_postpend
else
custom_extention noweb_stop_postpend
fi
for pidfile in ${BUILDDIR}/.toastermain.pid ${BUILDDIR}/.runbuilds.pid; do
if [ -f ${pidfile} ]; then
pid=`cat ${pidfile}`
while kill -0 $pid 2>/dev/null; do
kill -SIGTERM $pid 2>/dev/null
sleep 1
done
rm ${pidfile}
fi
done
}
webserverStartAll()
{
# do not start if toastermain points to a valid process
if ! cat "${BUILDDIR}/.toastermain.pid" 2>/dev/null | xargs -I{} kill -0 {} ; then
retval=1
rm "${BUILDDIR}/.toastermain.pid"
fi
retval=0
# check the database
databaseCheck || return 1
echo "Starting webserver..."
$MANAGE runserver --noreload "$ADDR_PORT" \
</dev/null >>${TOASTER_LOGS_DIR}/web.log 2>&1 \
& echo $! >${BUILDDIR}/.toastermain.pid
sleep 1
if ! cat "${BUILDDIR}/.toastermain.pid" | xargs -I{} kill -0 {} ; then
retval=1
rm "${BUILDDIR}/.toastermain.pid"
else
echo "Toaster development webserver started at http://$ADDR_PORT"
echo -e "\nYou can now run 'bitbake <target>' on the command line and monitor your build in Toaster.\nYou can also use a Toaster project to configure and run a build.\n"
custom_extention web_start_postpend $ADDR_PORT
fi
return $retval
}
INSTOPSYSTEM=0
# define the stop command
stop_system()
{
# prevent reentry
if [ $INSTOPSYSTEM -eq 1 ]; then return; fi
INSTOPSYSTEM=1
webserverKillAll
# unset exported variables
unset TOASTER_DIR
unset BITBAKE_UI
unset BBBASEDIR
trap - SIGHUP
#trap - SIGCHLD
INSTOPSYSTEM=0
}
verify_prereq() {
# Verify Django version
reqfile=$(python3 -c "import os; print(os.path.realpath('$BBBASEDIR/toaster-requirements.txt'))")
exp='s/Django\([><=]\+\)\([^,]\+\),\([><=]\+\)\(.\+\)/'
# expand version parts to 2 digits to support 1.10.x > 1.8
# (note:helper functions hard to insert in-line)
exp=$exp'import sys,django;'
exp=$exp'version=["%02d" % int(n) for n in django.get_version().split(".")];'
exp=$exp'vmin=["%02d" % int(n) for n in "\2".split(".")];'
exp=$exp'vmax=["%02d" % int(n) for n in "\4".split(".")];'
exp=$exp'sys.exit(not (version \1 vmin and version \3 vmax))'
exp=$exp'/p'
if ! sed -n "$exp" $reqfile | python3 - ; then
req=`grep ^Django $reqfile`
echo "This program needs $req"
echo "Please install with pip3 install -r $reqfile"
return 2
fi
return 0
}
# read command line parameters
if [ -n "$BASH_SOURCE" ] ; then
TOASTER=${BASH_SOURCE}
elif [ -n "$ZSH_NAME" ] ; then
TOASTER=${(%):-%x}
else
TOASTER=$0
fi
export BBBASEDIR=`dirname $TOASTER`/..
MANAGE="python3 $BBBASEDIR/lib/toaster/manage.py"
if [ -z "$OE_ROOT" ]; then
OE_ROOT=`dirname $TOASTER`/../..
fi
# this is the configuraton file we are using for toaster
# we are using the same logic that oe-setup-builddir uses
# (based on TEMPLATECONF and .templateconf) to determine
# which toasterconf.json to use.
# note: There are a number of relative path assumptions
# in the local layers that currently make using an arbitrary
# toasterconf.json difficult.
. $OE_ROOT/.templateconf
if [ -n "$TEMPLATECONF" ]; then
if [ ! -d "$TEMPLATECONF" ]; then
# Allow TEMPLATECONF=meta-xyz/conf as a shortcut
if [ -d "$OE_ROOT/$TEMPLATECONF" ]; then
TEMPLATECONF="$OE_ROOT/$TEMPLATECONF"
fi
fi
fi
unset OE_ROOT
WEBSERVER=1
export TOASTER_BUILDSERVER=1
ADDR_PORT="localhost:8000"
TOASTERDIR=`dirname $BUILDDIR`
# ${BUILDDIR}/toaster_logs/ became the default location for toaster logs
# This is needed for implemented django-log-viewer: https://pypi.org/project/django-log-viewer/
# If the directory does not exist, create it.
TOASTER_LOGS_DIR="${BUILDDIR}/toaster_logs/"
if [ ! -d $TOASTER_LOGS_DIR ]
then
mkdir $TOASTER_LOGS_DIR
fi
unset CMD
for param in $*; do
case $param in
noweb )
WEBSERVER=0
;;
nobuild )
TOASTER_BUILDSERVER=0
;;
start )
CMD=$param
;;
stop )
CMD=$param
;;
webport=*)
ADDR_PORT="${param#*=}"
# Split the addr:port string
ADDR=`echo $ADDR_PORT | cut -f 1 -d ':'`
PORT=`echo $ADDR_PORT | cut -f 2 -d ':'`
# If only a port has been speified then set address to localhost.
if [ $ADDR = $PORT ] ; then
ADDR_PORT="localhost:$PORT"
fi
;;
toasterdir=*)
TOASTERDIR="${param#*=}"
;;
manage )
CMD=$param
manage_cmd=""
;;
--help)
echo "$HELP"
return 0
;;
*)
if [ "manage" == "$CMD" ] ; then
manage_cmd="$manage_cmd $param"
else
echo "$HELP"
exit 1
fi
;;
esac
done
if [ `basename \"$0\"` = `basename \"${TOASTER}\"` ]; then
echo "Error: This script needs to be sourced. Please run as . $TOASTER"
return 1
fi
verify_prereq || return 1
# We make sure we're running in the current shell and in a good environment
if [ -z "$BUILDDIR" ] || ! which bitbake >/dev/null 2>&1 ; then
echo "Error: Build environment is not setup or bitbake is not in path." 1>&2
return 2
fi
# this defines the dir toaster will use for
# 1) clones of layers (in _toaster_clones )
# 2) the build dir (in build)
# 3) the sqlite db if that is being used.
# 4) pid's we need to clean up on exit/shutdown
export TOASTER_DIR=$TOASTERDIR
export BB_ENV_PASSTHROUGH_ADDITIONS="$BB_ENV_PASSTHROUGH_ADDITIONS TOASTER_DIR"
# Determine the action. If specified by arguments, fine, if not, toggle it
if [ "$CMD" = "start" ] ; then
if [ -n "$BBSERVER" ]; then
echo " Toaster is already running. Exiting..."
return 1
fi
elif [ "$CMD" = "" ]; then
echo "No command specified"
echo "$HELP"
return 1
fi
echo "The system will $CMD."
# Execute the commands
custom_extention toaster_prepend $CMD $ADDR_PORT
case $CMD in
start )
# check if addr:port is not in use
if [ "$CMD" == 'start' ]; then
if [ $WEBSERVER -gt 0 ]; then
$MANAGE checksocket "$ADDR_PORT" || return 1
fi
fi
# Create configuration file
conf=${BUILDDIR}/conf/local.conf
line='INHERIT+="toaster buildhistory"'
grep -q "$line" $conf || echo $line >> $conf
if [ $WEBSERVER -eq 0 ] ; then
# Do not update the database for "noweb" unless
# it does not yet exist
if [ ! -f "$TOASTER_DIR/toaster.sqlite" ] ; then
if ! databaseCheck; then
echo "Failed ${CMD}."
return 4
fi
fi
custom_extention noweb_start_postpend $ADDR_PORT
fi
if [ $WEBSERVER -gt 0 ] && ! webserverStartAll; then
echo "Failed ${CMD}."
return 4
fi
export BITBAKE_UI='toasterui'
if [ $TOASTER_BUILDSERVER -eq 1 ] ; then
$MANAGE runbuilds \
</dev/null >>${TOASTER_LOGS_DIR}/toaster_runbuilds.log 2>&1 \
& echo $! >${BUILDDIR}/.runbuilds.pid
else
echo "Toaster build server not started."
fi
# set fail safe stop system on terminal exit
trap stop_system SIGHUP
echo "Successful ${CMD}."
custom_extention toaster_postpend $CMD $ADDR_PORT
return 0
;;
stop )
stop_system
echo "Successful ${CMD}."
;;
manage )
cd $BBBASEDIR/lib/toaster
$MANAGE $manage_cmd
;;
esac
custom_extention toaster_postpend $CMD $ADDR_PORT

59
bitbake/bin/toaster-eventreplay Executable file
View File

@@ -0,0 +1,59 @@
#!/usr/bin/env python3
#
# Copyright (C) 2014 Alex Damian
#
# SPDX-License-Identifier: GPL-2.0-only
#
# This file re-uses code spread throughout other Bitbake source files.
# As such, all other copyrights belong to their own right holders.
#
"""
This command takes a filename as a single parameter. The filename is read
as a build eventlog, and the ToasterUI is used to process events in the file
and log data in the database
"""
import os
import sys
import json
import pickle
import codecs
import warnings
warnings.simplefilter("default")
from collections import namedtuple
# mangle syspath to allow easy import of modules
from os.path import join, dirname, abspath
sys.path.insert(0, join(dirname(dirname(abspath(__file__))), 'lib'))
import bb.cooker
from bb.ui import toasterui
from bb.ui import eventreplay
def main(argv):
with open(argv[-1]) as eventfile:
# load variables from the first line
variables = None
while line := eventfile.readline().strip():
try:
variables = json.loads(line)['allvariables']
break
except (KeyError, json.JSONDecodeError):
continue
if not variables:
sys.exit("Cannot find allvariables entry in event log file %s" % argv[-1])
eventfile.seek(0)
params = namedtuple('ConfigParams', ['observe_only'])(True)
player = eventreplay.EventPlayer(eventfile, variables)
return toasterui.main(player, player, params)
# run toaster ui on our mock bitbake class
if __name__ == "__main__":
if len(sys.argv) != 2:
print("Usage: %s <event file>" % os.path.basename(sys.argv[0]))
sys.exit(1)
sys.exit(main(sys.argv))

1
bitbake/contrib/README Normal file
View File

@@ -0,0 +1 @@
This directory is for additional contributed files which may be useful.

View File

@@ -0,0 +1,13 @@
{
"version": 1,
"loggers": {
"BitBake.SigGen.HashEquiv": {
"level": "VERBOSE",
"handlers": ["BitBake.verbconsole"]
},
"BitBake.RunQueue.HashEquiv": {
"level": "VERBOSE",
"handlers": ["BitBake.verbconsole"]
}
}
}

View File

@@ -0,0 +1,40 @@
#!/usr/bin/env python3
#
# Copyright OpenEmbedded Contributors
#
# SPDX-License-Identifier: MIT
#
# This script is to be called by b4:
# - through b4.send-auto-cc-cmd with "send-auto-cc-cmd" as first argument,
#
# When send-auto-cc-cmd is passed:
#
# This returns the list of Cc recipients for a patch.
#
# This script takes as stdin a patch.
import subprocess
import sys
cmd = sys.argv[1]
if cmd != "send-auto-cc-cmd":
sys.exit(-1)
patch = sys.stdin.read()
if subprocess.call(["which", "lsdiff"], stdout=subprocess.DEVNULL) != 0:
print("lsdiff missing from host, please install patchutils")
sys.exit(-1)
files = subprocess.check_output(["lsdiff", "--strip-match=1", "--strip=1", "--include=doc/*"],
input=patch, text=True)
if len(files):
print("docs@lists.yoctoproject.org")
else:
# Handle patches made with --no-prefix
files = subprocess.check_output(["lsdiff", "--include=doc/*"],
input=patch, text=True)
if len(files):
print("docs@lists.yoctoproject.org")
sys.exit(0)

31
bitbake/contrib/bbdev.sh Normal file
View File

@@ -0,0 +1,31 @@
# This is a shell function to be sourced into your shell or placed in your .profile,
# which makes setting things up for BitBake a bit easier.
#
# The author disclaims copyright to the contents of this file and places it in the
# public domain.
bbdev () {
local BBDIR PKGDIR BUILDDIR
if test x"$1" = "x--help"; then echo >&2 "syntax: bbdev [bbdir [pkgdir [builddir]]]"; return 1; fi
if test x"$1" = x; then BBDIR=`pwd`; else BBDIR=$1; fi
if test x"$2" = x; then PKGDIR=`pwd`; else PKGDIR=$2; fi
if test x"$3" = x; then BUILDDIR=`pwd`; else BUILDDIR=$3; fi
BBDIR=`readlink -f $BBDIR`
PKGDIR=`readlink -f $PKGDIR`
BUILDDIR=`readlink -f $BUILDDIR`
if ! (test -d $BBDIR && test -d $PKGDIR && test -d $BUILDDIR); then
echo >&2 "syntax: bbdev [bbdir [pkgdir [builddir]]]"
return 1
fi
PATH=$BBDIR/bin:$PATH
BBPATH=$BBDIR
if test x"$BBDIR" != x"$PKGDIR"; then
BBPATH=$PKGDIR:$BBPATH
fi
if test x"$PKGDIR" != x"$BUILDDIR"; then
BBPATH=$BUILDDIR:$BBPATH
fi
export BBPATH
}

View File

@@ -0,0 +1,89 @@
#! /usr/bin/env python3
#
# Copyright (C) 2020 Joshua Watt <JPEWhacker@gmail.com>
#
# SPDX-License-Identifier: MIT
import argparse
import os
import random
import shutil
import signal
import subprocess
import sys
import time
def try_unlink(path):
try:
os.unlink(path)
except:
pass
def main():
def cleanup():
shutil.rmtree("tmp/cache", ignore_errors=True)
try_unlink("bitbake-cookerdaemon.log")
try_unlink("bitbake.sock")
try_unlink("bitbake.lock")
parser = argparse.ArgumentParser(
description="Bitbake parser torture test",
epilog="""
A torture test for bitbake's parser. Repeatedly interrupts parsing until
bitbake decides to deadlock.
""",
)
args = parser.parse_args()
if not "BUILDDIR" in os.environ:
print(
"'BUILDDIR' not found in the environment. Did you initialize the build environment?"
)
return 1
os.chdir(os.environ["BUILDDIR"])
run_num = 0
while True:
if run_num % 100 == 0:
print("Calibrating wait time...")
cleanup()
start_time = time.monotonic()
r = subprocess.run(["bitbake", "-p"])
max_wait_time = time.monotonic() - start_time
if r.returncode != 0:
print("Calibration run exited with %d" % r.returncode)
return 1
print("Maximum wait time is %f seconds" % max_wait_time)
run_num += 1
wait_time = random.random() * max_wait_time
print("Run #%d" % run_num)
print("Will sleep for %f seconds" % wait_time)
cleanup()
with subprocess.Popen(["bitbake", "-p"]) as proc:
time.sleep(wait_time)
proc.send_signal(signal.SIGINT)
try:
proc.wait(45)
except subprocess.TimeoutExpired:
print("Run #%d: Waited too long. Possible deadlock!" % run_num)
proc.wait()
return 1
if proc.returncode == 0:
print("Exited successfully. Timeout too long?")
else:
print("Exited with %d" % proc.returncode)
if __name__ == "__main__":
sys.exit(main())

83
bitbake/contrib/dump_cache.py Executable file
View File

@@ -0,0 +1,83 @@
#!/usr/bin/env python3
#
# Copyright (C) 2012, 2018 Wind River Systems, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Used for dumping the bb_cache.dat
#
import os
import sys
import argparse
# For importing bb.cache
sys.path.insert(0, os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])), '../lib'))
from bb.cache import CoreRecipeInfo
import pickle
class DumpCache(object):
def __init__(self):
parser = argparse.ArgumentParser(
description="bb_cache.dat's dumper",
epilog="Use %(prog)s --help to get help")
parser.add_argument("-r", "--recipe",
help="specify the recipe, default: all recipes", action="store")
parser.add_argument("-m", "--members",
help = "specify the member, use comma as separator for multiple ones, default: all members", action="store", default="")
parser.add_argument("-s", "--skip",
help = "skip skipped recipes", action="store_true")
parser.add_argument("cachefile",
help = "specify bb_cache.dat", nargs = 1, action="store", default="")
self.args = parser.parse_args()
def main(self):
with open(self.args.cachefile[0], "rb") as cachefile:
pickled = pickle.Unpickler(cachefile)
while True:
try:
key = pickled.load()
val = pickled.load()
except Exception:
break
if isinstance(val, CoreRecipeInfo):
pn = val.pn
if self.args.recipe and self.args.recipe != pn:
continue
if self.args.skip and val.skipped:
continue
if self.args.members:
out = key
for member in self.args.members.split(','):
out += ": %s" % val.__dict__.get(member)
print("%s" % out)
else:
print("%s: %s" % (key, val.__dict__))
elif not self.args.recipe:
print("%s %s" % (key, val))
if __name__ == "__main__":
try:
dump = DumpCache()
ret = dump.main()
except Exception as esc:
ret = 1
import traceback
traceback.print_exc()
sys.exit(ret)

View File

@@ -0,0 +1,23 @@
# SPDX-License-Identifier: MIT
#
# Copyright (c) 2021 Joshua Watt <JPEWhacker@gmail.com>
#
# Dockerfile to build a bitbake hash equivalence server container
#
# From the root of the bitbake repository, run:
#
# docker build -f contrib/hashserv/Dockerfile .
#
FROM alpine:3.13.1
RUN apk add --no-cache python3 libgcc
COPY bin/bitbake-hashserv /opt/bbhashserv/bin/
COPY lib/hashserv /opt/bbhashserv/lib/hashserv/
COPY lib/bb /opt/bbhashserv/lib/bb/
COPY lib/codegen.py /opt/bbhashserv/lib/codegen.py
COPY lib/ply /opt/bbhashserv/lib/ply/
COPY lib/bs4 /opt/bbhashserv/lib/bs4/
ENTRYPOINT ["/opt/bbhashserv/bin/bitbake-hashserv"]

View File

@@ -0,0 +1,62 @@
# SPDX-License-Identifier: MIT
#
# Copyright (c) 2022 Daniel Gomez <daniel@qtec.com>
#
# Dockerfile to build a bitbake PR service container
#
# From the root of the bitbake repository, run:
#
# docker build -f contrib/prserv/Dockerfile . -t prserv
#
# Running examples:
#
# 1. PR Service in RW mode, port 18585:
#
# docker run --detach --tty \
# --env PORT=18585 \
# --publish 18585:18585 \
# --volume $PWD:/var/lib/bbprserv \
# prserv
#
# 2. PR Service in RO mode, default port (8585) and custom LOGFILE:
#
# docker run --detach --tty \
# --env DBMODE="--read-only" \
# --env LOGFILE=/var/lib/bbprserv/prservro.log \
# --publish 8585:8585 \
# --volume $PWD:/var/lib/bbprserv \
# prserv
#
FROM alpine:3.14.4
RUN apk add --no-cache python3
COPY bin/bitbake-prserv /opt/bbprserv/bin/
COPY lib/prserv /opt/bbprserv/lib/prserv/
COPY lib/bb /opt/bbprserv/lib/bb/
COPY lib/codegen.py /opt/bbprserv/lib/codegen.py
COPY lib/ply /opt/bbprserv/lib/ply/
COPY lib/bs4 /opt/bbprserv/lib/bs4/
ENV PATH=$PATH:/opt/bbprserv/bin
RUN mkdir -p /var/lib/bbprserv
ENV DBFILE=/var/lib/bbprserv/prserv.sqlite3 \
LOGFILE=/var/lib/bbprserv/prserv.log \
LOGLEVEL=debug \
HOST=0.0.0.0 \
PORT=8585 \
DBMODE=""
ENTRYPOINT [ "/bin/sh", "-c", \
"bitbake-prserv \
--file=$DBFILE \
--log=$LOGFILE \
--loglevel=$LOGLEVEL \
--start \
--host=$HOST \
--port=$PORT \
$DBMODE \
&& tail -f $LOGFILE"]

View File

@@ -0,0 +1,18 @@
The MIT License (MIT)
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,32 @@
" Vim filetype detection file
" Language: BitBake
" Author: Ricardo Salveti <rsalveti@rsalveti.net>
" Copyright: Copyright (C) 2008 Ricardo Salveti <rsalveti@rsalveti.net>
" Licence: You may redistribute this under the same terms as Vim itself
"
" This sets up the syntax highlighting for BitBake files, like .bb, .bbclass and .inc
if &compatible || version < 600 || exists("b:loaded_bitbake_plugin")
finish
endif
" .bb, .bbappend and .bbclass
au BufNewFile,BufRead *.{bb,bbappend,bbclass} setfiletype bitbake
" .inc -- meanwhile included upstream
if !has("patch-9.0.0055")
au BufNewFile,BufRead *.inc call s:BBIncDetect()
def s:BBIncDetect()
l:lines = getline(1) .. getline(2) .. getline(3)
if l:lines =~# '\<\%(require\|inherit\)\>' || lines =~# '[A-Z][A-Za-z0-9_:${}]*\s\+\%(??\|[?:+]\)\?= '
set filetype bitbake
endif
enddef
endif
" .conf
au BufNewFile,BufRead *.conf
\ if (match(expand("%:p:h"), "conf") > 0) |
\ set filetype=bitbake |
\ endif

View File

@@ -0,0 +1,13 @@
" Only do this when not done yet for this buffer
if exists("b:did_ftplugin")
finish
endif
" Don't load another plugin for this buffer
let b:did_ftplugin = 1
let b:undo_ftplugin = "setl cms< sts< sw< et< sua<"
setlocal commentstring=#\ %s
setlocal softtabstop=4 shiftwidth=4 expandtab
setlocal suffixesadd+=.bb,.bbclass

View File

@@ -0,0 +1,343 @@
" Vim indent file
" Language: BitBake
" Copyright: Copyright (C) 2019 Agilent Technologies, Inc.
" Maintainer: Chris Laplante <chris.laplante@agilent.com>
" License: You may redistribute this under the same terms as Vim itself
if exists("b:did_indent")
finish
endif
if exists("*BitbakeIndent")
finish
endif
runtime! indent/sh.vim
unlet b:did_indent
setlocal indentexpr=BitbakeIndent(v:lnum)
setlocal autoindent nolisp
function s:is_bb_python_func_def(lnum)
let stack = synstack(a:lnum, 1)
if len(stack) == 0
return 0
endif
let top = synIDattr(stack[0], "name")
echo top
return synIDattr(stack[0], "name") == "bbPyFuncDef"
endfunction
"""" begin modified from indent/python.vim, upstream commit 7a9bd7c1e0ce1baf5a02daf36eeae3638aa315c7
"""" This copied code is licensed the same as Vim itself.
setlocal indentkeys+=<:>,=elif,=except
let s:keepcpo= &cpo
set cpo&vim
let s:maxoff = 50 " maximum number of lines to look backwards for ()
function! GetBBPythonIndent(lnum)
" If this line is explicitly joined: If the previous line was also joined,
" line it up with that one, otherwise add two 'shiftwidth'
if getline(a:lnum - 1) =~ '\\$'
if a:lnum > 1 && getline(a:lnum - 2) =~ '\\$'
return indent(a:lnum - 1)
endif
return indent(a:lnum - 1) + (exists("g:pyindent_continue") ? eval(g:pyindent_continue) : (shiftwidth() * 2))
endif
" If the start of the line is in a string don't change the indent.
if has('syntax_items')
\ && synIDattr(synID(a:lnum, 1, 1), "name") =~ "String$"
return -1
endif
" Search backwards for the previous non-empty line.
let plnum = prevnonblank(v:lnum - 1)
if plnum == 0
" This is the first non-empty line, use zero indent.
return 0
endif
call cursor(plnum, 1)
" Identing inside parentheses can be very slow, regardless of the searchpair()
" timeout, so let the user disable this feature if he doesn't need it
let disable_parentheses_indenting = get(g:, "pyindent_disable_parentheses_indenting", 0)
if disable_parentheses_indenting == 1
let plindent = indent(plnum)
let plnumstart = plnum
else
" searchpair() can be slow sometimes, limit the time to 150 msec or what is
" put in g:pyindent_searchpair_timeout
let searchpair_stopline = 0
let searchpair_timeout = get(g:, 'pyindent_searchpair_timeout', 150)
" If the previous line is inside parenthesis, use the indent of the starting
" line.
" Trick: use the non-existing "dummy" variable to break out of the loop when
" going too far back.
let parlnum = searchpair('(\|{\|\[', '', ')\|}\|\]', 'nbW',
\ "line('.') < " . (plnum - s:maxoff) . " ? dummy :"
\ . " synIDattr(synID(line('.'), col('.'), 1), 'name')"
\ . " =~ '\\(Comment\\|Todo\\|String\\)$'",
\ searchpair_stopline, searchpair_timeout)
if parlnum > 0
" We may have found the opening brace of a BitBake Python task, e.g. 'python do_task {'
" If so, ignore it here - it will be handled later.
if s:is_bb_python_func_def(parlnum)
let parlnum = 0
let plindent = indent(plnum)
let plnumstart = plnum
else
let plindent = indent(parlnum)
let plnumstart = parlnum
endif
else
let plindent = indent(plnum)
let plnumstart = plnum
endif
" When inside parenthesis: If at the first line below the parenthesis add
" two 'shiftwidth', otherwise same as previous line.
" i = (a
" + b
" + c)
call cursor(a:lnum, 1)
let p = searchpair('(\|{\|\[', '', ')\|}\|\]', 'bW',
\ "line('.') < " . (a:lnum - s:maxoff) . " ? dummy :"
\ . " synIDattr(synID(line('.'), col('.'), 1), 'name')"
\ . " =~ '\\(Comment\\|Todo\\|String\\)$'",
\ searchpair_stopline, searchpair_timeout)
if p > 0
if s:is_bb_python_func_def(p)
" Handle first non-empty line inside a BB Python task
if p == plnum
return shiftwidth()
endif
" Handle the user actually trying to close a BitBake Python task
let line = getline(a:lnum)
if line =~ '^\s*}'
return -2
endif
" Otherwise ignore the brace
let p = 0
else
if p == plnum
" When the start is inside parenthesis, only indent one 'shiftwidth'.
let pp = searchpair('(\|{\|\[', '', ')\|}\|\]', 'bW',
\ "line('.') < " . (a:lnum - s:maxoff) . " ? dummy :"
\ . " synIDattr(synID(line('.'), col('.'), 1), 'name')"
\ . " =~ '\\(Comment\\|Todo\\|String\\)$'",
\ searchpair_stopline, searchpair_timeout)
if pp > 0
return indent(plnum) + (exists("g:pyindent_nested_paren") ? eval(g:pyindent_nested_paren) : shiftwidth())
endif
return indent(plnum) + (exists("g:pyindent_open_paren") ? eval(g:pyindent_open_paren) : (shiftwidth() * 2))
endif
if plnumstart == p
return indent(plnum)
endif
return plindent
endif
endif
endif
" Get the line and remove a trailing comment.
" Use syntax highlighting attributes when possible.
let pline = getline(plnum)
let pline_len = strlen(pline)
if has('syntax_items')
" If the last character in the line is a comment, do a binary search for
" the start of the comment. synID() is slow, a linear search would take
" too long on a long line.
if synIDattr(synID(plnum, pline_len, 1), "name") =~ "\\(Comment\\|Todo\\)$"
let min = 1
let max = pline_len
while min < max
let col = (min + max) / 2
if synIDattr(synID(plnum, col, 1), "name") =~ "\\(Comment\\|Todo\\)$"
let max = col
else
let min = col + 1
endif
endwhile
let pline = strpart(pline, 0, min - 1)
endif
else
let col = 0
while col < pline_len
if pline[col] == '#'
let pline = strpart(pline, 0, col)
break
endif
let col = col + 1
endwhile
endif
" If the previous line ended with a colon, indent this line
if pline =~ ':\s*$'
return plindent + shiftwidth()
endif
" If the previous line was a stop-execution statement...
" TODO: utilize this logic to deindent when ending a bbPyDefRegion
if getline(plnum) =~ '^\s*\(break\|continue\|raise\|return\|pass\|bb\.fatal\)\>'
" See if the user has already dedented
if indent(a:lnum) > indent(plnum) - shiftwidth()
" If not, recommend one dedent
return indent(plnum) - shiftwidth()
endif
" Otherwise, trust the user
return -1
endif
" If the current line begins with a keyword that lines up with "try"
if getline(a:lnum) =~ '^\s*\(except\|finally\)\>'
let lnum = a:lnum - 1
while lnum >= 1
if getline(lnum) =~ '^\s*\(try\|except\)\>'
let ind = indent(lnum)
if ind >= indent(a:lnum)
return -1 " indent is already less than this
endif
return ind " line up with previous try or except
endif
let lnum = lnum - 1
endwhile
return -1 " no matching "try"!
endif
" If the current line begins with a header keyword, dedent
if getline(a:lnum) =~ '^\s*\(elif\|else\)\>'
" Unless the previous line was a one-liner
if getline(plnumstart) =~ '^\s*\(for\|if\|try\)\>'
return plindent
endif
" Or the user has already dedented
if indent(a:lnum) <= plindent - shiftwidth()
return -1
endif
return plindent - shiftwidth()
endif
" When after a () construct we probably want to go back to the start line.
" a = (b
" + c)
" here
if parlnum > 0
return plindent
endif
return -1
endfunction
let &cpo = s:keepcpo
unlet s:keepcpo
""" end of stuff from indent/python.vim
let b:did_indent = 1
setlocal indentkeys+=0\"
function! BitbakeIndent(lnum)
if !has('syntax_items')
return -1
endif
let stack = synstack(a:lnum, 1)
if len(stack) == 0
return -1
endif
let name = synIDattr(stack[0], "name")
" TODO: support different styles of indentation for assignments. For now,
" we only support like this:
" VAR = " \
" value1 \
" value2 \
" "
"
" i.e. each value indented by shiftwidth(), with the final quote " completely unindented.
if name == "bbVarValue"
" Quote handling is tricky. kernel.bbclass has this line for instance:
" EXTRA_OEMAKE = " HOSTCC="${BUILD_CC} ${BUILD_CFLAGS} ${BUILD_LDFLAGS}" " HOSTCPP="${BUILD_CPP}""
" Instead of trying to handle crazy cases like that, just assume that a
" double-quote on a line by itself (following an assignment) means the
" user is closing the assignment, and de-dent.
if getline(a:lnum) =~ '^\s*"$'
return 0
endif
let prevstack = synstack(a:lnum - 1, 1)
if len(prevstack) == 0
return -1
endif
let prevname = synIDattr(prevstack[0], "name")
" Only indent if there was actually a continuation character on
" the previous line, to avoid misleading indentation.
let prevlinelastchar = synIDattr(synID(a:lnum - 1, col([a:lnum - 1, "$"]) - 1, 1), "name")
let prev_continued = prevlinelastchar == "bbContinue"
" Did the previous line introduce an assignment?
if index(["bbVarDef", "bbVarFlagDef"], prevname) != -1
if prev_continued
return shiftwidth()
endif
endif
if !prev_continued
return 0
endif
" Autoindent can take it from here
return -1
endif
if index(["bbPyDefRegion", "bbPyFuncRegion"], name) != -1
let ret = GetBBPythonIndent(a:lnum)
" Should normally always be indented by at least one shiftwidth; but allow
" return of -1 (defer to autoindent) or -2 (force indent to 0)
if ret == 0
return shiftwidth()
elseif ret == -2
return 0
endif
return ret
endif
" TODO: GetShIndent doesn't detect tasks prepended with 'fakeroot'
" Need to submit a patch upstream to Vim to provide an extension point.
" Unlike the Python indenter, the Sh indenter is way too large to copy and
" modify here.
if name == "bbShFuncRegion"
return GetShIndent()
endif
" TODO:
" + heuristics for de-denting out of a bbPyDefRegion? e.g. when the user
" types an obvious BB keyword like addhandler or addtask, or starts
" writing a shell task. Maybe too hard to implement...
return -1
endfunction

View File

@@ -0,0 +1,88 @@
" Vim plugin file
" Purpose: Create a template for new bb files
" Author: Ricardo Salveti <rsalveti@gmail.com>
" Copyright: Copyright (C) 2008 Ricardo Salveti <rsalveti@gmail.com>
"
" This file is licensed under the MIT license, see COPYING.MIT in
" this source distribution for the terms.
"
" Based on the gentoo-syntax package
"
" Will try to use git to find the user name and email
if &compatible || v:version < 600 || exists("b:loaded_bitbake_plugin")
finish
endif
fun! <SID>GetUserName()
let l:user_name = system("git config --get user.name")
if v:shell_error
return "Unknown User"
else
return substitute(l:user_name, "\n", "", "")
endfun
fun! <SID>GetUserEmail()
let l:user_email = system("git config --get user.email")
if v:shell_error
return "unknown@user.org"
else
return substitute(l:user_email, "\n", "", "")
endfun
fun! BBHeader()
let l:current_year = strftime("%Y")
let l:user_name = <SID>GetUserName()
let l:user_email = <SID>GetUserEmail()
0 put ='# Copyright (C) ' . l:current_year .
\ ' ' . l:user_name . ' <' . l:user_email . '>'
put ='# Released under the MIT license (see COPYING.MIT for the terms)'
$
endfun
fun! NewBBTemplate()
if line2byte(line('$') + 1) != -1
return
endif
let l:paste = &paste
set nopaste
" Get the header
call BBHeader()
" New the bb template
put ='SUMMARY = \"\"'
put ='HOMEPAGE = \"\"'
put ='LICENSE = \"\"'
put ='SECTION = \"\"'
put ='DEPENDS = \"\"'
put =''
put ='SRC_URI = \"\"'
" Go to the first place to edit
0
/^SUMMARY =/
exec "normal 2f\""
if paste == 1
set paste
endif
endfun
if !exists("g:bb_create_on_empty")
let g:bb_create_on_empty = 1
endif
" disable in case of vimdiff
if v:progname =~ "vimdiff"
let g:bb_create_on_empty = 0
endif
augroup NewBB
au BufNewFile,BufReadPost *.bb
\ if g:bb_create_on_empty |
\ call NewBBTemplate() |
\ endif
augroup END

View File

@@ -0,0 +1,46 @@
" Vim plugin file
" Purpose: Create a template for new bbappend file
" Author: Joshua Watt <JPEWhacker@gmail.com>
" Copyright: Copyright (C) 2017 Joshua Watt <JPEWhacker@gmail.com>
"
" This file is licensed under the MIT license, see COPYING.MIT in
" this source distribution for the terms.
"
if &compatible || v:version < 600 || exists("b:loaded_bitbake_plugin")
finish
endif
fun! NewBBAppendTemplate()
if line2byte(line('$') + 1) != -1
return
endif
let l:paste = &paste
set nopaste
" New bbappend template
0 put ='FILESEXTRAPATHS:prepend := \"${THISDIR}/${PN}:\"'
2
if paste == 1
set paste
endif
endfun
if !exists("g:bb_create_on_empty")
let g:bb_create_on_empty = 1
endif
" disable in case of vimdiff
if v:progname =~ "vimdiff"
let g:bb_create_on_empty = 0
endif
augroup NewBBAppend
au BufNewFile,BufReadPost *.bbappend
\ if g:bb_create_on_empty |
\ call NewBBAppendTemplate() |
\ endif
augroup END

View File

@@ -0,0 +1,131 @@
" Vim syntax file
" Language: BitBake bb/bbclasses/inc
" Author: Chris Larson <kergoth@handhelds.org>
" Ricardo Salveti <rsalveti@rsalveti.net>
" Copyright: Copyright (C) 2004 Chris Larson <kergoth@handhelds.org>
" Copyright (C) 2008 Ricardo Salveti <rsalveti@rsalveti.net>
"
" This file is licensed under the MIT license, see COPYING.MIT in
" this source distribution for the terms.
"
" Syntax highlighting for bb, bbclasses and inc files.
"
" It's an entirely new type, just has specific syntax in shell and python code
if &compatible || v:version < 600 || exists("b:loaded_bitbake_plugin")
finish
endif
if exists("b:current_syntax")
finish
endif
syn include @python syntax/python.vim
if exists("b:current_syntax")
unlet b:current_syntax
endif
" BitBake syntax
" Matching case
syn case match
" Indicates the error when nothing is matched
syn match bbUnmatched "."
" Comments
syn cluster bbCommentGroup contains=bbTodo,@Spell
syn keyword bbTodo COMBAK FIXME TODO XXX contained
syn match bbComment "#.*$" contains=@bbCommentGroup
" String helpers
syn match bbQuote +['"]+ contained
syn match bbDelimiter "[(){}=]" contained
syn match bbArrayBrackets "[\[\]]" contained
" BitBake strings
syn match bbContinue "\\$"
syn region bbString matchgroup=bbQuote start=+"+ skip=+\\$+ end=+"+ contained contains=bbTodo,bbContinue,bbVarDeref,bbVarPyValue,@Spell
syn region bbString matchgroup=bbQuote start=+'+ skip=+\\$+ end=+'+ contained contains=bbTodo,bbContinue,bbVarDeref,bbVarPyValue,@Spell
" Vars definition
syn match bbExport "^export" nextgroup=bbIdentifier skipwhite
syn keyword bbExportFlag export contained nextgroup=bbIdentifier skipwhite
syn match bbIdentifier "[a-zA-Z0-9\-_\.\/\+]\+" display contained
syn match bbVarDeref "${[a-zA-Z0-9\-_:\.\/\+]\+}" contained
syn match bbVarEq "\(:=\|+=\|=+\|\.=\|=\.\|?=\|??=\|=\)" contained nextgroup=bbVarValue
syn match bbVarDef "^\(export\s*\)\?\([a-zA-Z0-9\-_\.\/\+][${}a-zA-Z0-9\-_:\.\/\+]*\)\s*\(:=\|+=\|=+\|\.=\|=\.\|?=\|??=\|=\)\@=" contains=bbExportFlag,bbIdentifier,bbOverrideOperator,bbVarDeref nextgroup=bbVarEq
syn match bbVarValue ".*$" contained contains=bbString,bbVarDeref,bbVarPyValue
syn region bbVarPyValue start=+${@+ skip=+\\$+ end=+}+ contained contains=@python
" Vars metadata flags
syn match bbVarFlagDef "^\([a-zA-Z0-9\-_\.]\+\)\(\[[a-zA-Z0-9\-_\.+]\+\]\)\@=" contains=bbIdentifier nextgroup=bbVarFlagFlag
syn region bbVarFlagFlag matchgroup=bbArrayBrackets start="\[" end="\]\s*\(:=\|=\|.=\|=.|+=\|=+\|?=\)\@=" contained contains=bbIdentifier nextgroup=bbVarEq
" Includes and requires
syn keyword bbInclude inherit include require contained
syn match bbIncludeRest ".*$" contained contains=bbString,bbVarDeref,bbVarPyValue
syn match bbIncludeLine "^\(inherit\|include\|require\)\s\+" contains=bbInclude nextgroup=bbIncludeRest
" Add taks and similar
syn keyword bbStatement addtask deltask addhandler after before EXPORT_FUNCTIONS contained
syn match bbStatementRest /[^\\]*$/ skipwhite contained contains=bbStatement,bbVarDeref,bbVarPyValue
syn region bbStatementRestCont start=/.*\\$/ end=/^[^\\]*$/ contained contains=bbStatement,bbVarDeref,bbVarPyValue,bbContinue keepend
syn match bbStatementLine "^\(addtask\|deltask\|addhandler\|after\|before\|EXPORT_FUNCTIONS\)\s\+" contains=bbStatement nextgroup=bbStatementRest,bbStatementRestCont
" OE Important Functions
syn keyword bbOEFunctions do_fetch do_unpack do_patch do_configure do_compile do_stage do_install do_package contained
" Generic Functions
syn match bbFunction "\h[0-9A-Za-z_\-\.]*" display contained contains=bbOEFunctions
syn keyword bbOverrideOperator append prepend remove contained
" BitBake shell metadata
syn include @shell syntax/sh.vim
if exists("b:current_syntax")
unlet b:current_syntax
endif
syn keyword bbShFakeRootFlag fakeroot contained
syn match bbShFuncDef "^\(fakeroot\s*\)\?\([\.0-9A-Za-z_:${}\-\.]\+\)\(python\)\@<!\(\s*()\s*\)\({\)\@=" contains=bbShFakeRootFlag,bbFunction,bbOverrideOperator,bbVarDeref,bbDelimiter nextgroup=bbShFuncRegion skipwhite
syn region bbShFuncRegion matchgroup=bbDelimiter start="{\s*$" end="^}\s*$" contained contains=@shell
" Python value inside shell functions
syn region shDeref start=+${@+ skip=+\\$+ excludenl end=+}+ contained contains=@python
" BitBake python metadata
syn keyword bbPyFlag python contained
syn match bbPyFuncDef "^\(fakeroot\s*\)\?\(python\)\(\s\+[0-9A-Za-z_:${}\-\.]\+\)\?\(\s*()\s*\)\({\)\@=" contains=bbShFakeRootFlag,bbPyFlag,bbFunction,bbOverrideOperator,bbVarDeref,bbDelimiter nextgroup=bbPyFuncRegion skipwhite
syn region bbPyFuncRegion matchgroup=bbDelimiter start="{\s*$" end="^}\s*$" contained contains=@python
" BitBake 'def'd python functions
syn keyword bbPyDef def contained
syn region bbPyDefRegion start='^\(def\s\+\)\([0-9A-Za-z_-]\+\)\(\s*(.*)\s*\):\s*$' end='^\(\s\|$\)\@!' contains=@python
" Highlighting Definitions
hi def link bbUnmatched Error
hi def link bbInclude Include
hi def link bbTodo Todo
hi def link bbComment Comment
hi def link bbQuote String
hi def link bbString String
hi def link bbDelimiter Keyword
hi def link bbArrayBrackets Statement
hi def link bbContinue Special
hi def link bbExport Type
hi def link bbExportFlag Type
hi def link bbIdentifier Identifier
hi def link bbVarDeref PreProc
hi def link bbVarDef Identifier
hi def link bbVarValue String
hi def link bbShFakeRootFlag Type
hi def link bbFunction Function
hi def link bbPyFlag Type
hi def link bbPyDef Statement
hi def link bbStatement Statement
hi def link bbStatementRest Identifier
hi def link bbStatementRestCont Identifier
hi def link bbOEFunctions Special
hi def link bbVarPyValue PreProc
hi def link bbOverrideOperator Operator
let b:current_syntax = "bb"

1
bitbake/doc/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
_build/

339
bitbake/doc/COPYING.GPL Normal file
View File

@@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

17
bitbake/doc/COPYING.MIT Normal file
View File

@@ -0,0 +1,17 @@
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
THE USE OR OTHER DEALINGS IN THE SOFTWARE.

35
bitbake/doc/Makefile Normal file
View File

@@ -0,0 +1,35 @@
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?= -W --keep-going -j auto
SPHINXBUILD ?= sphinx-build
SOURCEDIR = .
BUILDDIR = _build
DESTDIR = final
ifeq ($(shell if which $(SPHINXBUILD) >/dev/null 2>&1; then echo 1; else echo 0; fi),0)
$(error "The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed")
endif
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile clean publish
publish: Makefile html singlehtml
rm -rf $(BUILDDIR)/$(DESTDIR)/
mkdir -p $(BUILDDIR)/$(DESTDIR)/
cp -r $(BUILDDIR)/html/* $(BUILDDIR)/$(DESTDIR)/
cp $(BUILDDIR)/singlehtml/index.html $(BUILDDIR)/$(DESTDIR)/singleindex.html
sed -i -e 's@index.html#@singleindex.html#@g' $(BUILDDIR)/$(DESTDIR)/singleindex.html
clean:
@rm -rf $(BUILDDIR)
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

55
bitbake/doc/README Normal file
View File

@@ -0,0 +1,55 @@
Documentation
=============
This is the directory that contains the BitBake documentation.
Manual Organization
===================
Folders exist for individual manuals as follows:
* bitbake-user-manual --- The BitBake User Manual
Each folder is self-contained regarding content and figures.
If you want to find HTML versions of the BitBake manuals on the web,
go to https://www.openembedded.org/wiki/Documentation.
Sphinx
======
The BitBake documentation was migrated from the original DocBook
format to Sphinx based documentation for the Yocto Project 3.2
release.
Additional information related to the Sphinx migration, and guidelines
for developers willing to contribute to the BitBake documentation can
be found in the Yocto Project Documentation README file:
https://git.yoctoproject.org/cgit/cgit.cgi/yocto-docs/tree/documentation/README
How to build the Yocto Project documentation
============================================
Sphinx is written in Python. While it might work with Python2, for
obvious reasons, we will only support building the BitBake
documentation with Python3.
Sphinx might be available in your Linux distro packages repositories,
however it is not recommend using distro packages, as they might be
old versions, especially if you are using an LTS version of your
distro. The recommended method to install Sphinx and all required
dependencies is to use the Python Package Index (pip).
To install all required packages run:
$ pip3 install sphinx sphinx_rtd_theme pyyaml
To build the documentation locally, run:
$ cd doc
$ make html
The resulting HTML index page will be _build/html/index.html, and you
can browse your own copy of the locally generated documentation with
your browser.

14
bitbake/doc/_templates/breadcrumbs.html vendored Normal file
View File

@@ -0,0 +1,14 @@
{% extends "!breadcrumbs.html" %}
{% block breadcrumbs %}
<li>
<span class="doctype_switcher_placeholder">{{ doctype or 'single' }}</span>
<span class="version_switcher_placeholder">{{ release }}</span>
</li>
<li> &raquo;</li>
{% for doc in parents %}
<li><a href="{{ doc.link|e }}">{{ doc.title }}</a> &raquo;</li>
{% endfor %}
<li>{{ title }}</li>
{% endblock %}

9
bitbake/doc/_templates/footer.html vendored Normal file
View File

@@ -0,0 +1,9 @@
<footer>
<hr/>
<div role="contentinfo">
<p>&copy; Copyright {{ copyright }}
<br>Last updated on {{ last_updated }} from the <a href="https://git.openembedded.org/bitbake/">bitbake</a> git repository.
</p>
</div>
</footer>

7
bitbake/doc/_templates/layout.html vendored Normal file
View File

@@ -0,0 +1,7 @@
{% extends "!layout.html" %}
{% block extrabody %}
<div id="outdated-warning" style="text-align: center; background-color: #FFBABA; color: #6A0E0E;">
</div>
{% endblock %}

View File

@@ -0,0 +1,761 @@
.. SPDX-License-Identifier: CC-BY-2.5
=========
Execution
=========
|
The primary purpose for running BitBake is to produce some kind of
output such as a single installable package, a kernel, a software
development kit, or even a full, board-specific bootable Linux image,
complete with bootloader, kernel, and root filesystem. Of course, you
can execute the ``bitbake`` command with options that cause it to
execute single tasks, compile single recipe files, capture or clear
data, or simply return information about the execution environment.
This chapter describes BitBake's execution process from start to finish
when you use it to create an image. The execution process is launched
using the following command form::
$ bitbake target
For information on
the BitBake command and its options, see ":ref:`The BitBake Command
<bitbake-user-manual-command>`" section.
.. note::
Prior to executing BitBake, you should take advantage of available
parallel thread execution on your build host by setting the
:term:`BB_NUMBER_THREADS` variable in
your project's ``local.conf`` configuration file.
A common method to determine this value for your build host is to run
the following::
$ grep processor /proc/cpuinfo
This command returns
the number of processors, which takes into account hyper-threading.
Thus, a quad-core build host with hyper-threading most likely shows
eight processors, which is the value you would then assign to
:term:`BB_NUMBER_THREADS`.
A possibly simpler solution is that some Linux distributions (e.g.
Debian and Ubuntu) provide the ``ncpus`` command.
Parsing the Base Configuration Metadata
=======================================
The first thing BitBake does is parse base configuration metadata. Base
configuration metadata consists of your project's ``bblayers.conf`` file
to determine what layers BitBake needs to recognize, all necessary
``layer.conf`` files (one from each layer), and ``bitbake.conf``. The
data itself is of various types:
- **Recipes:** Details about particular pieces of software.
- **Class Data:** An abstraction of common build information (e.g. how to
build a Linux kernel).
- **Configuration Data:** Machine-specific settings, policy decisions,
and so forth. Configuration data acts as the glue to bind everything
together.
The ``layer.conf`` files are used to construct key variables such as
:term:`BBPATH` and :term:`BBFILES`.
:term:`BBPATH` is used to search for configuration and class files under the
``conf`` and ``classes`` directories, respectively. :term:`BBFILES` is used
to locate both recipe and recipe append files (``.bb`` and
``.bbappend``). If there is no ``bblayers.conf`` file, it is assumed the
user has set the :term:`BBPATH` and :term:`BBFILES` directly in the environment.
Next, the ``bitbake.conf`` file is located using the :term:`BBPATH` variable
that was just constructed. The ``bitbake.conf`` file may also include
other configuration files using the ``include`` or ``require``
directives.
Prior to parsing configuration files, BitBake looks at certain
variables, including:
- :term:`BB_ENV_PASSTHROUGH`
- :term:`BB_ENV_PASSTHROUGH_ADDITIONS`
- :term:`BB_PRESERVE_ENV`
- :term:`BB_ORIGENV`
- :term:`BITBAKE_UI`
The first four variables in this list relate to how BitBake treats shell
environment variables during task execution. By default, BitBake cleans
the environment variables and provides tight control over the shell
execution environment. However, through the use of these first four
variables, you can apply your control regarding the environment
variables allowed to be used by BitBake in the shell during execution of
tasks. See the
":ref:`bitbake-user-manual/bitbake-user-manual-metadata:Passing Information Into the Build Task Environment`"
section and the information about these variables in the variable
glossary for more information on how they work and on how to use them.
The base configuration metadata is global and therefore affects all
recipes and tasks that are executed.
BitBake first searches the current working directory for an optional
``conf/bblayers.conf`` configuration file. This file is expected to
contain a :term:`BBLAYERS` variable that is a
space-delimited list of 'layer' directories. Recall that if BitBake
cannot find a ``bblayers.conf`` file, then it is assumed the user has
set the :term:`BBPATH` and :term:`BBFILES` variables directly in the
environment.
For each directory (layer) in this list, a ``conf/layer.conf`` file is
located and parsed with the :term:`LAYERDIR` variable
being set to the directory where the layer was found. The idea is these
files automatically set up :term:`BBPATH` and other
variables correctly for a given build directory.
BitBake then expects to find the ``conf/bitbake.conf`` file somewhere in
the user-specified :term:`BBPATH`. That configuration file generally has
include directives to pull in any other metadata such as files specific
to the architecture, the machine, the local environment, and so forth.
Only variable definitions and include directives are allowed in BitBake
``.conf`` files. Some variables directly influence BitBake's behavior.
These variables might have been set from the environment depending on
the environment variables previously mentioned or set in the
configuration files. The ":ref:`bitbake-user-manual/bitbake-user-manual-ref-variables:Variables Glossary`"
chapter presents a full list of
variables.
After parsing configuration files, BitBake uses its rudimentary
inheritance mechanism, which is through class files, to inherit some
standard classes. BitBake parses a class when the inherit directive
responsible for getting that class is encountered.
The ``base.bbclass`` file is always included. Other classes that are
specified in the configuration using the
:term:`INHERIT` variable are also included. BitBake
searches for class files in a ``classes`` subdirectory under the paths
in :term:`BBPATH` in the same way as configuration files.
A good way to get an idea of the configuration files and the class files
used in your execution environment is to run the following BitBake
command::
$ bitbake -e > mybb.log
Examining the top of the ``mybb.log``
shows you the many configuration files and class files used in your
execution environment.
.. note::
You need to be aware of how BitBake parses curly braces. If a recipe
uses a closing curly brace within the function and the character has
no leading spaces, BitBake produces a parsing error. If you use a
pair of curly braces in a shell function, the closing curly brace
must not be located at the start of the line without leading spaces.
Here is an example that causes BitBake to produce a parsing error::
fakeroot create_shar() {
cat << "EOF" > ${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.sh
usage()
{
echo "test"
###### The following "}" at the start of the line causes a parsing error ######
}
EOF
}
Writing the recipe this way avoids the error:
fakeroot create_shar() {
cat << "EOF" > ${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.sh
usage()
{
echo "test"
###### The following "}" with a leading space at the start of the line avoids the error ######
}
EOF
}
Locating and Parsing Recipes
============================
During the configuration phase, BitBake will have set
:term:`BBFILES`. BitBake now uses it to construct a
list of recipes to parse, along with any append files (``.bbappend``) to
apply. :term:`BBFILES` is a space-separated list of available files and
supports wildcards. An example would be::
BBFILES = "/path/to/bbfiles/*.bb /path/to/appends/*.bbappend"
BitBake parses each
recipe and append file located with :term:`BBFILES` and stores the values of
various variables into the datastore.
.. note::
Append files are applied in the order they are encountered in BBFILES.
For each file, a fresh copy of the base configuration is made, then the
recipe is parsed line by line. Any inherit statements cause BitBake to
find and then parse class files (``.bbclass``) using
:term:`BBPATH` as the search path. Finally, BitBake
parses in order any append files found in :term:`BBFILES`.
One common convention is to use the recipe filename to define pieces of
metadata. For example, in ``bitbake.conf`` the recipe name and version
are used to set the variables :term:`PN` and
:term:`PV`::
PN = "${@bb.parse.vars_from_file(d.getVar('FILE', False),d)[0] or 'defaultpkgname'}"
PV = "${@bb.parse.vars_from_file(d.getVar('FILE', False),d)[1] or '1.0'}"
In this example, a recipe called "something_1.2.3.bb" would set
:term:`PN` to "something" and :term:`PV` to "1.2.3".
By the time parsing is complete for a recipe, BitBake has a list of
tasks that the recipe defines and a set of data consisting of keys and
values as well as dependency information about the tasks.
BitBake does not need all of this information. It only needs a small
subset of the information to make decisions about the recipe.
Consequently, BitBake caches the values in which it is interested and
does not store the rest of the information. Experience has shown it is
faster to re-parse the metadata than to try and write it out to the disk
and then reload it.
Where possible, subsequent BitBake commands reuse this cache of recipe
information. The validity of this cache is determined by first computing
a checksum of the base configuration data (see
:term:`BB_HASHCONFIG_IGNORE_VARS`) and
then checking if the checksum matches. If that checksum matches what is
in the cache and the recipe and class files have not changed, BitBake is
able to use the cache. BitBake then reloads the cached information about
the recipe instead of reparsing it from scratch.
Recipe file collections exist to allow the user to have multiple
repositories of ``.bb`` files that contain the same exact package. For
example, one could easily use them to make one's own local copy of an
upstream repository, but with custom modifications that one does not
want upstream. Here is an example::
BBFILES = "/stuff/openembedded/*/*.bb /stuff/openembedded.modified/*/*.bb"
BBFILE_COLLECTIONS = "upstream local"
BBFILE_PATTERN_upstream = "^/stuff/openembedded/"
BBFILE_PATTERN_local = "^/stuff/openembedded.modified/"
BBFILE_PRIORITY_upstream = "5"
BBFILE_PRIORITY_local = "10"
.. note::
The layers mechanism is now the preferred method of collecting code.
While the collections code remains, its main use is to set layer
priorities and to deal with overlap (conflicts) between layers.
.. _bb-bitbake-providers:
Providers
=========
Assuming BitBake has been instructed to execute a target and that all
the recipe files have been parsed, BitBake starts to figure out how to
build the target. BitBake looks through the :term:`PROVIDES` list for each
of the recipes. A :term:`PROVIDES` list is the list of names by which the
recipe can be known. Each recipe's :term:`PROVIDES` list is created
implicitly through the recipe's :term:`PN` variable and
explicitly through the recipe's :term:`PROVIDES`
variable, which is optional.
When a recipe uses :term:`PROVIDES`, that recipe's functionality can be
found under an alternative name or names other than the implicit :term:`PN`
name. As an example, suppose a recipe named ``keyboard_1.0.bb``
contained the following::
PROVIDES += "fullkeyboard"
The :term:`PROVIDES`
list for this recipe becomes "keyboard", which is implicit, and
"fullkeyboard", which is explicit. Consequently, the functionality found
in ``keyboard_1.0.bb`` can be found under two different names.
.. _bb-bitbake-preferences:
Preferences
===========
The :term:`PROVIDES` list is only part of the solution for figuring out a
target's recipes. Because targets might have multiple providers, BitBake
needs to prioritize providers by determining provider preferences.
A common example in which a target has multiple providers is
"virtual/kernel", which is on the :term:`PROVIDES` list for each kernel
recipe. Each machine often selects the best kernel provider by using a
line similar to the following in the machine configuration file::
PREFERRED_PROVIDER_virtual/kernel = "linux-yocto"
The default :term:`PREFERRED_PROVIDER` is the provider
with the same name as the target. BitBake iterates through each target
it needs to build and resolves them and their dependencies using this
process.
Understanding how providers are chosen is made complicated by the fact
that multiple versions might exist for a given provider. BitBake
defaults to the highest version of a provider. Version comparisons are
made using the same method as Debian. You can use the
:term:`PREFERRED_VERSION` variable to
specify a particular version. You can influence the order by using the
:term:`DEFAULT_PREFERENCE` variable.
By default, files have a preference of "0". Setting
:term:`DEFAULT_PREFERENCE` to "-1" makes the recipe unlikely to be used
unless it is explicitly referenced. Setting :term:`DEFAULT_PREFERENCE` to
"1" makes it likely the recipe is used. :term:`PREFERRED_VERSION` overrides
any :term:`DEFAULT_PREFERENCE` setting. :term:`DEFAULT_PREFERENCE` is often used
to mark newer and more experimental recipe versions until they have
undergone sufficient testing to be considered stable.
When there are multiple "versions" of a given recipe, BitBake defaults
to selecting the most recent version, unless otherwise specified. If the
recipe in question has a
:term:`DEFAULT_PREFERENCE` set lower than
the other recipes (default is 0), then it will not be selected. This
allows the person or persons maintaining the repository of recipe files
to specify their preference for the default selected version.
Additionally, the user can specify their preferred version.
If the first recipe is named ``a_1.1.bb``, then the
:term:`PN` variable will be set to "a", and the
:term:`PV` variable will be set to 1.1.
Thus, if a recipe named ``a_1.2.bb`` exists, BitBake will choose 1.2 by
default. However, if you define the following variable in a ``.conf``
file that BitBake parses, you can change that preference::
PREFERRED_VERSION_a = "1.1"
.. note::
It is common for a recipe to provide two versions -- a stable,
numbered (and preferred) version, and a version that is automatically
checked out from a source code repository that is considered more
"bleeding edge" but can be selected only explicitly.
For example, in the OpenEmbedded codebase, there is a standard,
versioned recipe file for BusyBox, ``busybox_1.22.1.bb``, but there
is also a Git-based version, ``busybox_git.bb``, which explicitly
contains the line ::
DEFAULT_PREFERENCE = "-1"
to ensure that the
numbered, stable version is always preferred unless the developer
selects otherwise.
.. _bb-bitbake-dependencies:
Dependencies
============
Each target BitBake builds consists of multiple tasks such as ``fetch``,
``unpack``, ``patch``, ``configure``, and ``compile``. For best
performance on multi-core systems, BitBake considers each task as an
independent entity with its own set of dependencies.
Dependencies are defined through several variables. You can find
information about variables BitBake uses in the
:doc:`bitbake-user-manual-ref-variables` near the end of this manual. At a
basic level, it is sufficient to know that BitBake uses the
:term:`DEPENDS` and
:term:`RDEPENDS` variables when calculating
dependencies.
For more information on how BitBake handles dependencies, see the
:ref:`bitbake-user-manual/bitbake-user-manual-metadata:Dependencies`
section.
.. _ref-bitbake-tasklist:
The Task List
=============
Based on the generated list of providers and the dependency information,
BitBake can now calculate exactly what tasks it needs to run and in what
order it needs to run them. The
:ref:`bitbake-user-manual/bitbake-user-manual-execution:executing tasks`
section has more information on how BitBake chooses which task to
execute next.
The build now starts with BitBake forking off threads up to the limit
set in the :term:`BB_NUMBER_THREADS`
variable. BitBake continues to fork threads as long as there are tasks
ready to run, those tasks have all their dependencies met, and the
thread threshold has not been exceeded.
It is worth noting that you can greatly speed up the build time by
properly setting the :term:`BB_NUMBER_THREADS` variable.
As each task completes, a timestamp is written to the directory
specified by the :term:`STAMP` variable. On subsequent
runs, BitBake looks in the build directory within ``tmp/stamps`` and
does not rerun tasks that are already completed unless a timestamp is
found to be invalid. Currently, invalid timestamps are only considered
on a per recipe file basis. So, for example, if the configure stamp has
a timestamp greater than the compile timestamp for a given target, then
the compile task would rerun. Running the compile task again, however,
has no effect on other providers that depend on that target.
The exact format of the stamps is partly configurable. In modern
versions of BitBake, a hash is appended to the stamp so that if the
configuration changes, the stamp becomes invalid and the task is
automatically rerun. This hash, or signature used, is governed by the
signature policy that is configured (see the
:ref:`bitbake-user-manual/bitbake-user-manual-execution:checksums (signatures)`
section for information). It is also
possible to append extra metadata to the stamp using the
``[stamp-extra-info]`` task flag. For example, OpenEmbedded uses this
flag to make some tasks machine-specific.
.. note::
Some tasks are marked as "nostamp" tasks. No timestamp file is
created when these tasks are run. Consequently, "nostamp" tasks are
always rerun.
For more information on tasks, see the
:ref:`bitbake-user-manual/bitbake-user-manual-metadata:tasks` section.
Executing Tasks
===============
Tasks can be either a shell task or a Python task. For shell tasks,
BitBake writes a shell script to
``${``\ :term:`T`\ ``}/run.do_taskname.pid`` and then
executes the script. The generated shell script contains all the
exported variables, and the shell functions with all variables expanded.
Output from the shell script goes to the file
``${``\ :term:`T`\ ``}/log.do_taskname.pid``. Looking at the expanded shell functions in
the run file and the output in the log files is a useful debugging
technique.
For Python tasks, BitBake executes the task internally and logs
information to the controlling terminal. Future versions of BitBake will
write the functions to files similar to the way shell tasks are handled.
Logging will be handled in a way similar to shell tasks as well.
The order in which BitBake runs the tasks is controlled by its task
scheduler. It is possible to configure the scheduler and define custom
implementations for specific use cases. For more information, see these
variables that control the behavior:
- :term:`BB_SCHEDULER`
- :term:`BB_SCHEDULERS`
It is possible to have functions run before and after a task's main
function. This is done using the ``[prefuncs]`` and ``[postfuncs]``
flags of the task that lists the functions to run.
.. _checksums:
Checksums (Signatures)
======================
A checksum is a unique signature of a task's inputs. The signature of a
task can be used to determine if a task needs to be run. Because it is a
change in a task's inputs that triggers running the task, BitBake needs
to detect all the inputs to a given task. For shell tasks, this turns
out to be fairly easy because BitBake generates a "run" shell script for
each task and it is possible to create a checksum that gives you a good
idea of when the task's data changes.
To complicate the problem, some things should not be included in the
checksum. First, there is the actual specific build path of a given task
- the working directory. It does not matter if the working directory
changes because it should not affect the output for target packages. The
simplistic approach for excluding the working directory is to set it to
some fixed value and create the checksum for the "run" script. BitBake
goes one step better and uses the
:term:`BB_BASEHASH_IGNORE_VARS` variable
to define a list of variables that should never be included when
generating the signatures.
Another problem results from the "run" scripts containing functions that
might or might not get called. The incremental build solution contains
code that figures out dependencies between shell functions. This code is
used to prune the "run" scripts down to the minimum set, thereby
alleviating this problem and making the "run" scripts much more readable
as a bonus.
So far we have solutions for shell scripts. What about Python tasks? The
same approach applies even though these tasks are more difficult. The
process needs to figure out what variables a Python function accesses
and what functions it calls. Again, the incremental build solution
contains code that first figures out the variable and function
dependencies, and then creates a checksum for the data used as the input
to the task.
Like the working directory case, situations exist where dependencies
should be ignored. For these cases, you can instruct the build process
to ignore a dependency by using a line like the following::
PACKAGE_ARCHS[vardepsexclude] = "MACHINE"
This example ensures that the
``PACKAGE_ARCHS`` variable does not depend on the value of ``MACHINE``,
even if it does reference it.
Equally, there are cases where we need to add dependencies BitBake is
not able to find. You can accomplish this by using a line like the
following::
PACKAGE_ARCHS[vardeps] = "MACHINE"
This example explicitly
adds the ``MACHINE`` variable as a dependency for ``PACKAGE_ARCHS``.
Consider a case with in-line Python, for example, where BitBake is not
able to figure out dependencies. When running in debug mode (i.e. using
``-DDD``), BitBake produces output when it discovers something for which
it cannot figure out dependencies.
Thus far, this section has limited discussion to the direct inputs into
a task. Information based on direct inputs is referred to as the
"basehash" in the code. However, there is still the question of a task's
indirect inputs --- the things that were already built and present in the
build directory. The checksum (or signature) for a particular task needs
to add the hashes of all the tasks on which the particular task depends.
Choosing which dependencies to add is a policy decision. However, the
effect is to generate a master checksum that combines the basehash and
the hashes of the task's dependencies.
At the code level, there are a variety of ways both the basehash and the
dependent task hashes can be influenced. Within the BitBake
configuration file, we can give BitBake some extra information to help
it construct the basehash. The following statement effectively results
in a list of global variable dependency excludes --- variables never
included in any checksum. This example uses variables from OpenEmbedded
to help illustrate the concept::
BB_BASEHASH_IGNORE_VARS ?= "TMPDIR FILE PATH PWD BB_TASKHASH BBPATH DL_DIR \
SSTATE_DIR THISDIR FILESEXTRAPATHS FILE_DIRNAME HOME LOGNAME SHELL \
USER FILESPATH STAGING_DIR_HOST STAGING_DIR_TARGET COREBASE PRSERV_HOST \
PRSERV_DUMPDIR PRSERV_DUMPFILE PRSERV_LOCKDOWN PARALLEL_MAKE \
CCACHE_DIR EXTERNAL_TOOLCHAIN CCACHE CCACHE_DISABLE LICENSE_PATH SDKPKGSUFFIX"
The previous example excludes the work directory, which is part of
``TMPDIR``.
The rules for deciding which hashes of dependent tasks to include
through dependency chains are more complex and are generally
accomplished with a Python function. The code in
``meta/lib/oe/sstatesig.py`` shows two examples of this and also
illustrates how you can insert your own policy into the system if so
desired. This file defines the basic signature generator
OpenEmbedded-Core uses: "OEBasicHash". By default, there
is a dummy "noop" signature handler enabled in BitBake. This means that
behavior is unchanged from previous versions. ``OE-Core`` uses the
"OEBasicHash" signature handler by default through this setting in the
``bitbake.conf`` file::
BB_SIGNATURE_HANDLER ?= "OEBasicHash"
The main feature of the "OEBasicHash" :term:`BB_SIGNATURE_HANDLER` is that
it adds the task hash to the stamp files. Thanks to this, any metadata
change will change the task hash, automatically causing the task to be run
again. This removes the need to bump :term:`PR` values, and changes to
metadata automatically ripple across the build.
It is also worth noting that the end result of signature
generators is to make some dependency and hash information available to
the build. This information includes:
- ``BB_BASEHASH_task-``\ *taskname*: The base hashes for each task in the
recipe.
- ``BB_BASEHASH_``\ *filename:taskname*: The base hashes for each
dependent task.
- :term:`BB_TASKHASH`: The hash of the currently running task.
It is worth noting that BitBake's "-S" option lets you debug BitBake's
processing of signatures. The options passed to -S allow different
debugging modes to be used, either using BitBake's own debug functions
or possibly those defined in the metadata/signature handler itself. The
simplest parameter to pass is "none", which causes a set of signature
information to be written out into ``STAMPS_DIR`` corresponding to the
targets specified. The other currently available parameter is
"printdiff", which causes BitBake to try to establish the most recent
signature match it can (e.g. in the sstate cache) and then run
compare the matched signatures to determine the stamps and delta
where these two stamp trees diverge. This can be used to determine why
tasks need to be re-run in situations where that is not expected.
.. note::
It is likely that future versions of BitBake will provide other
signature handlers triggered through additional "-S" parameters.
You can find more information on checksum metadata in the
:ref:`bitbake-user-manual/bitbake-user-manual-metadata:task checksums and setscene`
section.
Setscene
========
The setscene process enables BitBake to handle "pre-built" artifacts.
The ability to handle and reuse these artifacts allows BitBake the
luxury of not having to build something from scratch every time.
Instead, BitBake can use, when possible, existing build artifacts.
BitBake needs to have reliable data indicating whether or not an
artifact is compatible. Signatures, described in the previous section,
provide an ideal way of representing whether an artifact is compatible.
If a signature is the same, an object can be reused.
If an object can be reused, the problem then becomes how to replace a
given task or set of tasks with the pre-built artifact. BitBake solves
the problem with the "setscene" process.
When BitBake is asked to build a given target, before building anything,
it first asks whether cached information is available for any of the
targets it's building, or any of the intermediate targets. If cached
information is available, BitBake uses this information instead of
running the main tasks.
BitBake first calls the function defined by the
:term:`BB_HASHCHECK_FUNCTION` variable
with a list of tasks and corresponding hashes it wants to build. This
function is designed to be fast and returns a list of the tasks for
which it believes in can obtain artifacts.
Next, for each of the tasks that were returned as possibilities, BitBake
executes a setscene version of the task that the possible artifact
covers. Setscene versions of a task have the string "_setscene" appended
to the task name. So, for example, the task with the name ``xxx`` has a
setscene task named ``xxx_setscene``. The setscene version of the task
executes and provides the necessary artifacts returning either success
or failure.
As previously mentioned, an artifact can cover more than one task. For
example, it is pointless to obtain a compiler if you already have the
compiled binary. To handle this, BitBake calls the
:term:`BB_SETSCENE_DEPVALID` function for
each successful setscene task to know whether or not it needs to obtain
the dependencies of that task.
You can find more information on setscene metadata in the
:ref:`bitbake-user-manual/bitbake-user-manual-metadata:task checksums and setscene`
section.
Logging
=======
In addition to the standard command line option to control how verbose
builds are when execute, bitbake also supports user defined
configuration of the `Python
logging <https://docs.python.org/3/library/logging.html>`__ facilities
through the :term:`BB_LOGCONFIG` variable. This
variable defines a JSON or YAML `logging
configuration <https://docs.python.org/3/library/logging.config.html>`__
that will be intelligently merged into the default configuration. The
logging configuration is merged using the following rules:
- The user defined configuration will completely replace the default
configuration if top level key ``bitbake_merge`` is set to the value
``False``. In this case, all other rules are ignored.
- The user configuration must have a top level ``version`` which must
match the value of the default configuration.
- Any keys defined in the ``handlers``, ``formatters``, or ``filters``,
will be merged into the same section in the default configuration,
with the user specified keys taking replacing a default one if there
is a conflict. In practice, this means that if both the default
configuration and user configuration specify a handler named
``myhandler``, the user defined one will replace the default. To
prevent the user from inadvertently replacing a default handler,
formatter, or filter, all of the default ones are named with a prefix
of "``BitBake.``"
- If a logger is defined by the user with the key ``bitbake_merge`` set
to ``False``, that logger will be completely replaced by user
configuration. In this case, no other rules will apply to that
logger.
- All user defined ``filter`` and ``handlers`` properties for a given
logger will be merged with corresponding properties from the default
logger. For example, if the user configuration adds a filter called
``myFilter`` to the ``BitBake.SigGen``, and the default configuration
adds a filter called ``BitBake.defaultFilter``, both filters will be
applied to the logger
As a first example, you can create a ``hashequiv.json`` user logging
configuration file to log all Hash Equivalence related messages of ``VERBOSE``
or higher priority to a file called ``hashequiv.log``::
{
"version": 1,
"handlers": {
"autobuilderlog": {
"class": "logging.FileHandler",
"formatter": "logfileFormatter",
"level": "DEBUG",
"filename": "hashequiv.log",
"mode": "w"
}
},
"formatters": {
"logfileFormatter": {
"format": "%(name)s: %(levelname)s: %(message)s"
}
},
"loggers": {
"BitBake.SigGen.HashEquiv": {
"level": "VERBOSE",
"handlers": ["autobuilderlog"]
},
"BitBake.RunQueue.HashEquiv": {
"level": "VERBOSE",
"handlers": ["autobuilderlog"]
}
}
}
Then set the :term:`BB_LOGCONFIG` variable in ``conf/local.conf``::
BB_LOGCONFIG = "hashequiv.json"
Another example is this ``warn.json`` file to log all ``WARNING`` and
higher priority messages to a ``warn.log`` file::
{
"version": 1,
"formatters": {
"warnlogFormatter": {
"()": "bb.msg.BBLogFormatter",
"format": "%(levelname)s: %(message)s"
}
},
"handlers": {
"warnlog": {
"class": "logging.FileHandler",
"formatter": "warnlogFormatter",
"level": "WARNING",
"filename": "warn.log"
}
},
"loggers": {
"BitBake": {
"handlers": ["warnlog"]
}
},
"@disable_existing_loggers": false
}
Note that BitBake's helper classes for structured logging are implemented in
``lib/bb/msg.py``.

View File

@@ -0,0 +1,851 @@
.. SPDX-License-Identifier: CC-BY-2.5
=====================
File Download Support
=====================
|
BitBake's fetch module is a standalone piece of library code that deals
with the intricacies of downloading source code and files from remote
systems. Fetching source code is one of the cornerstones of building
software. As such, this module forms an important part of BitBake.
The current fetch module is called "fetch2" and refers to the fact that
it is the second major version of the API. The original version is
obsolete and has been removed from the codebase. Thus, in all cases,
"fetch" refers to "fetch2" in this manual.
The Download (Fetch)
====================
BitBake takes several steps when fetching source code or files. The
fetcher codebase deals with two distinct processes in order: obtaining
the files from somewhere (cached or otherwise) and then unpacking those
files into a specific location and perhaps in a specific way. Getting
and unpacking the files is often optionally followed by patching.
Patching, however, is not covered by this module.
The code to execute the first part of this process, a fetch, looks
something like the following::
src_uri = (d.getVar('SRC_URI') or "").split()
fetcher = bb.fetch2.Fetch(src_uri, d)
fetcher.download()
This code sets up an instance of the fetch class. The instance uses a
space-separated list of URLs from the :term:`SRC_URI`
variable and then calls the ``download`` method to download the files.
The instantiation of the fetch class is usually followed by::
rootdir = l.getVar('WORKDIR')
fetcher.unpack(rootdir)
This code unpacks the downloaded files to the specified by ``WORKDIR``.
.. note::
For convenience, the naming in these examples matches the variables
used by OpenEmbedded. If you want to see the above code in action,
examine the OpenEmbedded class file ``base.bbclass``
.
The :term:`SRC_URI` and ``WORKDIR`` variables are not hardcoded into the
fetcher, since those fetcher methods can be (and are) called with
different variable names. In OpenEmbedded for example, the shared state
(sstate) code uses the fetch module to fetch the sstate files.
When the ``download()`` method is called, BitBake tries to resolve the
URLs by looking for source files in a specific search order:
- *Pre-mirror Sites:* BitBake first uses pre-mirrors to try and find
source files. These locations are defined using the
:term:`PREMIRRORS` variable.
- *Source URI:* If pre-mirrors fail, BitBake uses the original URL (e.g
from :term:`SRC_URI`).
- *Mirror Sites:* If fetch failures occur, BitBake next uses mirror
locations as defined by the :term:`MIRRORS` variable.
For each URL passed to the fetcher, the fetcher calls the submodule that
handles that particular URL type. This behavior can be the source of
some confusion when you are providing URLs for the :term:`SRC_URI` variable.
Consider the following two URLs::
https://git.yoctoproject.org/git/poky;protocol=git
git://git.yoctoproject.org/git/poky;protocol=http
In the former case, the URL is passed to the ``wget`` fetcher, which does not
understand "git". Therefore, the latter case is the correct form since the Git
fetcher does know how to use HTTP as a transport.
Here are some examples that show commonly used mirror definitions::
PREMIRRORS ?= "\
bzr://.*/.\* http://somemirror.org/sources/ \
cvs://.*/.\* http://somemirror.org/sources/ \
git://.*/.\* http://somemirror.org/sources/ \
hg://.*/.\* http://somemirror.org/sources/ \
osc://.*/.\* http://somemirror.org/sources/ \
p4://.*/.\* http://somemirror.org/sources/ \
svn://.*/.\* http://somemirror.org/sources/"
MIRRORS =+ "\
ftp://.*/.\* http://somemirror.org/sources/ \
http://.*/.\* http://somemirror.org/sources/ \
https://.*/.\* http://somemirror.org/sources/"
It is useful to note that BitBake
supports cross-URLs. It is possible to mirror a Git repository on an
HTTP server as a tarball. This is what the ``git://`` mapping in the
previous example does.
Since network accesses are slow, BitBake maintains a cache of files
downloaded from the network. Any source files that are not local (i.e.
downloaded from the Internet) are placed into the download directory,
which is specified by the :term:`DL_DIR` variable.
File integrity is of key importance for reproducing builds. For
non-local archive downloads, the fetcher code can verify SHA-256 and MD5
checksums to ensure the archives have been downloaded correctly. You can
specify these checksums by using the :term:`SRC_URI` variable with the
appropriate varflags as follows::
SRC_URI[md5sum] = "value"
SRC_URI[sha256sum] = "value"
You can also specify the checksums as
parameters on the :term:`SRC_URI` as shown below::
SRC_URI = "http://example.com/foobar.tar.bz2;md5sum=4a8e0f237e961fd7785d19d07fdb994d"
If multiple URIs exist, you can specify the checksums either directly as
in the previous example, or you can name the URLs. The following syntax
shows how you name the URIs::
SRC_URI = "http://example.com/foobar.tar.bz2;name=foo"
SRC_URI[foo.md5sum] = 4a8e0f237e961fd7785d19d07fdb994d
After a file has been downloaded and
has had its checksum checked, a ".done" stamp is placed in :term:`DL_DIR`.
BitBake uses this stamp during subsequent builds to avoid downloading or
comparing a checksum for the file again.
.. note::
It is assumed that local storage is safe from data corruption. If
this were not the case, there would be bigger issues to worry about.
If :term:`BB_STRICT_CHECKSUM` is set, any
download without a checksum triggers an error message. The
:term:`BB_NO_NETWORK` variable can be used to
make any attempted network access a fatal error, which is useful for
checking that mirrors are complete as well as other things.
If :term:`BB_CHECK_SSL_CERTS` is set to ``0`` then SSL certificate checking will
be disabled. This variable defaults to ``1`` so SSL certificates are normally
checked.
.. _bb-the-unpack:
The Unpack
==========
The unpack process usually immediately follows the download. For all
URLs except Git URLs, BitBake uses the common ``unpack`` method.
A number of parameters exist that you can specify within the URL to
govern the behavior of the unpack stage:
- *unpack:* Controls whether the URL components are unpacked. If set to
"1", which is the default, the components are unpacked. If set to
"0", the unpack stage leaves the file alone. This parameter is useful
when you want an archive to be copied in and not be unpacked.
- *dos:* Applies to ``.zip`` and ``.jar`` files and specifies whether
to use DOS line ending conversion on text files.
- *striplevel:* Strip specified number of leading components (levels)
from file names on extraction
- *subdir:* Unpacks the specific URL to the specified subdirectory
within the root directory.
The unpack call automatically decompresses and extracts files with ".Z",
".z", ".gz", ".xz", ".zip", ".jar", ".ipk", ".rpm". ".srpm", ".deb" and
".bz2" extensions as well as various combinations of tarball extensions.
As mentioned, the Git fetcher has its own unpack method that is
optimized to work with Git trees. Basically, this method works by
cloning the tree into the final directory. The process is completed
using references so that there is only one central copy of the Git
metadata needed.
.. _bb-fetchers:
Fetchers
========
As mentioned earlier, the URL prefix determines which fetcher submodule
BitBake uses. Each submodule can support different URL parameters, which
are described in the following sections.
.. _local-file-fetcher:
Local file fetcher (``file://``)
--------------------------------
This submodule handles URLs that begin with ``file://``. The filename
you specify within the URL can be either an absolute or relative path to
a file. If the filename is relative, the contents of the
:term:`FILESPATH` variable is used in the same way
``PATH`` is used to find executables. If the file cannot be found, it is
assumed that it is available in :term:`DL_DIR` by the
time the ``download()`` method is called.
If you specify a directory, the entire directory is unpacked.
Here are a couple of example URLs, the first relative and the second
absolute::
SRC_URI = "file://relativefile.patch"
SRC_URI = "file:///Users/ich/very_important_software"
.. _http-ftp-fetcher:
HTTP/FTP wget fetcher (``http://``, ``ftp://``, ``https://``)
-------------------------------------------------------------
This fetcher obtains files from web and FTP servers. Internally, the
fetcher uses the wget utility.
The executable and parameters used are specified by the
``FETCHCMD_wget`` variable, which defaults to sensible values. The
fetcher supports a parameter "downloadfilename" that allows the name of
the downloaded file to be specified. Specifying the name of the
downloaded file is useful for avoiding collisions in
:term:`DL_DIR` when dealing with multiple files that
have the same name.
If a username and password are specified in the ``SRC_URI``, a Basic
Authorization header will be added to each request, including across redirects.
To instead limit the Authorization header to the first request, add
"redirectauth=0" to the list of parameters.
Some example URLs are as follows::
SRC_URI = "http://oe.handhelds.org/not_there.aac"
SRC_URI = "ftp://oe.handhelds.org/not_there_as_well.aac"
SRC_URI = "ftp://you@oe.handhelds.org/home/you/secret.plan"
.. note::
Because URL parameters are delimited by semi-colons, this can
introduce ambiguity when parsing URLs that also contain semi-colons,
for example::
SRC_URI = "http://abc123.org/git/?p=gcc/gcc.git;a=snapshot;h=a5dd47"
Such URLs should should be modified by replacing semi-colons with '&'
characters::
SRC_URI = "http://abc123.org/git/?p=gcc/gcc.git&a=snapshot&h=a5dd47"
In most cases this should work. Treating semi-colons and '&' in
queries identically is recommended by the World Wide Web Consortium
(W3C). Note that due to the nature of the URL, you may have to
specify the name of the downloaded file as well::
SRC_URI = "http://abc123.org/git/?p=gcc/gcc.git&a=snapshot&h=a5dd47;downloadfilename=myfile.bz2"
.. _cvs-fetcher:
CVS fetcher (``(cvs://``)
-------------------------
This submodule handles checking out files from the CVS version control
system. You can configure it using a number of different variables:
- :term:`FETCHCMD_cvs <FETCHCMD>`: The name of the executable to use when running
the ``cvs`` command. This name is usually "cvs".
- :term:`SRCDATE`: The date to use when fetching the CVS source code. A
special value of "now" causes the checkout to be updated on every
build.
- :term:`CVSDIR`: Specifies where a temporary
checkout is saved. The location is often ``DL_DIR/cvs``.
- CVS_PROXY_HOST: The name to use as a "proxy=" parameter to the
``cvs`` command.
- CVS_PROXY_PORT: The port number to use as a "proxyport="
parameter to the ``cvs`` command.
As well as the standard username and password URL syntax, you can also
configure the fetcher with various URL parameters:
The supported parameters are as follows:
- *"method":* The protocol over which to communicate with the CVS
server. By default, this protocol is "pserver". If "method" is set to
"ext", BitBake examines the "rsh" parameter and sets ``CVS_RSH``. You
can use "dir" for local directories.
- *"module":* Specifies the module to check out. You must supply this
parameter.
- *"tag":* Describes which CVS TAG should be used for the checkout. By
default, the TAG is empty.
- *"date":* Specifies a date. If no "date" is specified, the
:term:`SRCDATE` of the configuration is used to
checkout a specific date. The special value of "now" causes the
checkout to be updated on every build.
- *"localdir":* Used to rename the module. Effectively, you are
renaming the output directory to which the module is unpacked. You
are forcing the module into a special directory relative to
:term:`CVSDIR`.
- *"rsh":* Used in conjunction with the "method" parameter.
- *"scmdata":* Causes the CVS metadata to be maintained in the tarball
the fetcher creates when set to "keep". The tarball is expanded into
the work directory. By default, the CVS metadata is removed.
- *"fullpath":* Controls whether the resulting checkout is at the
module level, which is the default, or is at deeper paths.
- *"norecurse":* Causes the fetcher to only checkout the specified
directory with no recurse into any subdirectories.
- *"port":* The port to which the CVS server connects.
Some example URLs are as follows::
SRC_URI = "cvs://CVSROOT;module=mymodule;tag=some-version;method=ext"
SRC_URI = "cvs://CVSROOT;module=mymodule;date=20060126;localdir=usethat"
.. _svn-fetcher:
Subversion (SVN) Fetcher (``svn://``)
-------------------------------------
This fetcher submodule fetches code from the Subversion source control
system. The executable used is specified by ``FETCHCMD_svn``, which
defaults to "svn". The fetcher's temporary working directory is set by
:term:`SVNDIR`, which is usually ``DL_DIR/svn``.
The supported parameters are as follows:
- *"module":* The name of the svn module to checkout. You must provide
this parameter. You can think of this parameter as the top-level
directory of the repository data you want.
- *"path_spec":* A specific directory in which to checkout the
specified svn module.
- *"protocol":* The protocol to use, which defaults to "svn". If
"protocol" is set to "svn+ssh", the "ssh" parameter is also used.
- *"rev":* The revision of the source code to checkout.
- *"scmdata":* Causes the ".svn" directories to be available during
compile-time when set to "keep". By default, these directories are
removed.
- *"ssh":* An optional parameter used when "protocol" is set to
"svn+ssh". You can use this parameter to specify the ssh program used
by svn.
- *"transportuser":* When required, sets the username for the
transport. By default, this parameter is empty. The transport
username is different than the username used in the main URL, which
is passed to the subversion command.
Following are three examples using svn::
SRC_URI = "svn://myrepos/proj1;module=vip;protocol=http;rev=667"
SRC_URI = "svn://myrepos/proj1;module=opie;protocol=svn+ssh"
SRC_URI = "svn://myrepos/proj1;module=trunk;protocol=http;path_spec=${MY_DIR}/proj1"
.. _git-fetcher:
Git Fetcher (``git://``)
------------------------
This fetcher submodule fetches code from the Git source control system.
The fetcher works by creating a bare clone of the remote into
:term:`GITDIR`, which is usually ``DL_DIR/git2``. This
bare clone is then cloned into the work directory during the unpack
stage when a specific tree is checked out. This is done using alternates
and by reference to minimize the amount of duplicate data on the disk
and make the unpack process fast. The executable used can be set with
``FETCHCMD_git``.
This fetcher supports the following parameters:
- *"protocol":* The protocol used to fetch the files. The default is
"git" when a hostname is set. If a hostname is not set, the Git
protocol is "file". You can also use "http", "https", "ssh" and
"rsync".
.. note::
When ``protocol`` is "ssh", the URL expected in :term:`SRC_URI` differs
from the one that is typically passed to ``git clone`` command and provided
by the Git server to fetch from. For example, the URL returned by GitLab
server for ``mesa`` when cloning over SSH is
``git@gitlab.freedesktop.org:mesa/mesa.git``, however the expected URL in
:term:`SRC_URI` is the following::
SRC_URI = "git://git@gitlab.freedesktop.org/mesa/mesa.git;branch=main;protocol=ssh;..."
Note the ``:`` character changed for a ``/`` before the path to the project.
- *"nocheckout":* Tells the fetcher to not checkout source code when
unpacking when set to "1". Set this option for the URL where there is
a custom routine to checkout code. The default is "0".
- *"rebaseable":* Indicates that the upstream Git repository can be
rebased. You should set this parameter to "1" if revisions can become
detached from branches. In this case, the source mirror tarball is
done per revision, which has a loss of efficiency. Rebasing the
upstream Git repository could cause the current revision to disappear
from the upstream repository. This option reminds the fetcher to
preserve the local cache carefully for future use. The default value
for this parameter is "0".
- *"nobranch":* Tells the fetcher to not check the SHA validation for
the branch when set to "1". The default is "0". Set this option for
the recipe that refers to the commit that is valid for any namespace
(branch, tag, ...) instead of the branch.
- *"bareclone":* Tells the fetcher to clone a bare clone into the
destination directory without checking out a working tree. Only the
raw Git metadata is provided. This parameter implies the "nocheckout"
parameter as well.
- *"branch":* The branch(es) of the Git tree to clone. Unless
"nobranch" is set to "1", this is a mandatory parameter. The number of
branch parameters must match the number of name parameters.
- *"rev":* The revision to use for the checkout. The default is
"master".
- *"tag":* Specifies a tag to use for the checkout. To correctly
resolve tags, BitBake must access the network. For that reason, tags
are often not used. As far as Git is concerned, the "tag" parameter
behaves effectively the same as the "rev" parameter.
- *"subpath":* Limits the checkout to a specific subpath of the tree.
By default, the whole tree is checked out.
- *"destsuffix":* The name of the path in which to place the checkout.
By default, the path is ``git/``.
- *"usehead":* Enables local ``git://`` URLs to use the current branch
HEAD as the revision for use with ``AUTOREV``. The "usehead"
parameter implies no branch and only works when the transfer protocol
is ``file://``.
Here are some example URLs::
SRC_URI = "git://github.com/fronteed/icheck.git;protocol=https;branch=${PV};tag=${PV}"
SRC_URI = "git://github.com/asciidoc/asciidoc-py;protocol=https;branch=main"
SRC_URI = "git://git@gitlab.freedesktop.org/mesa/mesa.git;branch=main;protocol=ssh;..."
.. note::
When using ``git`` as the fetcher of the main source code of your software,
``S`` should be set accordingly::
S = "${WORKDIR}/git"
.. note::
Specifying passwords directly in ``git://`` urls is not supported.
There are several reasons: :term:`SRC_URI` is often written out to logs and
other places, and that could easily leak passwords; it is also all too
easy to share metadata without removing passwords. SSH keys, ``~/.netrc``
and ``~/.ssh/config`` files can be used as alternatives.
Using tags with the git fetcher may cause surprising behaviour. Bitbake needs to
resolve the tag to a specific revision and to do that, it has to connect to and use
the upstream repository. This is because the revision the tags point at can change and
we've seen cases of this happening in well known public repositories. This can mean
many more network connections than expected and recipes may be reparsed at every build.
Source mirrors will also be bypassed as the upstream repository is the only source
of truth to resolve the revision accurately. For these reasons, whilst the fetcher
can support tags, we recommend being specific about revisions in recipes.
.. _gitsm-fetcher:
Git Submodule Fetcher (``gitsm://``)
------------------------------------
This fetcher submodule inherits from the :ref:`Git
fetcher<bitbake-user-manual/bitbake-user-manual-fetching:git fetcher
(\`\`git://\`\`)>` and extends that fetcher's behavior by fetching a
repository's submodules. :term:`SRC_URI` is passed to the Git fetcher as
described in the :ref:`bitbake-user-manual/bitbake-user-manual-fetching:git
fetcher (\`\`git://\`\`)` section.
.. note::
You must clean a recipe when switching between '``git://``' and
'``gitsm://``' URLs.
The Git Submodules fetcher is not a complete fetcher implementation.
The fetcher has known issues where it does not use the normal source
mirroring infrastructure properly. Further, the submodule sources it
fetches are not visible to the licensing and source archiving
infrastructures.
.. _clearcase-fetcher:
ClearCase Fetcher (``ccrc://``)
-------------------------------
This fetcher submodule fetches code from a
`ClearCase <http://en.wikipedia.org/wiki/Rational_ClearCase>`__
repository.
To use this fetcher, make sure your recipe has proper
:term:`SRC_URI`, :term:`SRCREV`, and
:term:`PV` settings. Here is an example::
SRC_URI = "ccrc://cc.example.org/ccrc;vob=/example_vob;module=/example_module"
SRCREV = "EXAMPLE_CLEARCASE_TAG"
PV = "${@d.getVar("SRCREV", False).replace("/", "+")}"
The fetcher uses the ``rcleartool`` or
``cleartool`` remote client, depending on which one is available.
Following are options for the :term:`SRC_URI` statement:
- *vob*: The name, which must include the prepending "/" character,
of the ClearCase VOB. This option is required.
- *module*: The module, which must include the prepending "/"
character, in the selected VOB.
.. note::
The module and vob options are combined to create the load rule in the
view config spec. As an example, consider the vob and module values from
the SRC_URI statement at the start of this section. Combining those values
results in the following::
load /example_vob/example_module
- *proto*: The protocol, which can be either ``http`` or ``https``.
By default, the fetcher creates a configuration specification. If you
want this specification written to an area other than the default, use
the ``CCASE_CUSTOM_CONFIG_SPEC`` variable in your recipe to define where
the specification is written.
.. note::
the SRCREV loses its functionality if you specify this variable. However,
SRCREV is still used to label the archive after a fetch even though it does
not define what is fetched.
Here are a couple of other behaviors worth mentioning:
- When using ``cleartool``, the login of ``cleartool`` is handled by
the system. The login require no special steps.
- In order to use ``rcleartool`` with authenticated users, an
"rcleartool login" is necessary before using the fetcher.
.. _perforce-fetcher:
Perforce Fetcher (``p4://``)
----------------------------
This fetcher submodule fetches code from the
`Perforce <https://www.perforce.com/>`__ source control system. The
executable used is specified by ``FETCHCMD_p4``, which defaults to "p4".
The fetcher's temporary working directory is set by
:term:`P4DIR`, which defaults to "DL_DIR/p4".
The fetcher does not make use of a perforce client, instead it
relies on ``p4 files`` to retrieve a list of
files and ``p4 print`` to transfer the content
of those files locally.
To use this fetcher, make sure your recipe has proper
:term:`SRC_URI`, :term:`SRCREV`, and
:term:`PV` values. The p4 executable is able to use the
config file defined by your system's ``P4CONFIG`` environment variable
in order to define the Perforce server URL and port, username, and
password if you do not wish to keep those values in a recipe itself. If
you choose not to use ``P4CONFIG``, or to explicitly set variables that
``P4CONFIG`` can contain, you can specify the ``P4PORT`` value, which is
the server's URL and port number, and you can specify a username and
password directly in your recipe within :term:`SRC_URI`.
Here is an example that relies on ``P4CONFIG`` to specify the server URL
and port, username, and password, and fetches the Head Revision::
SRC_URI = "p4://example-depot/main/source/..."
SRCREV = "${AUTOREV}"
PV = "p4-${SRCPV}"
S = "${WORKDIR}/p4"
Here is an example that specifies the server URL and port, username, and
password, and fetches a Revision based on a Label::
P4PORT = "tcp:p4server.example.net:1666"
SRC_URI = "p4://user:passwd@example-depot/main/source/..."
SRCREV = "release-1.0"
PV = "p4-${SRCPV}"
S = "${WORKDIR}/p4"
.. note::
You should always set S to "${WORKDIR}/p4" in your recipe.
By default, the fetcher strips the depot location from the local file paths. In
the above example, the content of ``example-depot/main/source/`` will be placed
in ``${WORKDIR}/p4``. For situations where preserving parts of the remote depot
paths locally is desirable, the fetcher supports two parameters:
- *"module":*
The top-level depot location or directory to fetch. The value of this
parameter can also point to a single file within the depot, in which case
the local file path will include the module path.
- *"remotepath":*
When used with the value "``keep``", the fetcher will mirror the full depot
paths locally for the specified location, even in combination with the
``module`` parameter.
Here is an example use of the the ``module`` parameter::
SRC_URI = "p4://user:passwd@example-depot/main;module=source/..."
In this case, the content of the top-level directory ``source/`` will be fetched
to ``${P4DIR}``, including the directory itself. The top-level directory will
be accesible at ``${P4DIR}/source/``.
Here is an example use of the the ``remotepath`` parameter::
SRC_URI = "p4://user:passwd@example-depot/main;module=source/...;remotepath=keep"
In this case, the content of the top-level directory ``source/`` will be fetched
to ``${P4DIR}``, but the complete depot paths will be mirrored locally. The
top-level directory will be accessible at
``${P4DIR}/example-depot/main/source/``.
.. _repo-fetcher:
Repo Fetcher (``repo://``)
--------------------------
This fetcher submodule fetches code from ``google-repo`` source control
system. The fetcher works by initiating and syncing sources of the
repository into :term:`REPODIR`, which is usually
``${DL_DIR}/repo``.
This fetcher supports the following parameters:
- *"protocol":* Protocol to fetch the repository manifest (default:
git).
- *"branch":* Branch or tag of repository to get (default: master).
- *"manifest":* Name of the manifest file (default: ``default.xml``).
Here are some example URLs::
SRC_URI = "repo://REPOROOT;protocol=git;branch=some_branch;manifest=my_manifest.xml"
SRC_URI = "repo://REPOROOT;protocol=file;branch=some_branch;manifest=my_manifest.xml"
.. _az-fetcher:
Az Fetcher (``az://``)
--------------------------
This submodule fetches data from an
`Azure Storage account <https://docs.microsoft.com/en-us/azure/storage/>`__ ,
it inherits its functionality from the HTTP wget fetcher, but modifies its
behavior to accomodate the usage of a
`Shared Access Signature (SAS) <https://docs.microsoft.com/en-us/azure/storage/common/storage-sas-overview>`__
for non-public data.
Such functionality is set by the variable:
- :term:`AZ_SAS`: The Azure Storage Shared Access Signature provides secure
delegate access to resources, if this variable is set, the Az Fetcher will
use it when fetching artifacts from the cloud.
You can specify the AZ_SAS variable as shown below::
AZ_SAS = "se=2021-01-01&sp=r&sv=2018-11-09&sr=c&skoid=<skoid>&sig=<signature>"
Here is an example URL::
SRC_URI = "az://<azure-storage-account>.blob.core.windows.net/<foo_container>/<bar_file>"
It can also be used when setting mirrors definitions using the :term:`PREMIRRORS` variable.
.. _gcp-fetcher:
GCP Fetcher (``gs://``)
--------------------------
This submodule fetches data from a
`Google Cloud Storage Bucket <https://cloud.google.com/storage/docs/buckets>`__.
It uses the `Google Cloud Storage Python Client <https://cloud.google.com/python/docs/reference/storage/latest>`__
to check the status of objects in the bucket and download them.
The use of the Python client makes it substantially faster than using command
line tools such as gsutil.
The fetcher requires the Google Cloud Storage Python Client to be installed, along
with the gsutil tool.
The fetcher requires that the machine has valid credentials for accessing the
chosen bucket. Instructions for authentication can be found in the
`Google Cloud documentation <https://cloud.google.com/docs/authentication/provide-credentials-adc#local-dev>`__.
If it used from the OpenEmbedded build system, the fetcher can be used for
fetching sstate artifacts from a GCS bucket by specifying the
``SSTATE_MIRRORS`` variable as shown below::
SSTATE_MIRRORS ?= "\
file://.* gs://<bucket name>/PATH \
"
The fetcher can also be used in recipes::
SRC_URI = "gs://<bucket name>/<foo_container>/<bar_file>"
However, the checksum of the file should be also be provided::
SRC_URI[sha256sum] = "<sha256 string>"
.. _crate-fetcher:
Crate Fetcher (``crate://``)
----------------------------
This submodule fetches code for
`Rust language "crates" <https://doc.rust-lang.org/reference/glossary.html?highlight=crate#crate>`__
corresponding to Rust libraries and programs to compile. Such crates are typically shared
on https://crates.io/ but this fetcher supports other crate registries too.
The format for the :term:`SRC_URI` setting must be::
SRC_URI = "crate://REGISTRY/NAME/VERSION"
Here is an example URL::
SRC_URI = "crate://crates.io/glob/0.2.11"
.. _npm-fetcher:
NPM Fetcher (``npm://``)
------------------------
This submodule fetches source code from an
`NPM <https://en.wikipedia.org/wiki/Npm_(software)>`__
Javascript package registry.
The format for the :term:`SRC_URI` setting must be::
SRC_URI = "npm://some.registry.url;ParameterA=xxx;ParameterB=xxx;..."
This fetcher supports the following parameters:
- *"package":* The NPM package name. This is a mandatory parameter.
- *"version":* The NPM package version. This is a mandatory parameter.
- *"downloadfilename":* Specifies the filename used when storing the downloaded file.
- *"destsuffix":* Specifies the directory to use to unpack the package (default: ``npm``).
Note that NPM fetcher only fetches the package source itself. The dependencies
can be fetched through the `npmsw-fetcher`_.
Here is an example URL with both fetchers::
SRC_URI = " \
npm://registry.npmjs.org/;package=cute-files;version=${PV} \
npmsw://${THISDIR}/${BPN}/npm-shrinkwrap.json \
"
See :yocto_docs:`Creating Node Package Manager (NPM) Packages
</dev-manual/packages.html#creating-node-package-manager-npm-packages>`
in the Yocto Project manual for details about using
:yocto_docs:`devtool <https://docs.yoctoproject.org/ref-manual/devtool-reference.html>`
to automatically create a recipe from an NPM URL.
.. _npmsw-fetcher:
NPM shrinkwrap Fetcher (``npmsw://``)
-------------------------------------
This submodule fetches source code from an
`NPM shrinkwrap <https://docs.npmjs.com/cli/v8/commands/npm-shrinkwrap>`__
description file, which lists the dependencies
of an NPM package while locking their versions.
The format for the :term:`SRC_URI` setting must be::
SRC_URI = "npmsw://some.registry.url;ParameterA=xxx;ParameterB=xxx;..."
This fetcher supports the following parameters:
- *"dev":* Set this parameter to ``1`` to install "devDependencies".
- *"destsuffix":* Specifies the directory to use to unpack the dependencies
(``${S}`` by default).
Note that the shrinkwrap file can also be provided by the recipe for
the package which has such dependencies, for example::
SRC_URI = " \
npm://registry.npmjs.org/;package=cute-files;version=${PV} \
npmsw://${THISDIR}/${BPN}/npm-shrinkwrap.json \
"
Such a file can automatically be generated using
:yocto_docs:`devtool <https://docs.yoctoproject.org/ref-manual/devtool-reference.html>`
as described in the :yocto_docs:`Creating Node Package Manager (NPM) Packages
</dev-manual/packages.html#creating-node-package-manager-npm-packages>`
section of the Yocto Project.
Other Fetchers
--------------
Fetch submodules also exist for the following:
- Bazaar (``bzr://``)
- Mercurial (``hg://``)
- OSC (``osc://``)
- S3 (``s3://``)
- Secure FTP (``sftp://``)
- Secure Shell (``ssh://``)
- Trees using Git Annex (``gitannex://``)
No documentation currently exists for these lesser used fetcher
submodules. However, you might find the code helpful and readable.
Auto Revisions
==============
We need to document ``AUTOREV`` and :term:`SRCREV_FORMAT` here.

View File

@@ -0,0 +1,408 @@
.. SPDX-License-Identifier: CC-BY-2.5
===================
Hello World Example
===================
BitBake Hello World
===================
The simplest example commonly used to demonstrate any new programming
language or tool is the "`Hello
World <http://en.wikipedia.org/wiki/Hello_world_program>`__" example.
This appendix demonstrates, in tutorial form, Hello World within the
context of BitBake. The tutorial describes how to create a new project
and the applicable metadata files necessary to allow BitBake to build
it.
Obtaining BitBake
=================
See the :ref:`bitbake-user-manual/bitbake-user-manual-intro:obtaining bitbake` section for
information on how to obtain BitBake. Once you have the source code on
your machine, the BitBake directory appears as follows::
$ ls -al
total 108
drwxr-xr-x 9 fawkh 10000 4096 feb 24 12:10 .
drwx------ 36 fawkh 10000 4096 mar 2 17:00 ..
-rw-r--r-- 1 fawkh 10000 365 feb 24 12:10 AUTHORS
drwxr-xr-x 2 fawkh 10000 4096 feb 24 12:10 bin
-rw-r--r-- 1 fawkh 10000 16501 feb 24 12:10 ChangeLog
drwxr-xr-x 2 fawkh 10000 4096 feb 24 12:10 classes
drwxr-xr-x 2 fawkh 10000 4096 feb 24 12:10 conf
drwxr-xr-x 5 fawkh 10000 4096 feb 24 12:10 contrib
drwxr-xr-x 6 fawkh 10000 4096 feb 24 12:10 doc
drwxr-xr-x 8 fawkh 10000 4096 mar 2 16:26 .git
-rw-r--r-- 1 fawkh 10000 31 feb 24 12:10 .gitattributes
-rw-r--r-- 1 fawkh 10000 392 feb 24 12:10 .gitignore
drwxr-xr-x 13 fawkh 10000 4096 feb 24 12:11 lib
-rw-r--r-- 1 fawkh 10000 1224 feb 24 12:10 LICENSE
-rw-r--r-- 1 fawkh 10000 15394 feb 24 12:10 LICENSE.GPL-2.0-only
-rw-r--r-- 1 fawkh 10000 1286 feb 24 12:10 LICENSE.MIT
-rw-r--r-- 1 fawkh 10000 229 feb 24 12:10 MANIFEST.in
-rw-r--r-- 1 fawkh 10000 2413 feb 24 12:10 README
-rw-r--r-- 1 fawkh 10000 43 feb 24 12:10 toaster-requirements.txt
-rw-r--r-- 1 fawkh 10000 2887 feb 24 12:10 TODO
At this point, you should have BitBake cloned to a directory that
matches the previous listing except for dates and user names.
Setting Up the BitBake Environment
==================================
First, you need to be sure that you can run BitBake. Set your working
directory to where your local BitBake files are and run the following
command::
$ ./bin/bitbake --version
BitBake Build Tool Core version 2.3.1
The console output tells you what version
you are running.
The recommended method to run BitBake is from a directory of your
choice. To be able to run BitBake from any directory, you need to add
the executable binary to your binary to your shell's environment
``PATH`` variable. First, look at your current ``PATH`` variable by
entering the following::
$ echo $PATH
Next, add the directory location
for the BitBake binary to the ``PATH``. Here is an example that adds the
``/home/scott-lenovo/bitbake/bin`` directory to the front of the
``PATH`` variable::
$ export PATH=/home/scott-lenovo/bitbake/bin:$PATH
You should now be able to enter the ``bitbake`` command from the command
line while working from any directory.
The Hello World Example
=======================
The overall goal of this exercise is to build a complete "Hello World"
example utilizing task and layer concepts. Because this is how modern
projects such as OpenEmbedded and the Yocto Project utilize BitBake, the
example provides an excellent starting point for understanding BitBake.
To help you understand how to use BitBake to build targets, the example
starts with nothing but the ``bitbake`` command, which causes BitBake to
fail and report problems. The example progresses by adding pieces to the
build to eventually conclude with a working, minimal "Hello World"
example.
While every attempt is made to explain what is happening during the
example, the descriptions cannot cover everything. You can find further
information throughout this manual. Also, you can actively participate
in the :oe_lists:`/g/bitbake-devel`
discussion mailing list about the BitBake build tool.
.. note::
This example was inspired by and drew heavily from
`Mailing List post - The BitBake equivalent of "Hello, World!"
<https://www.mail-archive.com/yocto@yoctoproject.org/msg09379.html>`_.
As stated earlier, the goal of this example is to eventually compile
"Hello World". However, it is unknown what BitBake needs and what you
have to provide in order to achieve that goal. Recall that BitBake
utilizes three types of metadata files:
:ref:`bitbake-user-manual/bitbake-user-manual-intro:configuration files`,
:ref:`bitbake-user-manual/bitbake-user-manual-intro:classes`, and
:ref:`bitbake-user-manual/bitbake-user-manual-intro:recipes`.
But where do they go? How does BitBake find
them? BitBake's error messaging helps you answer these types of
questions and helps you better understand exactly what is going on.
Following is the complete "Hello World" example.
#. **Create a Project Directory:** First, set up a directory for the
"Hello World" project. Here is how you can do so in your home
directory::
$ mkdir ~/hello
$ cd ~/hello
This is the directory that
BitBake will use to do all of its work. You can use this directory
to keep all the metafiles needed by BitBake. Having a project
directory is a good way to isolate your project.
#. **Run BitBake:** At this point, you have nothing but a project
directory. Run the ``bitbake`` command and see what it does::
$ bitbake
ERROR: The BBPATH variable is not set and bitbake did not find a conf/bblayers.conf file in the expected location.
Maybe you accidentally invoked bitbake from the wrong directory?
When you run BitBake, it begins looking for metadata files. The
:term:`BBPATH` variable is what tells BitBake where
to look for those files. :term:`BBPATH` is not set and you need to set
it. Without :term:`BBPATH`, BitBake cannot find any configuration files
(``.conf``) or recipe files (``.bb``) at all. BitBake also cannot
find the ``bitbake.conf`` file.
#. **Setting BBPATH:** For this example, you can set :term:`BBPATH` in
the same manner that you set ``PATH`` earlier in the appendix. You
should realize, though, that it is much more flexible to set the
:term:`BBPATH` variable up in a configuration file for each project.
From your shell, enter the following commands to set and export the
:term:`BBPATH` variable::
$ BBPATH="projectdirectory"
$ export BBPATH
Use your actual project directory in the command. BitBake uses that
directory to find the metadata it needs for your project.
.. note::
When specifying your project directory, do not use the tilde
("~") character as BitBake does not expand that character as the
shell would.
#. **Run BitBake:** Now that you have :term:`BBPATH` defined, run the
``bitbake`` command again::
$ bitbake
ERROR: Unable to parse /home/scott-lenovo/bitbake/lib/bb/parse/__init__.py
Traceback (most recent call last):
File "/home/scott-lenovo/bitbake/lib/bb/parse/__init__.py", line 127, in resolve_file(fn='conf/bitbake.conf', d=<bb.data_smart.DataSmart object at 0x7f22919a3df0>):
if not newfn:
> raise IOError(errno.ENOENT, "file %s not found in %s" % (fn, bbpath))
fn = newfn
FileNotFoundError: [Errno 2] file conf/bitbake.conf not found in <projectdirectory>
This sample output shows that BitBake could not find the
``conf/bitbake.conf`` file in the project directory. This file is
the first thing BitBake must find in order to build a target. And,
since the project directory for this example is empty, you need to
provide a ``conf/bitbake.conf`` file.
#. **Creating conf/bitbake.conf:** The ``conf/bitbake.conf`` includes
a number of configuration variables BitBake uses for metadata and
recipe files. For this example, you need to create the file in your
project directory and define some key BitBake variables. For more
information on the ``bitbake.conf`` file, see
https://git.openembedded.org/bitbake/tree/conf/bitbake.conf.
Use the following commands to create the ``conf`` directory in the
project directory::
$ mkdir conf
From within the ``conf`` directory,
use some editor to create the ``bitbake.conf`` so that it contains
the following::
PN = "${@bb.parse.vars_from_file(d.getVar('FILE', False),d)[0] or 'defaultpkgname'}"
TMPDIR = "${TOPDIR}/tmp"
CACHE = "${TMPDIR}/cache"
STAMP = "${TMPDIR}/${PN}/stamps"
T = "${TMPDIR}/${PN}/work"
B = "${TMPDIR}/${PN}"
.. note::
Without a value for :term:`PN`, the variables :term:`STAMP`, :term:`T`, and :term:`B`, prevent more
than one recipe from working. You can fix this by either setting :term:`PN` to
have a value similar to what OpenEmbedded and BitBake use in the default
``bitbake.conf`` file (see previous example). Or, by manually updating each
recipe to set :term:`PN`. You will also need to include :term:`PN` as part of the :term:`STAMP`,
:term:`T`, and :term:`B` variable definitions in the ``local.conf`` file.
The ``TMPDIR`` variable establishes a directory that BitBake uses
for build output and intermediate files other than the cached
information used by the
:ref:`bitbake-user-manual/bitbake-user-manual-execution:setscene`
process. Here, the ``TMPDIR`` directory is set to ``hello/tmp``.
.. tip::
You can always safely delete the tmp directory in order to rebuild a
BitBake target. The build process creates the directory for you when you
run BitBake.
For information about each of the other variables defined in this
example, check :term:`PN`, :term:`TOPDIR`, :term:`CACHE`, :term:`STAMP`,
:term:`T` or :term:`B` to take you to the definitions in the
glossary.
#. **Run BitBake:** After making sure that the ``conf/bitbake.conf`` file
exists, you can run the ``bitbake`` command again::
$ bitbake
ERROR: Unable to parse /home/scott-lenovo/bitbake/lib/bb/parse/parse_py/BBHandler.py
Traceback (most recent call last):
File "/home/scott-lenovo/bitbake/lib/bb/parse/parse_py/BBHandler.py", line 67, in inherit(files=['base'], fn='configuration INHERITs', lineno=0, d=<bb.data_smart.DataSmart object at 0x7fab6815edf0>):
if not os.path.exists(file):
> raise ParseError("Could not inherit file %s" % (file), fn, lineno)
bb.parse.ParseError: ParseError in configuration INHERITs: Could not inherit file classes/base.bbclass
In the sample output,
BitBake could not find the ``classes/base.bbclass`` file. You need
to create that file next.
#. **Creating classes/base.bbclass:** BitBake uses class files to
provide common code and functionality. The minimally required class
for BitBake is the ``classes/base.bbclass`` file. The ``base`` class
is implicitly inherited by every recipe. BitBake looks for the class
in the ``classes`` directory of the project (i.e ``hello/classes``
in this example).
Create the ``classes`` directory as follows::
$ cd $HOME/hello
$ mkdir classes
Move to the ``classes`` directory and then create the
``base.bbclass`` file by inserting this single line::
addtask build
The minimal task that BitBake runs is the ``do_build`` task. This is
all the example needs in order to build the project. Of course, the
``base.bbclass`` can have much more depending on which build
environments BitBake is supporting.
#. **Run BitBake:** After making sure that the ``classes/base.bbclass``
file exists, you can run the ``bitbake`` command again::
$ bitbake
Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information.
BitBake is finally reporting
no errors. However, you can see that it really does not have
anything to do. You need to create a recipe that gives BitBake
something to do.
#. **Creating a Layer:** While it is not really necessary for such a
small example, it is good practice to create a layer in which to
keep your code separate from the general metadata used by BitBake.
Thus, this example creates and uses a layer called "mylayer".
.. note::
You can find additional information on layers in the
":ref:`bitbake-user-manual/bitbake-user-manual-intro:Layers`" section.
Minimally, you need a recipe file and a layer configuration file in
your layer. The configuration file needs to be in the ``conf``
directory inside the layer. Use these commands to set up the layer
and the ``conf`` directory::
$ cd $HOME
$ mkdir mylayer
$ cd mylayer
$ mkdir conf
Move to the ``conf`` directory and create a ``layer.conf`` file that has the
following::
BBPATH .= ":${LAYERDIR}"
BBFILES += "${LAYERDIR}/*.bb"
BBFILE_COLLECTIONS += "mylayer"
BBFILE_PATTERN_mylayer := "^${LAYERDIR_RE}/"
LAYERSERIES_CORENAMES = "hello_world_example"
LAYERSERIES_COMPAT_mylayer = "hello_world_example"
For information on these variables, click on :term:`BBFILES`,
:term:`LAYERDIR`, :term:`BBFILE_COLLECTIONS`, :term:`BBFILE_PATTERN_mylayer <BBFILE_PATTERN>`
or :term:`LAYERSERIES_COMPAT` to go to the definitions in the glossary.
.. note::
We are setting both ``LAYERSERIES_CORENAMES`` and :term:`LAYERSERIES_COMPAT` in this particular case, because we
are using bitbake without OpenEmbedded.
You should usually just use :term:`LAYERSERIES_COMPAT` to specify the OE-Core versions for which your layer
is compatible, and add the meta-openembedded layer to your project.
You need to create the recipe file next. Inside your layer at the
top-level, use an editor and create a recipe file named
``printhello.bb`` that has the following::
DESCRIPTION = "Prints Hello World"
PN = 'printhello'
PV = '1'
python do_build() {
bb.plain("********************");
bb.plain("* *");
bb.plain("* Hello, World! *");
bb.plain("* *");
bb.plain("********************");
}
The recipe file simply provides
a description of the recipe, the name, version, and the ``do_build``
task, which prints out "Hello World" to the console. For more
information on :term:`DESCRIPTION`, :term:`PN` or :term:`PV`
follow the links to the glossary.
#. **Run BitBake With a Target:** Now that a BitBake target exists, run
the command and provide that target::
$ cd $HOME/hello
$ bitbake printhello
ERROR: no recipe files to build, check your BBPATH and BBFILES?
Summary: There was 1 ERROR message shown, returning a non-zero exit code.
We have created the layer with the recipe and
the layer configuration file but it still seems that BitBake cannot
find the recipe. BitBake needs a ``conf/bblayers.conf`` that lists
the layers for the project. Without this file, BitBake cannot find
the recipe.
#. **Creating conf/bblayers.conf:** BitBake uses the
``conf/bblayers.conf`` file to locate layers needed for the project.
This file must reside in the ``conf`` directory of the project (i.e.
``hello/conf`` for this example).
Set your working directory to the ``hello/conf`` directory and then
create the ``bblayers.conf`` file so that it contains the following::
BBLAYERS ?= " \
/home/<you>/mylayer \
"
You need to provide your own information for ``you`` in the file.
#. **Run BitBake With a Target:** Now that you have supplied the
``bblayers.conf`` file, run the ``bitbake`` command and provide the
target::
$ bitbake printhello
Loading cache: 100% |
Loaded 0 entries from dependency cache.
Parsing recipes: 100% |##################################################################################|
Parsing of 1 .bb files complete (0 cached, 1 parsed). 1 targets, 0 skipped, 0 masked, 0 errors.
NOTE: Resolving any missing task queue dependencies
Initialising tasks: 100% |###############################################################################|
NOTE: No setscene tasks
NOTE: Executing Tasks
********************
* *
* Hello, World! *
* *
********************
NOTE: Tasks Summary: Attempted 1 tasks of which 0 didn't need to be rerun and all succeeded.
.. note::
After the first execution, re-running bitbake printhello again will not
result in a BitBake run that prints the same console output. The reason
for this is that the first time the printhello.bb recipe's do_build task
executes successfully, BitBake writes a stamp file for the task. Thus,
the next time you attempt to run the task using that same bitbake
command, BitBake notices the stamp and therefore determines that the task
does not need to be re-run. If you delete the tmp directory or run
bitbake -c clean printhello and then re-run the build, the "Hello,
World!" message will be printed again.

View File

@@ -0,0 +1,679 @@
.. SPDX-License-Identifier: CC-BY-2.5
========
Overview
========
|
Welcome to the BitBake User Manual. This manual provides information on
the BitBake tool. The information attempts to be as independent as
possible regarding systems that use BitBake, such as OpenEmbedded and
the Yocto Project. In some cases, scenarios or examples within the
context of a build system are used in the manual to help with
understanding. For these cases, the manual clearly states the context.
.. _intro:
Introduction
============
Fundamentally, BitBake is a generic task execution engine that allows
shell and Python tasks to be run efficiently and in parallel while
working within complex inter-task dependency constraints. One of
BitBake's main users, OpenEmbedded, takes this core and builds embedded
Linux software stacks using a task-oriented approach.
Conceptually, BitBake is similar to GNU Make in some regards but has
significant differences:
- BitBake executes tasks according to the provided metadata that builds up
the tasks. Metadata is stored in recipe (``.bb``) and related recipe
"append" (``.bbappend``) files, configuration (``.conf``) and
underlying include (``.inc``) files, and in class (``.bbclass``)
files. The metadata provides BitBake with instructions on what tasks
to run and the dependencies between those tasks.
- BitBake includes a fetcher library for obtaining source code from
various places such as local files, source control systems, or
websites.
- The instructions for each unit to be built (e.g. a piece of software)
are known as "recipe" files and contain all the information about the
unit (dependencies, source file locations, checksums, description and
so on).
- BitBake includes a client/server abstraction and can be used from a
command line or used as a service over XML-RPC and has several
different user interfaces.
History and Goals
=================
BitBake was originally a part of the OpenEmbedded project. It was
inspired by the Portage package management system used by the Gentoo
Linux distribution. On December 7, 2004, OpenEmbedded project team
member Chris Larson split the project into two distinct pieces:
- BitBake, a generic task executor
- OpenEmbedded, a metadata set utilized by BitBake
Today, BitBake is the primary basis of the
`OpenEmbedded <https://www.openembedded.org/>`__ project, which is being
used to build and maintain Linux distributions such as the `Poky
Reference Distribution <https://www.yoctoproject.org/software-item/poky/>`__,
developed under the umbrella of the `Yocto Project <https://www.yoctoproject.org>`__.
Prior to BitBake, no other build tool adequately met the needs of an
aspiring embedded Linux distribution. All of the build systems used by
traditional desktop Linux distributions lacked important functionality,
and none of the ad hoc Buildroot-based systems, prevalent in the
embedded space, were scalable or maintainable.
Some important original goals for BitBake were:
- Handle cross-compilation.
- Handle inter-package dependencies (build time on target architecture,
build time on native architecture, and runtime).
- Support running any number of tasks within a given package,
including, but not limited to, fetching upstream sources, unpacking
them, patching them, configuring them, and so forth.
- Be Linux distribution agnostic for both build and target systems.
- Be architecture agnostic.
- Support multiple build and target operating systems (e.g. Cygwin, the
BSDs, and so forth).
- Be self-contained, rather than tightly integrated into the build
machine's root filesystem.
- Handle conditional metadata on the target architecture, operating
system, distribution, and machine.
- Be easy to use the tools to supply local metadata and packages
against which to operate.
- Be easy to use BitBake to collaborate between multiple projects for
their builds.
- Provide an inheritance mechanism to share common metadata between
many packages.
Over time it became apparent that some further requirements were
necessary:
- Handle variants of a base recipe (e.g. native, sdk, and multilib).
- Split metadata into layers and allow layers to enhance or override
other layers.
- Allow representation of a given set of input variables to a task as a
checksum. Based on that checksum, allow acceleration of builds with
prebuilt components.
BitBake satisfies all the original requirements and many more with
extensions being made to the basic functionality to reflect the
additional requirements. Flexibility and power have always been the
priorities. BitBake is highly extensible and supports embedded Python
code and execution of any arbitrary tasks.
.. _Concepts:
Concepts
========
BitBake is a program written in the Python language. At the highest
level, BitBake interprets metadata, decides what tasks are required to
run, and executes those tasks. Similar to GNU Make, BitBake controls how
software is built. GNU Make achieves its control through "makefiles",
while BitBake uses "recipes".
BitBake extends the capabilities of a simple tool like GNU Make by
allowing for the definition of much more complex tasks, such as
assembling entire embedded Linux distributions.
The remainder of this section introduces several concepts that should be
understood in order to better leverage the power of BitBake.
Recipes
-------
BitBake Recipes, which are denoted by the file extension ``.bb``, are
the most basic metadata files. These recipe files provide BitBake with
the following:
- Descriptive information about the package (author, homepage, license,
and so on)
- The version of the recipe
- Existing dependencies (both build and runtime dependencies)
- Where the source code resides and how to fetch it
- Whether the source code requires any patches, where to find them, and
how to apply them
- How to configure and compile the source code
- How to assemble the generated artifacts into one or more installable
packages
- Where on the target machine to install the package or packages
created
Within the context of BitBake, or any project utilizing BitBake as its
build system, files with the ``.bb`` extension are referred to as
recipes.
.. note::
The term "package" is also commonly used to describe recipes.
However, since the same word is used to describe packaged output from
a project, it is best to maintain a single descriptive term -
"recipes". Put another way, a single "recipe" file is quite capable
of generating a number of related but separately installable
"packages". In fact, that ability is fairly common.
Configuration Files
-------------------
Configuration files, which are denoted by the ``.conf`` extension,
define various configuration variables that govern the project's build
process. These files fall into several areas that define machine
configuration, distribution configuration, possible compiler tuning,
general common configuration, and user configuration. The main
configuration file is the sample ``bitbake.conf`` file, which is located
within the BitBake source tree ``conf`` directory.
Classes
-------
Class files, which are denoted by the ``.bbclass`` extension, contain
information that is useful to share between metadata files. The BitBake
source tree currently comes with one class metadata file called
``base.bbclass``. You can find this file in the ``classes`` directory.
The ``base.bbclass`` class files is special since it is always included
automatically for all recipes and classes. This class contains
definitions for standard basic tasks such as fetching, unpacking,
configuring (empty by default), compiling (runs any Makefile present),
installing (empty by default) and packaging (empty by default). These
tasks are often overridden or extended by other classes added during the
project development process.
Layers
------
Layers allow you to isolate different types of customizations from each
other. While you might find it tempting to keep everything in one layer
when working on a single project, the more modular your metadata, the
easier it is to cope with future changes.
To illustrate how you can use layers to keep things modular, consider
customizations you might make to support a specific target machine.
These types of customizations typically reside in a special layer,
rather than a general layer, called a Board Support Package (BSP) layer.
Furthermore, the machine customizations should be isolated from recipes
and metadata that support a new GUI environment, for example. This
situation gives you a couple of layers: one for the machine
configurations and one for the GUI environment. It is important to
understand, however, that the BSP layer can still make machine-specific
additions to recipes within the GUI environment layer without polluting
the GUI layer itself with those machine-specific changes. You can
accomplish this through a recipe that is a BitBake append
(``.bbappend``) file.
.. _append-bbappend-files:
Append Files
------------
Append files, which are files that have the ``.bbappend`` file
extension, extend or override information in an existing recipe file.
BitBake expects every append file to have a corresponding recipe file.
Furthermore, the append file and corresponding recipe file must use the
same root filename. The filenames can differ only in the file type
suffix used (e.g. ``formfactor_0.0.bb`` and
``formfactor_0.0.bbappend``).
Information in append files extends or overrides the information in the
underlying, similarly-named recipe files.
When you name an append file, you can use the "``%``" wildcard character
to allow for matching recipe names. For example, suppose you have an
append file named as follows::
busybox_1.21.%.bbappend
That append file
would match any ``busybox_1.21.``\ x\ ``.bb`` version of the recipe. So,
the append file would match the following recipe names::
busybox_1.21.1.bb
busybox_1.21.2.bb
busybox_1.21.3.bb
.. note::
The use of the " % " character is limited in that it only works directly in
front of the .bbappend portion of the append file's name. You cannot use the
wildcard character in any other location of the name.
If the ``busybox`` recipe was updated to ``busybox_1.3.0.bb``, the
append name would not match. However, if you named the append file
``busybox_1.%.bbappend``, then you would have a match.
In the most general case, you could name the append file something as
simple as ``busybox_%.bbappend`` to be entirely version independent.
Obtaining BitBake
=================
You can obtain BitBake several different ways:
- **Cloning BitBake:** Using Git to clone the BitBake source code
repository is the recommended method for obtaining BitBake. Cloning
the repository makes it easy to get bug fixes and have access to
stable branches and the master branch. Once you have cloned BitBake,
you should use the latest stable branch for development since the
master branch is for BitBake development and might contain less
stable changes.
You usually need a version of BitBake that matches the metadata you
are using. The metadata is generally backwards compatible but not
forward compatible.
Here is an example that clones the BitBake repository::
$ git clone git://git.openembedded.org/bitbake
This command clones the BitBake
Git repository into a directory called ``bitbake``. Alternatively,
you can designate a directory after the ``git clone`` command if you
want to call the new directory something other than ``bitbake``. Here
is an example that names the directory ``bbdev``::
$ git clone git://git.openembedded.org/bitbake bbdev
- **Installation using your Distribution Package Management System:**
This method is not recommended because the BitBake version that is
provided by your distribution, in most cases, is several releases
behind a snapshot of the BitBake repository.
- **Taking a snapshot of BitBake:** Downloading a snapshot of BitBake
from the source code repository gives you access to a known branch or
release of BitBake.
.. note::
Cloning the Git repository, as described earlier, is the preferred
method for getting BitBake. Cloning the repository makes it easier
to update as patches are added to the stable branches.
The following example downloads a snapshot of BitBake version 1.17.0::
$ wget https://git.openembedded.org/bitbake/snapshot/bitbake-1.17.0.tar.gz
$ tar zxpvf bitbake-1.17.0.tar.gz
After extraction of the tarball using
the tar utility, you have a directory entitled ``bitbake-1.17.0``.
- **Using the BitBake that Comes With Your Build Checkout:** A final
possibility for getting a copy of BitBake is that it already comes
with your checkout of a larger BitBake-based build system, such as
Poky. Rather than manually checking out individual layers and gluing
them together yourself, you can check out an entire build system. The
checkout will already include a version of BitBake that has been
thoroughly tested for compatibility with the other components. For
information on how to check out a particular BitBake-based build
system, consult that build system's supporting documentation.
.. _bitbake-user-manual-command:
The BitBake Command
===================
The ``bitbake`` command is the primary interface to the BitBake tool.
This section presents the BitBake command syntax and provides several
execution examples.
Usage and syntax
----------------
Following is the usage and syntax for BitBake::
$ bitbake -h
usage: bitbake [-s] [-e] [-g] [-u UI] [--version] [-h] [-f] [-c CMD]
[-C INVALIDATE_STAMP] [--runall RUNALL] [--runonly RUNONLY]
[--no-setscene] [--skip-setscene] [--setscene-only] [-n] [-p]
[-k] [-P] [-S SIGNATURE_HANDLER] [--revisions-changed]
[-b BUILDFILE] [-D] [-l DEBUG_DOMAINS] [-v] [-q]
[-w WRITEEVENTLOG] [-B BIND] [-T SERVER_TIMEOUT]
[--remote-server REMOTE_SERVER] [-m] [--token XMLRPCTOKEN]
[--observe-only] [--status-only] [--server-only] [-r PREFILE]
[-R POSTFILE] [-I EXTRA_ASSUME_PROVIDED]
[recipename/target ...]
It is assumed there is a conf/bblayers.conf available in cwd or in BBPATH
which will provide the layer, BBFILES and other configuration information.
General options:
recipename/target Execute the specified task (default is 'build') for
these target recipes (.bb files).
-s, --show-versions Show current and preferred versions of all recipes.
-e, --environment Show the global or per-recipe environment complete
with information about where variables were
set/changed.
-g, --graphviz Save dependency tree information for the specified
targets in the dot syntax.
-u UI, --ui UI The user interface to use (knotty, ncurses, taskexp,
taskexp_ncurses or teamcity - default knotty).
--version Show programs version and exit.
-h, --help Show this help message and exit.
Task control options:
-f, --force Force the specified targets/task to run (invalidating
any existing stamp file).
-c CMD, --cmd CMD Specify the task to execute. The exact options
available depend on the metadata. Some examples might
be 'compile' or 'populate_sysroot' or 'listtasks' may
give a list of the tasks available.
-C INVALIDATE_STAMP, --clear-stamp INVALIDATE_STAMP
Invalidate the stamp for the specified task such as
'compile' and then run the default task for the
specified target(s).
--runall RUNALL Run the specified task for any recipe in the taskgraph
of the specified target (even if it wouldn't otherwise
have run).
--runonly RUNONLY Run only the specified task within the taskgraph of
the specified targets (and any task dependencies those
tasks may have).
--no-setscene Do not run any setscene tasks. sstate will be ignored
and everything needed, built.
--skip-setscene Skip setscene tasks if they would be executed. Tasks
previously restored from sstate will be kept, unlike
--no-setscene.
--setscene-only Only run setscene tasks, don't run any real tasks.
Execution control options:
-n, --dry-run Don't execute, just go through the motions.
-p, --parse-only Quit after parsing the BB recipes.
-k, --continue Continue as much as possible after an error. While the
target that failed and anything depending on it cannot
be built, as much as possible will be built before
stopping.
-P, --profile Profile the command and save reports.
-S SIGNATURE_HANDLER, --dump-signatures SIGNATURE_HANDLER
Dump out the signature construction information, with
no task execution. The SIGNATURE_HANDLER parameter is
passed to the handler. Two common values are none and
printdiff but the handler may define more/less. none
means only dump the signature, printdiff means
recursively compare the dumped signature with the most
recent one in a local build or sstate cache (can be
used to find out why tasks re-run when that is not
expected)
--revisions-changed Set the exit code depending on whether upstream
floating revisions have changed or not.
-b BUILDFILE, --buildfile BUILDFILE
Execute tasks from a specific .bb recipe directly.
WARNING: Does not handle any dependencies from other
recipes.
Logging/output control options:
-D, --debug Increase the debug level. You can specify this more
than once. -D sets the debug level to 1, where only
bb.debug(1, ...) messages are printed to stdout; -DD
sets the debug level to 2, where both bb.debug(1, ...)
and bb.debug(2, ...) messages are printed; etc.
Without -D, no debug messages are printed. Note that
-D only affects output to stdout. All debug messages
are written to ${T}/log.do_taskname, regardless of the
debug level.
-l DEBUG_DOMAINS, --log-domains DEBUG_DOMAINS
Show debug logging for the specified logging domains.
-v, --verbose Enable tracing of shell tasks (with 'set -x'). Also
print bb.note(...) messages to stdout (in addition to
writing them to ${T}/log.do_<task>).
-q, --quiet Output less log message data to the terminal. You can
specify this more than once.
-w WRITEEVENTLOG, --write-log WRITEEVENTLOG
Writes the event log of the build to a bitbake event
json file. Use '' (empty string) to assign the name
automatically.
Server options:
-B BIND, --bind BIND The name/address for the bitbake xmlrpc server to bind
to.
-T SERVER_TIMEOUT, --idle-timeout SERVER_TIMEOUT
Set timeout to unload bitbake server due to
inactivity, set to -1 means no unload, default:
Environment variable BB_SERVER_TIMEOUT.
--remote-server REMOTE_SERVER
Connect to the specified server.
-m, --kill-server Terminate any running bitbake server.
--token XMLRPCTOKEN Specify the connection token to be used when
connecting to a remote server.
--observe-only Connect to a server as an observing-only client.
--status-only Check the status of the remote bitbake server.
--server-only Run bitbake without a UI, only starting a server
(cooker) process.
Configuration options:
-r PREFILE, --read PREFILE
Read the specified file before bitbake.conf.
-R POSTFILE, --postread POSTFILE
Read the specified file after bitbake.conf.
-I EXTRA_ASSUME_PROVIDED, --ignore-deps EXTRA_ASSUME_PROVIDED
Assume these dependencies don't exist and are already
provided (equivalent to ASSUME_PROVIDED). Useful to
make dependency graphs more appealing.
..
Bitbake help output generated with "stty columns 80; bin/bitbake -h"
.. _bitbake-examples:
Examples
--------
This section presents some examples showing how to use BitBake.
.. _example-executing-a-task-against-a-single-recipe:
Executing a Task Against a Single Recipe
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Executing tasks for a single recipe file is relatively simple. You
specify the file in question, and BitBake parses it and executes the
specified task. If you do not specify a task, BitBake executes the
default task, which is "build". BitBake obeys inter-task dependencies
when doing so.
The following command runs the build task, which is the default task, on
the ``foo_1.0.bb`` recipe file::
$ bitbake -b foo_1.0.bb
The following command runs the clean task on the ``foo.bb`` recipe file::
$ bitbake -b foo.bb -c clean
.. note::
The "-b" option explicitly does not handle recipe dependencies. Other
than for debugging purposes, it is instead recommended that you use
the syntax presented in the next section.
Executing Tasks Against a Set of Recipe Files
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
There are a number of additional complexities introduced when one wants
to manage multiple ``.bb`` files. Clearly there needs to be a way to
tell BitBake what files are available and, of those, which you want to
execute. There also needs to be a way for each recipe to express its
dependencies, both for build-time and runtime. There must be a way for
you to express recipe preferences when multiple recipes provide the same
functionality, or when there are multiple versions of a recipe.
The ``bitbake`` command, when not using "--buildfile" or "-b" only
accepts a "PROVIDES". You cannot provide anything else. By default, a
recipe file generally "PROVIDES" its "packagename" as shown in the
following example::
$ bitbake foo
This next example "PROVIDES" the
package name and also uses the "-c" option to tell BitBake to just
execute the ``do_clean`` task::
$ bitbake -c clean foo
Executing a List of Task and Recipe Combinations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The BitBake command line supports specifying different tasks for
individual targets when you specify multiple targets. For example,
suppose you had two targets (or recipes) ``myfirstrecipe`` and
``mysecondrecipe`` and you needed BitBake to run ``taskA`` for the first
recipe and ``taskB`` for the second recipe::
$ bitbake myfirstrecipe:do_taskA mysecondrecipe:do_taskB
Generating Dependency Graphs
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BitBake is able to generate dependency graphs using the ``dot`` syntax.
You can convert these graphs into images using the ``dot`` tool from
`Graphviz <http://www.graphviz.org>`__.
When you generate a dependency graph, BitBake writes two files to the
current working directory:
- ``task-depends.dot``: Shows dependencies between tasks. These
dependencies match BitBake's internal task execution list.
- ``pn-buildlist``: Shows a simple list of targets that are to be
built.
To stop depending on common depends, use the ``-I`` depend option and
BitBake omits them from the graph. Leaving this information out can
produce more readable graphs. This way, you can remove from the graph
:term:`DEPENDS` from inherited classes such as ``base.bbclass``.
Here are two examples that create dependency graphs. The second example
omits depends common in OpenEmbedded from the graph::
$ bitbake -g foo
$ bitbake -g -I virtual/kernel -I eglibc foo
Executing a Multiple Configuration Build
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BitBake is able to build multiple images or packages using a single
command where the different targets require different configurations
(multiple configuration builds). Each target, in this scenario, is
referred to as a "multiconfig".
To accomplish a multiple configuration build, you must define each
target's configuration separately using a parallel configuration file in
the build directory. The location for these multiconfig configuration
files is specific. They must reside in the current build directory in a
sub-directory of ``conf`` named ``multiconfig``. Following is an example
for two separate targets:
.. image:: figures/bb_multiconfig_files.png
:align: center
The reason for this required file hierarchy is because the :term:`BBPATH`
variable is not constructed until the layers are parsed. Consequently,
using the configuration file as a pre-configuration file is not possible
unless it is located in the current working directory.
Minimally, each configuration file must define the machine and the
temporary directory BitBake uses for the build. Suggested practice
dictates that you do not overlap the temporary directories used during
the builds.
Aside from separate configuration files for each target, you must also
enable BitBake to perform multiple configuration builds. Enabling is
accomplished by setting the
:term:`BBMULTICONFIG` variable in the
``local.conf`` configuration file. As an example, suppose you had
configuration files for ``target1`` and ``target2`` defined in the build
directory. The following statement in the ``local.conf`` file both
enables BitBake to perform multiple configuration builds and specifies
the two extra multiconfigs::
BBMULTICONFIG = "target1 target2"
Once the target configuration files are in place and BitBake has been
enabled to perform multiple configuration builds, use the following
command form to start the builds::
$ bitbake [mc:multiconfigname:]target [[[mc:multiconfigname:]target] ... ]
Here is an example for two extra multiconfigs: ``target1`` and ``target2``::
$ bitbake mc::target mc:target1:target mc:target2:target
.. _bb-enabling-multiple-configuration-build-dependencies:
Enabling Multiple Configuration Build Dependencies
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sometimes dependencies can exist between targets (multiconfigs) in a
multiple configuration build. For example, suppose that in order to
build an image for a particular architecture, the root filesystem of
another build for a different architecture needs to exist. In other
words, the image for the first multiconfig depends on the root
filesystem of the second multiconfig. This dependency is essentially
that the task in the recipe that builds one multiconfig is dependent on
the completion of the task in the recipe that builds another
multiconfig.
To enable dependencies in a multiple configuration build, you must
declare the dependencies in the recipe using the following statement
form::
task_or_package[mcdepends] = "mc:from_multiconfig:to_multiconfig:recipe_name:task_on_which_to_depend"
To better show how to use this statement, consider an example with two
multiconfigs: ``target1`` and ``target2``::
image_task[mcdepends] = "mc:target1:target2:image2:rootfs_task"
In this example, the
``from_multiconfig`` is "target1" and the ``to_multiconfig`` is "target2". The
task on which the image whose recipe contains image_task depends on the
completion of the rootfs_task used to build out image2, which is
associated with the "target2" multiconfig.
Once you set up this dependency, you can build the "target1" multiconfig
using a BitBake command as follows::
$ bitbake mc:target1:image1
This command executes all the tasks needed to create ``image1`` for the "target1"
multiconfig. Because of the dependency, BitBake also executes through
the ``rootfs_task`` for the "target2" multiconfig build.
Having a recipe depend on the root filesystem of another build might not
seem that useful. Consider this change to the statement in the image1
recipe::
image_task[mcdepends] = "mc:target1:target2:image2:image_task"
In this case, BitBake must create ``image2`` for the "target2" build since
the "target1" build depends on it.
Because "target1" and "target2" are enabled for multiple configuration
builds and have separate configuration files, BitBake places the
artifacts for each build in the respective temporary build directories.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,91 @@
.. SPDX-License-Identifier: CC-BY-2.5
================
Variable Context
================
|
Variables might only have an impact or can be used in certain contexts. Some
should only be used in global files like ``.conf``, while others are intended only
for local files like ``.bb``. This chapter aims to describe some important variable
contexts.
.. _ref-varcontext-configuration:
BitBake's own configuration
===========================
Variables starting with ``BB_`` usually configure the behaviour of BitBake itself.
For example, one could configure:
- System resources, like disk space to be used (:term:`BB_DISKMON_DIRS`),
or the number of tasks to be run in parallel by BitBake (:term:`BB_NUMBER_THREADS`).
- How the fetchers shall behave, e.g., :term:`BB_FETCH_PREMIRRORONLY` is used
by BitBake to determine if BitBake's fetcher shall search only
:term:`PREMIRRORS` for files.
Those variables are usually configured globally.
BitBake configuration
=====================
There are variables:
- Like :term:`B` or :term:`T`, that are used to specify directories used by
BitBake during the build of a particular recipe. Those variables are
specified in ``bitbake.conf``. Some, like :term:`B`, are quite often
overwritten in recipes.
- Starting with ``FAKEROOT``, to configure how the ``fakeroot`` command is
handled. Those are usually set by ``bitbake.conf`` and might get adapted in a
``bbclass``.
- Detailing where BitBake will store and fetch information from, for
data reuse between build runs like :term:`CACHE`, :term:`DL_DIR` or
:term:`PERSISTENT_DIR`. Those are usually global.
Layers and files
================
Variables starting with ``LAYER`` configure how BitBake handles layers.
Additionally, variables starting with ``BB`` configure how layers and files are
handled. For example:
- :term:`LAYERDEPENDS` is used to configure on which layers a given layer
depends.
- The configured layers are contained in :term:`BBLAYERS` and files in
:term:`BBFILES`.
Those variables are often used in the files ``layer.conf`` and ``bblayers.conf``.
Recipes and packages
====================
Variables handling recipes and packages can be split into:
- :term:`PN`, :term:`PV` or :term:`PF` for example, contain information about
the name or revision of a recipe or package. Usually, the default set in
``bitbake.conf`` is used, but those are from time to time overwritten in
recipes.
- :term:`SUMMARY`, :term:`DESCRIPTION`, :term:`LICENSE` or :term:`HOMEPAGE`
contain the expected information and should be set specifically for every
recipe.
- In recipes, variables are also used to control build and runtime
dependencies between recipes/packages with other recipes/packages. The
most common should be: :term:`PROVIDES`, :term:`RPROVIDES`, :term:`DEPENDS`,
and :term:`RDEPENDS`.
- There are further variables starting with ``SRC`` that specify the sources in
a recipe like :term:`SRC_URI` or :term:`SRCDATE`. Those are also usually set
in recipes.
- Which version or provider of a recipe should be given preference when
multiple recipes would provide the same item, is controlled by variables
starting with ``PREFERRED_``. Those are normally set in the configuration
files of a ``MACHINE`` or ``DISTRO``.

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

142
bitbake/doc/bitbake.1 Normal file
View File

@@ -0,0 +1,142 @@
.\" Hey, EMACS: -*- nroff -*-
.\" First parameter, NAME, should be all caps
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
.\" other parameters are allowed: see man(7), man(1)
.TH BITBAKE 1 "November 19, 2006"
.\" Please adjust this date whenever revising the manpage.
.\"
.\" Some roff macros, for reference:
.\" .nh disable hyphenation
.\" .hy enable hyphenation
.\" .ad l left justify
.\" .ad b justify to both left and right margins
.\" .nf disable filling
.\" .fi enable filling
.\" .br insert line break
.\" .sp <n> insert n+1 empty lines
.\" for manpage-specific macros, see man(7)
.SH NAME
BitBake \- simple tool for the execution of tasks
.SH SYNOPSIS
.B bitbake
.RI [ options ] " packagenames"
.br
.SH DESCRIPTION
This manual page documents briefly the
.B bitbake
command.
.PP
.\" TeX users may be more comfortable with the \fB<whatever>\fP and
.\" \fI<whatever>\fP escape sequences to invode bold face and italics,
.\" respectively.
\fBbitbake\fP is a program that executes the specified task (default is 'build')
for a given set of BitBake files.
.br
It expects that BBFILES is defined, which is a space separated list of files to
be executed. BBFILES does support wildcards.
.br
Default BBFILES are the .bb files in the current directory.
.SH OPTIONS
This program follow the usual GNU command line syntax, with long
options starting with two dashes (`-').
.TP
.B \-h, \-\-help
Show summary of options.
.TP
.B \-\-version
Show version of program.
.TP
.B \-bBUILDFILE, \-\-buildfile=BUILDFILE
execute the task against this .bb file, rather than a package from BBFILES.
.TP
.B \-k, \-\-continue
continue as much as possible after an error. While the target that failed, and
those that depend on it, cannot be remade, the other dependencies of these
targets can be processed all the same.
.TP
.B \-a, \-\-tryaltconfigs
continue with builds by trying to use alternative providers where possible.
.TP
.B \-f, \-\-force
force run of specified cmd, regardless of stamp status
.TP
.B \-i, \-\-interactive
drop into the interactive mode also called the BitBake shell.
.TP
.B \-cCMD, \-\-cmd=CMD
Specify task to execute. Note that this only executes the specified task for
the providee and the packages it depends on, i.e. 'compile' does not implicitly
call stage for the dependencies (IOW: use only if you know what you are doing).
Depending on the base.bbclass a listtasks task is defined and will show
available tasks.
.TP
.B \-rFILE, \-\-read=FILE
read the specified file before bitbake.conf
.TP
.B \-v, \-\-verbose
output more chit-chat to the terminal
.TP
.B \-D, \-\-debug
Increase the debug level. You can specify this more than once.
.TP
.B \-n, \-\-dry-run
don't execute, just go through the motions
.TP
.B \-p, \-\-parse-only
quit after parsing the BB files (developers only)
.TP
.B \-s, \-\-show-versions
show current and preferred versions of all packages
.TP
.B \-e, \-\-environment
show the global or per-recipe environment (this is what used to be bbread)
.TP
.B \-g, \-\-graphviz
emit the dependency trees of the specified packages in the dot syntax
.TP
.B \-IIGNORED\_DOT\_DEPS, \-\-ignore-deps=IGNORED_DOT_DEPS
Stop processing at the given list of dependencies when generating dependency
graphs. This can help to make the graph more appealing
.TP
.B \-lDEBUG_DOMAINS, \-\-log-domains=DEBUG_DOMAINS
Show debug logging for the specified logging domains
.TP
.B \-P, \-\-profile
profile the command and print a report
.TP
.B \-uUI, \-\-ui=UI
User interface to use. Currently, knotty, taskexp or ncurses can be specified as UI.
.TP
.B \-tSERVERTYPE, \-\-servertype=SERVERTYPE
Choose which server to use, none, process or xmlrpc.
.TP
.B \-\-revisions-changed
Set the exit code depending on whether upstream floating revisions have changed or not.
.TP
.B \-\-server-only
Run bitbake without UI, the frontend can connect with bitbake server itself.
.TP
.B \-BBIND, \-\-bind=BIND
The name/address for the bitbake server to bind to.
.TP
.B \-\-no\-setscene
Do not run any setscene tasks, forces builds.
.SH ENVIRONMENT VARIABLES
bitbake uses the following environment variables to control its
operation:
.TP
.B BITBAKE_UI
The bitbake user interface; overridden by the \fB-u\fP commandline option.
.SH AUTHORS
BitBake was written by
Phil Blundell,
Holger Freyther,
Chris Larson,
Mickey Lauer,
Richard Purdie,
Holger Schurig
.PP
This manual page was written by Marcin Juszkiewicz <marcin@hrw.one.pl>
for the Debian project (but may be used by others).

101
bitbake/doc/conf.py Normal file
View File

@@ -0,0 +1,101 @@
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))
import sys
import datetime
current_version = "dev"
# String used in sidebar
version = 'Version: ' + current_version
if current_version == 'dev':
version = 'Version: Current Development'
# Version seen in documentation_options.js and hence in js switchers code
release = current_version
# -- Project information -----------------------------------------------------
project = 'Bitbake'
copyright = '2004-%s, Richard Purdie, Chris Larson, and Phil Blundell' \
% datetime.datetime.now().year
author = 'Richard Purdie, Chris Larson, and Phil Blundell'
# external links and substitutions
extlinks = {
'yocto_docs': ('https://docs.yoctoproject.org%s', None),
'oe_lists': ('https://lists.openembedded.org%s', None),
}
# -- General configuration ---------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autosectionlabel',
'sphinx.ext.extlinks',
]
autosectionlabel_prefix_document = True
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
# master document name. The default changed from contents to index. so better
# set it ourselves.
master_doc = 'index'
# create substitution for project configuration variables
rst_prolog = """
.. |project_name| replace:: %s
.. |copyright| replace:: %s
.. |author| replace:: %s
""" % (project, copyright, author)
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
try:
import sphinx_rtd_theme
html_theme = 'sphinx_rtd_theme'
except ImportError:
sys.stderr.write("The Sphinx sphinx_rtd_theme HTML theme was not found.\
\nPlease make sure to install the sphinx_rtd_theme python package.\n")
sys.exit(1)
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['sphinx-static']
# Add customm CSS and JS files
html_css_files = ['theme_overrides.css']
html_js_files = ['switchers.js']
# Hide 'Created using Sphinx' text
html_show_sphinx = False
# Add 'Last updated' on each page
html_last_updated_fmt = '%b %d, %Y'
# Remove the trailing 'dot' in section numbers
html_secnumber_suffix = " "

3
bitbake/doc/genindex.rst Normal file
View File

@@ -0,0 +1,3 @@
=====
Index
=====

39
bitbake/doc/index.rst Normal file
View File

@@ -0,0 +1,39 @@
.. SPDX-License-Identifier: CC-BY-2.5
===================
BitBake User Manual
===================
|
.. toctree::
:caption: Table of Contents
:numbered:
bitbake-user-manual/bitbake-user-manual-intro
bitbake-user-manual/bitbake-user-manual-execution
bitbake-user-manual/bitbake-user-manual-metadata
bitbake-user-manual/bitbake-user-manual-ref-variables-context
bitbake-user-manual/bitbake-user-manual-fetching
bitbake-user-manual/bitbake-user-manual-ref-variables
bitbake-user-manual/bitbake-user-manual-hello
.. toctree::
:maxdepth: 1
:hidden:
genindex
releases
----
.. include:: <xhtml1-lat1.txt>
| BitBake Community
| Copyright |copy| |copyright|
| <bitbake-devel@lists.openembedded.org>
This work is licensed under the Creative Commons Attribution License. To view a
copy of this license, visit http://creativecommons.org/licenses/by/2.5/ or send
a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain View,
California 94041, USA.

187
bitbake/doc/releases.rst Normal file
View File

@@ -0,0 +1,187 @@
.. SPDX-License-Identifier: CC-BY-2.5
=================================
BitBake Supported Release Manuals
=================================
****************************
Release Series 5.1 (styhead)
****************************
- :yocto_docs:`BitBake 2.10 User Manual </bitbake/2.10/>`
*******************************
Release Series 5.0 (scarthgap)
*******************************
- :yocto_docs:`BitBake 2.8 User Manual </bitbake/2.8/>`
******************************
Release Series 4.0 (kirkstone)
******************************
- :yocto_docs:`BitBake 2.0 User Manual </bitbake/2.0/>`
================================
BitBake Outdated Release Manuals
================================
*******************************
Release Series 4.3 (nanbield)
*******************************
- :yocto_docs:`BitBake 2.6 User Manual </bitbake/2.6/>`
*******************************
Release Series 4.2 (mickledore)
*******************************
- :yocto_docs:`BitBake 2.4 User Manual </bitbake/2.4/>`
*****************************
Release Series 4.1 (langdale)
*****************************
- :yocto_docs:`BitBake 2.2 User Manual </bitbake/2.2/>`
******************************
Release Series 3.4 (honister)
******************************
- :yocto_docs:`BitBake 1.52 User Manual </bitbake/1.52/>`
******************************
Release Series 3.3 (hardknott)
******************************
- :yocto_docs:`BitBake 1.50 User Manual </bitbake/1.50/>`
*******************************
Release Series 3.2 (gatesgarth)
*******************************
- :yocto_docs:`BitBake 1.48 User Manual </bitbake/1.48/>`
****************************
Release Series 3.1 (dunfell)
****************************
- :yocto_docs:`BitBake 1.46 User Manual </bitbake/1.46/>`
- :yocto_docs:`3.1 BitBake User Manual </3.1/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`3.1.1 BitBake User Manual </3.1.1/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`3.1.2 BitBake User Manual </3.1.2/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`3.1.3 BitBake User Manual </3.1.3/bitbake-user-manual/bitbake-user-manual.html>`
*************************
Release Series 3.0 (zeus)
*************************
- :yocto_docs:`3.0 BitBake User Manual </3.0/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`3.0.1 BitBake User Manual </3.0.1/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`3.0.2 BitBake User Manual </3.0.2/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`3.0.3 BitBake User Manual </3.0.3/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`3.0.4 BitBake User Manual </3.0.4/bitbake-user-manual/bitbake-user-manual.html>`
****************************
Release Series 2.7 (warrior)
****************************
- :yocto_docs:`2.7 BitBake User Manual </2.7/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`2.7.1 BitBake User Manual </2.7.1/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`2.7.2 BitBake User Manual </2.7.2/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`2.7.3 BitBake User Manual </2.7.3/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`2.7.4 BitBake User Manual </2.7.4/bitbake-user-manual/bitbake-user-manual.html>`
*************************
Release Series 2.6 (thud)
*************************
- :yocto_docs:`2.6 BitBake User Manual </2.6/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`2.6.1 BitBake User Manual </2.6.1/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`2.6.2 BitBake User Manual </2.6.2/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`2.6.3 BitBake User Manual </2.6.3/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`2.6.4 BitBake User Manual </2.6.4/bitbake-user-manual/bitbake-user-manual.html>`
*************************
Release Series 2.5 (sumo)
*************************
- :yocto_docs:`2.5 Documentation </2.5>`
- :yocto_docs:`2.5.1 Documentation </2.5.1>`
- :yocto_docs:`2.5.2 Documentation </2.5.2>`
- :yocto_docs:`2.5.3 Documentation </2.5.3>`
**************************
Release Series 2.4 (rocko)
**************************
- :yocto_docs:`2.4 BitBake User Manual </2.4/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`2.4.1 BitBake User Manual </2.4.1/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`2.4.2 BitBake User Manual </2.4.2/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`2.4.3 BitBake User Manual </2.4.3/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`2.4.4 BitBake User Manual </2.4.4/bitbake-user-manual/bitbake-user-manual.html>`
*************************
Release Series 2.3 (pyro)
*************************
- :yocto_docs:`2.3 BitBake User Manual </2.3/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`2.3.1 BitBake User Manual </2.3.1/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`2.3.2 BitBake User Manual </2.3.2/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`2.3.3 BitBake User Manual </2.3.3/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`2.3.4 BitBake User Manual </2.3.4/bitbake-user-manual/bitbake-user-manual.html>`
**************************
Release Series 2.2 (morty)
**************************
- :yocto_docs:`2.2 BitBake User Manual </2.2/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`2.2.1 BitBake User Manual </2.2.1/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`2.2.2 BitBake User Manual </2.2.2/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`2.2.3 BitBake User Manual </2.2.3/bitbake-user-manual/bitbake-user-manual.html>`
****************************
Release Series 2.1 (krogoth)
****************************
- :yocto_docs:`2.1 BitBake User Manual </2.1/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`2.1.1 BitBake User Manual </2.1.1/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`2.1.2 BitBake User Manual </2.1.2/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`2.1.3 BitBake User Manual </2.1.3/bitbake-user-manual/bitbake-user-manual.html>`
***************************
Release Series 2.0 (jethro)
***************************
- :yocto_docs:`1.9 BitBake User Manual </1.9/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`2.0 BitBake User Manual </2.0/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`2.0.1 BitBake User Manual </2.0.1/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`2.0.2 BitBake User Manual </2.0.2/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`2.0.3 BitBake User Manual </2.0.3/bitbake-user-manual/bitbake-user-manual.html>`
*************************
Release Series 1.8 (fido)
*************************
- :yocto_docs:`1.8 BitBake User Manual </1.8/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`1.8.1 BitBake User Manual </1.8.1/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`1.8.2 BitBake User Manual </1.8.2/bitbake-user-manual/bitbake-user-manual.html>`
**************************
Release Series 1.7 (dizzy)
**************************
- :yocto_docs:`1.7 BitBake User Manual </1.7/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`1.7.1 BitBake User Manual </1.7.1/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`1.7.2 BitBake User Manual </1.7.2/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`1.7.3 BitBake User Manual </1.7.3/bitbake-user-manual/bitbake-user-manual.html>`
**************************
Release Series 1.6 (daisy)
**************************
- :yocto_docs:`1.6 BitBake User Manual </1.6/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`1.6.1 BitBake User Manual </1.6.1/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`1.6.2 BitBake User Manual </1.6.2/bitbake-user-manual/bitbake-user-manual.html>`
- :yocto_docs:`1.6.3 BitBake User Manual </1.6.3/bitbake-user-manual/bitbake-user-manual.html>`

View File

@@ -0,0 +1,233 @@
(function() {
'use strict';
var all_versions = {
'dev': 'dev (3.2)',
'3.1.2': '3.1.2',
'3.0.3': '3.0.3',
'2.7.4': '2.7.4',
};
var all_doctypes = {
'single': 'Individual Webpages',
'mega': "All-in-one 'Mega' Manual",
};
// Simple version comparision
// Return 1 if a > b
// Return -1 if a < b
// Return 0 if a == b
function ver_compare(a, b) {
if (a == "dev") {
return 1;
}
if (a === b) {
return 0;
}
var a_components = a.split(".");
var b_components = b.split(".");
var len = Math.min(a_components.length, b_components.length);
// loop while the components are equal
for (var i = 0; i < len; i++) {
// A bigger than B
if (parseInt(a_components[i]) > parseInt(b_components[i])) {
return 1;
}
// B bigger than A
if (parseInt(a_components[i]) < parseInt(b_components[i])) {
return -1;
}
}
// If one's a prefix of the other, the longer one is greater.
if (a_components.length > b_components.length) {
return 1;
}
if (a_components.length < b_components.length) {
return -1;
}
// Otherwise they are the same.
return 0;
}
function build_version_select(current_series, current_version) {
var buf = ['<select>'];
$.each(all_versions, function(version, title) {
var series = version.substr(0, 3);
if (series == current_series) {
if (version == current_version)
buf.push('<option value="' + version + '" selected="selected">' + title + '</option>');
else
buf.push('<option value="' + version + '">' + title + '</option>');
if (version != current_version)
buf.push('<option value="' + current_version + '" selected="selected">' + current_version + '</option>');
} else {
buf.push('<option value="' + version + '">' + title + '</option>');
}
});
buf.push('</select>');
return buf.join('');
}
function build_doctype_select(current_doctype) {
var buf = ['<select>'];
$.each(all_doctypes, function(doctype, title) {
if (doctype == current_doctype)
buf.push('<option value="' + doctype + '" selected="selected">' +
all_doctypes[current_doctype] + '</option>');
else
buf.push('<option value="' + doctype + '">' + title + '</option>');
});
if (!(current_doctype in all_doctypes)) {
// In case we're browsing a doctype that is not yet in all_doctypes.
buf.push('<option value="' + current_doctype + '" selected="selected">' +
current_doctype + '</option>');
all_doctypes[current_doctype] = current_doctype;
}
buf.push('</select>');
return buf.join('');
}
function navigate_to_first_existing(urls) {
// Navigate to the first existing URL in urls.
var url = urls.shift();
// Web browsers won't redirect file:// urls to file urls using ajax but
// its useful for local testing
if (url.startsWith("file://")) {
window.location.href = url;
return;
}
if (urls.length == 0) {
window.location.href = url;
return;
}
$.ajax({
url: url,
success: function() {
window.location.href = url;
},
error: function() {
navigate_to_first_existing(urls);
}
});
}
function get_docroot_url() {
var url = window.location.href;
var root = DOCUMENTATION_OPTIONS.URL_ROOT;
var urlarray = url.split('/');
// Trim off anything after '/'
urlarray.pop();
var depth = (root.match(/\.\.\//g) || []).length;
for (var i = 0; i < depth; i++) {
urlarray.pop();
}
return urlarray.join('/') + '/';
}
function on_version_switch() {
var selected_version = $(this).children('option:selected').attr('value');
var url = window.location.href;
var current_version = DOCUMENTATION_OPTIONS.VERSION;
var docroot = get_docroot_url()
var new_versionpath = selected_version + '/';
if (selected_version == "dev")
new_versionpath = '';
// dev versions have no version prefix
if (current_version == "dev") {
var new_url = docroot + new_versionpath + url.replace(docroot, "");
var fallback_url = docroot + new_versionpath;
} else {
var new_url = url.replace('/' + current_version + '/', '/' + new_versionpath);
var fallback_url = new_url.replace(url.replace(docroot, ""), "");
}
console.log(get_docroot_url())
console.log(url + " to url " + new_url);
console.log(url + " to fallback " + fallback_url);
if (new_url != url) {
navigate_to_first_existing([
new_url,
fallback_url,
'https://www.yoctoproject.org/docs/',
]);
}
}
function on_doctype_switch() {
var selected_doctype = $(this).children('option:selected').attr('value');
var url = window.location.href;
if (selected_doctype == 'mega') {
var docroot = get_docroot_url()
var current_version = DOCUMENTATION_OPTIONS.VERSION;
// Assume manuals before 3.2 are using old docbook mega-manual
if (ver_compare(current_version, "3.2") < 0) {
var new_url = docroot + "mega-manual/mega-manual.html";
} else {
var new_url = docroot + "singleindex.html";
}
} else {
var new_url = url.replace("singleindex.html", "index.html")
}
if (new_url != url) {
navigate_to_first_existing([
new_url,
'https://www.yoctoproject.org/docs/',
]);
}
}
// Returns the current doctype based upon the url
function doctype_segment_from_url(url) {
if (url.includes("singleindex") || url.includes("mega-manual"))
return "mega";
return "single";
}
$(document).ready(function() {
var release = DOCUMENTATION_OPTIONS.VERSION;
var current_doctype = doctype_segment_from_url(window.location.href);
var current_series = release.substr(0, 3);
var version_select = build_version_select(current_series, release);
$('.version_switcher_placeholder').html(version_select);
$('.version_switcher_placeholder select').bind('change', on_version_switch);
var doctype_select = build_doctype_select(current_doctype);
$('.doctype_switcher_placeholder').html(doctype_select);
$('.doctype_switcher_placeholder select').bind('change', on_doctype_switch);
if (ver_compare(release, "3.1") < 0) {
$('#outdated-warning').html('Version ' + release + ' of the project is now considered obsolete, please select and use a more recent version');
$('#outdated-warning').css('padding', '.5em');
} else if (release != "dev") {
$.each(all_versions, function(version, title) {
var series = version.substr(0, 3);
if (series == current_series && version != release) {
$('#outdated-warning').html('This document is for outdated version ' + release + ', you should select the latest release version in this series, ' + version + '.');
$('#outdated-warning').css('padding', '.5em');
}
});
}
});
})();

View File

@@ -0,0 +1,162 @@
/*
SPDX-License-Identifier: CC-BY-2.0-UK
*/
body {
font-family: Verdana, Sans, sans-serif;
margin: 0em auto;
color: #333;
}
h1,h2,h3,h4,h5,h6,h7 {
font-family: Arial, Sans;
color: #00557D;
clear: both;
}
h1 {
font-size: 2em;
text-align: left;
padding: 0em 0em 0em 0em;
margin: 2em 0em 0em 0em;
}
h2.subtitle {
margin: 0.10em 0em 3.0em 0em;
padding: 0em 0em 0em 0em;
font-size: 1.8em;
padding-left: 20%;
font-weight: normal;
font-style: italic;
}
h2 {
margin: 2em 0em 0.66em 0em;
padding: 0.5em 0em 0em 0em;
font-size: 1.5em;
font-weight: bold;
}
h3.subtitle {
margin: 0em 0em 1em 0em;
padding: 0em 0em 0em 0em;
font-size: 142.14%;
text-align: right;
}
h3 {
margin: 1em 0em 0.5em 0em;
padding: 1em 0em 0em 0em;
font-size: 140%;
font-weight: bold;
}
h4 {
margin: 1em 0em 0.5em 0em;
padding: 1em 0em 0em 0em;
font-size: 120%;
font-weight: bold;
}
h5 {
margin: 1em 0em 0.5em 0em;
padding: 1em 0em 0em 0em;
font-size: 110%;
font-weight: bold;
}
h6 {
margin: 1em 0em 0em 0em;
padding: 1em 0em 0em 0em;
font-size: 110%;
font-weight: bold;
}
em {
font-weight: bold;
}
.pre {
font-size: medium;
font-family: Courier, monospace;
}
.wy-nav-content a {
text-decoration: underline;
color: #444;
background: transparent;
}
.wy-nav-content a:hover {
text-decoration: underline;
background-color: #dedede;
}
.wy-nav-content a:visited {
color: #444;
}
[alt='Permalink'] { color: #eee; }
[alt='Permalink']:hover { color: black; }
@media screen {
/* content column
*
* RTD theme's default is 800px as max width for the content, but we have
* tables with tons of columns, which need the full width of the view-port.
*/
.wy-nav-content{max-width: none; }
/* inline literal: drop the borderbox, padding and red color */
code, .rst-content tt, .rst-content code {
color: inherit;
border: none;
padding: unset;
background: inherit;
font-size: 85%;
}
.rst-content tt.literal,.rst-content tt.literal,.rst-content code.literal {
color: inherit;
}
/* Admonition should be gray, not blue or green */
.rst-content .note .admonition-title,
.rst-content .tip .admonition-title,
.rst-content .warning .admonition-title,
.rst-content .caution .admonition-title,
.rst-content .important .admonition-title {
background: #f0f0f2;
color: #00557D;
}
.rst-content .note,
.rst-content .tip,
.rst-content .important,
.rst-content .warning,
.rst-content .caution {
background: #f0f0f2;
}
/* Remove the icon in front of note/tip element, and before the logo */
.icon-home:before, .rst-content .admonition-title:before {
display: none
}
/* a custom informalexample container is used in some doc */
.informalexample {
border: 1px solid;
border-color: #aaa;
margin: 1em 0em;
padding: 1em;
page-break-inside: avoid;
}
/* Remove the blue background in the top left corner, around the logo */
.wy-side-nav-search {
background: inherit;
}
}

BIN
bitbake/doc/template/Vera.ttf vendored Normal file

Binary file not shown.

BIN
bitbake/doc/template/VeraMoBd.ttf vendored Normal file

Binary file not shown.

BIN
bitbake/doc/template/VeraMono.ttf vendored Normal file

Binary file not shown.

BIN
bitbake/doc/template/draft.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

199
bitbake/lib/bb/COW.py Normal file
View File

@@ -0,0 +1,199 @@
#
# This is a copy on write dictionary and set which abuses classes to try and be nice and fast.
#
# Copyright (C) 2006 Tim Ansell
#
# SPDX-License-Identifier: GPL-2.0-only
#
# Please Note:
# Be careful when using mutable types (ie Dict and Lists) - operations involving these are SLOW.
# Assign a file to __warn__ to get warnings about slow operations.
#
import copy
ImmutableTypes = (
bool,
complex,
float,
int,
tuple,
frozenset,
str
)
MUTABLE = "__mutable__"
class COWMeta(type):
pass
class COWDictMeta(COWMeta):
__warn__ = False
__hasmutable__ = False
__marker__ = tuple()
def __str__(cls):
ignored_keys = set(["__count__", "__doc__", "__module__", "__firstlineno__", "__static_attributes__"])
keys = set(cls.__dict__.keys()) - ignored_keys
return "<COWDict Level: %i Current Keys: %i>" % (cls.__count__, len(keys))
__repr__ = __str__
def cow(cls):
class C(cls):
__count__ = cls.__count__ + 1
return C
copy = cow
__call__ = cow
def __setitem__(cls, key, value):
if value is not None and not isinstance(value, ImmutableTypes):
if not isinstance(value, COWMeta):
cls.__hasmutable__ = True
key += MUTABLE
setattr(cls, key, value)
def __getmutable__(cls, key, readonly=False):
nkey = key + MUTABLE
try:
return cls.__dict__[nkey]
except KeyError:
pass
value = getattr(cls, nkey)
if readonly:
return value
if not cls.__warn__ is False and not isinstance(value, COWMeta):
print("Warning: Doing a copy because %s is a mutable type." % key, file=cls.__warn__)
try:
value = value.copy()
except AttributeError as e:
value = copy.copy(value)
setattr(cls, nkey, value)
return value
__getmarker__ = []
def __getreadonly__(cls, key, default=__getmarker__):
"""
Get a value (even if mutable) which you promise not to change.
"""
return cls.__getitem__(key, default, True)
def __getitem__(cls, key, default=__getmarker__, readonly=False):
try:
try:
value = getattr(cls, key)
except AttributeError:
value = cls.__getmutable__(key, readonly)
# This is for values which have been deleted
if value is cls.__marker__:
raise AttributeError("key %s does not exist." % key)
return value
except AttributeError as e:
if not default is cls.__getmarker__:
return default
raise KeyError(str(e))
def __delitem__(cls, key):
cls.__setitem__(key, cls.__marker__)
def __revertitem__(cls, key):
if key not in cls.__dict__:
key += MUTABLE
delattr(cls, key)
def __contains__(cls, key):
return cls.has_key(key)
def has_key(cls, key):
value = cls.__getreadonly__(key, cls.__marker__)
if value is cls.__marker__:
return False
return True
def iter(cls, type, readonly=False):
for key in dir(cls):
if key.startswith("__"):
continue
if key.endswith(MUTABLE):
key = key[:-len(MUTABLE)]
if type == "keys":
yield key
try:
if readonly:
value = cls.__getreadonly__(key)
else:
value = cls[key]
except KeyError:
continue
if type == "values":
yield value
if type == "items":
yield (key, value)
return
def iterkeys(cls):
return cls.iter("keys")
def itervalues(cls, readonly=False):
if not cls.__warn__ is False and cls.__hasmutable__ and readonly is False:
print("Warning: If you aren't going to change any of the values call with True.", file=cls.__warn__)
return cls.iter("values", readonly)
def iteritems(cls, readonly=False):
if not cls.__warn__ is False and cls.__hasmutable__ and readonly is False:
print("Warning: If you aren't going to change any of the values call with True.", file=cls.__warn__)
return cls.iter("items", readonly)
class COWSetMeta(COWDictMeta):
def __str__(cls):
ignored_keys = set(["__count__", "__doc__", "__module__", "__firstlineno__", "__static_attributes__"])
keys = set(cls.__dict__.keys()) - ignored_keys
return "<COWSet Level: %i Current Keys: %i>" % (cls.__count__, len(keys))
__repr__ = __str__
def cow(cls):
class C(cls):
__count__ = cls.__count__ + 1
return C
def add(cls, value):
COWDictMeta.__setitem__(cls, repr(hash(value)), value)
def remove(cls, value):
COWDictMeta.__delitem__(cls, repr(hash(value)))
def __in__(cls, value):
return repr(hash(value)) in COWDictMeta
def iterkeys(cls):
raise TypeError("sets don't have keys")
def iteritems(cls):
raise TypeError("sets don't have 'items'")
# These are the actual classes you use!
class COWDictBase(metaclass=COWDictMeta):
__count__ = 0
class COWSetBase(metaclass=COWSetMeta):
__count__ = 0

220
bitbake/lib/bb/__init__.py Normal file
View File

@@ -0,0 +1,220 @@
#
# BitBake Build System Python Library
#
# Copyright (C) 2003 Holger Schurig
# Copyright (C) 2003, 2004 Chris Larson
#
# Based on Gentoo's portage.py.
#
# SPDX-License-Identifier: GPL-2.0-only
#
__version__ = "2.12.0"
import sys
if sys.version_info < (3, 9, 0):
raise RuntimeError("Sorry, python 3.9.0 or later is required for this version of bitbake")
if sys.version_info < (3, 10, 0):
# With python 3.8 and 3.9, we see errors of "libgcc_s.so.1 must be installed for pthread_cancel to work"
# https://stackoverflow.com/questions/64797838/libgcc-s-so-1-must-be-installed-for-pthread-cancel-to-work
# https://bugs.ams1.psf.io/issue42888
# so ensure libgcc_s is loaded early on
import ctypes
libgcc_s = ctypes.CDLL('libgcc_s.so.1')
class BBHandledException(Exception):
"""
The big dilemma for generic bitbake code is what information to give the user
when an exception occurs. Any exception inheriting this base exception class
has already provided information to the user via some 'fired' message type such as
an explicitly fired event using bb.fire, or a bb.error message. If bitbake
encounters an exception derived from this class, no backtrace or other information
will be given to the user, its assumed the earlier event provided the relevant information.
"""
pass
import os
import logging
from collections import namedtuple
class NullHandler(logging.Handler):
def emit(self, record):
pass
class BBLoggerMixin(object):
def __init__(self, *args, **kwargs):
# Does nothing to allow calling super() from derived classes
pass
def setup_bblogger(self, name):
if name.split(".")[0] == "BitBake":
self.debug = self._debug_helper
def _debug_helper(self, *args, **kwargs):
return self.bbdebug(1, *args, **kwargs)
def debug2(self, *args, **kwargs):
return self.bbdebug(2, *args, **kwargs)
def debug3(self, *args, **kwargs):
return self.bbdebug(3, *args, **kwargs)
def bbdebug(self, level, msg, *args, **kwargs):
loglevel = logging.DEBUG - level + 1
if not bb.event.worker_pid:
if self.name in bb.msg.loggerDefaultDomains and loglevel > (bb.msg.loggerDefaultDomains[self.name]):
return
if loglevel < bb.msg.loggerDefaultLogLevel:
return
if not isinstance(level, int) or not isinstance(msg, str):
mainlogger.warning("Invalid arguments in bbdebug: %s" % repr((level, msg,) + args))
return self.log(loglevel, msg, *args, **kwargs)
def plain(self, msg, *args, **kwargs):
return self.log(logging.INFO + 1, msg, *args, **kwargs)
def verbose(self, msg, *args, **kwargs):
return self.log(logging.INFO - 1, msg, *args, **kwargs)
def verbnote(self, msg, *args, **kwargs):
return self.log(logging.INFO + 2, msg, *args, **kwargs)
def warnonce(self, msg, *args, **kwargs):
return self.log(logging.WARNING - 1, msg, *args, **kwargs)
def erroronce(self, msg, *args, **kwargs):
return self.log(logging.ERROR - 1, msg, *args, **kwargs)
Logger = logging.getLoggerClass()
class BBLogger(Logger, BBLoggerMixin):
def __init__(self, name, *args, **kwargs):
self.setup_bblogger(name)
super().__init__(name, *args, **kwargs)
logging.raiseExceptions = False
logging.setLoggerClass(BBLogger)
class BBLoggerAdapter(logging.LoggerAdapter, BBLoggerMixin):
def __init__(self, logger, *args, **kwargs):
self.setup_bblogger(logger.name)
super().__init__(logger, *args, **kwargs)
logging.LoggerAdapter = BBLoggerAdapter
logger = logging.getLogger("BitBake")
logger.addHandler(NullHandler())
logger.setLevel(logging.DEBUG - 2)
mainlogger = logging.getLogger("BitBake.Main")
class PrefixLoggerAdapter(logging.LoggerAdapter):
def __init__(self, prefix, logger):
super().__init__(logger, {})
self.__msg_prefix = prefix
def process(self, msg, kwargs):
return "%s%s" %(self.__msg_prefix, msg), kwargs
# This has to be imported after the setLoggerClass, as the import of bb.msg
# can result in construction of the various loggers.
import bb.msg
from bb import fetch2 as fetch
sys.modules['bb.fetch'] = sys.modules['bb.fetch2']
# Messaging convenience functions
def plain(*args):
mainlogger.plain(''.join(args))
def debug(lvl, *args):
if isinstance(lvl, str):
mainlogger.warning("Passed invalid debug level '%s' to bb.debug", lvl)
args = (lvl,) + args
lvl = 1
mainlogger.bbdebug(lvl, ''.join(args))
def note(*args):
mainlogger.info(''.join(args))
#
# A higher prioity note which will show on the console but isn't a warning
#
# Something is happening the user should be aware of but they probably did
# something to make it happen
#
def verbnote(*args):
mainlogger.verbnote(''.join(args))
#
# Warnings - things the user likely needs to pay attention to and fix
#
def warn(*args):
mainlogger.warning(''.join(args))
def warnonce(*args):
mainlogger.warnonce(''.join(args))
def error(*args, **kwargs):
mainlogger.error(''.join(args), extra=kwargs)
def erroronce(*args):
mainlogger.erroronce(''.join(args))
def fatal(*args, **kwargs):
mainlogger.critical(''.join(args), extra=kwargs)
raise BBHandledException()
def deprecated(func, name=None, advice=""):
"""This is a decorator which can be used to mark functions
as deprecated. It will result in a warning being emitted
when the function is used."""
import warnings
if advice:
advice = ": %s" % advice
if name is None:
name = func.__name__
def newFunc(*args, **kwargs):
warnings.warn("Call to deprecated function %s%s." % (name,
advice),
category=DeprecationWarning,
stacklevel=2)
return func(*args, **kwargs)
newFunc.__name__ = func.__name__
newFunc.__doc__ = func.__doc__
newFunc.__dict__.update(func.__dict__)
return newFunc
# For compatibility
def deprecate_import(current, modulename, fromlist, renames = None):
"""Import objects from one module into another, wrapping them with a DeprecationWarning"""
module = __import__(modulename, fromlist = fromlist)
for position, objname in enumerate(fromlist):
obj = getattr(module, objname)
newobj = deprecated(obj, "{0}.{1}".format(current, objname),
"Please use {0}.{1} instead".format(modulename, objname))
if renames:
newname = renames[position]
else:
newname = objname
setattr(sys.modules[current], newname, newobj)
TaskData = namedtuple("TaskData", [
"pn",
"taskname",
"fn",
"deps",
"provides",
"taskhash",
"unihash",
"hashfn",
"taskhash_deps",
])

213
bitbake/lib/bb/acl.py Executable file
View File

@@ -0,0 +1,213 @@
#! /usr/bin/env python3
#
# Copyright 2023 by Garmin Ltd. or its subsidiaries
#
# SPDX-License-Identifier: MIT
import sys
import ctypes
import os
import errno
import pwd
import grp
libacl = ctypes.CDLL("libacl.so.1", use_errno=True)
ACL_TYPE_ACCESS = 0x8000
ACL_TYPE_DEFAULT = 0x4000
ACL_FIRST_ENTRY = 0
ACL_NEXT_ENTRY = 1
ACL_UNDEFINED_TAG = 0x00
ACL_USER_OBJ = 0x01
ACL_USER = 0x02
ACL_GROUP_OBJ = 0x04
ACL_GROUP = 0x08
ACL_MASK = 0x10
ACL_OTHER = 0x20
ACL_READ = 0x04
ACL_WRITE = 0x02
ACL_EXECUTE = 0x01
acl_t = ctypes.c_void_p
acl_entry_t = ctypes.c_void_p
acl_permset_t = ctypes.c_void_p
acl_perm_t = ctypes.c_uint
acl_tag_t = ctypes.c_int
libacl.acl_free.argtypes = [acl_t]
def acl_free(acl):
libacl.acl_free(acl)
libacl.acl_get_file.restype = acl_t
libacl.acl_get_file.argtypes = [ctypes.c_char_p, ctypes.c_uint]
def acl_get_file(path, typ):
acl = libacl.acl_get_file(os.fsencode(path), typ)
if acl is None:
err = ctypes.get_errno()
raise OSError(err, os.strerror(err), str(path))
return acl
libacl.acl_get_entry.argtypes = [acl_t, ctypes.c_int, ctypes.c_void_p]
def acl_get_entry(acl, entry_id):
entry = acl_entry_t()
ret = libacl.acl_get_entry(acl, entry_id, ctypes.byref(entry))
if ret < 0:
err = ctypes.get_errno()
raise OSError(err, os.strerror(err))
if ret == 0:
return None
return entry
libacl.acl_get_tag_type.argtypes = [acl_entry_t, ctypes.c_void_p]
def acl_get_tag_type(entry_d):
tag = acl_tag_t()
ret = libacl.acl_get_tag_type(entry_d, ctypes.byref(tag))
if ret < 0:
err = ctypes.get_errno()
raise OSError(err, os.strerror(err))
return tag.value
libacl.acl_get_qualifier.restype = ctypes.c_void_p
libacl.acl_get_qualifier.argtypes = [acl_entry_t]
def acl_get_qualifier(entry_d):
ret = libacl.acl_get_qualifier(entry_d)
if ret is None:
err = ctypes.get_errno()
raise OSError(err, os.strerror(err))
return ctypes.c_void_p(ret)
libacl.acl_get_permset.argtypes = [acl_entry_t, ctypes.c_void_p]
def acl_get_permset(entry_d):
permset = acl_permset_t()
ret = libacl.acl_get_permset(entry_d, ctypes.byref(permset))
if ret < 0:
err = ctypes.get_errno()
raise OSError(err, os.strerror(err))
return permset
libacl.acl_get_perm.argtypes = [acl_permset_t, acl_perm_t]
def acl_get_perm(permset_d, perm):
ret = libacl.acl_get_perm(permset_d, perm)
if ret < 0:
err = ctypes.get_errno()
raise OSError(err, os.strerror(err))
return bool(ret)
class Entry(object):
def __init__(self, tag, qualifier, mode):
self.tag = tag
self.qualifier = qualifier
self.mode = mode
def __str__(self):
typ = ""
qual = ""
if self.tag == ACL_USER:
typ = "user"
qual = pwd.getpwuid(self.qualifier).pw_name
elif self.tag == ACL_GROUP:
typ = "group"
qual = grp.getgrgid(self.qualifier).gr_name
elif self.tag == ACL_USER_OBJ:
typ = "user"
elif self.tag == ACL_GROUP_OBJ:
typ = "group"
elif self.tag == ACL_MASK:
typ = "mask"
elif self.tag == ACL_OTHER:
typ = "other"
r = "r" if self.mode & ACL_READ else "-"
w = "w" if self.mode & ACL_WRITE else "-"
x = "x" if self.mode & ACL_EXECUTE else "-"
return f"{typ}:{qual}:{r}{w}{x}"
class ACL(object):
def __init__(self, acl):
self.acl = acl
def __del__(self):
acl_free(self.acl)
def entries(self):
entry_id = ACL_FIRST_ENTRY
while True:
entry = acl_get_entry(self.acl, entry_id)
if entry is None:
break
permset = acl_get_permset(entry)
mode = 0
for m in (ACL_READ, ACL_WRITE, ACL_EXECUTE):
if acl_get_perm(permset, m):
mode |= m
qualifier = None
tag = acl_get_tag_type(entry)
if tag == ACL_USER or tag == ACL_GROUP:
qual = acl_get_qualifier(entry)
qualifier = ctypes.cast(qual, ctypes.POINTER(ctypes.c_int))[0]
yield Entry(tag, qualifier, mode)
entry_id = ACL_NEXT_ENTRY
@classmethod
def from_path(cls, path, typ):
acl = acl_get_file(path, typ)
return cls(acl)
def main():
import argparse
from pathlib import Path
parser = argparse.ArgumentParser()
parser.add_argument("path", help="File Path", type=Path)
args = parser.parse_args()
acl = ACL.from_path(args.path, ACL_TYPE_ACCESS)
for entry in acl.entries():
print(str(entry))
return 0
if __name__ == "__main__":
sys.exit(main())

View File

@@ -0,0 +1,16 @@
#
# Copyright BitBake Contributors
#
# SPDX-License-Identifier: GPL-2.0-only
#
from .client import AsyncClient, Client
from .serv import AsyncServer, AsyncServerConnection
from .connection import DEFAULT_MAX_CHUNK
from .exceptions import (
ClientError,
ServerError,
ConnectionClosedError,
InvokeError,
)

View File

@@ -0,0 +1,271 @@
#
# Copyright BitBake Contributors
#
# SPDX-License-Identifier: GPL-2.0-only
#
import abc
import asyncio
import json
import os
import socket
import sys
import re
import contextlib
from threading import Thread
from .connection import StreamConnection, WebsocketConnection, DEFAULT_MAX_CHUNK
from .exceptions import ConnectionClosedError, InvokeError
UNIX_PREFIX = "unix://"
WS_PREFIX = "ws://"
WSS_PREFIX = "wss://"
ADDR_TYPE_UNIX = 0
ADDR_TYPE_TCP = 1
ADDR_TYPE_WS = 2
WEBSOCKETS_MIN_VERSION = (9, 1)
# Need websockets 10 with python 3.10+
if sys.version_info >= (3, 10, 0):
WEBSOCKETS_MIN_VERSION = (10, 0)
def parse_address(addr):
if addr.startswith(UNIX_PREFIX):
return (ADDR_TYPE_UNIX, (addr[len(UNIX_PREFIX) :],))
elif addr.startswith(WS_PREFIX) or addr.startswith(WSS_PREFIX):
return (ADDR_TYPE_WS, (addr,))
else:
m = re.match(r"\[(?P<host>[^\]]*)\]:(?P<port>\d+)$", addr)
if m is not None:
host = m.group("host")
port = m.group("port")
else:
host, port = addr.split(":")
return (ADDR_TYPE_TCP, (host, int(port)))
class AsyncClient(object):
def __init__(
self,
proto_name,
proto_version,
logger,
timeout=30,
server_headers=False,
headers={},
):
self.socket = None
self.max_chunk = DEFAULT_MAX_CHUNK
self.proto_name = proto_name
self.proto_version = proto_version
self.logger = logger
self.timeout = timeout
self.needs_server_headers = server_headers
self.server_headers = {}
self.headers = headers
async def connect_tcp(self, address, port):
async def connect_sock():
reader, writer = await asyncio.open_connection(address, port)
return StreamConnection(reader, writer, self.timeout, self.max_chunk)
self._connect_sock = connect_sock
async def connect_unix(self, path):
async def connect_sock():
# AF_UNIX has path length issues so chdir here to workaround
cwd = os.getcwd()
try:
os.chdir(os.path.dirname(path))
# The socket must be opened synchronously so that CWD doesn't get
# changed out from underneath us so we pass as a sock into asyncio
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM, 0)
sock.connect(os.path.basename(path))
finally:
os.chdir(cwd)
reader, writer = await asyncio.open_unix_connection(sock=sock)
return StreamConnection(reader, writer, self.timeout, self.max_chunk)
self._connect_sock = connect_sock
async def connect_websocket(self, uri):
import websockets
try:
version = tuple(
int(v)
for v in websockets.__version__.split(".")[
0 : len(WEBSOCKETS_MIN_VERSION)
]
)
except ValueError:
raise ImportError(
f"Unable to parse websockets version '{websockets.__version__}'"
)
if version < WEBSOCKETS_MIN_VERSION:
min_ver_str = ".".join(str(v) for v in WEBSOCKETS_MIN_VERSION)
raise ImportError(
f"Websockets version {websockets.__version__} is less than minimum required version {min_ver_str}"
)
async def connect_sock():
try:
websocket = await websockets.connect(
uri,
ping_interval=None,
open_timeout=self.timeout,
)
except asyncio.exceptions.TimeoutError:
raise ConnectionError("Timeout while connecting to websocket")
except (OSError, websockets.InvalidHandshake, websockets.InvalidURI) as exc:
raise ConnectionError(f"Could not connect to websocket: {exc}") from exc
return WebsocketConnection(websocket, self.timeout)
self._connect_sock = connect_sock
async def setup_connection(self):
# Send headers
await self.socket.send("%s %s" % (self.proto_name, self.proto_version))
await self.socket.send(
"needs-headers: %s" % ("true" if self.needs_server_headers else "false")
)
for k, v in self.headers.items():
await self.socket.send("%s: %s" % (k, v))
# End of headers
await self.socket.send("")
self.server_headers = {}
if self.needs_server_headers:
while True:
line = await self.socket.recv()
if not line:
# End headers
break
tag, value = line.split(":", 1)
self.server_headers[tag.lower()] = value.strip()
async def get_header(self, tag, default):
await self.connect()
return self.server_headers.get(tag, default)
async def connect(self):
if self.socket is None:
self.socket = await self._connect_sock()
await self.setup_connection()
async def disconnect(self):
if self.socket is not None:
await self.socket.close()
self.socket = None
async def close(self):
await self.disconnect()
async def _send_wrapper(self, proc):
count = 0
while True:
try:
await self.connect()
return await proc()
except (
OSError,
ConnectionError,
ConnectionClosedError,
json.JSONDecodeError,
UnicodeDecodeError,
) as e:
self.logger.warning("Error talking to server: %s" % e)
if count >= 3:
if not isinstance(e, ConnectionError):
raise ConnectionError(str(e))
raise e
await self.close()
count += 1
def check_invoke_error(self, msg):
if isinstance(msg, dict) and "invoke-error" in msg:
raise InvokeError(msg["invoke-error"]["message"])
async def invoke(self, msg):
async def proc():
await self.socket.send_message(msg)
return await self.socket.recv_message()
result = await self._send_wrapper(proc)
self.check_invoke_error(result)
return result
async def ping(self):
return await self.invoke({"ping": {}})
async def __aenter__(self):
return self
async def __aexit__(self, exc_type, exc_value, traceback):
await self.close()
class Client(object):
def __init__(self):
self.client = self._get_async_client()
self.loop = asyncio.new_event_loop()
# Override any pre-existing loop.
# Without this, the PR server export selftest triggers a hang
# when running with Python 3.7. The drawback is that there is
# potential for issues if the PR and hash equiv (or some new)
# clients need to both be instantiated in the same process.
# This should be revisited if/when Python 3.9 becomes the
# minimum required version for BitBake, as it seems not
# required (but harmless) with it.
asyncio.set_event_loop(self.loop)
self._add_methods("connect_tcp", "ping")
@abc.abstractmethod
def _get_async_client(self):
pass
def _get_downcall_wrapper(self, downcall):
def wrapper(*args, **kwargs):
return self.loop.run_until_complete(downcall(*args, **kwargs))
return wrapper
def _add_methods(self, *methods):
for m in methods:
downcall = getattr(self.client, m)
setattr(self, m, self._get_downcall_wrapper(downcall))
def connect_unix(self, path):
self.loop.run_until_complete(self.client.connect_unix(path))
self.loop.run_until_complete(self.client.connect())
@property
def max_chunk(self):
return self.client.max_chunk
@max_chunk.setter
def max_chunk(self, value):
self.client.max_chunk = value
def disconnect(self):
self.loop.run_until_complete(self.client.close())
def close(self):
if self.loop:
self.loop.run_until_complete(self.client.close())
self.loop.run_until_complete(self.loop.shutdown_asyncgens())
self.loop.close()
self.loop = None
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, traceback):
self.close()
return False

View File

@@ -0,0 +1,146 @@
#
# Copyright BitBake Contributors
#
# SPDX-License-Identifier: GPL-2.0-only
#
import asyncio
import itertools
import json
from datetime import datetime
from .exceptions import ClientError, ConnectionClosedError
# The Python async server defaults to a 64K receive buffer, so we hardcode our
# maximum chunk size. It would be better if the client and server reported to
# each other what the maximum chunk sizes were, but that will slow down the
# connection setup with a round trip delay so I'd rather not do that unless it
# is necessary
DEFAULT_MAX_CHUNK = 32 * 1024
def chunkify(msg, max_chunk):
if len(msg) < max_chunk - 1:
yield "".join((msg, "\n"))
else:
yield "".join((json.dumps({"chunk-stream": None}), "\n"))
args = [iter(msg)] * (max_chunk - 1)
for m in map("".join, itertools.zip_longest(*args, fillvalue="")):
yield "".join(itertools.chain(m, "\n"))
yield "\n"
def json_serialize(obj):
if isinstance(obj, datetime):
return obj.isoformat()
raise TypeError("Type %s not serializeable" % type(obj))
class StreamConnection(object):
def __init__(self, reader, writer, timeout, max_chunk=DEFAULT_MAX_CHUNK):
self.reader = reader
self.writer = writer
self.timeout = timeout
self.max_chunk = max_chunk
@property
def address(self):
return self.writer.get_extra_info("peername")
async def send_message(self, msg):
for c in chunkify(json.dumps(msg, default=json_serialize), self.max_chunk):
self.writer.write(c.encode("utf-8"))
await self.writer.drain()
async def recv_message(self):
l = await self.recv()
m = json.loads(l)
if not m:
return m
if "chunk-stream" in m:
lines = []
while True:
l = await self.recv()
if not l:
break
lines.append(l)
m = json.loads("".join(lines))
return m
async def send(self, msg):
self.writer.write(("%s\n" % msg).encode("utf-8"))
await self.writer.drain()
async def recv(self):
if self.timeout < 0:
line = await self.reader.readline()
else:
try:
line = await asyncio.wait_for(self.reader.readline(), self.timeout)
except asyncio.TimeoutError:
raise ConnectionError("Timed out waiting for data")
if not line:
raise ConnectionClosedError("Connection closed")
line = line.decode("utf-8")
if not line.endswith("\n"):
raise ConnectionError("Bad message %r" % (line))
return line.rstrip()
async def close(self):
self.reader = None
if self.writer is not None:
self.writer.close()
self.writer = None
class WebsocketConnection(object):
def __init__(self, socket, timeout):
self.socket = socket
self.timeout = timeout
@property
def address(self):
return ":".join(str(s) for s in self.socket.remote_address)
async def send_message(self, msg):
await self.send(json.dumps(msg, default=json_serialize))
async def recv_message(self):
m = await self.recv()
return json.loads(m)
async def send(self, msg):
import websockets.exceptions
try:
await self.socket.send(msg)
except websockets.exceptions.ConnectionClosed:
raise ConnectionClosedError("Connection closed")
async def recv(self):
import websockets.exceptions
try:
if self.timeout < 0:
return await self.socket.recv()
try:
return await asyncio.wait_for(self.socket.recv(), self.timeout)
except asyncio.TimeoutError:
raise ConnectionError("Timed out waiting for data")
except websockets.exceptions.ConnectionClosed:
raise ConnectionClosedError("Connection closed")
async def close(self):
if self.socket is not None:
await self.socket.close()
self.socket = None

View File

@@ -0,0 +1,21 @@
#
# Copyright BitBake Contributors
#
# SPDX-License-Identifier: GPL-2.0-only
#
class ClientError(Exception):
pass
class InvokeError(Exception):
pass
class ServerError(Exception):
pass
class ConnectionClosedError(Exception):
pass

View File

@@ -0,0 +1,410 @@
#
# Copyright BitBake Contributors
#
# SPDX-License-Identifier: GPL-2.0-only
#
import abc
import asyncio
import json
import os
import signal
import socket
import sys
import multiprocessing
import logging
from .connection import StreamConnection, WebsocketConnection
from .exceptions import ClientError, ServerError, ConnectionClosedError, InvokeError
class ClientLoggerAdapter(logging.LoggerAdapter):
def process(self, msg, kwargs):
return f"[Client {self.extra['address']}] {msg}", kwargs
class AsyncServerConnection(object):
# If a handler returns this object (e.g. `return self.NO_RESPONSE`), no
# return message will be automatically be sent back to the client
NO_RESPONSE = object()
def __init__(self, socket, proto_name, logger):
self.socket = socket
self.proto_name = proto_name
self.handlers = {
"ping": self.handle_ping,
}
self.logger = ClientLoggerAdapter(
logger,
{
"address": socket.address,
},
)
self.client_headers = {}
async def close(self):
await self.socket.close()
async def handle_headers(self, headers):
return {}
async def process_requests(self):
try:
self.logger.info("Client %r connected" % (self.socket.address,))
# Read protocol and version
client_protocol = await self.socket.recv()
if not client_protocol:
return
(client_proto_name, client_proto_version) = client_protocol.split()
if client_proto_name != self.proto_name:
self.logger.debug("Rejecting invalid protocol %s" % (self.proto_name))
return
self.proto_version = tuple(int(v) for v in client_proto_version.split("."))
if not self.validate_proto_version():
self.logger.debug(
"Rejecting invalid protocol version %s" % (client_proto_version)
)
return
# Read headers
self.client_headers = {}
while True:
header = await self.socket.recv()
if not header:
# Empty line. End of headers
break
tag, value = header.split(":", 1)
self.client_headers[tag.lower()] = value.strip()
if self.client_headers.get("needs-headers", "false") == "true":
for k, v in (await self.handle_headers(self.client_headers)).items():
await self.socket.send("%s: %s" % (k, v))
await self.socket.send("")
# Handle messages
while True:
d = await self.socket.recv_message()
if d is None:
break
try:
response = await self.dispatch_message(d)
except InvokeError as e:
await self.socket.send_message(
{"invoke-error": {"message": str(e)}}
)
break
if response is not self.NO_RESPONSE:
await self.socket.send_message(response)
except ConnectionClosedError as e:
self.logger.info(str(e))
except (ClientError, ConnectionError) as e:
self.logger.error(str(e))
finally:
await self.close()
async def dispatch_message(self, msg):
for k in self.handlers.keys():
if k in msg:
self.logger.debug("Handling %s" % k)
return await self.handlers[k](msg[k])
raise ClientError("Unrecognized command %r" % msg)
async def handle_ping(self, request):
return {"alive": True}
class StreamServer(object):
def __init__(self, handler, logger):
self.handler = handler
self.logger = logger
self.closed = False
async def handle_stream_client(self, reader, writer):
# writer.transport.set_write_buffer_limits(0)
socket = StreamConnection(reader, writer, -1)
if self.closed:
await socket.close()
return
await self.handler(socket)
async def stop(self):
self.closed = True
class TCPStreamServer(StreamServer):
def __init__(self, host, port, handler, logger, *, reuseport=False):
super().__init__(handler, logger)
self.host = host
self.port = port
self.reuseport = reuseport
def start(self, loop):
self.server = loop.run_until_complete(
asyncio.start_server(
self.handle_stream_client,
self.host,
self.port,
reuse_port=self.reuseport,
)
)
for s in self.server.sockets:
self.logger.debug("Listening on %r" % (s.getsockname(),))
# Newer python does this automatically. Do it manually here for
# maximum compatibility
s.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1)
s.setsockopt(socket.SOL_TCP, socket.TCP_QUICKACK, 1)
# Enable keep alives. This prevents broken client connections
# from persisting on the server for long periods of time.
s.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 30)
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 15)
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 4)
name = self.server.sockets[0].getsockname()
if self.server.sockets[0].family == socket.AF_INET6:
self.address = "[%s]:%d" % (name[0], name[1])
else:
self.address = "%s:%d" % (name[0], name[1])
return [self.server.wait_closed()]
async def stop(self):
await super().stop()
self.server.close()
def cleanup(self):
pass
class UnixStreamServer(StreamServer):
def __init__(self, path, handler, logger):
super().__init__(handler, logger)
self.path = path
def start(self, loop):
cwd = os.getcwd()
try:
# Work around path length limits in AF_UNIX
os.chdir(os.path.dirname(self.path))
self.server = loop.run_until_complete(
asyncio.start_unix_server(
self.handle_stream_client, os.path.basename(self.path)
)
)
finally:
os.chdir(cwd)
self.logger.debug("Listening on %r" % self.path)
self.address = "unix://%s" % os.path.abspath(self.path)
return [self.server.wait_closed()]
async def stop(self):
await super().stop()
self.server.close()
def cleanup(self):
os.unlink(self.path)
class WebsocketsServer(object):
def __init__(self, host, port, handler, logger, *, reuseport=False):
self.host = host
self.port = port
self.handler = handler
self.logger = logger
self.reuseport = reuseport
def start(self, loop):
import websockets.server
self.server = loop.run_until_complete(
websockets.server.serve(
self.client_handler,
self.host,
self.port,
ping_interval=None,
reuse_port=self.reuseport,
)
)
for s in self.server.sockets:
self.logger.debug("Listening on %r" % (s.getsockname(),))
# Enable keep alives. This prevents broken client connections
# from persisting on the server for long periods of time.
s.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 30)
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 15)
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 4)
name = self.server.sockets[0].getsockname()
if self.server.sockets[0].family == socket.AF_INET6:
self.address = "ws://[%s]:%d" % (name[0], name[1])
else:
self.address = "ws://%s:%d" % (name[0], name[1])
return [self.server.wait_closed()]
async def stop(self):
self.server.close()
def cleanup(self):
pass
async def client_handler(self, websocket):
socket = WebsocketConnection(websocket, -1)
await self.handler(socket)
class AsyncServer(object):
def __init__(self, logger):
self.logger = logger
self.loop = None
self.run_tasks = []
def start_tcp_server(self, host, port, *, reuseport=False):
self.server = TCPStreamServer(
host,
port,
self._client_handler,
self.logger,
reuseport=reuseport,
)
def start_unix_server(self, path):
self.server = UnixStreamServer(path, self._client_handler, self.logger)
def start_websocket_server(self, host, port, reuseport=False):
self.server = WebsocketsServer(
host,
port,
self._client_handler,
self.logger,
reuseport=reuseport,
)
async def _client_handler(self, socket):
address = socket.address
try:
client = self.accept_client(socket)
await client.process_requests()
except Exception as e:
import traceback
self.logger.error(
"Error from client %s: %s" % (address, str(e)), exc_info=True
)
traceback.print_exc()
finally:
self.logger.debug("Client %s disconnected", address)
await socket.close()
@abc.abstractmethod
def accept_client(self, socket):
pass
async def stop(self):
self.logger.debug("Stopping server")
await self.server.stop()
def start(self):
tasks = self.server.start(self.loop)
self.address = self.server.address
return tasks
def signal_handler(self):
self.logger.debug("Got exit signal")
self.loop.create_task(self.stop())
def _serve_forever(self, tasks):
try:
self.loop.add_signal_handler(signal.SIGTERM, self.signal_handler)
self.loop.add_signal_handler(signal.SIGINT, self.signal_handler)
self.loop.add_signal_handler(signal.SIGQUIT, self.signal_handler)
signal.pthread_sigmask(signal.SIG_UNBLOCK, [signal.SIGTERM])
self.loop.run_until_complete(asyncio.gather(*tasks))
self.logger.debug("Server shutting down")
finally:
self.server.cleanup()
def serve_forever(self):
"""
Serve requests in the current process
"""
self._create_loop()
tasks = self.start()
self._serve_forever(tasks)
self.loop.close()
def _create_loop(self):
# Create loop and override any loop that may have existed in
# a parent process. It is possible that the usecases of
# serve_forever might be constrained enough to allow using
# get_event_loop here, but better safe than sorry for now.
self.loop = asyncio.new_event_loop()
asyncio.set_event_loop(self.loop)
def serve_as_process(self, *, prefunc=None, args=(), log_level=None):
"""
Serve requests in a child process
"""
def run(queue):
# Create loop and override any loop that may have existed
# in a parent process. Without doing this and instead
# using get_event_loop, at the very minimum the hashserv
# unit tests will hang when running the second test.
# This happens since get_event_loop in the spawned server
# process for the second testcase ends up with the loop
# from the hashserv client created in the unit test process
# when running the first testcase. The problem is somewhat
# more general, though, as any potential use of asyncio in
# Cooker could create a loop that needs to replaced in this
# new process.
self._create_loop()
try:
self.address = None
tasks = self.start()
finally:
# Always put the server address to wake up the parent task
queue.put(self.address)
queue.close()
if prefunc is not None:
prefunc(self, *args)
if log_level is not None:
self.logger.setLevel(log_level)
self._serve_forever(tasks)
self.loop.run_until_complete(self.loop.shutdown_asyncgens())
self.loop.close()
queue = multiprocessing.Queue()
# Temporarily block SIGTERM. The server process will inherit this
# block which will ensure it doesn't receive the SIGTERM until the
# handler is ready for it
mask = signal.pthread_sigmask(signal.SIG_BLOCK, [signal.SIGTERM])
try:
self.process = multiprocessing.Process(target=run, args=(queue,))
self.process.start()
self.address = queue.get()
queue.close()
queue.join_thread()
return self.process
finally:
signal.pthread_sigmask(signal.SIG_SETMASK, mask)

1036
bitbake/lib/bb/build.py Normal file

File diff suppressed because it is too large Load Diff

988
bitbake/lib/bb/cache.py Normal file
View File

@@ -0,0 +1,988 @@
#
# BitBake Cache implementation
#
# Caching of bitbake variables before task execution
# Copyright (C) 2006 Richard Purdie
# Copyright (C) 2012 Intel Corporation
# but small sections based on code from bin/bitbake:
# Copyright (C) 2003, 2004 Chris Larson
# Copyright (C) 2003, 2004 Phil Blundell
# Copyright (C) 2003 - 2005 Michael 'Mickey' Lauer
# Copyright (C) 2005 Holger Hans Peter Freyther
# Copyright (C) 2005 ROAD GmbH
#
# SPDX-License-Identifier: GPL-2.0-only
#
import os
import logging
import pickle
from collections import defaultdict
from collections.abc import Mapping
import bb.utils
from bb import PrefixLoggerAdapter
import re
import shutil
logger = logging.getLogger("BitBake.Cache")
__cache_version__ = "156"
def getCacheFile(path, filename, mc, data_hash):
mcspec = ''
if mc:
mcspec = ".%s" % mc
return os.path.join(path, filename + mcspec + "." + data_hash)
# RecipeInfoCommon defines common data retrieving methods
# from meta data for caches. CoreRecipeInfo as well as other
# Extra RecipeInfo needs to inherit this class
class RecipeInfoCommon(object):
@classmethod
def listvar(cls, var, metadata):
return cls.getvar(var, metadata).split()
@classmethod
def intvar(cls, var, metadata):
return int(cls.getvar(var, metadata) or 0)
@classmethod
def depvar(cls, var, metadata):
return bb.utils.explode_deps(cls.getvar(var, metadata))
@classmethod
def pkgvar(cls, var, packages, metadata):
return dict((pkg, cls.depvar("%s:%s" % (var, pkg), metadata))
for pkg in packages)
@classmethod
def taskvar(cls, var, tasks, metadata):
return dict((task, cls.getvar("%s:task-%s" % (var, task), metadata))
for task in tasks)
@classmethod
def flaglist(cls, flag, varlist, metadata, squash=False):
out_dict = dict((var, metadata.getVarFlag(var, flag))
for var in varlist)
if squash:
return dict((k,v) for (k,v) in out_dict.items() if v)
else:
return out_dict
@classmethod
def getvar(cls, var, metadata, expand = True):
return metadata.getVar(var, expand) or ''
class CoreRecipeInfo(RecipeInfoCommon):
__slots__ = ()
cachefile = "bb_cache.dat"
def __init__(self, filename, metadata):
self.file_depends = metadata.getVar('__depends', False)
self.timestamp = bb.parse.cached_mtime(filename)
self.variants = self.listvar('__VARIANTS', metadata) + ['']
self.appends = self.listvar('__BBAPPEND', metadata)
self.nocache = self.getvar('BB_DONT_CACHE', metadata)
self.provides = self.depvar('PROVIDES', metadata)
self.rprovides = self.depvar('RPROVIDES', metadata)
self.pn = self.getvar('PN', metadata) or bb.parse.vars_from_file(filename,metadata)[0]
self.packages = self.listvar('PACKAGES', metadata)
if not self.packages:
self.packages.append(self.pn)
self.packages_dynamic = self.listvar('PACKAGES_DYNAMIC', metadata)
self.rprovides_pkg = self.pkgvar('RPROVIDES', self.packages, metadata)
self.skipreason = self.getvar('__SKIPPED', metadata)
if self.skipreason:
self.skipped = True
return
self.tasks = metadata.getVar('__BBTASKS', False)
self.basetaskhashes = metadata.getVar('__siggen_basehashes', False) or {}
self.hashfilename = self.getvar('BB_HASHFILENAME', metadata)
self.task_deps = metadata.getVar('_task_deps', False) or {'tasks': [], 'parents': {}}
self.skipped = False
self.pe = self.getvar('PE', metadata)
self.pv = self.getvar('PV', metadata)
self.pr = self.getvar('PR', metadata)
self.defaultpref = self.intvar('DEFAULT_PREFERENCE', metadata)
self.not_world = self.getvar('EXCLUDE_FROM_WORLD', metadata)
self.stamp = self.getvar('STAMP', metadata)
self.stampclean = self.getvar('STAMPCLEAN', metadata)
self.stamp_extrainfo = self.flaglist('stamp-extra-info', self.tasks, metadata)
self.file_checksums = self.flaglist('file-checksums', self.tasks, metadata, True)
self.depends = self.depvar('DEPENDS', metadata)
self.rdepends = self.depvar('RDEPENDS', metadata)
self.rrecommends = self.depvar('RRECOMMENDS', metadata)
self.rdepends_pkg = self.pkgvar('RDEPENDS', self.packages, metadata)
self.rrecommends_pkg = self.pkgvar('RRECOMMENDS', self.packages, metadata)
self.inherits = self.getvar('__inherit_cache', metadata, expand=False)
self.fakerootenv = self.getvar('FAKEROOTENV', metadata)
self.fakerootdirs = self.getvar('FAKEROOTDIRS', metadata)
self.fakerootlogs = self.getvar('FAKEROOTLOGS', metadata)
self.fakerootnoenv = self.getvar('FAKEROOTNOENV', metadata)
self.extradepsfunc = self.getvar('calculate_extra_depends', metadata)
@classmethod
def init_cacheData(cls, cachedata):
# CacheData in Core RecipeInfo Class
cachedata.task_deps = {}
cachedata.pkg_fn = {}
cachedata.pkg_pn = defaultdict(list)
cachedata.pkg_pepvpr = {}
cachedata.pkg_dp = {}
cachedata.stamp = {}
cachedata.stampclean = {}
cachedata.stamp_extrainfo = {}
cachedata.file_checksums = {}
cachedata.fn_provides = {}
cachedata.pn_provides = defaultdict(list)
cachedata.all_depends = []
cachedata.deps = defaultdict(list)
cachedata.packages = defaultdict(list)
cachedata.providers = defaultdict(list)
cachedata.rproviders = defaultdict(list)
cachedata.packages_dynamic = defaultdict(list)
cachedata.rundeps = defaultdict(lambda: defaultdict(list))
cachedata.runrecs = defaultdict(lambda: defaultdict(list))
cachedata.possible_world = []
cachedata.universe_target = []
cachedata.hashfn = {}
cachedata.basetaskhash = {}
cachedata.inherits = {}
cachedata.fakerootenv = {}
cachedata.fakerootnoenv = {}
cachedata.fakerootdirs = {}
cachedata.fakerootlogs = {}
cachedata.extradepsfunc = {}
def add_cacheData(self, cachedata, fn):
cachedata.task_deps[fn] = self.task_deps
cachedata.pkg_fn[fn] = self.pn
cachedata.pkg_pn[self.pn].append(fn)
cachedata.pkg_pepvpr[fn] = (self.pe, self.pv, self.pr)
cachedata.pkg_dp[fn] = self.defaultpref
cachedata.stamp[fn] = self.stamp
cachedata.stampclean[fn] = self.stampclean
cachedata.stamp_extrainfo[fn] = self.stamp_extrainfo
cachedata.file_checksums[fn] = self.file_checksums
provides = [self.pn]
for provide in self.provides:
if provide not in provides:
provides.append(provide)
cachedata.fn_provides[fn] = provides
for provide in provides:
cachedata.providers[provide].append(fn)
if provide not in cachedata.pn_provides[self.pn]:
cachedata.pn_provides[self.pn].append(provide)
for dep in self.depends:
if dep not in cachedata.deps[fn]:
cachedata.deps[fn].append(dep)
if dep not in cachedata.all_depends:
cachedata.all_depends.append(dep)
rprovides = self.rprovides
for package in self.packages:
cachedata.packages[package].append(fn)
rprovides += self.rprovides_pkg[package]
for rprovide in rprovides:
if fn not in cachedata.rproviders[rprovide]:
cachedata.rproviders[rprovide].append(fn)
for package in self.packages_dynamic:
cachedata.packages_dynamic[package].append(fn)
# Build hash of runtime depends and recommends
for package in self.packages:
cachedata.rundeps[fn][package] = list(self.rdepends) + self.rdepends_pkg[package]
cachedata.runrecs[fn][package] = list(self.rrecommends) + self.rrecommends_pkg[package]
# Collect files we may need for possible world-dep
# calculations
if not bb.utils.to_boolean(self.not_world):
cachedata.possible_world.append(fn)
#else:
# logger.debug2("EXCLUDE FROM WORLD: %s", fn)
# create a collection of all targets for sanity checking
# tasks, such as upstream versions, license, and tools for
# task and image creation.
cachedata.universe_target.append(self.pn)
cachedata.hashfn[fn] = self.hashfilename
for task, taskhash in self.basetaskhashes.items():
identifier = '%s:%s' % (fn, task)
cachedata.basetaskhash[identifier] = taskhash
cachedata.inherits[fn] = self.inherits
cachedata.fakerootenv[fn] = self.fakerootenv
cachedata.fakerootnoenv[fn] = self.fakerootnoenv
cachedata.fakerootdirs[fn] = self.fakerootdirs
cachedata.fakerootlogs[fn] = self.fakerootlogs
cachedata.extradepsfunc[fn] = self.extradepsfunc
class SiggenRecipeInfo(RecipeInfoCommon):
__slots__ = ()
classname = "SiggenRecipeInfo"
cachefile = "bb_cache_" + classname +".dat"
# we don't want to show this information in graph files so don't set cachefields
#cachefields = []
def __init__(self, filename, metadata):
self.siggen_gendeps = metadata.getVar("__siggen_gendeps", False)
self.siggen_varvals = metadata.getVar("__siggen_varvals", False)
self.siggen_taskdeps = metadata.getVar("__siggen_taskdeps", False)
@classmethod
def init_cacheData(cls, cachedata):
cachedata.siggen_taskdeps = {}
cachedata.siggen_gendeps = {}
cachedata.siggen_varvals = {}
def add_cacheData(self, cachedata, fn):
cachedata.siggen_gendeps[fn] = self.siggen_gendeps
cachedata.siggen_varvals[fn] = self.siggen_varvals
cachedata.siggen_taskdeps[fn] = self.siggen_taskdeps
# The siggen variable data is large and impacts:
# - bitbake's overall memory usage
# - the amount of data sent over IPC between parsing processes and the server
# - the size of the cache files on disk
# - the size of "sigdata" hash information files on disk
# The data consists of strings (some large) or frozenset lists of variables
# As such, we a) deplicate the data here and b) pass references to the object at second
# access (e.g. over IPC or saving into pickle).
store = {}
save_map = {}
save_count = 1
restore_map = {}
restore_count = {}
@classmethod
def reset(cls):
# Needs to be called before starting new streamed data in a given process
# (e.g. writing out the cache again)
cls.save_map = {}
cls.save_count = 1
cls.restore_map = {}
@classmethod
def _save(cls, deps):
ret = []
if not deps:
return deps
for dep in deps:
fs = deps[dep]
if fs is None:
ret.append((dep, None, None))
elif fs in cls.save_map:
ret.append((dep, None, cls.save_map[fs]))
else:
cls.save_map[fs] = cls.save_count
ret.append((dep, fs, cls.save_count))
cls.save_count = cls.save_count + 1
return ret
@classmethod
def _restore(cls, deps, pid):
ret = {}
if not deps:
return deps
if pid not in cls.restore_map:
cls.restore_map[pid] = {}
map = cls.restore_map[pid]
for dep, fs, mapnum in deps:
if fs is None and mapnum is None:
ret[dep] = None
elif fs is None:
ret[dep] = map[mapnum]
else:
try:
fs = cls.store[fs]
except KeyError:
cls.store[fs] = fs
map[mapnum] = fs
ret[dep] = fs
return ret
def __getstate__(self):
ret = {}
for key in ["siggen_gendeps", "siggen_taskdeps", "siggen_varvals"]:
ret[key] = self._save(self.__dict__[key])
ret['pid'] = os.getpid()
return ret
def __setstate__(self, state):
pid = state['pid']
for key in ["siggen_gendeps", "siggen_taskdeps", "siggen_varvals"]:
setattr(self, key, self._restore(state[key], pid))
def virtualfn2realfn(virtualfn):
"""
Convert a virtual file name to a real one + the associated subclass keyword
"""
mc = ""
if virtualfn.startswith('mc:') and virtualfn.count(':') >= 2:
(_, mc, virtualfn) = virtualfn.split(':', 2)
fn = virtualfn
cls = ""
if virtualfn.startswith('virtual:'):
elems = virtualfn.split(':')
cls = ":".join(elems[1:-1])
fn = elems[-1]
return (fn, cls, mc)
def realfn2virtual(realfn, cls, mc):
"""
Convert a real filename + the associated subclass keyword to a virtual filename
"""
if cls:
realfn = "virtual:" + cls + ":" + realfn
if mc:
realfn = "mc:" + mc + ":" + realfn
return realfn
def variant2virtual(realfn, variant):
"""
Convert a real filename + a variant to a virtual filename
"""
if variant == "":
return realfn
if variant.startswith("mc:") and variant.count(':') >= 2:
elems = variant.split(":")
if elems[2]:
return "mc:" + elems[1] + ":virtual:" + ":".join(elems[2:]) + ":" + realfn
return "mc:" + elems[1] + ":" + realfn
return "virtual:" + variant + ":" + realfn
#
# Cooker calls cacheValid on its recipe list, then either calls loadCached
# from it's main thread or parse from separate processes to generate an up to
# date cache
#
class Cache(object):
"""
BitBake Cache implementation
"""
def __init__(self, databuilder, mc, data_hash, caches_array):
self.databuilder = databuilder
self.data = databuilder.data
# Pass caches_array information into Cache Constructor
# It will be used later for deciding whether we
# need extra cache file dump/load support
self.mc = mc
self.logger = PrefixLoggerAdapter("Cache: %s: " % (mc if mc else ''), logger)
self.caches_array = caches_array
self.cachedir = self.data.getVar("CACHE")
self.clean = set()
self.checked = set()
self.depends_cache = {}
self.data_fn = None
self.cacheclean = True
self.data_hash = data_hash
self.filelist_regex = re.compile(r'(?:(?<=:True)|(?<=:False))\s+')
if self.cachedir in [None, '']:
bb.fatal("Please ensure CACHE is set to the cache directory for BitBake to use")
def getCacheFile(self, cachefile):
return getCacheFile(self.cachedir, cachefile, self.mc, self.data_hash)
def prepare_cache(self, progress):
loaded = 0
self.cachefile = self.getCacheFile("bb_cache.dat")
self.logger.debug("Cache dir: %s", self.cachedir)
bb.utils.mkdirhier(self.cachedir)
cache_ok = True
if self.caches_array:
for cache_class in self.caches_array:
cachefile = self.getCacheFile(cache_class.cachefile)
cache_exists = os.path.exists(cachefile)
self.logger.debug2("Checking if %s exists: %r", cachefile, cache_exists)
cache_ok = cache_ok and cache_exists
cache_class.init_cacheData(self)
if cache_ok:
loaded = self.load_cachefile(progress)
elif os.path.isfile(self.cachefile):
self.logger.info("Out of date cache found, rebuilding...")
else:
self.logger.debug("Cache file %s not found, building..." % self.cachefile)
# We don't use the symlink, its just for debugging convinience
if self.mc:
symlink = os.path.join(self.cachedir, "bb_cache.dat.%s" % self.mc)
else:
symlink = os.path.join(self.cachedir, "bb_cache.dat")
if os.path.exists(symlink) or os.path.islink(symlink):
bb.utils.remove(symlink)
try:
os.symlink(os.path.basename(self.cachefile), symlink)
except OSError:
pass
return loaded
def cachesize(self):
cachesize = 0
for cache_class in self.caches_array:
cachefile = self.getCacheFile(cache_class.cachefile)
try:
with open(cachefile, "rb") as cachefile:
cachesize += os.fstat(cachefile.fileno()).st_size
except FileNotFoundError:
pass
return cachesize
def load_cachefile(self, progress):
previous_progress = 0
for cache_class in self.caches_array:
cachefile = self.getCacheFile(cache_class.cachefile)
self.logger.debug('Loading cache file: %s' % cachefile)
with open(cachefile, "rb") as cachefile:
pickled = pickle.Unpickler(cachefile)
# Check cache version information
try:
cache_ver = pickled.load()
bitbake_ver = pickled.load()
except Exception:
self.logger.info('Invalid cache, rebuilding...')
return 0
if cache_ver != __cache_version__:
self.logger.info('Cache version mismatch, rebuilding...')
return 0
elif bitbake_ver != bb.__version__:
self.logger.info('Bitbake version mismatch, rebuilding...')
return 0
# Load the rest of the cache file
current_progress = 0
while cachefile:
try:
key = pickled.load()
value = pickled.load()
except Exception:
break
if not isinstance(key, str):
bb.warn("%s from extras cache is not a string?" % key)
break
if not isinstance(value, RecipeInfoCommon):
bb.warn("%s from extras cache is not a RecipeInfoCommon class?" % value)
break
if key in self.depends_cache:
self.depends_cache[key].append(value)
else:
self.depends_cache[key] = [value]
# only fire events on even percentage boundaries
current_progress = cachefile.tell() + previous_progress
progress(cachefile.tell() + previous_progress)
previous_progress += current_progress
return len(self.depends_cache)
def parse(self, filename, appends, layername):
"""Parse the specified filename, returning the recipe information"""
self.logger.debug("Parsing %s", filename)
infos = []
datastores = self.databuilder.parseRecipeVariants(filename, appends, mc=self.mc, layername=layername)
depends = []
variants = []
# Process the "real" fn last so we can store variants list
for variant, data in sorted(datastores.items(),
key=lambda i: i[0],
reverse=True):
virtualfn = variant2virtual(filename, variant)
variants.append(variant)
depends = depends + (data.getVar("__depends", False) or [])
if depends and not variant:
data.setVar("__depends", depends)
if virtualfn == filename:
data.setVar("__VARIANTS", " ".join(variants))
info_array = []
for cache_class in self.caches_array:
info = cache_class(filename, data)
info_array.append(info)
infos.append((virtualfn, info_array))
return infos
def loadCached(self, filename, appends):
"""Obtain the recipe information for the specified filename,
using cached values.
"""
infos = []
# info_array item is a list of [CoreRecipeInfo, XXXRecipeInfo]
info_array = self.depends_cache[filename]
for variant in info_array[0].variants:
virtualfn = variant2virtual(filename, variant)
infos.append((virtualfn, self.depends_cache[virtualfn]))
return infos
def cacheValid(self, fn, appends):
"""
Is the cache valid for fn?
Fast version, no timestamps checked.
"""
if fn not in self.checked:
self.cacheValidUpdate(fn, appends)
if fn in self.clean:
return True
return False
def cacheValidUpdate(self, fn, appends):
"""
Is the cache valid for fn?
Make thorough (slower) checks including timestamps.
"""
self.checked.add(fn)
# File isn't in depends_cache
if not fn in self.depends_cache:
self.logger.debug2("%s is not cached", fn)
return False
mtime = bb.parse.cached_mtime_noerror(fn)
# Check file still exists
if mtime == 0:
self.logger.debug2("%s no longer exists", fn)
self.remove(fn)
return False
info_array = self.depends_cache[fn]
# Check the file's timestamp
if mtime != info_array[0].timestamp:
self.logger.debug2("%s changed", fn)
self.remove(fn)
return False
# Check dependencies are still valid
depends = info_array[0].file_depends
if depends:
for f, old_mtime in depends:
fmtime = bb.parse.cached_mtime_noerror(f)
# Check if file still exists
if old_mtime != 0 and fmtime == 0:
self.logger.debug2("%s's dependency %s was removed",
fn, f)
self.remove(fn)
return False
if (fmtime != old_mtime):
self.logger.debug2("%s's dependency %s changed",
fn, f)
self.remove(fn)
return False
if hasattr(info_array[0], 'file_checksums'):
for _, fl in info_array[0].file_checksums.items():
fl = fl.strip()
if not fl:
continue
# Have to be careful about spaces and colons in filenames
flist = self.filelist_regex.split(fl)
for f in flist:
if not f:
continue
f, exist = f.rsplit(":", 1)
if (exist == "True" and not os.path.exists(f)) or (exist == "False" and os.path.exists(f)):
self.logger.debug2("%s's file checksum list file %s changed",
fn, f)
self.remove(fn)
return False
if tuple(appends) != tuple(info_array[0].appends):
self.logger.debug2("appends for %s changed", fn)
self.logger.debug2("%s to %s" % (str(appends), str(info_array[0].appends)))
self.remove(fn)
return False
invalid = False
for cls in info_array[0].variants:
virtualfn = variant2virtual(fn, cls)
self.clean.add(virtualfn)
if virtualfn not in self.depends_cache:
self.logger.debug2("%s is not cached", virtualfn)
invalid = True
elif len(self.depends_cache[virtualfn]) != len(self.caches_array):
self.logger.debug2("Extra caches missing for %s?" % virtualfn)
invalid = True
# If any one of the variants is not present, mark as invalid for all
if invalid:
for cls in info_array[0].variants:
virtualfn = variant2virtual(fn, cls)
if virtualfn in self.clean:
self.logger.debug2("Removing %s from cache", virtualfn)
self.clean.remove(virtualfn)
if fn in self.clean:
self.logger.debug2("Marking %s as not clean", fn)
self.clean.remove(fn)
return False
self.clean.add(fn)
return True
def remove(self, fn):
"""
Remove a fn from the cache
Called from the parser in error cases
"""
if fn in self.depends_cache:
self.logger.debug("Removing %s from cache", fn)
del self.depends_cache[fn]
if fn in self.clean:
self.logger.debug("Marking %s as unclean", fn)
self.clean.remove(fn)
def sync(self):
"""
Save the cache
Called from the parser when complete (or exiting)
"""
if self.cacheclean:
self.logger.debug2("Cache is clean, not saving.")
return
for cache_class in self.caches_array:
cache_class_name = cache_class.__name__
cachefile = self.getCacheFile(cache_class.cachefile)
self.logger.debug2("Writing %s", cachefile)
with open(cachefile, "wb") as f:
p = pickle.Pickler(f, pickle.HIGHEST_PROTOCOL)
p.dump(__cache_version__)
p.dump(bb.__version__)
for key, info_array in self.depends_cache.items():
for info in info_array:
if isinstance(info, RecipeInfoCommon) and info.__class__.__name__ == cache_class_name:
p.dump(key)
p.dump(info)
del self.depends_cache
SiggenRecipeInfo.reset()
@staticmethod
def mtime(cachefile):
return bb.parse.cached_mtime_noerror(cachefile)
def add_info(self, filename, info_array, cacheData, parsed=None, watcher=None):
if self.mc is not None:
(fn, cls, mc) = virtualfn2realfn(filename)
if mc:
self.logger.error("Unexpected multiconfig %s", filename)
return
vfn = realfn2virtual(fn, cls, self.mc)
else:
vfn = filename
if isinstance(info_array[0], CoreRecipeInfo) and (not info_array[0].skipped):
cacheData.add_from_recipeinfo(vfn, info_array)
if watcher:
watcher(info_array[0].file_depends)
if (info_array[0].skipped or 'SRCREVINACTION' not in info_array[0].pv) and not info_array[0].nocache:
if parsed:
self.cacheclean = False
self.depends_cache[filename] = info_array
class MulticonfigCache(Mapping):
def __init__(self, databuilder, data_hash, caches_array):
def progress(p):
nonlocal current_progress
nonlocal previous_progress
nonlocal previous_percent
nonlocal cachesize
current_progress = previous_progress + p
if current_progress > cachesize:
# we might have calculated incorrect total size because a file
# might've been written out just after we checked its size
cachesize = current_progress
current_percent = 100 * current_progress / cachesize
if current_percent > previous_percent:
previous_percent = current_percent
bb.event.fire(bb.event.CacheLoadProgress(current_progress, cachesize),
databuilder.data)
cachesize = 0
current_progress = 0
previous_progress = 0
previous_percent = 0
self.__caches = {}
for mc, mcdata in databuilder.mcdata.items():
self.__caches[mc] = Cache(databuilder, mc, data_hash, caches_array)
cachesize += self.__caches[mc].cachesize()
bb.event.fire(bb.event.CacheLoadStarted(cachesize), databuilder.data)
loaded = 0
for c in self.__caches.values():
SiggenRecipeInfo.reset()
loaded += c.prepare_cache(progress)
previous_progress = current_progress
# Note: depends cache number is corresponding to the parsing file numbers.
# The same file has several caches, still regarded as one item in the cache
bb.event.fire(bb.event.CacheLoadCompleted(cachesize, loaded), databuilder.data)
def __len__(self):
return len(self.__caches)
def __getitem__(self, key):
return self.__caches[key]
def __contains__(self, key):
return key in self.__caches
def __iter__(self):
for k in self.__caches:
yield k
class CacheData(object):
"""
The data structures we compile from the cached data
"""
def __init__(self, caches_array):
self.caches_array = caches_array
for cache_class in self.caches_array:
if not issubclass(cache_class, RecipeInfoCommon):
bb.error("Extra cache data class %s should subclass RecipeInfoCommon class" % cache_class)
cache_class.init_cacheData(self)
# Direct cache variables
self.task_queues = {}
self.preferred = {}
self.tasks = {}
# Indirect Cache variables (set elsewhere)
self.ignored_dependencies = []
self.world_target = set()
self.bbfile_priority = {}
def add_from_recipeinfo(self, fn, info_array):
for info in info_array:
info.add_cacheData(self, fn)
class MultiProcessCache(object):
"""
BitBake multi-process cache implementation
Used by the codeparser & file checksum caches
"""
def __init__(self):
self.cachefile = None
self.cachedata = self.create_cachedata()
self.cachedata_extras = self.create_cachedata()
def init_cache(self, cachedir, cache_file_name=None):
if not cachedir:
return
bb.utils.mkdirhier(cachedir)
self.cachefile = os.path.join(cachedir,
cache_file_name or self.__class__.cache_file_name)
logger.debug("Using cache in '%s'", self.cachefile)
glf = bb.utils.lockfile(self.cachefile + ".lock")
try:
with open(self.cachefile, "rb") as f:
p = pickle.Unpickler(f)
data, version = p.load()
except:
bb.utils.unlockfile(glf)
return
bb.utils.unlockfile(glf)
if version != self.__class__.CACHE_VERSION:
return
self.cachedata = data
def create_cachedata(self):
data = [{}]
return data
def clear_cache(self):
if not self.cachefile:
bb.fatal("Can't clear invalid cachefile")
self.cachedata = self.create_cachedata()
self.cachedata_extras = self.create_cachedata()
with bb.utils.fileslocked([self.cachefile + ".lock"]):
bb.utils.remove(self.cachefile)
bb.utils.remove(self.cachefile + "-*")
def save_extras(self):
if not self.cachefile:
return
have_data = any(self.cachedata_extras)
if not have_data:
return
glf = bb.utils.lockfile(self.cachefile + ".lock", shared=True)
i = os.getpid()
lf = None
while not lf:
lf = bb.utils.lockfile(self.cachefile + ".lock." + str(i), retry=False)
if not lf or os.path.exists(self.cachefile + "-" + str(i)):
if lf:
bb.utils.unlockfile(lf)
lf = None
i = i + 1
continue
with open(self.cachefile + "-" + str(i), "wb") as f:
p = pickle.Pickler(f, -1)
p.dump([self.cachedata_extras, self.__class__.CACHE_VERSION])
bb.utils.unlockfile(lf)
bb.utils.unlockfile(glf)
def merge_data(self, source, dest):
for j in range(0,len(dest)):
for h in source[j]:
if h not in dest[j]:
dest[j][h] = source[j][h]
def save_merge(self):
if not self.cachefile:
return
glf = bb.utils.lockfile(self.cachefile + ".lock")
data = self.cachedata
have_data = False
for f in [y for y in os.listdir(os.path.dirname(self.cachefile)) if y.startswith(os.path.basename(self.cachefile) + '-')]:
f = os.path.join(os.path.dirname(self.cachefile), f)
try:
with open(f, "rb") as fd:
p = pickle.Unpickler(fd)
extradata, version = p.load()
except (IOError, EOFError):
os.unlink(f)
continue
if version != self.__class__.CACHE_VERSION:
os.unlink(f)
continue
have_data = True
self.merge_data(extradata, data)
os.unlink(f)
if have_data:
with open(self.cachefile, "wb") as f:
p = pickle.Pickler(f, -1)
p.dump([data, self.__class__.CACHE_VERSION])
bb.utils.unlockfile(glf)
class SimpleCache(object):
"""
BitBake multi-process cache implementation
Used by the codeparser & file checksum caches
"""
def __init__(self, version):
self.cachefile = None
self.cachedata = None
self.cacheversion = version
def init_cache(self, d, cache_file_name=None, defaultdata=None):
cachedir = (d.getVar("PERSISTENT_DIR") or
d.getVar("CACHE"))
if not cachedir:
return defaultdata
bb.utils.mkdirhier(cachedir)
self.cachefile = os.path.join(cachedir,
cache_file_name or self.__class__.cache_file_name)
logger.debug("Using cache in '%s'", self.cachefile)
glf = bb.utils.lockfile(self.cachefile + ".lock")
try:
with open(self.cachefile, "rb") as f:
p = pickle.Unpickler(f)
data, version = p.load()
except:
bb.utils.unlockfile(glf)
return defaultdata
bb.utils.unlockfile(glf)
if version != self.cacheversion:
return defaultdata
return data
def save(self, data):
if not self.cachefile:
return
glf = bb.utils.lockfile(self.cachefile + ".lock")
with open(self.cachefile, "wb") as f:
p = pickle.Pickler(f, -1)
p.dump([data, self.cacheversion])
bb.utils.unlockfile(glf)
def copyfile(self, target):
if not self.cachefile:
return
glf = bb.utils.lockfile(self.cachefile + ".lock")
shutil.copy(self.cachefile, target)
bb.utils.unlockfile(glf)

View File

@@ -0,0 +1,63 @@
#
# Extra RecipeInfo will be all defined in this file. Currently,
# Only Hob (Image Creator) Requests some extra fields. So
# HobRecipeInfo is defined. It's named HobRecipeInfo because it
# is introduced by 'hob'. Users could also introduce other
# RecipeInfo or simply use those already defined RecipeInfo.
# In the following patch, this newly defined new extra RecipeInfo
# will be dynamically loaded and used for loading/saving the extra
# cache fields
# Copyright (C) 2011, Intel Corporation. All rights reserved.
# SPDX-License-Identifier: GPL-2.0-only
#
from bb.cache import RecipeInfoCommon
class HobRecipeInfo(RecipeInfoCommon):
__slots__ = ()
classname = "HobRecipeInfo"
# please override this member with the correct data cache file
# such as (bb_cache.dat, bb_extracache_hob.dat)
cachefile = "bb_extracache_" + classname +".dat"
# override this member with the list of extra cache fields
# that this class will provide
cachefields = ['summary', 'license', 'section',
'description', 'homepage', 'bugtracker',
'prevision', 'files_info']
def __init__(self, filename, metadata):
self.summary = self.getvar('SUMMARY', metadata)
self.license = self.getvar('LICENSE', metadata)
self.section = self.getvar('SECTION', metadata)
self.description = self.getvar('DESCRIPTION', metadata)
self.homepage = self.getvar('HOMEPAGE', metadata)
self.bugtracker = self.getvar('BUGTRACKER', metadata)
self.prevision = self.getvar('PR', metadata)
self.files_info = self.getvar('FILES_INFO', metadata)
@classmethod
def init_cacheData(cls, cachedata):
# CacheData in Hob RecipeInfo Class
cachedata.summary = {}
cachedata.license = {}
cachedata.section = {}
cachedata.description = {}
cachedata.homepage = {}
cachedata.bugtracker = {}
cachedata.prevision = {}
cachedata.files_info = {}
def add_cacheData(self, cachedata, fn):
cachedata.summary[fn] = self.summary
cachedata.license[fn] = self.license
cachedata.section[fn] = self.section
cachedata.description[fn] = self.description
cachedata.homepage[fn] = self.homepage
cachedata.bugtracker[fn] = self.bugtracker
cachedata.prevision[fn] = self.prevision
cachedata.files_info[fn] = self.files_info

169
bitbake/lib/bb/checksum.py Normal file
View File

@@ -0,0 +1,169 @@
# Local file checksum cache implementation
#
# Copyright (C) 2012 Intel Corporation
#
# SPDX-License-Identifier: GPL-2.0-only
#
import glob
import operator
import os
import stat
import bb.utils
import logging
import re
from bb.cache import MultiProcessCache
logger = logging.getLogger("BitBake.Cache")
filelist_regex = re.compile(r'(?:(?<=:True)|(?<=:False))\s+')
# mtime cache (non-persistent)
# based upon the assumption that files do not change during bitbake run
class FileMtimeCache(object):
cache = {}
def cached_mtime(self, f):
if f not in self.cache:
self.cache[f] = os.stat(f)[stat.ST_MTIME]
return self.cache[f]
def cached_mtime_noerror(self, f):
if f not in self.cache:
try:
self.cache[f] = os.stat(f)[stat.ST_MTIME]
except OSError:
return 0
return self.cache[f]
def update_mtime(self, f):
self.cache[f] = os.stat(f)[stat.ST_MTIME]
return self.cache[f]
def clear(self):
self.cache.clear()
# Checksum + mtime cache (persistent)
class FileChecksumCache(MultiProcessCache):
cache_file_name = "local_file_checksum_cache.dat"
CACHE_VERSION = 1
def __init__(self):
self.mtime_cache = FileMtimeCache()
MultiProcessCache.__init__(self)
def get_checksum(self, f):
f = os.path.normpath(f)
entry = self.cachedata[0].get(f)
cmtime = self.mtime_cache.cached_mtime(f)
if entry:
(mtime, hashval) = entry
if cmtime == mtime:
return hashval
else:
bb.debug(2, "file %s changed mtime, recompute checksum" % f)
hashval = bb.utils.md5_file(f)
self.cachedata_extras[0][f] = (cmtime, hashval)
return hashval
def merge_data(self, source, dest):
for h in source[0]:
if h in dest:
(smtime, _) = source[0][h]
(dmtime, _) = dest[0][h]
if smtime > dmtime:
dest[0][h] = source[0][h]
else:
dest[0][h] = source[0][h]
def get_checksums(self, filelist, pn, localdirsexclude):
"""Get checksums for a list of files"""
def checksum_file(f):
try:
checksum = self.get_checksum(f)
except OSError as e:
bb.warn("Unable to get checksum for %s SRC_URI entry %s: %s" % (pn, os.path.basename(f), e))
return None
return checksum
#
# Changing the format of file-checksums is problematic as both OE and Bitbake have
# knowledge of them. We need to encode a new piece of data, the portion of the path
# we care about from a checksum perspective. This means that files that change subdirectory
# are tracked by the task hashes. To do this, we do something horrible and put a "/./" into
# the path. The filesystem handles it but it gives us a marker to know which subsection
# of the path to cache.
#
def checksum_dir(pth):
# Handle directories recursively
if pth == "/":
bb.fatal("Refusing to checksum /")
pth = pth.rstrip("/")
dirchecksums = []
for root, dirs, files in os.walk(pth, topdown=True):
[dirs.remove(d) for d in list(dirs) if d in localdirsexclude]
for name in files:
fullpth = os.path.join(root, name).replace(pth, os.path.join(pth, "."))
checksum = checksum_file(fullpth)
if checksum:
dirchecksums.append((fullpth, checksum))
return dirchecksums
checksums = []
for pth in filelist_regex.split(filelist):
if not pth:
continue
pth = pth.strip()
if not pth:
continue
exist = pth.split(":")[1]
if exist == "False":
continue
pth = pth.split(":")[0]
if '*' in pth:
# Handle globs
for f in glob.glob(pth):
if os.path.isdir(f):
if not os.path.islink(f):
checksums.extend(checksum_dir(f))
else:
checksum = checksum_file(f)
if checksum:
checksums.append((f, checksum))
elif os.path.isdir(pth):
if not os.path.islink(pth):
checksums.extend(checksum_dir(pth))
else:
checksum = checksum_file(pth)
if checksum:
checksums.append((pth, checksum))
checksums.sort(key=operator.itemgetter(1))
return checksums
class RevisionsCache(MultiProcessCache):
cache_file_name = "local_srcrevisions.dat"
CACHE_VERSION = 1
def __init__(self):
MultiProcessCache.__init__(self)
def get_revs(self):
return self.cachedata[0]
def get_rev(self, k):
if k in self.cachedata_extras[0]:
return self.cachedata_extras[0][k]
if k in self.cachedata[0]:
return self.cachedata[0][k]
return None
def set_rev(self, k, v):
self.cachedata[0][k] = v
self.cachedata_extras[0][k] = v
def merge_data(self, source, dest):
for h in source[0]:
dest[0][h] = source[0][h]

View File

@@ -0,0 +1,562 @@
#
# Copyright BitBake Contributors
#
# SPDX-License-Identifier: GPL-2.0-only
#
"""
BitBake code parser
Parses actual code (i.e. python and shell) for functions and in-line
expressions. Used mainly to determine dependencies on other functions
and variables within the BitBake metadata. Also provides a cache for
this information in order to speed up processing.
(Not to be confused with the code that parses the metadata itself,
see lib/bb/parse/ for that).
NOTE: if you change how the parsers gather information you will almost
certainly need to increment CodeParserCache.CACHE_VERSION below so that
any existing codeparser cache gets invalidated. Additionally you'll need
to increment __cache_version__ in cache.py in order to ensure that old
recipe caches don't trigger "Taskhash mismatch" errors.
"""
import ast
import sys
import codegen
import logging
import inspect
import bb.pysh as pysh
import bb.utils, bb.data
import hashlib
from itertools import chain
from bb.pysh import pyshyacc, pyshlex
from bb.cache import MultiProcessCache
logger = logging.getLogger('BitBake.CodeParser')
def bbhash(s):
return hashlib.sha256(s.encode("utf-8")).hexdigest()
def check_indent(codestr):
"""If the code is indented, add a top level piece of code to 'remove' the indentation"""
i = 0
while codestr[i] in ["\n", "\t", " "]:
i = i + 1
if i == 0:
return codestr
if codestr[i-1] == "\t" or codestr[i-1] == " ":
if codestr[0] == "\n":
# Since we're adding a line, we need to remove one line of any empty padding
# to ensure line numbers are correct
codestr = codestr[1:]
return "if 1:\n" + codestr
return codestr
modulecode_deps = {}
def add_module_functions(fn, functions, namespace):
import os
fstat = os.stat(fn)
fixedhash = fn + ":" + str(fstat.st_size) + ":" + str(fstat.st_mtime)
for f in functions:
name = "%s.%s" % (namespace, f)
parser = PythonParser(name, logger)
try:
parser.parse_python(None, filename=fn, lineno=1, fixedhash=fixedhash+f)
#bb.warn("Cached %s" % f)
except KeyError:
try:
targetfn = inspect.getsourcefile(functions[f])
except TypeError:
# Builtin
continue
if fn != targetfn:
# Skip references to other modules outside this file
#bb.warn("Skipping %s" % name)
continue
try:
lines, lineno = inspect.getsourcelines(functions[f])
except TypeError:
# Builtin
continue
src = "".join(lines)
parser.parse_python(src, filename=fn, lineno=lineno, fixedhash=fixedhash+f)
#bb.warn("Not cached %s" % f)
execs = parser.execs.copy()
# Expand internal module exec references
for e in parser.execs:
if e in functions:
execs.remove(e)
execs.add(namespace + "." + e)
visitorcode = None
if hasattr(functions[f], 'visitorcode'):
visitorcode = getattr(functions[f], "visitorcode")
modulecode_deps[name] = [parser.references.copy(), execs, parser.var_execs.copy(), parser.contains.copy(), parser.extra, visitorcode]
#bb.warn("%s: %s\nRefs:%s Execs: %s %s %s" % (name, fn, parser.references, parser.execs, parser.var_execs, parser.contains))
def update_module_dependencies(d):
for mod in modulecode_deps:
excludes = set((d.getVarFlag(mod, "vardepsexclude") or "").split())
if excludes:
modulecode_deps[mod] = [modulecode_deps[mod][0] - excludes, modulecode_deps[mod][1] - excludes, modulecode_deps[mod][2] - excludes, modulecode_deps[mod][3], modulecode_deps[mod][4], modulecode_deps[mod][5]]
# A custom getstate/setstate using tuples is actually worth 15% cachesize by
# avoiding duplication of the attribute names!
class SetCache(object):
def __init__(self):
self.setcache = {}
def internSet(self, items):
new = []
for i in items:
new.append(sys.intern(i))
s = frozenset(new)
h = hash(s)
if h in self.setcache:
return self.setcache[h]
self.setcache[h] = s
return s
codecache = SetCache()
class pythonCacheLine(object):
def __init__(self, refs, execs, contains, extra):
self.refs = codecache.internSet(refs)
self.execs = codecache.internSet(execs)
self.contains = {}
for c in contains:
self.contains[c] = codecache.internSet(contains[c])
self.extra = extra
def __getstate__(self):
return (self.refs, self.execs, self.contains, self.extra)
def __setstate__(self, state):
(refs, execs, contains, extra) = state
self.__init__(refs, execs, contains, extra)
def __hash__(self):
l = (hash(self.refs), hash(self.execs), hash(self.extra))
for c in sorted(self.contains.keys()):
l = l + (c, hash(self.contains[c]))
return hash(l)
def __repr__(self):
return " ".join([str(self.refs), str(self.execs), str(self.contains)])
class shellCacheLine(object):
def __init__(self, execs):
self.execs = codecache.internSet(execs)
def __getstate__(self):
return (self.execs)
def __setstate__(self, state):
(execs) = state
self.__init__(execs)
def __hash__(self):
return hash(self.execs)
def __repr__(self):
return str(self.execs)
class CodeParserCache(MultiProcessCache):
cache_file_name = "bb_codeparser.dat"
# NOTE: you must increment this if you change how the parsers gather information,
# so that an existing cache gets invalidated. Additionally you'll need
# to increment __cache_version__ in cache.py in order to ensure that old
# recipe caches don't trigger "Taskhash mismatch" errors.
CACHE_VERSION = 14
def __init__(self):
MultiProcessCache.__init__(self)
self.pythoncache = self.cachedata[0]
self.shellcache = self.cachedata[1]
self.pythoncacheextras = self.cachedata_extras[0]
self.shellcacheextras = self.cachedata_extras[1]
# To avoid duplication in the codeparser cache, keep
# a lookup of hashes of objects we already have
self.pythoncachelines = {}
self.shellcachelines = {}
def newPythonCacheLine(self, refs, execs, contains, extra):
cacheline = pythonCacheLine(refs, execs, contains, extra)
h = hash(cacheline)
if h in self.pythoncachelines:
return self.pythoncachelines[h]
self.pythoncachelines[h] = cacheline
return cacheline
def newShellCacheLine(self, execs):
cacheline = shellCacheLine(execs)
h = hash(cacheline)
if h in self.shellcachelines:
return self.shellcachelines[h]
self.shellcachelines[h] = cacheline
return cacheline
def init_cache(self, cachedir):
# Check if we already have the caches
if self.pythoncache:
return
MultiProcessCache.init_cache(self, cachedir)
# cachedata gets re-assigned in the parent
self.pythoncache = self.cachedata[0]
self.shellcache = self.cachedata[1]
def create_cachedata(self):
data = [{}, {}]
return data
codeparsercache = CodeParserCache()
def parser_cache_init(cachedir):
codeparsercache.init_cache(cachedir)
def parser_cache_save():
codeparsercache.save_extras()
def parser_cache_savemerge():
codeparsercache.save_merge()
Logger = logging.getLoggerClass()
class BufferedLogger(Logger):
def __init__(self, name, level=0, target=None):
Logger.__init__(self, name)
self.setLevel(level)
self.buffer = []
self.target = target
def handle(self, record):
self.buffer.append(record)
def flush(self):
for record in self.buffer:
if self.target.isEnabledFor(record.levelno):
self.target.handle(record)
self.buffer = []
class DummyLogger():
def flush(self):
return
class PythonParser():
getvars = (".getVar", ".appendVar", ".prependVar", "oe.utils.conditional")
getvarflags = (".getVarFlag", ".appendVarFlag", ".prependVarFlag")
containsfuncs = ("bb.utils.contains", "base_contains")
containsanyfuncs = ("bb.utils.contains_any", "bb.utils.filter")
execfuncs = ("bb.build.exec_func", "bb.build.exec_task")
def warn(self, func, arg):
"""Warn about calls of bitbake APIs which pass a non-literal
argument for the variable name, as we're not able to track such
a reference.
"""
try:
funcstr = codegen.to_source(func)
argstr = codegen.to_source(arg)
except TypeError:
self.log.debug2('Failed to convert function and argument to source form')
else:
self.log.debug(self.unhandled_message % (funcstr, argstr))
def visit_Call(self, node):
name = self.called_node_name(node.func)
if name and name in modulecode_deps and modulecode_deps[name][5]:
visitorcode = modulecode_deps[name][5]
contains, execs, warn = visitorcode(name, node.args)
for i in contains:
self.contains[i] = contains[i]
self.execs |= execs
if warn:
self.warn(node.func, warn)
elif name and (name.endswith(self.getvars) or name.endswith(self.getvarflags) or name in self.containsfuncs or name in self.containsanyfuncs):
if isinstance(node.args[0], ast.Constant) and isinstance(node.args[0].value, str):
varname = node.args[0].value
if name in self.containsfuncs and isinstance(node.args[1], ast.Constant):
if varname not in self.contains:
self.contains[varname] = set()
self.contains[varname].add(node.args[1].value)
elif name in self.containsanyfuncs and isinstance(node.args[1], ast.Constant):
if varname not in self.contains:
self.contains[varname] = set()
self.contains[varname].update(node.args[1].value.split())
elif name.endswith(self.getvarflags):
if isinstance(node.args[1], ast.Constant):
self.references.add('%s[%s]' % (varname, node.args[1].value))
else:
self.warn(node.func, node.args[1])
else:
self.references.add(varname)
else:
self.warn(node.func, node.args[0])
elif name and name.endswith(".expand"):
if isinstance(node.args[0], ast.Constant):
value = node.args[0].value
d = bb.data.init()
parser = d.expandWithRefs(value, self.name)
self.references |= parser.references
self.execs |= parser.execs
for varname in parser.contains:
if varname not in self.contains:
self.contains[varname] = set()
self.contains[varname] |= parser.contains[varname]
elif name in self.execfuncs:
if isinstance(node.args[0], ast.Constant):
self.var_execs.add(node.args[0].value)
else:
self.warn(node.func, node.args[0])
elif name and isinstance(node.func, (ast.Name, ast.Attribute)):
self.execs.add(name)
def called_node_name(self, node):
"""Given a called node, return its original string form"""
components = []
while node:
if isinstance(node, ast.Attribute):
components.append(node.attr)
node = node.value
elif isinstance(node, ast.Name):
components.append(node.id)
return '.'.join(reversed(components))
else:
break
def __init__(self, name, log):
self.name = name
self.var_execs = set()
self.contains = {}
self.execs = set()
self.references = set()
self._log = log
# Defer init as expensive
self.log = DummyLogger()
self.unhandled_message = "in call of %s, argument '%s' is not a string literal"
self.unhandled_message = "while parsing %s, %s" % (name, self.unhandled_message)
# For the python module code it is expensive to have the function text so it is
# uses a different fixedhash to cache against. We can take the hit on obtaining the
# text if it isn't in the cache.
def parse_python(self, node, lineno=0, filename="<string>", fixedhash=None):
if not fixedhash and (not node or not node.strip()):
return
if fixedhash:
h = fixedhash
else:
h = bbhash(str(node))
if h in codeparsercache.pythoncache:
self.references = set(codeparsercache.pythoncache[h].refs)
self.execs = set(codeparsercache.pythoncache[h].execs)
self.contains = {}
for i in codeparsercache.pythoncache[h].contains:
self.contains[i] = set(codeparsercache.pythoncache[h].contains[i])
self.extra = codeparsercache.pythoncache[h].extra
return
if h in codeparsercache.pythoncacheextras:
self.references = set(codeparsercache.pythoncacheextras[h].refs)
self.execs = set(codeparsercache.pythoncacheextras[h].execs)
self.contains = {}
for i in codeparsercache.pythoncacheextras[h].contains:
self.contains[i] = set(codeparsercache.pythoncacheextras[h].contains[i])
self.extra = codeparsercache.pythoncacheextras[h].extra
return
if fixedhash and not node:
raise KeyError
# Need to parse so take the hit on the real log buffer
self.log = BufferedLogger('BitBake.Data.PythonParser', logging.DEBUG, self._log)
# We can't add to the linenumbers for compile, we can pad to the correct number of blank lines though
node = "\n" * int(lineno) + node
code = compile(check_indent(str(node)), filename, "exec",
ast.PyCF_ONLY_AST)
for n in ast.walk(code):
if n.__class__.__name__ == "Call":
self.visit_Call(n)
self.execs.update(self.var_execs)
self.extra = None
if fixedhash:
self.extra = bbhash(str(node))
codeparsercache.pythoncacheextras[h] = codeparsercache.newPythonCacheLine(self.references, self.execs, self.contains, self.extra)
class ShellParser():
def __init__(self, name, log):
self.funcdefs = set()
self.allexecs = set()
self.execs = set()
self._name = name
self._log = log
# Defer init as expensive
self.log = DummyLogger()
self.unhandled_template = "unable to handle non-literal command '%s'"
self.unhandled_template = "while parsing %s, %s" % (name, self.unhandled_template)
def parse_shell(self, value):
"""Parse the supplied shell code in a string, returning the external
commands it executes.
"""
h = bbhash(str(value))
if h in codeparsercache.shellcache:
self.execs = set(codeparsercache.shellcache[h].execs)
return self.execs
if h in codeparsercache.shellcacheextras:
self.execs = set(codeparsercache.shellcacheextras[h].execs)
return self.execs
# Need to parse so take the hit on the real log buffer
self.log = BufferedLogger('BitBake.Data.%s' % self._name, logging.DEBUG, self._log)
self._parse_shell(value)
self.execs = set(cmd for cmd in self.allexecs if cmd not in self.funcdefs)
codeparsercache.shellcacheextras[h] = codeparsercache.newShellCacheLine(self.execs)
return self.execs
def _parse_shell(self, value):
try:
tokens, _ = pyshyacc.parse(value, eof=True, debug=False)
except Exception:
bb.error('Error during parse shell code, the last 5 lines are:\n%s' % '\n'.join(value.split('\n')[-5:]))
raise
self.process_tokens(tokens)
def process_tokens(self, tokens):
"""Process a supplied portion of the syntax tree as returned by
pyshyacc.parse.
"""
def function_definition(value):
self.funcdefs.add(value.name)
return [value.body], None
def case_clause(value):
# Element 0 of each item in the case is the list of patterns, and
# Element 1 of each item in the case is the list of commands to be
# executed when that pattern matches.
words = chain(*[item[0] for item in value.items])
cmds = chain(*[item[1] for item in value.items])
return cmds, words
def if_clause(value):
main = chain(value.cond, value.if_cmds)
rest = value.else_cmds
if isinstance(rest, tuple) and rest[0] == "elif":
return chain(main, if_clause(rest[1]))
else:
return chain(main, rest)
def simple_command(value):
return None, chain(value.words, (assign[1] for assign in value.assigns))
token_handlers = {
"and_or": lambda x: ((x.left, x.right), None),
"async": lambda x: ([x], None),
"brace_group": lambda x: (x.cmds, None),
"for_clause": lambda x: (x.cmds, x.items),
"function_definition": function_definition,
"if_clause": lambda x: (if_clause(x), None),
"pipeline": lambda x: (x.commands, None),
"redirect_list": lambda x: ([x.cmd], None),
"subshell": lambda x: (x.cmds, None),
"while_clause": lambda x: (chain(x.condition, x.cmds), None),
"until_clause": lambda x: (chain(x.condition, x.cmds), None),
"simple_command": simple_command,
"case_clause": case_clause,
}
def process_token_list(tokens):
for token in tokens:
if isinstance(token, list):
process_token_list(token)
continue
name, value = token
try:
more_tokens, words = token_handlers[name](value)
except KeyError:
raise NotImplementedError("Unsupported token type " + name)
if more_tokens:
self.process_tokens(more_tokens)
if words:
self.process_words(words)
process_token_list(tokens)
def process_words(self, words):
"""Process a set of 'words' in pyshyacc parlance, which includes
extraction of executed commands from $() blocks, as well as grabbing
the command name argument.
"""
words = list(words)
for word in words:
wtree = pyshlex.make_wordtree(word[1])
for part in wtree:
if not isinstance(part, list):
continue
candidates = [part]
# If command is of type:
#
# var="... $(cmd [...]) ..."
#
# Then iterate on what's between the quotes and if we find a
# list, make that what we check for below.
if len(part) >= 3 and part[0] == '"':
for p in part[1:-1]:
if isinstance(p, list):
candidates.append(p)
for candidate in candidates:
if len(candidate) >= 2:
if candidate[0] in ('`', '$('):
command = pyshlex.wordtree_as_string(candidate[1:-1])
self._parse_shell(command)
if word[0] in ("cmd_name", "cmd_word"):
if word in words:
words.remove(word)
usetoken = False
for word in words:
if word[0] in ("cmd_name", "cmd_word") or \
(usetoken and word[0] == "TOKEN"):
if "=" in word[1]:
usetoken = True
continue
cmd = word[1]
if cmd.startswith("$"):
self.log.debug(self.unhandled_template % cmd)
elif cmd == "eval":
command = " ".join(word for _, word in words[1:])
self._parse_shell(command)
else:
self.allexecs.add(cmd)
break

813
bitbake/lib/bb/command.py Normal file
View File

@@ -0,0 +1,813 @@
"""
BitBake 'Command' module
Provide an interface to interact with the bitbake server through 'commands'
"""
# Copyright (C) 2006-2007 Richard Purdie
#
# SPDX-License-Identifier: GPL-2.0-only
#
"""
The bitbake server takes 'commands' from its UI/commandline.
Commands are either synchronous or asynchronous.
Async commands return data to the client in the form of events.
Sync commands must only return data through the function return value
and must not trigger events, directly or indirectly.
Commands are queued in a CommandQueue
"""
from collections import OrderedDict, defaultdict
import io
import bb.event
import bb.cooker
import bb.remotedata
import bb.parse
class DataStoreConnectionHandle(object):
def __init__(self, dsindex=0):
self.dsindex = dsindex
class CommandCompleted(bb.event.Event):
pass
class CommandExit(bb.event.Event):
def __init__(self, exitcode):
bb.event.Event.__init__(self)
self.exitcode = int(exitcode)
class CommandFailed(CommandExit):
def __init__(self, message):
self.error = message
CommandExit.__init__(self, 1)
def __str__(self):
return "Command execution failed: %s" % self.error
class CommandError(Exception):
pass
class Command:
"""
A queue of asynchronous commands for bitbake
"""
def __init__(self, cooker, process_server):
self.cooker = cooker
self.cmds_sync = CommandsSync()
self.cmds_async = CommandsAsync()
self.remotedatastores = None
self.process_server = process_server
# Access with locking using process_server.{get/set/clear}_async_cmd()
self.currentAsyncCommand = None
def runCommand(self, commandline, process_server, ro_only=False):
command = commandline.pop(0)
# Ensure cooker is ready for commands
if command not in ["updateConfig", "setFeatures", "ping"]:
try:
self.cooker.init_configdata()
if not self.remotedatastores:
self.remotedatastores = bb.remotedata.RemoteDatastores(self.cooker)
except (Exception, SystemExit) as exc:
import traceback
if isinstance(exc, bb.BBHandledException):
# We need to start returning real exceptions here. Until we do, we can't
# tell if an exception is an instance of bb.BBHandledException
return None, "bb.BBHandledException()\n" + traceback.format_exc()
return None, traceback.format_exc()
if hasattr(CommandsSync, command):
# Can run synchronous commands straight away
command_method = getattr(self.cmds_sync, command)
if ro_only:
if not hasattr(command_method, 'readonly') or not getattr(command_method, 'readonly'):
return None, "Not able to execute not readonly commands in readonly mode"
try:
if getattr(command_method, 'needconfig', True):
self.cooker.updateCacheSync()
result = command_method(self, commandline)
except CommandError as exc:
return None, exc.args[0]
except (Exception, SystemExit) as exc:
import traceback
if isinstance(exc, bb.BBHandledException):
# We need to start returning real exceptions here. Until we do, we can't
# tell if an exception is an instance of bb.BBHandledException
return None, "bb.BBHandledException()\n" + traceback.format_exc()
return None, traceback.format_exc()
else:
return result, None
if command not in CommandsAsync.__dict__:
return None, "No such command"
if not process_server.set_async_cmd((command, commandline)):
return None, "Busy (%s in progress)" % self.process_server.get_async_cmd()[0]
self.cooker.idleCallBackRegister(self.runAsyncCommand, process_server)
return True, None
def runAsyncCommand(self, _, process_server, halt):
try:
if self.cooker.state in (bb.cooker.State.ERROR, bb.cooker.State.SHUTDOWN, bb.cooker.State.FORCE_SHUTDOWN):
# updateCache will trigger a shutdown of the parser
# and then raise BBHandledException triggering an exit
self.cooker.updateCache()
return bb.server.process.idleFinish("Cooker in error state")
cmd = process_server.get_async_cmd()
if cmd is not None:
(command, options) = cmd
commandmethod = getattr(CommandsAsync, command)
needcache = getattr( commandmethod, "needcache" )
if needcache and self.cooker.state != bb.cooker.State.RUNNING:
self.cooker.updateCache()
return True
else:
commandmethod(self.cmds_async, self, options)
return False
else:
return bb.server.process.idleFinish("Nothing to do, no async command?")
except KeyboardInterrupt as exc:
return bb.server.process.idleFinish("Interrupted")
except SystemExit as exc:
arg = exc.args[0]
if isinstance(arg, str):
return bb.server.process.idleFinish(arg)
else:
return bb.server.process.idleFinish("Exited with %s" % arg)
except Exception as exc:
import traceback
if isinstance(exc, bb.BBHandledException):
return bb.server.process.idleFinish("")
else:
return bb.server.process.idleFinish(traceback.format_exc())
def finishAsyncCommand(self, msg=None, code=None):
self.cooker.finishcommand()
self.process_server.clear_async_cmd()
if msg or msg == "":
bb.event.fire(CommandFailed(msg), self.cooker.data)
elif code:
bb.event.fire(CommandExit(code), self.cooker.data)
else:
bb.event.fire(CommandCompleted(), self.cooker.data)
def reset(self):
if self.remotedatastores:
self.remotedatastores = bb.remotedata.RemoteDatastores(self.cooker)
class CommandsSync:
"""
A class of synchronous commands
These should run quickly so as not to hurt interactive performance.
These must not influence any running synchronous command.
"""
def ping(self, command, params):
"""
Allow a UI to check the server is still alive
"""
return "Still alive!"
ping.needconfig = False
ping.readonly = True
def stateShutdown(self, command, params):
"""
Trigger cooker 'shutdown' mode
"""
command.cooker.shutdown(False)
def stateForceShutdown(self, command, params):
"""
Stop the cooker
"""
command.cooker.shutdown(True)
def getAllKeysWithFlags(self, command, params):
"""
Returns a dump of the global state. Call with
variable flags to be retrieved as params.
"""
flaglist = params[0]
return command.cooker.getAllKeysWithFlags(flaglist)
getAllKeysWithFlags.readonly = True
def getVariable(self, command, params):
"""
Read the value of a variable from data
"""
varname = params[0]
expand = True
if len(params) > 1:
expand = (params[1] == "True")
return command.cooker.data.getVar(varname, expand)
getVariable.readonly = True
def setVariable(self, command, params):
"""
Set the value of variable in data
"""
varname = params[0]
value = str(params[1])
command.cooker.extraconfigdata[varname] = value
command.cooker.data.setVar(varname, value)
def getSetVariable(self, command, params):
"""
Read the value of a variable from data and set it into the datastore
which effectively expands and locks the value.
"""
varname = params[0]
result = self.getVariable(command, params)
command.cooker.data.setVar(varname, result)
return result
def setConfig(self, command, params):
"""
Set the value of variable in configuration
"""
varname = params[0]
value = str(params[1])
setattr(command.cooker.configuration, varname, value)
def enableDataTracking(self, command, params):
"""
Enable history tracking for variables
"""
command.cooker.enableDataTracking()
def disableDataTracking(self, command, params):
"""
Disable history tracking for variables
"""
command.cooker.disableDataTracking()
def setPrePostConfFiles(self, command, params):
prefiles = params[0].split()
postfiles = params[1].split()
command.cooker.configuration.prefile = prefiles
command.cooker.configuration.postfile = postfiles
setPrePostConfFiles.needconfig = False
def matchFile(self, command, params):
fMatch = params[0]
try:
mc = params[0]
except IndexError:
mc = ''
return command.cooker.matchFile(fMatch, mc)
matchFile.needconfig = False
def getUIHandlerNum(self, command, params):
return bb.event.get_uihandler()
getUIHandlerNum.needconfig = False
getUIHandlerNum.readonly = True
def setEventMask(self, command, params):
handlerNum = params[0]
llevel = params[1]
debug_domains = params[2]
mask = params[3]
return bb.event.set_UIHmask(handlerNum, llevel, debug_domains, mask)
setEventMask.needconfig = False
setEventMask.readonly = True
def setFeatures(self, command, params):
"""
Set the cooker features to include the passed list of features
"""
features = params[0]
command.cooker.setFeatures(features)
setFeatures.needconfig = False
# although we change the internal state of the cooker, this is transparent since
# we always take and leave the cooker in state.initial
setFeatures.readonly = True
def updateConfig(self, command, params):
options = params[0]
environment = params[1]
cmdline = params[2]
command.cooker.updateConfigOpts(options, environment, cmdline)
updateConfig.needconfig = False
def parseConfiguration(self, command, params):
"""Instruct bitbake to parse its configuration
NOTE: it is only necessary to call this if you aren't calling any normal action
(otherwise parsing is taken care of automatically)
"""
command.cooker.parseConfiguration()
parseConfiguration.needconfig = False
def getLayerPriorities(self, command, params):
command.cooker.parseConfiguration()
ret = []
# regex objects cannot be marshalled by xmlrpc
for collection, pattern, regex, pri in command.cooker.bbfile_config_priorities:
ret.append((collection, pattern, regex.pattern, pri))
return ret
getLayerPriorities.readonly = True
def revalidateCaches(self, command, params):
"""Called by UI clients when metadata may have changed"""
command.cooker.revalidateCaches()
revalidateCaches.needconfig = False
def getRecipes(self, command, params):
try:
mc = params[0]
except IndexError:
mc = ''
return list(command.cooker.recipecaches[mc].pkg_pn.items())
getRecipes.readonly = True
def getRecipeDepends(self, command, params):
try:
mc = params[0]
except IndexError:
mc = ''
return list(command.cooker.recipecaches[mc].deps.items())
getRecipeDepends.readonly = True
def getRecipeVersions(self, command, params):
try:
mc = params[0]
except IndexError:
mc = ''
return command.cooker.recipecaches[mc].pkg_pepvpr
getRecipeVersions.readonly = True
def getRecipeProvides(self, command, params):
try:
mc = params[0]
except IndexError:
mc = ''
return command.cooker.recipecaches[mc].fn_provides
getRecipeProvides.readonly = True
def getRecipePackages(self, command, params):
try:
mc = params[0]
except IndexError:
mc = ''
return command.cooker.recipecaches[mc].packages
getRecipePackages.readonly = True
def getRecipePackagesDynamic(self, command, params):
try:
mc = params[0]
except IndexError:
mc = ''
return command.cooker.recipecaches[mc].packages_dynamic
getRecipePackagesDynamic.readonly = True
def getRProviders(self, command, params):
try:
mc = params[0]
except IndexError:
mc = ''
return command.cooker.recipecaches[mc].rproviders
getRProviders.readonly = True
def getRuntimeDepends(self, command, params):
ret = []
try:
mc = params[0]
except IndexError:
mc = ''
rundeps = command.cooker.recipecaches[mc].rundeps
for key, value in rundeps.items():
if isinstance(value, defaultdict):
value = dict(value)
ret.append((key, value))
return ret
getRuntimeDepends.readonly = True
def getRuntimeRecommends(self, command, params):
ret = []
try:
mc = params[0]
except IndexError:
mc = ''
runrecs = command.cooker.recipecaches[mc].runrecs
for key, value in runrecs.items():
if isinstance(value, defaultdict):
value = dict(value)
ret.append((key, value))
return ret
getRuntimeRecommends.readonly = True
def getRecipeInherits(self, command, params):
try:
mc = params[0]
except IndexError:
mc = ''
return command.cooker.recipecaches[mc].inherits
getRecipeInherits.readonly = True
def getBbFilePriority(self, command, params):
try:
mc = params[0]
except IndexError:
mc = ''
return command.cooker.recipecaches[mc].bbfile_priority
getBbFilePriority.readonly = True
def getDefaultPreference(self, command, params):
try:
mc = params[0]
except IndexError:
mc = ''
return command.cooker.recipecaches[mc].pkg_dp
getDefaultPreference.readonly = True
def getSkippedRecipes(self, command, params):
"""
Get the map of skipped recipes for the specified multiconfig/mc name (`params[0]`).
Invoked by `bb.tinfoil.Tinfoil.get_skipped_recipes`
:param command: Internally used parameter.
:param params: Parameter array. params[0] is multiconfig/mc name. If not given, then default mc '' is assumed.
:return: Dict whose keys are virtualfns and values are `bb.cooker.SkippedPackage`
"""
try:
mc = params[0]
except IndexError:
mc = ''
# Return list sorted by reverse priority order
import bb.cache
def sortkey(x):
vfn, _ = x
realfn, _, item_mc = bb.cache.virtualfn2realfn(vfn)
return -command.cooker.collections[item_mc].calc_bbfile_priority(realfn)[0], vfn
skipdict = OrderedDict(sorted(command.cooker.skiplist_by_mc[mc].items(), key=sortkey))
return list(skipdict.items())
getSkippedRecipes.readonly = True
def getOverlayedRecipes(self, command, params):
try:
mc = params[0]
except IndexError:
mc = ''
return list(command.cooker.collections[mc].overlayed.items())
getOverlayedRecipes.readonly = True
def getFileAppends(self, command, params):
fn = params[0]
try:
mc = params[1]
except IndexError:
mc = ''
return command.cooker.collections[mc].get_file_appends(fn)
getFileAppends.readonly = True
def getAllAppends(self, command, params):
try:
mc = params[0]
except IndexError:
mc = ''
return command.cooker.collections[mc].bbappends
getAllAppends.readonly = True
def findProviders(self, command, params):
try:
mc = params[0]
except IndexError:
mc = ''
return command.cooker.findProviders(mc)
findProviders.readonly = True
def findBestProvider(self, command, params):
(mc, pn) = bb.runqueue.split_mc(params[0])
return command.cooker.findBestProvider(pn, mc)
findBestProvider.readonly = True
def allProviders(self, command, params):
try:
mc = params[0]
except IndexError:
mc = ''
return list(bb.providers.allProviders(command.cooker.recipecaches[mc]).items())
allProviders.readonly = True
def getRuntimeProviders(self, command, params):
rprovide = params[0]
try:
mc = params[1]
except IndexError:
mc = ''
all_p = bb.providers.getRuntimeProviders(command.cooker.recipecaches[mc], rprovide)
if all_p:
best = bb.providers.filterProvidersRunTime(all_p, rprovide,
command.cooker.data,
command.cooker.recipecaches[mc])[0][0]
else:
best = None
return all_p, best
getRuntimeProviders.readonly = True
def dataStoreConnectorCmd(self, command, params):
dsindex = params[0]
method = params[1]
args = params[2]
kwargs = params[3]
d = command.remotedatastores[dsindex]
ret = getattr(d, method)(*args, **kwargs)
if isinstance(ret, bb.data_smart.DataSmart):
idx = command.remotedatastores.store(ret)
return DataStoreConnectionHandle(idx)
return ret
def dataStoreConnectorVarHistCmd(self, command, params):
dsindex = params[0]
method = params[1]
args = params[2]
kwargs = params[3]
d = command.remotedatastores[dsindex].varhistory
return getattr(d, method)(*args, **kwargs)
def dataStoreConnectorVarHistCmdEmit(self, command, params):
dsindex = params[0]
var = params[1]
oval = params[2]
val = params[3]
d = command.remotedatastores[params[4]]
o = io.StringIO()
command.remotedatastores[dsindex].varhistory.emit(var, oval, val, o, d)
return o.getvalue()
def dataStoreConnectorIncHistCmd(self, command, params):
dsindex = params[0]
method = params[1]
args = params[2]
kwargs = params[3]
d = command.remotedatastores[dsindex].inchistory
return getattr(d, method)(*args, **kwargs)
def dataStoreConnectorRelease(self, command, params):
dsindex = params[0]
if dsindex <= 0:
raise CommandError('dataStoreConnectorRelease: invalid index %d' % dsindex)
command.remotedatastores.release(dsindex)
def parseRecipeFile(self, command, params):
"""
Parse the specified recipe file (with or without bbappends)
and return a datastore object representing the environment
for the recipe.
"""
virtualfn = params[0]
(fn, cls, mc) = bb.cache.virtualfn2realfn(virtualfn)
appends = params[1]
appendlist = params[2]
if len(params) > 3:
config_data = command.remotedatastores[params[3]]
else:
config_data = None
if appends:
if appendlist is not None:
appendfiles = appendlist
else:
appendfiles = command.cooker.collections[mc].get_file_appends(fn)
else:
appendfiles = []
layername = command.cooker.collections[mc].calc_bbfile_priority(fn)[2]
# We are calling bb.cache locally here rather than on the server,
# but that's OK because it doesn't actually need anything from
# the server barring the global datastore (which we have a remote
# version of)
if config_data:
# We have to use a different function here if we're passing in a datastore
# NOTE: we took a copy above, so we don't do it here again
envdata = command.cooker.databuilder._parse_recipe(config_data, fn, appendfiles, mc, layername)[cls]
else:
# Use the standard path
envdata = command.cooker.databuilder.parseRecipe(virtualfn, appendfiles, layername)
idx = command.remotedatastores.store(envdata)
return DataStoreConnectionHandle(idx)
parseRecipeFile.readonly = True
def finalizeData(self, command, params):
newdata = command.cooker.data.createCopy()
bb.data.expandKeys(newdata)
bb.parse.ast.runAnonFuncs(newdata)
idx = command.remotedatastores.store(newdata)
return DataStoreConnectionHandle(idx)
class CommandsAsync:
"""
A class of asynchronous commands
These functions communicate via generated events.
Any function that requires metadata parsing should be here.
"""
def buildFile(self, command, params):
"""
Build a single specified .bb file
"""
bfile = params[0]
task = params[1]
if len(params) > 2:
internal = params[2]
else:
internal = False
if internal:
command.cooker.buildFileInternal(bfile, task, fireevents=False, quietlog=True)
else:
command.cooker.buildFile(bfile, task)
buildFile.needcache = False
def buildTargets(self, command, params):
"""
Build a set of targets
"""
pkgs_to_build = params[0]
task = params[1]
command.cooker.buildTargets(pkgs_to_build, task)
buildTargets.needcache = True
def generateDepTreeEvent(self, command, params):
"""
Generate an event containing the dependency information
"""
pkgs_to_build = params[0]
task = params[1]
command.cooker.generateDepTreeEvent(pkgs_to_build, task)
command.finishAsyncCommand()
generateDepTreeEvent.needcache = True
def generateDotGraph(self, command, params):
"""
Dump dependency information to disk as .dot files
"""
pkgs_to_build = params[0]
task = params[1]
command.cooker.generateDotGraphFiles(pkgs_to_build, task)
command.finishAsyncCommand()
generateDotGraph.needcache = True
def generateTargetsTree(self, command, params):
"""
Generate a tree of buildable targets.
If klass is provided ensure all recipes that inherit the class are
included in the package list.
If pkg_list provided use that list (plus any extras brought in by
klass) rather than generating a tree for all packages.
"""
klass = params[0]
pkg_list = params[1]
command.cooker.generateTargetsTree(klass, pkg_list)
command.finishAsyncCommand()
generateTargetsTree.needcache = True
def findConfigFiles(self, command, params):
"""
Find config files which provide appropriate values
for the passed configuration variable. i.e. MACHINE
"""
varname = params[0]
command.cooker.findConfigFiles(varname)
command.finishAsyncCommand()
findConfigFiles.needcache = False
def findFilesMatchingInDir(self, command, params):
"""
Find implementation files matching the specified pattern
in the requested subdirectory of a BBPATH
"""
pattern = params[0]
directory = params[1]
command.cooker.findFilesMatchingInDir(pattern, directory)
command.finishAsyncCommand()
findFilesMatchingInDir.needcache = False
def testCookerCommandEvent(self, command, params):
"""
Dummy command used by OEQA selftest to test tinfoil without IO
"""
pattern = params[0]
command.cooker.testCookerCommandEvent(pattern)
command.finishAsyncCommand()
testCookerCommandEvent.needcache = False
def findConfigFilePath(self, command, params):
"""
Find the path of the requested configuration file
"""
configfile = params[0]
command.cooker.findConfigFilePath(configfile)
command.finishAsyncCommand()
findConfigFilePath.needcache = False
def showVersions(self, command, params):
"""
Show the currently selected versions
"""
command.cooker.showVersions()
command.finishAsyncCommand()
showVersions.needcache = True
def showEnvironmentTarget(self, command, params):
"""
Print the environment of a target recipe
(needs the cache to work out which recipe to use)
"""
pkg = params[0]
command.cooker.showEnvironment(None, pkg)
command.finishAsyncCommand()
showEnvironmentTarget.needcache = True
def showEnvironment(self, command, params):
"""
Print the standard environment
or if specified the environment for a specified recipe
"""
bfile = params[0]
command.cooker.showEnvironment(bfile)
command.finishAsyncCommand()
showEnvironment.needcache = False
def parseFiles(self, command, params):
"""
Parse the .bb files
"""
command.cooker.updateCache()
command.finishAsyncCommand()
parseFiles.needcache = True
def compareRevisions(self, command, params):
"""
Parse the .bb files
"""
if bb.fetch.fetcher_compare_revisions(command.cooker.data):
command.finishAsyncCommand(code=1)
else:
command.finishAsyncCommand()
compareRevisions.needcache = True
def triggerEvent(self, command, params):
"""
Trigger a certain event
"""
event = params[0]
bb.event.fire(eval(event), command.cooker.data)
process_server.clear_async_cmd()
triggerEvent.needcache = False
def resetCooker(self, command, params):
"""
Reset the cooker to its initial state, thus forcing a reparse for
any async command that has the needcache property set to True
"""
command.cooker.reset()
command.finishAsyncCommand()
resetCooker.needcache = False
def clientComplete(self, command, params):
"""
Do the right thing when the controlling client exits
"""
command.cooker.clientComplete()
command.finishAsyncCommand()
clientComplete.needcache = False
def findSigInfo(self, command, params):
"""
Find signature info files via the signature generator
"""
(mc, pn) = bb.runqueue.split_mc(params[0])
taskname = params[1]
sigs = params[2]
bb.siggen.check_siggen_version(bb.siggen)
res = bb.siggen.find_siginfo(pn, taskname, sigs, command.cooker.databuilder.mcdata[mc])
bb.event.fire(bb.event.FindSigInfoResult(res), command.cooker.databuilder.mcdata[mc])
command.finishAsyncCommand()
findSigInfo.needcache = False
def getTaskSignatures(self, command, params):
res = command.cooker.getTaskSignatures(params[0], params[1])
bb.event.fire(bb.event.GetTaskSignatureResult(res), command.cooker.data)
command.finishAsyncCommand()
getTaskSignatures.needcache = True

View File

@@ -0,0 +1,196 @@
#
# Copyright BitBake Contributors
#
# SPDX-License-Identifier: GPL-2.0-only
#
# Helper library to implement streaming compression and decompression using an
# external process
#
# This library should be used directly by end users; a wrapper library for the
# specific compression tool should be created
import builtins
import io
import os
import subprocess
def open_wrap(
cls, filename, mode="rb", *, encoding=None, errors=None, newline=None, **kwargs
):
"""
Open a compressed file in binary or text mode.
Users should not call this directly. A specific compression library can use
this helper to provide it's own "open" command
The filename argument can be an actual filename (a str or bytes object), or
an existing file object to read from or write to.
The mode argument can be "r", "rb", "w", "wb", "x", "xb", "a" or "ab" for
binary mode, or "rt", "wt", "xt" or "at" for text mode. The default mode is
"rb".
For binary mode, this function is equivalent to the cls constructor:
cls(filename, mode). In this case, the encoding, errors and newline
arguments must not be provided.
For text mode, a cls object is created, and wrapped in an
io.TextIOWrapper instance with the specified encoding, error handling
behavior, and line ending(s).
"""
if "t" in mode:
if "b" in mode:
raise ValueError("Invalid mode: %r" % (mode,))
else:
if encoding is not None:
raise ValueError("Argument 'encoding' not supported in binary mode")
if errors is not None:
raise ValueError("Argument 'errors' not supported in binary mode")
if newline is not None:
raise ValueError("Argument 'newline' not supported in binary mode")
file_mode = mode.replace("t", "")
if isinstance(filename, (str, bytes, os.PathLike, int)):
binary_file = cls(filename, file_mode, **kwargs)
elif hasattr(filename, "read") or hasattr(filename, "write"):
binary_file = cls(None, file_mode, fileobj=filename, **kwargs)
else:
raise TypeError("filename must be a str or bytes object, or a file")
if "t" in mode:
return io.TextIOWrapper(
binary_file, encoding, errors, newline, write_through=True
)
else:
return binary_file
class CompressionError(OSError):
pass
class PipeFile(io.RawIOBase):
"""
Class that implements generically piping to/from a compression program
Derived classes should add the function get_compress() and get_decompress()
that return the required commands. Input will be piped into stdin and the
(de)compressed output should be written to stdout, e.g.:
class FooFile(PipeCompressionFile):
def get_decompress(self):
return ["fooc", "--decompress", "--stdout"]
def get_compress(self):
return ["fooc", "--compress", "--stdout"]
"""
READ = 0
WRITE = 1
def __init__(self, filename=None, mode="rb", *, stderr=None, fileobj=None):
if "t" in mode or "U" in mode:
raise ValueError("Invalid mode: {!r}".format(mode))
if not "b" in mode:
mode += "b"
if mode.startswith("r"):
self.mode = self.READ
elif mode.startswith("w"):
self.mode = self.WRITE
else:
raise ValueError("Invalid mode %r" % mode)
if fileobj is not None:
self.fileobj = fileobj
else:
self.fileobj = builtins.open(filename, mode or "rb")
if self.mode == self.READ:
self.p = subprocess.Popen(
self.get_decompress(),
stdin=self.fileobj,
stdout=subprocess.PIPE,
stderr=stderr,
close_fds=True,
)
self.pipe = self.p.stdout
else:
self.p = subprocess.Popen(
self.get_compress(),
stdin=subprocess.PIPE,
stdout=self.fileobj,
stderr=stderr,
close_fds=True,
)
self.pipe = self.p.stdin
self.__closed = False
def _check_process(self):
if self.p is None:
return
returncode = self.p.wait()
if returncode:
raise CompressionError("Process died with %d" % returncode)
self.p = None
def close(self):
if self.closed:
return
self.pipe.close()
if self.p is not None:
self._check_process()
self.fileobj.close()
self.__closed = True
@property
def closed(self):
return self.__closed
def fileno(self):
return self.pipe.fileno()
def flush(self):
self.pipe.flush()
def isatty(self):
return self.pipe.isatty()
def readable(self):
return self.mode == self.READ
def writable(self):
return self.mode == self.WRITE
def readinto(self, b):
if self.mode != self.READ:
import errno
raise OSError(
errno.EBADF, "read() on write-only %s object" % self.__class__.__name__
)
size = self.pipe.readinto(b)
if size == 0:
self._check_process()
return size
def write(self, data):
if self.mode != self.WRITE:
import errno
raise OSError(
errno.EBADF, "write() on read-only %s object" % self.__class__.__name__
)
data = self.pipe.write(data)
if not data:
self._check_process()
return data

View File

@@ -0,0 +1,19 @@
#
# Copyright BitBake Contributors
#
# SPDX-License-Identifier: GPL-2.0-only
#
import bb.compress._pipecompress
def open(*args, **kwargs):
return bb.compress._pipecompress.open_wrap(LZ4File, *args, **kwargs)
class LZ4File(bb.compress._pipecompress.PipeFile):
def get_compress(self):
return ["lz4", "-z", "-c"]
def get_decompress(self):
return ["lz4", "-d", "-c"]

View File

@@ -0,0 +1,30 @@
#
# Copyright BitBake Contributors
#
# SPDX-License-Identifier: GPL-2.0-only
#
import bb.compress._pipecompress
import shutil
def open(*args, **kwargs):
return bb.compress._pipecompress.open_wrap(ZstdFile, *args, **kwargs)
class ZstdFile(bb.compress._pipecompress.PipeFile):
def __init__(self, *args, num_threads=1, compresslevel=3, **kwargs):
self.num_threads = num_threads
self.compresslevel = compresslevel
super().__init__(*args, **kwargs)
def _get_zstd(self):
if self.num_threads == 1 or not shutil.which("pzstd"):
return ["zstd"]
return ["pzstd", "-p", "%d" % self.num_threads]
def get_compress(self):
return self._get_zstd() + ["-c", "-%d" % self.compresslevel]
def get_decompress(self):
return self._get_zstd() + ["-d", "-c"]

2381
bitbake/lib/bb/cooker.py Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,552 @@
#
# Copyright (C) 2003, 2004 Chris Larson
# Copyright (C) 2003, 2004 Phil Blundell
# Copyright (C) 2003 - 2005 Michael 'Mickey' Lauer
# Copyright (C) 2005 Holger Hans Peter Freyther
# Copyright (C) 2005 ROAD GmbH
# Copyright (C) 2006 Richard Purdie
#
# SPDX-License-Identifier: GPL-2.0-only
#
import logging
import os
import re
import sys
import hashlib
from functools import wraps
import bb
from bb import data
import bb.parse
logger = logging.getLogger("BitBake")
parselog = logging.getLogger("BitBake.Parsing")
class ConfigParameters(object):
def __init__(self, argv=None):
self.options, targets = self.parseCommandLine(argv or sys.argv)
self.environment = self.parseEnvironment()
self.options.pkgs_to_build = targets or []
for key, val in self.options.__dict__.items():
setattr(self, key, val)
def parseCommandLine(self, argv=sys.argv):
raise Exception("Caller must implement commandline option parsing")
def parseEnvironment(self):
return os.environ.copy()
def updateFromServer(self, server):
if not self.options.cmd:
defaulttask, error = server.runCommand(["getVariable", "BB_DEFAULT_TASK"])
if error:
raise Exception("Unable to get the value of BB_DEFAULT_TASK from the server: %s" % error)
self.options.cmd = defaulttask or "build"
_, error = server.runCommand(["setConfig", "cmd", self.options.cmd])
if error:
raise Exception("Unable to set configuration option 'cmd' on the server: %s" % error)
if not self.options.pkgs_to_build:
bbpkgs, error = server.runCommand(["getVariable", "BBTARGETS"])
if error:
raise Exception("Unable to get the value of BBTARGETS from the server: %s" % error)
if bbpkgs:
self.options.pkgs_to_build.extend(bbpkgs.split())
def updateToServer(self, server, environment):
options = {}
for o in ["halt", "force", "invalidate_stamp",
"dry_run", "dump_signatures",
"extra_assume_provided", "profile",
"prefile", "postfile", "server_timeout",
"nosetscene", "setsceneonly", "skipsetscene",
"runall", "runonly", "writeeventlog"]:
options[o] = getattr(self.options, o)
options['build_verbose_shell'] = self.options.verbose
options['build_verbose_stdout'] = self.options.verbose
options['default_loglevel'] = bb.msg.loggerDefaultLogLevel
options['debug_domains'] = bb.msg.loggerDefaultDomains
ret, error = server.runCommand(["updateConfig", options, environment, sys.argv])
if error:
raise Exception("Unable to update the server configuration with local parameters: %s" % error)
def parseActions(self):
# Parse any commandline into actions
action = {'action':None, 'msg':None}
if self.options.show_environment:
if 'world' in self.options.pkgs_to_build:
action['msg'] = "'world' is not a valid target for --environment."
elif 'universe' in self.options.pkgs_to_build:
action['msg'] = "'universe' is not a valid target for --environment."
elif len(self.options.pkgs_to_build) > 1:
action['msg'] = "Only one target can be used with the --environment option."
elif self.options.buildfile and len(self.options.pkgs_to_build) > 0:
action['msg'] = "No target should be used with the --environment and --buildfile options."
elif self.options.pkgs_to_build:
action['action'] = ["showEnvironmentTarget", self.options.pkgs_to_build]
else:
action['action'] = ["showEnvironment", self.options.buildfile]
elif self.options.buildfile is not None:
action['action'] = ["buildFile", self.options.buildfile, self.options.cmd]
elif self.options.revisions_changed:
action['action'] = ["compareRevisions"]
elif self.options.show_versions:
action['action'] = ["showVersions"]
elif self.options.parse_only:
action['action'] = ["parseFiles"]
elif self.options.dot_graph:
if self.options.pkgs_to_build:
action['action'] = ["generateDotGraph", self.options.pkgs_to_build, self.options.cmd]
else:
action['msg'] = "Please specify a package name for dependency graph generation."
else:
if self.options.pkgs_to_build:
action['action'] = ["buildTargets", self.options.pkgs_to_build, self.options.cmd]
else:
#action['msg'] = "Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information."
action = None
self.options.initialaction = action
return action
class CookerConfiguration(object):
"""
Manages build options and configurations for one run
"""
def __init__(self):
self.debug_domains = bb.msg.loggerDefaultDomains
self.default_loglevel = bb.msg.loggerDefaultLogLevel
self.extra_assume_provided = []
self.prefile = []
self.postfile = []
self.cmd = None
self.halt = True
self.force = False
self.profile = False
self.nosetscene = False
self.setsceneonly = False
self.skipsetscene = False
self.invalidate_stamp = False
self.dump_signatures = []
self.build_verbose_shell = False
self.build_verbose_stdout = False
self.dry_run = False
self.tracking = False
self.writeeventlog = False
self.limited_deps = False
self.runall = []
self.runonly = []
self.env = {}
def __getstate__(self):
state = {}
for key in self.__dict__.keys():
state[key] = getattr(self, key)
return state
def __setstate__(self,state):
for k in state:
setattr(self, k, state[k])
def catch_parse_error(func):
"""Exception handling bits for our parsing"""
@wraps(func)
def wrapped(fn, *args):
try:
return func(fn, *args)
except Exception as exc:
import traceback
bbdir = os.path.dirname(__file__) + os.sep
exc_class, exc, tb = sys.exc_info()
for tb in iter(lambda: tb.tb_next, None):
# Skip frames in bitbake itself, we only want the metadata
fn, _, _, _ = traceback.extract_tb(tb, 1)[0]
if not fn.startswith(bbdir):
break
parselog.critical("Unable to parse %s" % fn, exc_info=(exc_class, exc, tb))
raise bb.BBHandledException()
return wrapped
@catch_parse_error
def parse_config_file(fn, data, include=True):
return bb.parse.handle(fn, data, include, baseconfig=True)
@catch_parse_error
def _inherit(bbclass, data):
bb.parse.BBHandler.inherit(bbclass, "configuration INHERITs", 0, data)
return data
def findConfigFile(configfile, data):
search = []
bbpath = data.getVar("BBPATH")
if bbpath:
for i in bbpath.split(":"):
search.append(os.path.join(i, "conf", configfile))
path = os.getcwd()
while path != "/":
search.append(os.path.join(path, "conf", configfile))
path, _ = os.path.split(path)
for i in search:
if os.path.exists(i):
return i
return None
#
# We search for a conf/bblayers.conf under an entry in BBPATH or in cwd working
# up to /. If that fails, bitbake would fall back to cwd.
#
def findTopdir():
d = bb.data.init()
bbpath = None
if 'BBPATH' in os.environ:
bbpath = os.environ['BBPATH']
d.setVar('BBPATH', bbpath)
layerconf = findConfigFile("bblayers.conf", d)
if layerconf:
return os.path.dirname(os.path.dirname(layerconf))
return os.path.abspath(os.getcwd())
class CookerDataBuilder(object):
def __init__(self, cookercfg, worker = False):
self.prefiles = cookercfg.prefile
self.postfiles = cookercfg.postfile
self.tracking = cookercfg.tracking
bb.utils.set_context(bb.utils.clean_context())
bb.event.set_class_handlers(bb.event.clean_class_handlers())
self.basedata = bb.data.init()
if self.tracking:
self.basedata.enableTracking()
# Keep a datastore of the initial environment variables and their
# values from when BitBake was launched to enable child processes
# to use environment variables which have been cleaned from the
# BitBake processes env
self.savedenv = bb.data.init()
for k in cookercfg.env:
self.savedenv.setVar(k, cookercfg.env[k])
if k in bb.data_smart.bitbake_renamed_vars:
bb.error('Shell environment variable %s has been renamed to %s' % (k, bb.data_smart.bitbake_renamed_vars[k]))
bb.fatal("Exiting to allow enviroment variables to be corrected")
filtered_keys = bb.utils.approved_variables()
bb.data.inheritFromOS(self.basedata, self.savedenv, filtered_keys)
self.basedata.setVar("BB_ORIGENV", self.savedenv)
self.basedata.setVar("__bbclasstype", "global")
if worker:
self.basedata.setVar("BB_WORKERCONTEXT", "1")
self.data = self.basedata
self.mcdata = {}
def calc_datastore_hashes(self):
data_hash = hashlib.sha256()
data_hash.update(self.data.get_hash().encode('utf-8'))
multiconfig = (self.data.getVar("BBMULTICONFIG") or "").split()
for config in multiconfig:
data_hash.update(self.mcdata[config].get_hash().encode('utf-8'))
self.data_hash = data_hash.hexdigest()
def parseBaseConfiguration(self, worker=False):
mcdata = {}
try:
self.data = self.parseConfigurationFiles(self.prefiles, self.postfiles)
servercontext = self.data.getVar("BB_WORKERCONTEXT", False) is None and not worker
bb.fetch.fetcher_init(self.data, servercontext)
bb.parse.init_parser(self.data)
bb.event.fire(bb.event.ConfigParsed(), self.data)
reparse_cnt = 0
while self.data.getVar("BB_INVALIDCONF", False) is True:
if reparse_cnt > 20:
logger.error("Configuration has been re-parsed over 20 times, "
"breaking out of the loop...")
raise Exception("Too deep config re-parse loop. Check locations where "
"BB_INVALIDCONF is being set (ConfigParsed event handlers)")
self.data.setVar("BB_INVALIDCONF", False)
self.data = self.parseConfigurationFiles(self.prefiles, self.postfiles)
reparse_cnt += 1
bb.event.fire(bb.event.ConfigParsed(), self.data)
bb.parse.init_parser(self.data)
mcdata[''] = self.data
multiconfig = (self.data.getVar("BBMULTICONFIG") or "").split()
for config in multiconfig:
if config[0].isdigit():
bb.fatal("Multiconfig name '%s' is invalid as multiconfigs cannot start with a digit" % config)
parsed_mcdata = self.parseConfigurationFiles(self.prefiles, self.postfiles, config)
bb.event.fire(bb.event.ConfigParsed(), parsed_mcdata)
mcdata[config] = parsed_mcdata
if multiconfig:
bb.event.fire(bb.event.MultiConfigParsed(mcdata), self.data)
except bb.data_smart.ExpansionError as e:
logger.error(str(e))
raise bb.BBHandledException()
bb.codeparser.update_module_dependencies(self.data)
# Handle obsolete variable names
d = self.data
renamedvars = d.getVarFlags('BB_RENAMED_VARIABLES') or {}
renamedvars.update(bb.data_smart.bitbake_renamed_vars)
issues = False
for v in renamedvars:
if d.getVar(v) != None or d.hasOverrides(v):
issues = True
loginfo = {}
history = d.varhistory.get_variable_refs(v)
for h in history:
for line in history[h]:
loginfo = {'file' : h, 'line' : line}
bb.data.data_smart._print_rename_error(v, loginfo, renamedvars)
if not history:
bb.data.data_smart._print_rename_error(v, loginfo, renamedvars)
if issues:
raise bb.BBHandledException()
for mc in mcdata:
mcdata[mc].renameVar("__depends", "__base_depends")
mcdata[mc].setVar("__bbclasstype", "recipe")
# Create a copy so we can reset at a later date when UIs disconnect
self.mcorigdata = mcdata
for mc in mcdata:
self.mcdata[mc] = bb.data.createCopy(mcdata[mc])
self.data = self.mcdata['']
self.calc_datastore_hashes()
def reset(self):
# We may not have run parseBaseConfiguration() yet
if not hasattr(self, 'mcorigdata'):
return
for mc in self.mcorigdata:
self.mcdata[mc] = bb.data.createCopy(self.mcorigdata[mc])
self.data = self.mcdata['']
def _findLayerConf(self, data):
return findConfigFile("bblayers.conf", data)
def parseConfigurationFiles(self, prefiles, postfiles, mc = ""):
data = bb.data.createCopy(self.basedata)
data.setVar("BB_CURRENT_MC", mc)
# Parse files for loading *before* bitbake.conf and any includes
for f in prefiles:
data = parse_config_file(f, data)
layerconf = self._findLayerConf(data)
if layerconf:
parselog.debug2("Found bblayers.conf (%s)", layerconf)
# By definition bblayers.conf is in conf/ of TOPDIR.
# We may have been called with cwd somewhere else so reset TOPDIR
data.setVar("TOPDIR", os.path.dirname(os.path.dirname(layerconf)))
data = parse_config_file(layerconf, data)
if not data.getVar("BB_CACHEDIR"):
data.setVar("BB_CACHEDIR", "${TOPDIR}/cache")
bb.codeparser.parser_cache_init(data.getVar("BB_CACHEDIR"))
layers = (data.getVar('BBLAYERS') or "").split()
broken_layers = []
if not layers:
bb.fatal("The bblayers.conf file doesn't contain any BBLAYERS definition")
data = bb.data.createCopy(data)
approved = bb.utils.approved_variables()
# Check whether present layer directories exist
for layer in layers:
if not os.path.isdir(layer):
broken_layers.append(layer)
if broken_layers:
parselog.critical("The following layer directories do not exist:")
for layer in broken_layers:
parselog.critical(" %s", layer)
parselog.critical("Please check BBLAYERS in %s" % (layerconf))
raise bb.BBHandledException()
layerseries = None
compat_entries = {}
for layer in layers:
parselog.debug2("Adding layer %s", layer)
if 'HOME' in approved and '~' in layer:
layer = os.path.expanduser(layer)
if layer.endswith('/'):
layer = layer.rstrip('/')
data.setVar('LAYERDIR', layer)
data.setVar('LAYERDIR_RE', re.escape(layer))
data = parse_config_file(os.path.join(layer, "conf", "layer.conf"), data)
data.expandVarref('LAYERDIR')
data.expandVarref('LAYERDIR_RE')
# Sadly we can't have nice things.
# Some layers think they're going to be 'clever' and copy the values from
# another layer, e.g. using ${LAYERSERIES_COMPAT_core}. The whole point of
# this mechanism is to make it clear which releases a layer supports and
# show when a layer master branch is bitrotting and is unmaintained.
# We therefore avoid people doing this here.
collections = (data.getVar('BBFILE_COLLECTIONS') or "").split()
for c in collections:
compat_entry = data.getVar("LAYERSERIES_COMPAT_%s" % c)
if compat_entry:
compat_entries[c] = set(compat_entry.split())
data.delVar("LAYERSERIES_COMPAT_%s" % c)
if not layerseries:
layerseries = set((data.getVar("LAYERSERIES_CORENAMES") or "").split())
if layerseries:
data.delVar("LAYERSERIES_CORENAMES")
data.delVar('LAYERDIR_RE')
data.delVar('LAYERDIR')
for c in compat_entries:
data.setVar("LAYERSERIES_COMPAT_%s" % c, " ".join(sorted(compat_entries[c])))
bbfiles_dynamic = (data.getVar('BBFILES_DYNAMIC') or "").split()
collections = (data.getVar('BBFILE_COLLECTIONS') or "").split()
invalid = []
for entry in bbfiles_dynamic:
parts = entry.split(":", 1)
if len(parts) != 2:
invalid.append(entry)
continue
l, f = parts
invert = l[0] == "!"
if invert:
l = l[1:]
if (l in collections and not invert) or (l not in collections and invert):
data.appendVar("BBFILES", " " + f)
if invalid:
bb.fatal("BBFILES_DYNAMIC entries must be of the form {!}<collection name>:<filename pattern>, not:\n %s" % "\n ".join(invalid))
collections_tmp = collections[:]
for c in collections:
collections_tmp.remove(c)
if c in collections_tmp:
bb.fatal("Found duplicated BBFILE_COLLECTIONS '%s', check bblayers.conf or layer.conf to fix it." % c)
compat = set()
if c in compat_entries:
compat = compat_entries[c]
if compat and not layerseries:
bb.fatal("No core layer found to work with layer '%s'. Missing entry in bblayers.conf?" % c)
if compat and not (compat & layerseries):
bb.fatal("Layer %s is not compatible with the core layer which only supports these series: %s (layer is compatible with %s)"
% (c, " ".join(layerseries), " ".join(compat)))
elif not compat and not data.getVar("BB_WORKERCONTEXT"):
bb.warn("Layer %s should set LAYERSERIES_COMPAT_%s in its conf/layer.conf file to list the core layer names it is compatible with." % (c, c))
data.setVar("LAYERSERIES_CORENAMES", " ".join(sorted(layerseries)))
if not data.getVar("BBPATH"):
msg = "The BBPATH variable is not set"
if not layerconf:
msg += (" and bitbake did not find a conf/bblayers.conf file in"
" the expected location.\nMaybe you accidentally"
" invoked bitbake from the wrong directory?")
bb.fatal(msg)
if not data.getVar("TOPDIR"):
data.setVar("TOPDIR", os.path.abspath(os.getcwd()))
if not data.getVar("BB_CACHEDIR"):
data.setVar("BB_CACHEDIR", "${TOPDIR}/cache")
bb.codeparser.parser_cache_init(data.getVar("BB_CACHEDIR"))
data = parse_config_file(os.path.join("conf", "bitbake.conf"), data)
# Parse files for loading *after* bitbake.conf and any includes
for p in postfiles:
data = parse_config_file(p, data)
# Handle any INHERITs and inherit the base class
bbclasses = ["base"] + (data.getVar('INHERIT') or "").split()
for bbclass in bbclasses:
data = _inherit(bbclass, data)
# Normally we only register event handlers at the end of parsing .bb files
# We register any handlers we've found so far here...
for var in data.getVar('__BBHANDLERS', False) or []:
handlerfn = data.getVarFlag(var, "filename", False)
if not handlerfn:
parselog.critical("Undefined event handler function '%s'" % var)
raise bb.BBHandledException()
handlerln = int(data.getVarFlag(var, "lineno", False))
bb.event.register(var, data.getVar(var, False), (data.getVarFlag(var, "eventmask") or "").split(), handlerfn, handlerln, data)
data.setVar('BBINCLUDED',bb.parse.get_file_depends(data))
return data
@staticmethod
def _parse_recipe(bb_data, bbfile, appends, mc, layername):
bb_data.setVar("__BBMULTICONFIG", mc)
bb_data.setVar("FILE_LAYERNAME", layername)
bbfile_loc = os.path.abspath(os.path.dirname(bbfile))
bb.parse.cached_mtime_noerror(bbfile_loc)
if appends:
bb_data.setVar('__BBAPPEND', " ".join(appends))
return bb.parse.handle(bbfile, bb_data)
def parseRecipeVariants(self, bbfile, appends, virtonly=False, mc=None, layername=None):
"""
Load and parse one .bb build file
Return the data and whether parsing resulted in the file being skipped
"""
if virtonly:
(bbfile, virtual, mc) = bb.cache.virtualfn2realfn(bbfile)
bb_data = self.mcdata[mc].createCopy()
bb_data.setVar("__ONLYFINALISE", virtual or "default")
return self._parse_recipe(bb_data, bbfile, appends, mc, layername)
if mc is not None:
bb_data = self.mcdata[mc].createCopy()
return self._parse_recipe(bb_data, bbfile, appends, mc, layername)
bb_data = self.data.createCopy()
datastores = self._parse_recipe(bb_data, bbfile, appends, '', layername)
for mc in self.mcdata:
if not mc:
continue
bb_data = self.mcdata[mc].createCopy()
newstores = self._parse_recipe(bb_data, bbfile, appends, mc, layername)
for ns in newstores:
datastores["mc:%s:%s" % (mc, ns)] = newstores[ns]
return datastores
def parseRecipe(self, virtualfn, appends, layername):
"""
Return a complete set of data for fn.
To do this, we need to parse the file.
"""
logger.debug("Parsing %s (full)" % virtualfn)
(fn, virtual, mc) = bb.cache.virtualfn2realfn(virtualfn)
datastores = self.parseRecipeVariants(virtualfn, appends, virtonly=True, layername=layername)
return datastores[virtual]

Some files were not shown because too many files have changed in this diff Show More