<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://developerwiki.proventusnova.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Andres</id>
	<title>ProventusNova DeveloperWiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://developerwiki.proventusnova.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Andres"/>
	<link rel="alternate" type="text/html" href="https://developerwiki.proventusnova.com/Special:Contributions/Andres"/>
	<updated>2026-04-18T04:50:42Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.17</generator>
	<entry>
		<id>https://developerwiki.proventusnova.com/index.php?title=Linux_RAM_Layout_Visualizer_Script&amp;diff=558</id>
		<title>Linux RAM Layout Visualizer Script</title>
		<link rel="alternate" type="text/html" href="https://developerwiki.proventusnova.com/index.php?title=Linux_RAM_Layout_Visualizer_Script&amp;diff=558"/>
		<updated>2026-02-20T16:22:03Z</updated>

		<summary type="html">&lt;p&gt;Andres: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&#039;&#039;&#039;mempix&#039;&#039;&#039; is a lightweight bash utility designed to visualize physical memory allocation and real-time occupancy. It maps the data from &amp;lt;code&amp;gt;/proc/iomem&amp;lt;/code&amp;gt; and correlates it with global memory statistics from &amp;lt;code&amp;gt;/proc/meminfo&amp;lt;/code&amp;gt; to provide a per-block visual &amp;quot;pixel map.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
It is specifically optimized for both &#039;&#039;&#039;embedded Yocto environments&#039;&#039;&#039; (like the MediaTek Genio 720) and &#039;&#039;&#039;standard Desktop Linux&#039;&#039;&#039; (Ubuntu/Debian).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
* &#039;&#039;&#039;Visual Occupancy:&#039;&#039;&#039; A 12-character progress bar showing used vs. free space within each RAM block.&lt;br /&gt;
* &#039;&#039;&#039;Threshold Marker:&#039;&#039;&#039; A red marker (&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;|&amp;lt;/span&amp;gt;) indicating the exact transition point between used and free memory.&lt;br /&gt;
* &#039;&#039;&#039;Unit Intelligence:&#039;&#039;&#039; Automatically scales between KB, MB, and GB based on block size.&lt;br /&gt;
* &#039;&#039;&#039;Hardware Mapping:&#039;&#039;&#039; Identifies non-RAM regions (PCIe, GPU, Reserved) that are &amp;quot;locked&amp;quot; by hardware.&lt;br /&gt;
* &#039;&#039;&#039;Universal Compatibility:&#039;&#039;&#039; Uses POSIX-compliant math and standard escape codes for serial consoles.&lt;br /&gt;
&lt;br /&gt;
== Map Legend ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Symbol !! Color !! Meaning&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;###&amp;lt;/code&amp;gt; || &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;Green&amp;lt;/span&amp;gt; || &#039;&#039;&#039;Used System RAM&#039;&#039;&#039;: Memory currently occupied by the kernel or processes.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;---&amp;lt;/code&amp;gt; || &amp;lt;span style=&amp;quot;color:darkcyan&amp;quot;&amp;gt;Cyan&amp;lt;/span&amp;gt; || &#039;&#039;&#039;Free System RAM&#039;&#039;&#039;: Available memory within that physical address range.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;amp;#124;&amp;lt;/code&amp;gt; || &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;Red&amp;lt;/span&amp;gt; || &#039;&#039;&#039;Occupancy Marker&#039;&#039;&#039;: The specific boundary of current memory pressure.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;...&amp;lt;/code&amp;gt; || &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;Red&amp;lt;/span&amp;gt; || &#039;&#039;&#039;Reserved/IO&#039;&#039;&#039;: Non-system RAM (MMIO, GPU, Reserved by Firmware).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
=== Standard Run ===&lt;br /&gt;
On Yocto (root), run directly. On Ubuntu, use sudo:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo ./mempix.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Real-time Monitoring ===&lt;br /&gt;
To watch memory blocks change live as processes open/close:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
watch -c sudo ./mempix.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Source Code ==&lt;br /&gt;
Save the following code as &amp;lt;code&amp;gt;mempix.sh&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot; line&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
IOMEM=&amp;quot;/proc/iomem&amp;quot;&lt;br /&gt;
MEMINFO=&amp;quot;/proc/meminfo&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# --- PERMISSION CHECK ---&lt;br /&gt;
# Try to actually read one line. If empty, the kernel is masking the data.&lt;br /&gt;
CHECK_READ=$(head -n 1 &amp;quot;$IOMEM&amp;quot; 2&amp;gt;/dev/null)&lt;br /&gt;
if [ -z &amp;quot;$CHECK_READ&amp;quot; ]; then&lt;br /&gt;
    echo -e &amp;quot;\033[31mError: Cannot read physical addresses from $IOMEM.\033[0m&amp;quot;&lt;br /&gt;
    echo &amp;quot;If on Ubuntu, you must run this script with sudo.&amp;quot;&lt;br /&gt;
    exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
# 1. Get Global Stats&lt;br /&gt;
T_MEM_KB=$(grep MemTotal &amp;quot;$MEMINFO&amp;quot; | awk &#039;{print $2}&#039;)&lt;br /&gt;
F_MEM_KB=$(grep MemFree &amp;quot;$MEMINFO&amp;quot; | awk &#039;{print $2}&#039;)&lt;br /&gt;
OCC_RATIO=$(awk &amp;quot;BEGIN {print 1 - ($F_MEM_KB/$T_MEM_KB)}&amp;quot;)&lt;br /&gt;
FREE_RATIO=$(awk &amp;quot;BEGIN {print $F_MEM_KB/$T_MEM_KB}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
format_matched() {&lt;br /&gt;
    local val_mb=&amp;quot;$1&amp;quot;&lt;br /&gt;
    local target_unit=&amp;quot;$2&amp;quot;&lt;br /&gt;
    local is_small=$(awk &amp;quot;BEGIN {if ($val_mb &amp;lt; 0.1) print 1; else print 0}&amp;quot;)&lt;br /&gt;
    if [ &amp;quot;$is_small&amp;quot; -eq 1 ]; then&lt;br /&gt;
        awk &amp;quot;BEGIN {printf \&amp;quot;%.1f KB\&amp;quot;, $val_mb * 1024}&amp;quot;&lt;br /&gt;
    elif [ &amp;quot;$target_unit&amp;quot; == &amp;quot;GB&amp;quot; ]; then&lt;br /&gt;
        awk &amp;quot;BEGIN {printf \&amp;quot;%.2f GB\&amp;quot;, $val_mb / 1024}&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
        awk &amp;quot;BEGIN {printf \&amp;quot;%.1f MB\&amp;quot;, $val_mb}&amp;quot;&lt;br /&gt;
    fi&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# --- LEGEND ---&lt;br /&gt;
echo -e &amp;quot;\033[1mMAP LEGEND:\033[0m&amp;quot;&lt;br /&gt;
echo -e &amp;quot;\033[32m###\033[0m : Used System RAM   \033[1;31m|\033[0m : Occupancy Marker&amp;quot;&lt;br /&gt;
echo -e &amp;quot;\033[36m---\033[0m : Free System RAM   \033[31m...\033[0m : Reserved/Hardware/IO&amp;quot;&lt;br /&gt;
echo &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
echo -e &amp;quot;\033[1mPHYSICAL BLOCK ANALYSIS\033[0m&amp;quot;&lt;br /&gt;
printf &amp;quot;%-12s | %-12s | %-18s | %-12s | %s\n&amp;quot; &amp;quot;ADDRESS&amp;quot; &amp;quot;PIXEL MAP&amp;quot; &amp;quot;FREE (MATCHED)&amp;quot; &amp;quot;TOTAL SIZE&amp;quot; &amp;quot;LABEL&amp;quot;&lt;br /&gt;
echo &amp;quot;---------------------------------------------------------------------------------------------------&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Clean input and iterate&lt;br /&gt;
grep -E &amp;quot;System RAM|Kernel|reserved|pcie|gpu&amp;quot; &amp;quot;$IOMEM&amp;quot; | sed &#039;s/^[ ]*//&#039; | while read -r line; do&lt;br /&gt;
    ADDR=$(echo &amp;quot;$line&amp;quot; | cut -d&#039; &#039; -f1)&lt;br /&gt;
    LABEL=$(echo &amp;quot;$line&amp;quot; | cut -d&#039;:&#039; -f2- | xargs)&lt;br /&gt;
    S_HEX=$(echo &amp;quot;$ADDR&amp;quot; | cut -d&#039;-&#039; -f1)&lt;br /&gt;
    E_HEX=$(echo &amp;quot;$ADDR&amp;quot; | cut -d&#039;-&#039; -f2)&lt;br /&gt;
&lt;br /&gt;
    # Validate Hex&lt;br /&gt;
    if [[ ! $S_HEX =~ ^[0-9a-fA-F]+$ ]]; then continue; fi&lt;br /&gt;
&lt;br /&gt;
    S_DEC=$(printf &amp;quot;%d&amp;quot; &amp;quot;0x$S_HEX&amp;quot; 2&amp;gt;/dev/null)&lt;br /&gt;
    E_DEC=$(printf &amp;quot;%d&amp;quot; &amp;quot;0x$E_HEX&amp;quot; 2&amp;gt;/dev/null)&lt;br /&gt;
    SIZE_MB=$(awk &amp;quot;BEGIN {print ($E_DEC - $S_DEC + 1) / 1048576}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    UNIT=&amp;quot;MB&amp;quot;; [ $(awk &amp;quot;BEGIN {if ($SIZE_MB &amp;gt;= 1024) print 1; else print 0}&amp;quot;) -eq 1 ] &amp;amp;&amp;amp; UNIT=&amp;quot;GB&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    if [[ &amp;quot;$LABEL&amp;quot; == &amp;quot;System RAM&amp;quot; ]]; then&lt;br /&gt;
        FREE_MB=$(awk &amp;quot;BEGIN {print $SIZE_MB * $FREE_RATIO}&amp;quot;)&lt;br /&gt;
        P_FREE=$(awk &amp;quot;BEGIN {printf \&amp;quot;%.1f%%\&amp;quot;, $FREE_RATIO * 100}&amp;quot;)&lt;br /&gt;
        U_CH=$(awk &amp;quot;BEGIN {val = 12 * $OCC_RATIO; printf \&amp;quot;%.0f\&amp;quot;, (val&amp;lt;1 &amp;amp;&amp;amp; val&amp;gt;0)?1:val}&amp;quot;)&lt;br /&gt;
        [ &amp;quot;$U_CH&amp;quot; -gt 12 ] &amp;amp;&amp;amp; U_CH=12&lt;br /&gt;
        F_CH=$((12 - U_CH))&lt;br /&gt;
&lt;br /&gt;
        if [ &amp;quot;$U_CH&amp;quot; -gt 0 ]; then&lt;br /&gt;
            BAR_USED=$(printf &amp;quot;%$((U_CH-1))s&amp;quot; | tr &#039; &#039; &#039;#&#039;)&lt;br /&gt;
            MARKER=&amp;quot;\033[1;31m|\033[0m&amp;quot;&lt;br /&gt;
            BAR_FREE=$(printf &amp;quot;%${F_CH}s&amp;quot; | tr &#039; &#039; &#039;-&#039;)&lt;br /&gt;
            PIX=&amp;quot;\033[32m${BAR_USED}${MARKER}\033[36m${BAR_FREE}\033[0m&amp;quot;&lt;br /&gt;
        else&lt;br /&gt;
            PIX=&amp;quot;\033[36m------------\033[0m&amp;quot;&lt;br /&gt;
        fi&lt;br /&gt;
        STR_FREE=$(format_matched &amp;quot;$FREE_MB&amp;quot; &amp;quot;$UNIT&amp;quot;)&lt;br /&gt;
        STR_TOTAL=$(format_matched &amp;quot;$SIZE_MB&amp;quot; &amp;quot;$UNIT&amp;quot;)&lt;br /&gt;
    else&lt;br /&gt;
        PIX=&amp;quot;\033[31m............\033[0m&amp;quot;&lt;br /&gt;
        P_FREE=&amp;quot;0.0%&amp;quot;&lt;br /&gt;
        STR_FREE=$(format_matched 0 &amp;quot;$UNIT&amp;quot;)&lt;br /&gt;
        STR_TOTAL=$(format_matched &amp;quot;$SIZE_MB&amp;quot; &amp;quot;$UNIT&amp;quot;)&lt;br /&gt;
    fi&lt;br /&gt;
&lt;br /&gt;
    printf &amp;quot;0x%08s | %b | %-18s | %-12s | %s\n&amp;quot; &amp;quot;$S_HEX&amp;quot; &amp;quot;$PIX&amp;quot; &amp;quot;$P_FREE ($STR_FREE)&amp;quot; &amp;quot;$STR_TOTAL&amp;quot; &amp;quot;$LABEL&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
=== Error: Cannot read physical addresses ===&lt;br /&gt;
If you see this error, it means the Kernel is masking &amp;lt;code&amp;gt;/proc/iomem&amp;lt;/code&amp;gt; for security. &lt;br /&gt;
* &#039;&#039;&#039;Desktop:&#039;&#039;&#039; Ensure you are using &amp;lt;code&amp;gt;sudo&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &#039;&#039;&#039;Embedded:&#039;&#039;&#039; Ensure you are logged in as a user with root privileges.&lt;br /&gt;
&lt;br /&gt;
{{Footer}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Tools]]&lt;br /&gt;
[[Category:Linux Kernel]]&lt;br /&gt;
[[Category:Debugging]]&lt;/div&gt;</summary>
		<author><name>Andres</name></author>
	</entry>
	<entry>
		<id>https://developerwiki.proventusnova.com/index.php?title=Linux_RAM_Layout_Visualizer_Script&amp;diff=557</id>
		<title>Linux RAM Layout Visualizer Script</title>
		<link rel="alternate" type="text/html" href="https://developerwiki.proventusnova.com/index.php?title=Linux_RAM_Layout_Visualizer_Script&amp;diff=557"/>
		<updated>2026-02-20T16:21:22Z</updated>

		<summary type="html">&lt;p&gt;Andres: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&#039;&#039;&#039;mempix&#039;&#039;&#039; is a lightweight bash utility designed to visualize physical memory allocation and real-time occupancy. It maps the data from &amp;lt;code&amp;gt;/proc/iomem&amp;lt;/code&amp;gt; and correlates it with global memory statistics from &amp;lt;code&amp;gt;/proc/meminfo&amp;lt;/code&amp;gt; to provide a per-block visual &amp;quot;pixel map.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
It is specifically optimized for both &#039;&#039;&#039;embedded Yocto environments&#039;&#039;&#039; (like the MediaTek Genio 720) and &#039;&#039;&#039;standard Desktop Linux&#039;&#039;&#039; (Ubuntu/Debian).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
* &#039;&#039;&#039;Visual Occupancy:&#039;&#039;&#039; A 12-character progress bar showing used vs. free space within each RAM block.&lt;br /&gt;
* &#039;&#039;&#039;Threshold Marker:&#039;&#039;&#039; A red marker (&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;|&amp;lt;/span&amp;gt;) indicating the exact transition point between used and free memory.&lt;br /&gt;
* &#039;&#039;&#039;Unit Intelligence:&#039;&#039;&#039; Automatically scales between KB, MB, and GB based on block size.&lt;br /&gt;
* &#039;&#039;&#039;Hardware Mapping:&#039;&#039;&#039; Identifies non-RAM regions (PCIe, GPU, Reserved) that are &amp;quot;locked&amp;quot; by hardware.&lt;br /&gt;
* &#039;&#039;&#039;Universal Compatibility:&#039;&#039;&#039; Uses POSIX-compliant math and standard escape codes for serial consoles.&lt;br /&gt;
&lt;br /&gt;
== Map Legend ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Symbol !! Color !! Meaning&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;###&amp;lt;/code&amp;gt; || &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;Green&amp;lt;/span&amp;gt; || &#039;&#039;&#039;Used System RAM&#039;&#039;&#039;: Memory currently occupied by the kernel or processes.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;---&amp;lt;/code&amp;gt; || &amp;lt;span style=&amp;quot;color:darkcyan&amp;quot;&amp;gt;Cyan&amp;lt;/span&amp;gt; || &#039;&#039;&#039;Free System RAM&#039;&#039;&#039;: Available memory within that physical address range.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;amp;#124;&amp;lt;/code&amp;gt; || &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;Red&amp;lt;/span&amp;gt; || &#039;&#039;&#039;Occupancy Marker&#039;&#039;&#039;: The specific boundary of current memory pressure.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;...&amp;lt;/code&amp;gt; || &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;Red&amp;lt;/span&amp;gt; || &#039;&#039;&#039;Reserved/IO&#039;&#039;&#039;: Non-system RAM (MMIO, GPU, Reserved by Firmware).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
=== Standard Run ===&lt;br /&gt;
On Yocto (root), run directly. On Ubuntu, use sudo:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo ./mempix.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Real-time Monitoring ===&lt;br /&gt;
To watch memory blocks change live as processes open/close:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
watch -c sudo ./mempix.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Source Code ==&lt;br /&gt;
Save the following code as &amp;lt;code&amp;gt;mempix.sh&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot; line&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
IOMEM=&amp;quot;/proc/iomem&amp;quot;&lt;br /&gt;
MEMINFO=&amp;quot;/proc/meminfo&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# --- PERMISSION CHECK ---&lt;br /&gt;
# Try to actually read one line. If empty, the kernel is masking the data.&lt;br /&gt;
CHECK_READ=$(head -n 1 &amp;quot;$IOMEM&amp;quot; 2&amp;gt;/dev/null)&lt;br /&gt;
if [ -z &amp;quot;$CHECK_READ&amp;quot; ]; then&lt;br /&gt;
    echo -e &amp;quot;\033[31mError: Cannot read physical addresses from $IOMEM.\033[0m&amp;quot;&lt;br /&gt;
    echo &amp;quot;If on Ubuntu, you must run this script with sudo.&amp;quot;&lt;br /&gt;
    exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
# 1. Get Global Stats&lt;br /&gt;
T_MEM_KB=$(grep MemTotal &amp;quot;$MEMINFO&amp;quot; | awk &#039;{print $2}&#039;)&lt;br /&gt;
F_MEM_KB=$(grep MemFree &amp;quot;$MEMINFO&amp;quot; | awk &#039;{print $2}&#039;)&lt;br /&gt;
OCC_RATIO=$(awk &amp;quot;BEGIN {print 1 - ($F_MEM_KB/$T_MEM_KB)}&amp;quot;)&lt;br /&gt;
FREE_RATIO=$(awk &amp;quot;BEGIN {print $F_MEM_KB/$T_MEM_KB}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
format_matched() {&lt;br /&gt;
    local val_mb=&amp;quot;$1&amp;quot;&lt;br /&gt;
    local target_unit=&amp;quot;$2&amp;quot;&lt;br /&gt;
    local is_small=$(awk &amp;quot;BEGIN {if ($val_mb &amp;lt; 0.1) print 1; else print 0}&amp;quot;)&lt;br /&gt;
    if [ &amp;quot;$is_small&amp;quot; -eq 1 ]; then&lt;br /&gt;
        awk &amp;quot;BEGIN {printf \&amp;quot;%.1f KB\&amp;quot;, $val_mb * 1024}&amp;quot;&lt;br /&gt;
    elif [ &amp;quot;$target_unit&amp;quot; == &amp;quot;GB&amp;quot; ]; then&lt;br /&gt;
        awk &amp;quot;BEGIN {printf \&amp;quot;%.2f GB\&amp;quot;, $val_mb / 1024}&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
        awk &amp;quot;BEGIN {printf \&amp;quot;%.1f MB\&amp;quot;, $val_mb}&amp;quot;&lt;br /&gt;
    fi&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# --- LEGEND ---&lt;br /&gt;
echo -e &amp;quot;\033[1mMAP LEGEND:\033[0m&amp;quot;&lt;br /&gt;
echo -e &amp;quot;\033[32m###\033[0m : Used System RAM   \033[1;31m|\033[0m : Occupancy Marker&amp;quot;&lt;br /&gt;
echo -e &amp;quot;\033[36m---\033[0m : Free System RAM   \033[31m...\033[0m : Reserved/Hardware/IO&amp;quot;&lt;br /&gt;
echo &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
echo -e &amp;quot;\033[1mPHYSICAL BLOCK ANALYSIS\033[0m&amp;quot;&lt;br /&gt;
printf &amp;quot;%-12s | %-12s | %-18s | %-12s | %s\n&amp;quot; &amp;quot;ADDRESS&amp;quot; &amp;quot;PIXEL MAP&amp;quot; &amp;quot;FREE (MATCHED)&amp;quot; &amp;quot;TOTAL SIZE&amp;quot; &amp;quot;LABEL&amp;quot;&lt;br /&gt;
echo &amp;quot;---------------------------------------------------------------------------------------------------&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Clean input and iterate&lt;br /&gt;
grep -E &amp;quot;System RAM|Kernel|reserved|pcie|gpu&amp;quot; &amp;quot;$IOMEM&amp;quot; | sed &#039;s/^[ ]*//&#039; | while read -r line; do&lt;br /&gt;
    ADDR=$(echo &amp;quot;$line&amp;quot; | cut -d&#039; &#039; -f1)&lt;br /&gt;
    LABEL=$(echo &amp;quot;$line&amp;quot; | cut -d&#039;:&#039; -f2- | xargs)&lt;br /&gt;
    S_HEX=$(echo &amp;quot;$ADDR&amp;quot; | cut -d&#039;-&#039; -f1)&lt;br /&gt;
    E_HEX=$(echo &amp;quot;$ADDR&amp;quot; | cut -d&#039;-&#039; -f2)&lt;br /&gt;
&lt;br /&gt;
    # Validate Hex&lt;br /&gt;
    if [[ ! $S_HEX =~ ^[0-9a-fA-F]+$ ]]; then continue; fi&lt;br /&gt;
&lt;br /&gt;
    S_DEC=$(printf &amp;quot;%d&amp;quot; &amp;quot;0x$S_HEX&amp;quot; 2&amp;gt;/dev/null)&lt;br /&gt;
    E_DEC=$(printf &amp;quot;%d&amp;quot; &amp;quot;0x$E_HEX&amp;quot; 2&amp;gt;/dev/null)&lt;br /&gt;
    SIZE_MB=$(awk &amp;quot;BEGIN {print ($E_DEC - $S_DEC + 1) / 1048576}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    UNIT=&amp;quot;MB&amp;quot;; [ $(awk &amp;quot;BEGIN {if ($SIZE_MB &amp;gt;= 1024) print 1; else print 0}&amp;quot;) -eq 1 ] &amp;amp;&amp;amp; UNIT=&amp;quot;GB&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    if [[ &amp;quot;$LABEL&amp;quot; == &amp;quot;System RAM&amp;quot; ]]; then&lt;br /&gt;
        FREE_MB=$(awk &amp;quot;BEGIN {print $SIZE_MB * $FREE_RATIO}&amp;quot;)&lt;br /&gt;
        P_FREE=$(awk &amp;quot;BEGIN {printf \&amp;quot;%.1f%%\&amp;quot;, $FREE_RATIO * 100}&amp;quot;)&lt;br /&gt;
        U_CH=$(awk &amp;quot;BEGIN {val = 12 * $OCC_RATIO; printf \&amp;quot;%.0f\&amp;quot;, (val&amp;lt;1 &amp;amp;&amp;amp; val&amp;gt;0)?1:val}&amp;quot;)&lt;br /&gt;
        [ &amp;quot;$U_CH&amp;quot; -gt 12 ] &amp;amp;&amp;amp; U_CH=12&lt;br /&gt;
        F_CH=$((12 - U_CH))&lt;br /&gt;
&lt;br /&gt;
        if [ &amp;quot;$U_CH&amp;quot; -gt 0 ]; then&lt;br /&gt;
            BAR_USED=$(printf &amp;quot;%$((U_CH-1))s&amp;quot; | tr &#039; &#039; &#039;#&#039;)&lt;br /&gt;
            MARKER=&amp;quot;\033[1;31m|\033[0m&amp;quot;&lt;br /&gt;
            BAR_FREE=$(printf &amp;quot;%${F_CH}s&amp;quot; | tr &#039; &#039; &#039;-&#039;)&lt;br /&gt;
            PIX=&amp;quot;\033[32m${BAR_USED}${MARKER}\033[36m${BAR_FREE}\033[0m&amp;quot;&lt;br /&gt;
        else&lt;br /&gt;
            PIX=&amp;quot;\033[36m------------\033[0m&amp;quot;&lt;br /&gt;
        fi&lt;br /&gt;
        STR_FREE=$(format_matched &amp;quot;$FREE_MB&amp;quot; &amp;quot;$UNIT&amp;quot;)&lt;br /&gt;
        STR_TOTAL=$(format_matched &amp;quot;$SIZE_MB&amp;quot; &amp;quot;$UNIT&amp;quot;)&lt;br /&gt;
    else&lt;br /&gt;
        PIX=&amp;quot;\033[31m............\033[0m&amp;quot;&lt;br /&gt;
        P_FREE=&amp;quot;0.0%&amp;quot;&lt;br /&gt;
        STR_FREE=$(format_matched 0 &amp;quot;$UNIT&amp;quot;)&lt;br /&gt;
        STR_TOTAL=$(format_matched &amp;quot;$SIZE_MB&amp;quot; &amp;quot;$UNIT&amp;quot;)&lt;br /&gt;
    fi&lt;br /&gt;
&lt;br /&gt;
    printf &amp;quot;0x%08s | %b | %-18s | %-12s | %s\n&amp;quot; &amp;quot;$S_HEX&amp;quot; &amp;quot;$PIX&amp;quot; &amp;quot;$P_FREE ($STR_FREE)&amp;quot; &amp;quot;$STR_TOTAL&amp;quot; &amp;quot;$LABEL&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
=== Error: Cannot read physical addresses ===&lt;br /&gt;
If you see this error, it means the Kernel is masking &amp;lt;code&amp;gt;/proc/iomem&amp;lt;/code&amp;gt; for security. &lt;br /&gt;
* &#039;&#039;&#039;Desktop:&#039;&#039;&#039; Ensure you are using &amp;lt;code&amp;gt;sudo&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &#039;&#039;&#039;Embedded:&#039;&#039;&#039; Ensure you are logged in as a user with root privileges.&lt;br /&gt;
&lt;br /&gt;
[[Category:Tools]]&lt;br /&gt;
[[Category:Linux Kernel]]&lt;br /&gt;
[[Category:Debugging]]&lt;/div&gt;</summary>
		<author><name>Andres</name></author>
	</entry>
	<entry>
		<id>https://developerwiki.proventusnova.com/index.php?title=Linux_RAM_Layout_Visualizer_Script&amp;diff=556</id>
		<title>Linux RAM Layout Visualizer Script</title>
		<link rel="alternate" type="text/html" href="https://developerwiki.proventusnova.com/index.php?title=Linux_RAM_Layout_Visualizer_Script&amp;diff=556"/>
		<updated>2026-02-20T16:17:47Z</updated>

		<summary type="html">&lt;p&gt;Andres: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&#039;&#039;&#039;mempix&#039;&#039;&#039; is a lightweight bash utility designed to visualize physical memory allocation and real-time occupancy. It maps the data from &amp;lt;code&amp;gt;/proc/iomem&amp;lt;/code&amp;gt; and correlates it with global memory statistics from &amp;lt;code&amp;gt;/proc/meminfo&amp;lt;/code&amp;gt; to provide a per-block visual &amp;quot;pixel map.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
It is specifically optimized for both &#039;&#039;&#039;embedded Yocto environments&#039;&#039;&#039; (like the MediaTek Genio 720) and &#039;&#039;&#039;standard Desktop Linux&#039;&#039;&#039; (Ubuntu/Debian).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
* &#039;&#039;&#039;Visual Occupancy:&#039;&#039;&#039; A 12-character progress bar showing used vs. free space within each RAM block.&lt;br /&gt;
* &#039;&#039;&#039;Threshold Marker:&#039;&#039;&#039; A red marker (&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;|&amp;lt;/span&amp;gt;) indicating the exact transition point between used and free memory.&lt;br /&gt;
* &#039;&#039;&#039;Unit Intelligence:&#039;&#039;&#039; Automatically scales between KB, MB, and GB based on block size.&lt;br /&gt;
* &#039;&#039;&#039;Hardware Mapping:&#039;&#039;&#039; Identifies non-RAM regions (PCIe, GPU, Reserved) that are &amp;quot;locked&amp;quot; by hardware.&lt;br /&gt;
* &#039;&#039;&#039;Universal Compatibility:&#039;&#039;&#039; Uses POSIX-compliant math and standard escape codes for serial consoles.&lt;br /&gt;
&lt;br /&gt;
== Map Legend ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Symbol !! Color !! Meaning&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;###&amp;lt;/code&amp;gt; || &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;Green&amp;lt;/span&amp;gt; || &#039;&#039;&#039;Used System RAM&#039;&#039;&#039;: Memory currently occupied by the kernel or processes.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;---&amp;lt;/code&amp;gt; || &amp;lt;span style=&amp;quot;color:darkcyan&amp;quot;&amp;gt;Cyan&amp;lt;/span&amp;gt; || &#039;&#039;&#039;Free System RAM&#039;&#039;&#039;: Available memory within that physical address range.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;|&amp;lt;/code&amp;gt; || &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;Red&amp;lt;/span&amp;gt; || &#039;&#039;&#039;Occupancy Marker&#039;&#039;&#039;: The specific boundary of current memory pressure.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;...&amp;lt;/code&amp;gt; || &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;Red&amp;lt;/span&amp;gt; || &#039;&#039;&#039;Reserved/IO&#039;&#039;&#039;: Non-system RAM (MMIO, GPU, Reserved by Firmware).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
=== Standard Run ===&lt;br /&gt;
On Yocto (root), run directly. On Ubuntu, use sudo:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo ./mempix.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Real-time Monitoring ===&lt;br /&gt;
To watch memory blocks change live as processes open/close:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
watch -c sudo ./mempix.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Source Code ==&lt;br /&gt;
Save the following code as &amp;lt;code&amp;gt;mempix.sh&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot; line&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
IOMEM=&amp;quot;/proc/iomem&amp;quot;&lt;br /&gt;
MEMINFO=&amp;quot;/proc/meminfo&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# --- PERMISSION CHECK ---&lt;br /&gt;
# Try to actually read one line. If empty, the kernel is masking the data.&lt;br /&gt;
CHECK_READ=$(head -n 1 &amp;quot;$IOMEM&amp;quot; 2&amp;gt;/dev/null)&lt;br /&gt;
if [ -z &amp;quot;$CHECK_READ&amp;quot; ]; then&lt;br /&gt;
    echo -e &amp;quot;\033[31mError: Cannot read physical addresses from $IOMEM.\033[0m&amp;quot;&lt;br /&gt;
    echo &amp;quot;If on Ubuntu, you must run this script with sudo.&amp;quot;&lt;br /&gt;
    exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
# 1. Get Global Stats&lt;br /&gt;
T_MEM_KB=$(grep MemTotal &amp;quot;$MEMINFO&amp;quot; | awk &#039;{print $2}&#039;)&lt;br /&gt;
F_MEM_KB=$(grep MemFree &amp;quot;$MEMINFO&amp;quot; | awk &#039;{print $2}&#039;)&lt;br /&gt;
OCC_RATIO=$(awk &amp;quot;BEGIN {print 1 - ($F_MEM_KB/$T_MEM_KB)}&amp;quot;)&lt;br /&gt;
FREE_RATIO=$(awk &amp;quot;BEGIN {print $F_MEM_KB/$T_MEM_KB}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
format_matched() {&lt;br /&gt;
    local val_mb=&amp;quot;$1&amp;quot;&lt;br /&gt;
    local target_unit=&amp;quot;$2&amp;quot;&lt;br /&gt;
    local is_small=$(awk &amp;quot;BEGIN {if ($val_mb &amp;lt; 0.1) print 1; else print 0}&amp;quot;)&lt;br /&gt;
    if [ &amp;quot;$is_small&amp;quot; -eq 1 ]; then&lt;br /&gt;
        awk &amp;quot;BEGIN {printf \&amp;quot;%.1f KB\&amp;quot;, $val_mb * 1024}&amp;quot;&lt;br /&gt;
    elif [ &amp;quot;$target_unit&amp;quot; == &amp;quot;GB&amp;quot; ]; then&lt;br /&gt;
        awk &amp;quot;BEGIN {printf \&amp;quot;%.2f GB\&amp;quot;, $val_mb / 1024}&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
        awk &amp;quot;BEGIN {printf \&amp;quot;%.1f MB\&amp;quot;, $val_mb}&amp;quot;&lt;br /&gt;
    fi&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# --- LEGEND ---&lt;br /&gt;
echo -e &amp;quot;\033[1mMAP LEGEND:\033[0m&amp;quot;&lt;br /&gt;
echo -e &amp;quot;\033[32m###\033[0m : Used System RAM   \033[1;31m|\033[0m : Occupancy Marker&amp;quot;&lt;br /&gt;
echo -e &amp;quot;\033[36m---\033[0m : Free System RAM   \033[31m...\033[0m : Reserved/Hardware/IO&amp;quot;&lt;br /&gt;
echo &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
echo -e &amp;quot;\033[1mPHYSICAL BLOCK ANALYSIS\033[0m&amp;quot;&lt;br /&gt;
printf &amp;quot;%-12s | %-12s | %-18s | %-12s | %s\n&amp;quot; &amp;quot;ADDRESS&amp;quot; &amp;quot;PIXEL MAP&amp;quot; &amp;quot;FREE (MATCHED)&amp;quot; &amp;quot;TOTAL SIZE&amp;quot; &amp;quot;LABEL&amp;quot;&lt;br /&gt;
echo &amp;quot;---------------------------------------------------------------------------------------------------&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Clean input and iterate&lt;br /&gt;
grep -E &amp;quot;System RAM|Kernel|reserved|pcie|gpu&amp;quot; &amp;quot;$IOMEM&amp;quot; | sed &#039;s/^[ ]*//&#039; | while read -r line; do&lt;br /&gt;
    ADDR=$(echo &amp;quot;$line&amp;quot; | cut -d&#039; &#039; -f1)&lt;br /&gt;
    LABEL=$(echo &amp;quot;$line&amp;quot; | cut -d&#039;:&#039; -f2- | xargs)&lt;br /&gt;
    S_HEX=$(echo &amp;quot;$ADDR&amp;quot; | cut -d&#039;-&#039; -f1)&lt;br /&gt;
    E_HEX=$(echo &amp;quot;$ADDR&amp;quot; | cut -d&#039;-&#039; -f2)&lt;br /&gt;
&lt;br /&gt;
    # Validate Hex&lt;br /&gt;
    if [[ ! $S_HEX =~ ^[0-9a-fA-F]+$ ]]; then continue; fi&lt;br /&gt;
&lt;br /&gt;
    S_DEC=$(printf &amp;quot;%d&amp;quot; &amp;quot;0x$S_HEX&amp;quot; 2&amp;gt;/dev/null)&lt;br /&gt;
    E_DEC=$(printf &amp;quot;%d&amp;quot; &amp;quot;0x$E_HEX&amp;quot; 2&amp;gt;/dev/null)&lt;br /&gt;
    SIZE_MB=$(awk &amp;quot;BEGIN {print ($E_DEC - $S_DEC + 1) / 1048576}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    UNIT=&amp;quot;MB&amp;quot;; [ $(awk &amp;quot;BEGIN {if ($SIZE_MB &amp;gt;= 1024) print 1; else print 0}&amp;quot;) -eq 1 ] &amp;amp;&amp;amp; UNIT=&amp;quot;GB&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    if [[ &amp;quot;$LABEL&amp;quot; == &amp;quot;System RAM&amp;quot; ]]; then&lt;br /&gt;
        FREE_MB=$(awk &amp;quot;BEGIN {print $SIZE_MB * $FREE_RATIO}&amp;quot;)&lt;br /&gt;
        P_FREE=$(awk &amp;quot;BEGIN {printf \&amp;quot;%.1f%%\&amp;quot;, $FREE_RATIO * 100}&amp;quot;)&lt;br /&gt;
        U_CH=$(awk &amp;quot;BEGIN {val = 12 * $OCC_RATIO; printf \&amp;quot;%.0f\&amp;quot;, (val&amp;lt;1 &amp;amp;&amp;amp; val&amp;gt;0)?1:val}&amp;quot;)&lt;br /&gt;
        [ &amp;quot;$U_CH&amp;quot; -gt 12 ] &amp;amp;&amp;amp; U_CH=12&lt;br /&gt;
        F_CH=$((12 - U_CH))&lt;br /&gt;
&lt;br /&gt;
        if [ &amp;quot;$U_CH&amp;quot; -gt 0 ]; then&lt;br /&gt;
            BAR_USED=$(printf &amp;quot;%$((U_CH-1))s&amp;quot; | tr &#039; &#039; &#039;#&#039;)&lt;br /&gt;
            MARKER=&amp;quot;\033[1;31m|\033[0m&amp;quot;&lt;br /&gt;
            BAR_FREE=$(printf &amp;quot;%${F_CH}s&amp;quot; | tr &#039; &#039; &#039;-&#039;)&lt;br /&gt;
            PIX=&amp;quot;\033[32m${BAR_USED}${MARKER}\033[36m${BAR_FREE}\033[0m&amp;quot;&lt;br /&gt;
        else&lt;br /&gt;
            PIX=&amp;quot;\033[36m------------\033[0m&amp;quot;&lt;br /&gt;
        fi&lt;br /&gt;
        STR_FREE=$(format_matched &amp;quot;$FREE_MB&amp;quot; &amp;quot;$UNIT&amp;quot;)&lt;br /&gt;
        STR_TOTAL=$(format_matched &amp;quot;$SIZE_MB&amp;quot; &amp;quot;$UNIT&amp;quot;)&lt;br /&gt;
    else&lt;br /&gt;
        PIX=&amp;quot;\033[31m............\033[0m&amp;quot;&lt;br /&gt;
        P_FREE=&amp;quot;0.0%&amp;quot;&lt;br /&gt;
        STR_FREE=$(format_matched 0 &amp;quot;$UNIT&amp;quot;)&lt;br /&gt;
        STR_TOTAL=$(format_matched &amp;quot;$SIZE_MB&amp;quot; &amp;quot;$UNIT&amp;quot;)&lt;br /&gt;
    fi&lt;br /&gt;
&lt;br /&gt;
    printf &amp;quot;0x%08s | %b | %-18s | %-12s | %s\n&amp;quot; &amp;quot;$S_HEX&amp;quot; &amp;quot;$PIX&amp;quot; &amp;quot;$P_FREE ($STR_FREE)&amp;quot; &amp;quot;$STR_TOTAL&amp;quot; &amp;quot;$LABEL&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
=== Error: Cannot read physical addresses ===&lt;br /&gt;
If you see this error, it means the Kernel is masking &amp;lt;code&amp;gt;/proc/iomem&amp;lt;/code&amp;gt; for security. &lt;br /&gt;
* &#039;&#039;&#039;Desktop:&#039;&#039;&#039; Ensure you are using &amp;lt;code&amp;gt;sudo&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &#039;&#039;&#039;Embedded:&#039;&#039;&#039; Ensure you are logged in as a user with root privileges.&lt;br /&gt;
&lt;br /&gt;
[[Category:Tools]]&lt;br /&gt;
[[Category:Linux Kernel]]&lt;br /&gt;
[[Category:Debugging]]&lt;/div&gt;</summary>
		<author><name>Andres</name></author>
	</entry>
	<entry>
		<id>https://developerwiki.proventusnova.com/index.php?title=Linux_RAM_Layout_Visualizer_Script&amp;diff=555</id>
		<title>Linux RAM Layout Visualizer Script</title>
		<link rel="alternate" type="text/html" href="https://developerwiki.proventusnova.com/index.php?title=Linux_RAM_Layout_Visualizer_Script&amp;diff=555"/>
		<updated>2026-02-20T16:15:28Z</updated>

		<summary type="html">&lt;p&gt;Andres: Created page with &amp;quot;__TOC__  == Overview == &amp;#039;&amp;#039;&amp;#039;mempix&amp;#039;&amp;#039;&amp;#039; is a lightweight bash utility designed to visualize physical memory allocation and real-time occupancy. It maps the data from {{Code|/proc/iomem}} and correlates it with global memory statistics from {{Code|/proc/meminfo}} to provide a per-block visual &amp;quot;pixel map.&amp;quot;  It is specifically optimized for both &amp;#039;&amp;#039;&amp;#039;embedded Yocto environments&amp;#039;&amp;#039;&amp;#039; (like the MediaTek Genio 720) and &amp;#039;&amp;#039;&amp;#039;standard Desktop Linux&amp;#039;&amp;#039;&amp;#039; (Ubuntu/Debian).  == Features == * &amp;#039;...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&#039;&#039;&#039;mempix&#039;&#039;&#039; is a lightweight bash utility designed to visualize physical memory allocation and real-time occupancy. It maps the data from {{Code|/proc/iomem}} and correlates it with global memory statistics from {{Code|/proc/meminfo}} to provide a per-block visual &amp;quot;pixel map.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
It is specifically optimized for both &#039;&#039;&#039;embedded Yocto environments&#039;&#039;&#039; (like the MediaTek Genio 720) and &#039;&#039;&#039;standard Desktop Linux&#039;&#039;&#039; (Ubuntu/Debian).&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
* &#039;&#039;&#039;Visual Occupancy:&#039;&#039;&#039; A 12-character progress bar showing used vs. free space within each RAM block.&lt;br /&gt;
* &#039;&#039;&#039;Threshold Marker:&#039;&#039;&#039; A red marker ({{Color|red||}}) indicating the exact transition point between used and free memory.&lt;br /&gt;
* &#039;&#039;&#039;Unit Intelligence:&#039;&#039;&#039; Automatically scales between KB, MB, and GB based on block size.&lt;br /&gt;
* &#039;&#039;&#039;Hardware Mapping:&#039;&#039;&#039; Identifies non-RAM regions (PCIe, GPU, Reserved) that are &amp;quot;locked&amp;quot; by hardware.&lt;br /&gt;
* &#039;&#039;&#039;Universal Compatibility:&#039;&#039;&#039; Uses POSIX-compliant math and standard escape codes for serial consoles.&lt;br /&gt;
&lt;br /&gt;
== Map Legend ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Symbol !! Color !! Meaning&lt;br /&gt;
|-&lt;br /&gt;
| {{Code|###}} || {{Color|green|Green}} || &#039;&#039;&#039;Used System RAM&#039;&#039;&#039;: Memory currently occupied by the kernel or processes.&lt;br /&gt;
|-&lt;br /&gt;
| {{Code|---}} || {{Color|cyan|Cyan}} || &#039;&#039;&#039;Free System RAM&#039;&#039;&#039;: Available memory within that physical address range.&lt;br /&gt;
|-&lt;br /&gt;
| {{Code||}} || {{Color|red|Red}} || &#039;&#039;&#039;Occupancy Marker&#039;&#039;&#039;: The specific boundary of current memory pressure.&lt;br /&gt;
|-&lt;br /&gt;
| {{Code|...}} || {{Color|red|Red}} || &#039;&#039;&#039;Reserved/IO&#039;&#039;&#039;: Non-system RAM (MMIO, GPU, Reserved by Firmware).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
=== Standard Run ===&lt;br /&gt;
On Yocto (root), run directly. On Ubuntu, use sudo:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo ./mempix.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Real-time Monitoring ===&lt;br /&gt;
To watch memory blocks change live as processes open/close:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
watch -c sudo ./mempix.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Source Code ==&lt;br /&gt;
Save the following code as {{Code|mempix.sh}}:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot; line&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
IOMEM=&amp;quot;/proc/iomem&amp;quot;&lt;br /&gt;
MEMINFO=&amp;quot;/proc/meminfo&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# --- PERMISSION CHECK ---&lt;br /&gt;
# Try to actually read one line. If empty, the kernel is masking the data.&lt;br /&gt;
CHECK_READ=$(head -n 1 &amp;quot;$IOMEM&amp;quot; 2&amp;gt;/dev/null)&lt;br /&gt;
if [ -z &amp;quot;$CHECK_READ&amp;quot; ]; then&lt;br /&gt;
    echo -e &amp;quot;\033[31mError: Cannot read physical addresses from $IOMEM.\033[0m&amp;quot;&lt;br /&gt;
    echo &amp;quot;If on Ubuntu, you must run this script with sudo.&amp;quot;&lt;br /&gt;
    exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
# 1. Get Global Stats&lt;br /&gt;
T_MEM_KB=$(grep MemTotal &amp;quot;$MEMINFO&amp;quot; | awk &#039;{print $2}&#039;)&lt;br /&gt;
F_MEM_KB=$(grep MemFree &amp;quot;$MEMINFO&amp;quot; | awk &#039;{print $2}&#039;)&lt;br /&gt;
OCC_RATIO=$(awk &amp;quot;BEGIN {print 1 - ($F_MEM_KB/$T_MEM_KB)}&amp;quot;)&lt;br /&gt;
FREE_RATIO=$(awk &amp;quot;BEGIN {print $F_MEM_KB/$T_MEM_KB}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
format_matched() {&lt;br /&gt;
    local val_mb=&amp;quot;$1&amp;quot;&lt;br /&gt;
    local target_unit=&amp;quot;$2&amp;quot;&lt;br /&gt;
    local is_small=$(awk &amp;quot;BEGIN {if ($val_mb &amp;lt; 0.1) print 1; else print 0}&amp;quot;)&lt;br /&gt;
    if [ &amp;quot;$is_small&amp;quot; -eq 1 ]; then&lt;br /&gt;
        awk &amp;quot;BEGIN {printf \&amp;quot;%.1f KB\&amp;quot;, $val_mb * 1024}&amp;quot;&lt;br /&gt;
    elif [ &amp;quot;$target_unit&amp;quot; == &amp;quot;GB&amp;quot; ]; then&lt;br /&gt;
        awk &amp;quot;BEGIN {printf \&amp;quot;%.2f GB\&amp;quot;, $val_mb / 1024}&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
        awk &amp;quot;BEGIN {printf \&amp;quot;%.1f MB\&amp;quot;, $val_mb}&amp;quot;&lt;br /&gt;
    fi&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# --- LEGEND ---&lt;br /&gt;
echo -e &amp;quot;\033[1mMAP LEGEND:\033[0m&amp;quot;&lt;br /&gt;
echo -e &amp;quot;\033[32m###\033[0m : Used System RAM   \033[1;31m|\033[0m : Occupancy Marker&amp;quot;&lt;br /&gt;
echo -e &amp;quot;\033[36m---\033[0m : Free System RAM   \033[31m...\033[0m : Reserved/Hardware/IO&amp;quot;&lt;br /&gt;
echo &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
echo -e &amp;quot;\033[1mPHYSICAL BLOCK ANALYSIS\033[0m&amp;quot;&lt;br /&gt;
printf &amp;quot;%-12s | %-12s | %-18s | %-12s | %s\n&amp;quot; &amp;quot;ADDRESS&amp;quot; &amp;quot;PIXEL MAP&amp;quot; &amp;quot;FREE (MATCHED)&amp;quot; &amp;quot;TOTAL SIZE&amp;quot; &amp;quot;LABEL&amp;quot;&lt;br /&gt;
echo &amp;quot;---------------------------------------------------------------------------------------------------&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Clean input and iterate&lt;br /&gt;
grep -E &amp;quot;System RAM|Kernel|reserved|pcie|gpu&amp;quot; &amp;quot;$IOMEM&amp;quot; | sed &#039;s/^[ ]*//&#039; | while read -r line; do&lt;br /&gt;
    ADDR=$(echo &amp;quot;$line&amp;quot; | cut -d&#039; &#039; -f1)&lt;br /&gt;
    LABEL=$(echo &amp;quot;$line&amp;quot; | cut -d&#039;:&#039; -f2- | xargs)&lt;br /&gt;
    S_HEX=$(echo &amp;quot;$ADDR&amp;quot; | cut -d&#039;-&#039; -f1)&lt;br /&gt;
    E_HEX=$(echo &amp;quot;$ADDR&amp;quot; | cut -d&#039;-&#039; -f2)&lt;br /&gt;
&lt;br /&gt;
    # Validate Hex&lt;br /&gt;
    if [[ ! $S_HEX =~ ^[0-9a-fA-F]+$ ]]; then continue; fi&lt;br /&gt;
&lt;br /&gt;
    S_DEC=$(printf &amp;quot;%d&amp;quot; &amp;quot;0x$S_HEX&amp;quot; 2&amp;gt;/dev/null)&lt;br /&gt;
    E_DEC=$(printf &amp;quot;%d&amp;quot; &amp;quot;0x$E_HEX&amp;quot; 2&amp;gt;/dev/null)&lt;br /&gt;
    SIZE_MB=$(awk &amp;quot;BEGIN {print ($E_DEC - $S_DEC + 1) / 1048576}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    UNIT=&amp;quot;MB&amp;quot;; [ $(awk &amp;quot;BEGIN {if ($SIZE_MB &amp;gt;= 1024) print 1; else print 0}&amp;quot;) -eq 1 ] &amp;amp;&amp;amp; UNIT=&amp;quot;GB&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    if [[ &amp;quot;$LABEL&amp;quot; == &amp;quot;System RAM&amp;quot; ]]; then&lt;br /&gt;
        FREE_MB=$(awk &amp;quot;BEGIN {print $SIZE_MB * $FREE_RATIO}&amp;quot;)&lt;br /&gt;
        P_FREE=$(awk &amp;quot;BEGIN {printf \&amp;quot;%.1f%%\&amp;quot;, $FREE_RATIO * 100}&amp;quot;)&lt;br /&gt;
        U_CH=$(awk &amp;quot;BEGIN {val = 12 * $OCC_RATIO; printf \&amp;quot;%.0f\&amp;quot;, (val&amp;lt;1 &amp;amp;&amp;amp; val&amp;gt;0)?1:val}&amp;quot;)&lt;br /&gt;
        [ &amp;quot;$U_CH&amp;quot; -gt 12 ] &amp;amp;&amp;amp; U_CH=12&lt;br /&gt;
        F_CH=$((12 - U_CH))&lt;br /&gt;
&lt;br /&gt;
        if [ &amp;quot;$U_CH&amp;quot; -gt 0 ]; then&lt;br /&gt;
            BAR_USED=$(printf &amp;quot;%$((U_CH-1))s&amp;quot; | tr &#039; &#039; &#039;#&#039;)&lt;br /&gt;
            MARKER=&amp;quot;\033[1;31m|\033[0m&amp;quot;&lt;br /&gt;
            BAR_FREE=$(printf &amp;quot;%${F_CH}s&amp;quot; | tr &#039; &#039; &#039;-&#039;)&lt;br /&gt;
            PIX=&amp;quot;\033[32m${BAR_USED}${MARKER}\033[36m${BAR_FREE}\033[0m&amp;quot;&lt;br /&gt;
        else&lt;br /&gt;
            PIX=&amp;quot;\033[36m------------\033[0m&amp;quot;&lt;br /&gt;
        fi&lt;br /&gt;
        STR_FREE=$(format_matched &amp;quot;$FREE_MB&amp;quot; &amp;quot;$UNIT&amp;quot;)&lt;br /&gt;
        STR_TOTAL=$(format_matched &amp;quot;$SIZE_MB&amp;quot; &amp;quot;$UNIT&amp;quot;)&lt;br /&gt;
    else&lt;br /&gt;
        PIX=&amp;quot;\033[31m............\033[0m&amp;quot;&lt;br /&gt;
        P_FREE=&amp;quot;0.0%&amp;quot;&lt;br /&gt;
        STR_FREE=$(format_matched 0 &amp;quot;$UNIT&amp;quot;)&lt;br /&gt;
        STR_TOTAL=$(format_matched &amp;quot;$SIZE_MB&amp;quot; &amp;quot;$UNIT&amp;quot;)&lt;br /&gt;
    fi&lt;br /&gt;
&lt;br /&gt;
    printf &amp;quot;0x%08s | %b | %-18s | %-12s | %s\n&amp;quot; &amp;quot;$S_HEX&amp;quot; &amp;quot;$PIX&amp;quot; &amp;quot;$P_FREE ($STR_FREE)&amp;quot; &amp;quot;$STR_TOTAL&amp;quot; &amp;quot;$LABEL&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
=== Error: Cannot read physical addresses ===&lt;br /&gt;
If you see this error, it means the Kernel is masking {{Code|/proc/iomem}} for security. &lt;br /&gt;
* &#039;&#039;&#039;Desktop:&#039;&#039;&#039; Ensure you are using {{Code|sudo}}.&lt;br /&gt;
* &#039;&#039;&#039;Embedded:&#039;&#039;&#039; Ensure you are logged in as a user with root privileges.&lt;br /&gt;
&lt;br /&gt;
[[Category:Tools]]&lt;br /&gt;
[[Category:Linux Kernel]]&lt;br /&gt;
[[Category:Debugging]]&lt;/div&gt;</summary>
		<author><name>Andres</name></author>
	</entry>
	<entry>
		<id>https://developerwiki.proventusnova.com/index.php?title=Template:Footer&amp;diff=554</id>
		<title>Template:Footer</title>
		<link rel="alternate" type="text/html" href="https://developerwiki.proventusnova.com/index.php?title=Template:Footer&amp;diff=554"/>
		<updated>2026-02-05T18:26:58Z</updated>

		<summary type="html">&lt;p&gt;Andres: /* Need Further Support? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Need Further Support? =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;📞 Book Consultation Call:&#039;&#039;&#039; [https://proventusnova.com/#home-contact Show Calendar!]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;📩 Contact Via Email:&#039;&#039;&#039; [mailto:support@proventusnova.com support@proventusnova.com]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;🌐 Visit Our Website:&#039;&#039;&#039; [https://proventusnova.com ProventusNova.com]&lt;/div&gt;</summary>
		<author><name>Andres</name></author>
	</entry>
	<entry>
		<id>https://developerwiki.proventusnova.com/index.php?title=Get_started_with_PDDL_on_NVIDIA_Jetson&amp;diff=553</id>
		<title>Get started with PDDL on NVIDIA Jetson</title>
		<link rel="alternate" type="text/html" href="https://developerwiki.proventusnova.com/index.php?title=Get_started_with_PDDL_on_NVIDIA_Jetson&amp;diff=553"/>
		<updated>2026-02-05T00:31:41Z</updated>

		<summary type="html">&lt;p&gt;Andres: Created page with &amp;quot;__TOC__  == Project Overview: Symbolic AI Planning on NVIDIA Jetson ==  This project demonstrates the implementation of &amp;#039;&amp;#039;&amp;#039;Symbolic AI Planning&amp;#039;&amp;#039;&amp;#039; on an NVIDIA Jetson (ARM64) using &amp;#039;&amp;#039;&amp;#039;PDDL&amp;#039;&amp;#039;&amp;#039; (Planning Domain Definition Language). Unlike traditional machine learning, this approach focuses on deterministic logic and reasoning to solve complex multi-step tasks.  === 🛠️ Environment Setup === Because the Jetson uses an ARM64 architecture, traditional x86 planners (like...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Project Overview: Symbolic AI Planning on NVIDIA Jetson ==&lt;br /&gt;
&lt;br /&gt;
This project demonstrates the implementation of &#039;&#039;&#039;Symbolic AI Planning&#039;&#039;&#039; on an NVIDIA Jetson (ARM64) using &#039;&#039;&#039;PDDL&#039;&#039;&#039; (Planning Domain Definition Language). Unlike traditional machine learning, this approach focuses on deterministic logic and reasoning to solve complex multi-step tasks.&lt;br /&gt;
&lt;br /&gt;
=== 🛠️ Environment Setup ===&lt;br /&gt;
Because the Jetson uses an ARM64 architecture, traditional x86 planners (like those found in planutils) often fail. We utilize a native Python approach for maximum compatibility.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Hardware:&#039;&#039;&#039; NVIDIA Jetson (Nano/Xavier/Orin)&lt;br /&gt;
* &#039;&#039;&#039;OS:&#039;&#039;&#039; Ubuntu 20.04/22.04 LTS&lt;br /&gt;
* &#039;&#039;&#039;Language:&#039;&#039;&#039; Python 3.10+&lt;br /&gt;
* &#039;&#039;&#039;Library:&#039;&#039;&#039; [https://github.com/aibasel/pyperplan Pyperplan] (Pure Python PDDL Planner)&lt;br /&gt;
&lt;br /&gt;
==== Installation ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Install the planner&lt;br /&gt;
pip install pyperplan&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
== 📋 The Logistics Domain ==&lt;br /&gt;
The domain defines the &amp;quot;physics&amp;quot; of our world. We use `:typing` to categorize objects for the planner.&lt;br /&gt;
&lt;br /&gt;
=== Domain Code (logistics_domain.pddl) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;pddl&amp;quot;&amp;gt;&lt;br /&gt;
(define (domain logistics)&lt;br /&gt;
  (:requirements :strips :typing)&lt;br /&gt;
  &lt;br /&gt;
  (:types location truck package)&lt;br /&gt;
&lt;br /&gt;
  (:predicates &lt;br /&gt;
    (at ?obj ?loc)&lt;br /&gt;
    (in ?p ?t)&lt;br /&gt;
  )&lt;br /&gt;
&lt;br /&gt;
  (:action drive&lt;br /&gt;
    :parameters (?t - truck ?from - location ?to - location)&lt;br /&gt;
    :precondition (and (at ?t ?from))&lt;br /&gt;
    :effect (and (at ?t ?to) (not (at ?t ?from)))&lt;br /&gt;
  )&lt;br /&gt;
&lt;br /&gt;
  (:action load&lt;br /&gt;
    :parameters (?p - package ?t - truck ?l - location)&lt;br /&gt;
    :precondition (and (at ?p ?l) (at ?t ?l))&lt;br /&gt;
    :effect (and (in ?p ?t) (not (at ?p ?l)))&lt;br /&gt;
  )&lt;br /&gt;
&lt;br /&gt;
  (:action unload&lt;br /&gt;
    :parameters (?p - package ?t - truck ?l - location)&lt;br /&gt;
    :precondition (and (in ?p ?t) (at ?t ?l))&lt;br /&gt;
    :effect (and (at ?p ?l) (not (in ?p ?t)))&lt;br /&gt;
  )&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
== 📍 The Problem Definition ==&lt;br /&gt;
The problem defines the specific starting state and the desired goal.&lt;br /&gt;
&lt;br /&gt;
=== Problem Code (logistics_problem.pddl) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;pddl&amp;quot;&amp;gt;&lt;br /&gt;
(define (problem delivery-task)&lt;br /&gt;
  (:domain logistics)&lt;br /&gt;
  &lt;br /&gt;
  (:objects &lt;br /&gt;
    warehouse hospital post_office - location&lt;br /&gt;
    truck1 - truck&lt;br /&gt;
    meds food - package&lt;br /&gt;
  )&lt;br /&gt;
&lt;br /&gt;
  (:init &lt;br /&gt;
    (at truck1 warehouse)&lt;br /&gt;
    (at meds warehouse)&lt;br /&gt;
    (at food warehouse)&lt;br /&gt;
  )&lt;br /&gt;
&lt;br /&gt;
  (:goal (and &lt;br /&gt;
    (at meds hospital)&lt;br /&gt;
    (at food post_office)&lt;br /&gt;
  ))&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
== 🚀 Execution &amp;amp; Results ==&lt;br /&gt;
Run the following command in the Jetson terminal:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
pyperplan logistics_domain.pddl logistics_problem.pddl&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Expected Output ===&lt;br /&gt;
The planner uses Breadth-First Search (BFS) to find the shortest path.&lt;br /&gt;
* &#039;&#039;&#039;Search Time:&#039;&#039;&#039; ~0.00092s&lt;br /&gt;
* &#039;&#039;&#039;Nodes Expanded:&#039;&#039;&#039; 42&lt;br /&gt;
* &#039;&#039;&#039;Plan Length:&#039;&#039;&#039; 6 steps&lt;br /&gt;
&lt;br /&gt;
The generated plan is saved to &amp;lt;code&amp;gt;logistics_problem.pddl.soln&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
== ⚠️ Troubleshooting &amp;amp; Lessons Learned ==&lt;br /&gt;
* &#039;&#039;&#039;Architecture Conflicts:&#039;&#039;&#039; Avoid using &amp;lt;code&amp;gt;planutils&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;up-tamer&amp;lt;/code&amp;gt; on Jetson as they rely on x86 pre-compiled binaries or Apptainer images that lack ARM64 support.&lt;br /&gt;
* &#039;&#039;&#039;Typing Requirement:&#039;&#039;&#039; Ensure &amp;lt;code&amp;gt;(:requirements :typing)&amp;lt;/code&amp;gt; is declared in the domain if using typed objects (e.g., &amp;lt;code&amp;gt;- location&amp;lt;/code&amp;gt;), otherwise, Pyperplan will throw a &amp;lt;code&amp;gt;SemanticError&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &#039;&#039;&#039;Validation:&#039;&#039;&#039; If &amp;lt;code&amp;gt;validate&amp;lt;/code&amp;gt; is missing from PATH, the plan still runs but cannot be formally verified by the software.&lt;br /&gt;
&lt;br /&gt;
[[Category:Robotics]] [[Category:Artificial Intelligence]] [[Category:Jetson]]&lt;/div&gt;</summary>
		<author><name>Andres</name></author>
	</entry>
	<entry>
		<id>https://developerwiki.proventusnova.com/index.php?title=Fixing_ARM_Compute_Library_Fetch_Error_24_02_Yocto&amp;diff=443</id>
		<title>Fixing ARM Compute Library Fetch Error 24 02 Yocto</title>
		<link rel="alternate" type="text/html" href="https://developerwiki.proventusnova.com/index.php?title=Fixing_ARM_Compute_Library_Fetch_Error_24_02_Yocto&amp;diff=443"/>
		<updated>2025-11-15T01:32:05Z</updated>

		<summary type="html">&lt;p&gt;Andres: Created page with &amp;quot;== ⚠️ Fixing Yocto Fetch Error: arm-compute-library 24.02 (Wrong Git Branch) == This page documents a specific fetch error encountered during a Yocto build when retrieving the source code for the &amp;#039;&amp;#039;&amp;#039;ARM Compute Library&amp;#039;&amp;#039;&amp;#039; recipe version 24.02, and provides the fix using a &amp;#039;&amp;#039;&amp;#039;.bbappend&amp;#039;&amp;#039;&amp;#039; file.  === The Error Message === The Yocto build fails during the &amp;#039;&amp;#039;&amp;#039;do_fetch&amp;#039;&amp;#039;&amp;#039; task for the &amp;#039;&amp;#039;arm-compute-library-24.02&amp;#039;&amp;#039; recipe, indicating that the required commit cannot be foun...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== ⚠️ Fixing Yocto Fetch Error: arm-compute-library 24.02 (Wrong Git Branch) ==&lt;br /&gt;
This page documents a specific fetch error encountered during a Yocto build when retrieving the source code for the &#039;&#039;&#039;ARM Compute Library&#039;&#039;&#039; recipe version 24.02, and provides the fix using a &#039;&#039;&#039;.bbappend&#039;&#039;&#039; file.&lt;br /&gt;
&lt;br /&gt;
=== The Error Message ===&lt;br /&gt;
The Yocto build fails during the &#039;&#039;&#039;do_fetch&#039;&#039;&#039; task for the &#039;&#039;arm-compute-library-24.02&#039;&#039; recipe, indicating that the required commit cannot be found in the default branch:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
WARNING: arm-compute-library-24.02-r0 do_fetch: Failed to fetch URL git://github.com/ARM-software/ComputeLibrary.git;protocol=https;branch=main;name=arm-compute-library, attempting MIRRORS if available&lt;br /&gt;
ERROR: arm-compute-library-24.02-r0 do_fetch: Fetcher failure: Unable to find revision bc89a0b690200750040770bda0981f4a37b389c4 in branch main even from upstream&lt;br /&gt;
ERROR: arm-compute-library-24.02-r0 do_fetch: Bitbake Fetcher Error: FetchError(&#039;Unable to fetch URL from any source.&#039;, &#039;git://github.com/ARM-software/ComputeLibrary.git;protocol=https;branch=main;name=arm-compute-library&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Root Cause Analysis ===&lt;br /&gt;
The specific Git commit hash (`bc89a0b690200750040770bda0981f4a37b389c4`) required by the recipe has been moved on the upstream repository. It no longer resides in the expected &#039;&#039;&#039;main&#039;&#039;&#039; branch, but has been relocated to the &#039;&#039;&#039;archived-releases&#039;&#039;&#039; branch. Consequently, the BitBake fetcher, looking only in &#039;&#039;main&#039;&#039;, fails to locate the source code.&lt;br /&gt;
&lt;br /&gt;
=== 💡 The Solution: Overriding the Branch with a `.bbappend` ===&lt;br /&gt;
The issue is resolved by creating an &#039;&#039;&#039;arm-compute-library_24.02.bbappend&#039;&#039;&#039; file in your custom meta-layer to explicitly override the default source Uniform Resource Identifier (URI) and point it to the correct Git branch.&lt;br /&gt;
&lt;br /&gt;
==== Step 1: Create the `.bbappend` File ====&lt;br /&gt;
Place the override file within the following path structure in your custom meta-layer (e.g., in a directory named `meta-pn-mtk`):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;YOUR_CUSTOM_META_LAYER&amp;gt;/recipes-armnn/arm-compute-library/arm-compute-library_24.02.bbappend&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Step 2: Add the Override Content ====&lt;br /&gt;
Populate the &#039;&#039;&#039;arm-compute-library_24.02.bbappend&#039;&#039;&#039; file with the following content. This configuration changes the source branch to &#039;&#039;&#039;archived-releases&#039;&#039;&#039; while ensuring the correct &#039;&#039;&#039;SRCREV&#039;&#039;&#039; (commit hash) is used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SRC_URI = &amp;quot;git://github.com/ARM-software/ComputeLibrary.git;protocol=https;branch=archived-releases;name=arm-compute-library \&lt;br /&gt;
           file://0001-enable-yocto-build.patch \&lt;br /&gt;
           file://0001-Remove-unknown-variables-treated-as-error.patch \&lt;br /&gt;
           file://0001-Prefer-to-use-libmali-as-the-provider-of-OpenCL.patch \&lt;br /&gt;
           file://0001-remove-clUpdateMutableCommandsKHR-reference.patch \&lt;br /&gt;
           &amp;quot;&lt;br /&gt;
&lt;br /&gt;
SRCREV = &amp;quot;bc89a0b690200750040770bda0981f4a37b389c4&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;code&amp;gt;SRC_URI&amp;lt;/code&amp;gt;&#039;&#039;&#039;: The URL parameter is modified to specify &#039;&#039;&#039;&amp;lt;code&amp;gt;branch=archived-releases&amp;lt;/code&amp;gt;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;code&amp;gt;SRCREV&amp;lt;/code&amp;gt;&#039;&#039;&#039;: The exact commit hash is retained to fetch the desired version of the library.&lt;br /&gt;
&lt;br /&gt;
After adding this file, BitBake will use the new branch setting, allowing the source code fetch to succeed on the next build attempt.&lt;/div&gt;</summary>
		<author><name>Andres</name></author>
	</entry>
	<entry>
		<id>https://developerwiki.proventusnova.com/index.php?title=How_to_NVIDIA_Jetson_Orin_Nano_UART_Console&amp;diff=223</id>
		<title>How to NVIDIA Jetson Orin Nano UART Console</title>
		<link rel="alternate" type="text/html" href="https://developerwiki.proventusnova.com/index.php?title=How_to_NVIDIA_Jetson_Orin_Nano_UART_Console&amp;diff=223"/>
		<updated>2025-08-04T14:40:27Z</updated>

		<summary type="html">&lt;p&gt;Andres: Created page with &amp;quot;= How to Connect to NVIDIA Jetson Orin Nano UART Console =  This guide explains how to connect to the UART serial console of the NVIDIA Jetson Orin Nano Developer Kit using a TTL-to-USB adapter. This is useful for accessing boot logs, debugging early kernel messages, or interacting with the board when other interfaces are unavailable.  == Requirements ==  * NVIDIA Jetson Orin Nano Developer Kit * TTL-to-USB Serial Adapter (e.g., based on CP2102, CH340, or FT232) * Jumper...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= How to Connect to NVIDIA Jetson Orin Nano UART Console =&lt;br /&gt;
&lt;br /&gt;
This guide explains how to connect to the UART serial console of the NVIDIA Jetson Orin Nano Developer Kit using a TTL-to-USB adapter. This is useful for accessing boot logs, debugging early kernel messages, or interacting with the board when other interfaces are unavailable.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
&lt;br /&gt;
* NVIDIA Jetson Orin Nano Developer Kit&lt;br /&gt;
* TTL-to-USB Serial Adapter (e.g., based on CP2102, CH340, or FT232)&lt;br /&gt;
* Jumper wires (Female-to-Female)&lt;br /&gt;
* A host computer running Linux or macOS&lt;br /&gt;
* Serial terminal software: &#039;&#039;&#039;screen&#039;&#039;&#039; or &#039;&#039;&#039;minicom&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== NVIDIA Jetson Orin Nano UART Pinout and Wiring ==&lt;br /&gt;
&lt;br /&gt;
Connect the TTL-to-USB adapter to the 40-pin GPIO header of the Jetson Orin Nano as follows:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ UART Pinout (J41 Header on Orin Nano)&lt;br /&gt;
! Pin Number !! Signal !! Description !! TTL Adapter Wire&lt;br /&gt;
|-&lt;br /&gt;
| 8 || UART_TX || Transmit from Jetson || Connect to RXD on adapter&lt;br /&gt;
|-&lt;br /&gt;
| 10 || UART_RX || Receive into Jetson || Connect to TXD on adapter&lt;br /&gt;
|-&lt;br /&gt;
| 14 || GND || Ground || Connect to GND on adapter&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Step-by-Step Instructions ==&lt;br /&gt;
&lt;br /&gt;
=== 1. Connect Hardware ===&lt;br /&gt;
# Power off the Jetson Orin Nano.&lt;br /&gt;
# Connect jumper wires as described in the table above.&lt;br /&gt;
# Plug the TTL-to-USB adapter into your computer.&lt;br /&gt;
&lt;br /&gt;
=== 2. Identify the Serial Device ===&lt;br /&gt;
On your host machine, run:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ls /dev/ttyUSB*&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You should see something like &#039;&#039;&#039;/dev/ttyUSB0&#039;&#039;&#039;. This is the serial device you&#039;ll use.&lt;br /&gt;
&lt;br /&gt;
== Using screen ==&lt;br /&gt;
&lt;br /&gt;
=== Install screen ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt install screen&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Start Serial Console ===&lt;br /&gt;
Replace &#039;&#039;&#039;/dev/ttyUSB0&#039;&#039;&#039; with your actual device:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
screen /dev/ttyUSB0 115200&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To exit &#039;&#039;&#039;screen&#039;&#039;&#039;, press:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Ctrl + A, then K, then press Y to confirm&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Using minicom ==&lt;br /&gt;
&lt;br /&gt;
=== Install minicom ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt install minicom&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Configure minicom ===&lt;br /&gt;
First, run:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo minicom -s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Navigate to **Serial port setup** and set:&lt;br /&gt;
* **Serial device**: `/dev/ttyUSB0`&lt;br /&gt;
* **Bps/Par/Bits**: `115200 8N1`&lt;br /&gt;
* **Hardware Flow Control**: **No**&lt;br /&gt;
* **Software Flow Control**: **No**&lt;br /&gt;
&lt;br /&gt;
Save settings and exit.&lt;br /&gt;
&lt;br /&gt;
=== Start Serial Console ===&lt;br /&gt;
After configuration:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo minicom&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To exit &#039;&#039;&#039;minicom&#039;&#039;&#039;, press:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Ctrl + A, then X&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Boot Log Output ==&lt;br /&gt;
&lt;br /&gt;
Once connected, power on the Jetson Orin Nano. You should see U-Boot and Linux boot messages in your terminal window. This console can be used to log in if graphical access is unavailable.&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
* Make sure your TTL-to-USB adapter is recognized by the OS (&#039;&#039;&#039;dmesg | grep ttyUSB&#039;&#039;&#039;)&lt;br /&gt;
* Verify correct TX/RX wiring (cross them)&lt;br /&gt;
* Use only one terminal program at a time (minicom or screen)&lt;br /&gt;
* Ensure baud rate is set to &#039;&#039;&#039;115200&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{{Footer}}&lt;/div&gt;</summary>
		<author><name>Andres</name></author>
	</entry>
	<entry>
		<id>https://developerwiki.proventusnova.com/index.php?title=How_to_Enable_OpenCL_Support_in_OpenCV_for_MediaTek_Yocto_Platforms&amp;diff=222</id>
		<title>How to Enable OpenCL Support in OpenCV for MediaTek Yocto Platforms</title>
		<link rel="alternate" type="text/html" href="https://developerwiki.proventusnova.com/index.php?title=How_to_Enable_OpenCL_Support_in_OpenCV_for_MediaTek_Yocto_Platforms&amp;diff=222"/>
		<updated>2025-07-24T13:58:35Z</updated>

		<summary type="html">&lt;p&gt;Andres: /* How to Enable OpenCL Support in OpenCV for MediaTek Yocto Platforms */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= How to Enable OpenCL Support in OpenCV for MediaTek Yocto Platforms =&lt;br /&gt;
&lt;br /&gt;
This guide explains how to add OpenCL support to OpenCV in a Yocto-based BSP for MediaTek Genio or similar platforms by modifying the OpenCV recipe through a &#039;&#039;&#039;.bbappend&#039;&#039;&#039; file.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
&lt;br /&gt;
Before proceeding, make sure you have:&lt;br /&gt;
* A working Yocto Project build setup for your MediaTek Genio or similar platform.&lt;br /&gt;
* A custom meta-layer where you can place &#039;&#039;&#039;.bbappend&#039;&#039;&#039; files.&lt;br /&gt;
* Basic knowledge of BitBake and Yocto layer structure.&lt;br /&gt;
&lt;br /&gt;
== Step 1: Locate the Base Recipe ==&lt;br /&gt;
&lt;br /&gt;
OpenCV is typically provided by &#039;&#039;&#039;meta-openembedded&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
meta-oe/recipes-support/opencv/opencv_4.5.5.bb&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We will extend this recipe with a &#039;&#039;&#039;.bbappend&#039;&#039;&#039; in your custom layer.&lt;br /&gt;
&lt;br /&gt;
== Step 2: Create the .bbappend File ==&lt;br /&gt;
&lt;br /&gt;
Create the following directory structure in your custom layer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
meta-yourlayer/&lt;br /&gt;
└── recipes-support/&lt;br /&gt;
    └── opencv/&lt;br /&gt;
        └── opencv_4.5.5.bbappend&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Step 3: Enable OpenCL via PACKAGECONFIG ==&lt;br /&gt;
&lt;br /&gt;
Edit &#039;&#039;&#039;opencv_4.5.5.bbappend&#039;&#039;&#039; and add:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bitbake&amp;quot;&amp;gt;&lt;br /&gt;
# Enable OpenCL in OpenCV build&lt;br /&gt;
PACKAGECONFIG:append = &amp;quot; opencl&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This appends &#039;&#039;&#039;opencl&#039;&#039;&#039; to the build configuration options, enabling OpenCL support during the CMake configuration.&lt;br /&gt;
&lt;br /&gt;
== Step 4: Rebuild OpenCV ==&lt;br /&gt;
&lt;br /&gt;
To apply the changes, clean and rebuild OpenCV:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bitbake -c clean opencv&lt;br /&gt;
bitbake opencv&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Footer}}&lt;/div&gt;</summary>
		<author><name>Andres</name></author>
	</entry>
	<entry>
		<id>https://developerwiki.proventusnova.com/index.php?title=How_to_Enable_OpenCL_Support_in_OpenCV_for_MediaTek_Yocto_Platforms&amp;diff=221</id>
		<title>How to Enable OpenCL Support in OpenCV for MediaTek Yocto Platforms</title>
		<link rel="alternate" type="text/html" href="https://developerwiki.proventusnova.com/index.php?title=How_to_Enable_OpenCL_Support_in_OpenCV_for_MediaTek_Yocto_Platforms&amp;diff=221"/>
		<updated>2025-07-24T13:54:05Z</updated>

		<summary type="html">&lt;p&gt;Andres: Created page with &amp;quot;= How to Enable OpenCL Support in OpenCV for MediaTek Yocto Platforms =  This guide explains how to add OpenCL support to OpenCV in a Yocto-based BSP for MediaTek Genio or similar platforms by modifying the OpenCV recipe through a `.bbappend` file.  == 🧠 Prerequisites ==  Before proceeding, make sure you have: * A working Yocto Project build setup for your MediaTek Genio or similar platform. * A custom meta-layer (e.g. &amp;lt;code&amp;gt;meta-yourlayer&amp;lt;/code&amp;gt;) where you can place...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= How to Enable OpenCL Support in OpenCV for MediaTek Yocto Platforms =&lt;br /&gt;
&lt;br /&gt;
This guide explains how to add OpenCL support to OpenCV in a Yocto-based BSP for MediaTek Genio or similar platforms by modifying the OpenCV recipe through a `.bbappend` file.&lt;br /&gt;
&lt;br /&gt;
== 🧠 Prerequisites ==&lt;br /&gt;
&lt;br /&gt;
Before proceeding, make sure you have:&lt;br /&gt;
* A working Yocto Project build setup for your MediaTek Genio or similar platform.&lt;br /&gt;
* A custom meta-layer (e.g. &amp;lt;code&amp;gt;meta-yourlayer&amp;lt;/code&amp;gt;) where you can place `.bbappend` files.&lt;br /&gt;
* Basic knowledge of BitBake and Yocto layer structure.&lt;br /&gt;
&lt;br /&gt;
== 🧩 Step 1: Locate the Base Recipe ==&lt;br /&gt;
&lt;br /&gt;
OpenCV is typically provided by `meta-openembedded`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
meta-oe/recipes-support/opencv/opencv_4.5.5.bb&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We will extend this recipe with a `.bbappend` in your custom layer.&lt;br /&gt;
&lt;br /&gt;
== 🛠️ Step 2: Create the .bbappend File ==&lt;br /&gt;
&lt;br /&gt;
Create the following directory structure in your custom layer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
meta-yourlayer/&lt;br /&gt;
└── recipes-support/&lt;br /&gt;
    └── opencv/&lt;br /&gt;
        └── opencv_4.5.5.bbappend&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 🧾 Step 3: Enable OpenCL via PACKAGECONFIG ==&lt;br /&gt;
&lt;br /&gt;
Edit &amp;lt;code&amp;gt;opencv_4.5.5.bbappend&amp;lt;/code&amp;gt; and add:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bitbake&amp;quot;&amp;gt;&lt;br /&gt;
# Enable OpenCL in OpenCV build&lt;br /&gt;
PACKAGECONFIG:append = &amp;quot; opencl&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This appends &amp;lt;code&amp;gt;opencl&amp;lt;/code&amp;gt; to the build configuration options, enabling OpenCL support during the CMake configuration.&lt;br /&gt;
&lt;br /&gt;
== ✅ Step 4: Rebuild OpenCV ==&lt;br /&gt;
&lt;br /&gt;
To apply the changes, clean and rebuild OpenCV:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bitbake -c clean opencv&lt;br /&gt;
bitbake opencv&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 🔍 Step 5: Verify OpenCL Support ==&lt;br /&gt;
&lt;br /&gt;
Once built, verify that OpenCL support is present. You can inspect OpenCV with:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ldd /usr/bin/opencv_version&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or use a Python snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import cv2&lt;br /&gt;
print(cv2.ocl.haveOpenCL())&lt;br /&gt;
print(cv2.ocl.useOpenCL())&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 🧩 Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
* Ensure your platform supports OpenCL (e.g. Genio 1200 with Mali GPU).&lt;br /&gt;
* Confirm that OpenCL headers and runtime (e.g., &amp;lt;code&amp;gt;ocl-icd&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;libopencl&amp;lt;/code&amp;gt;) are available in your image.&lt;br /&gt;
* If the OpenCL option is ignored, double-check that the &amp;lt;code&amp;gt;PACKAGECONFIG&amp;lt;/code&amp;gt; is not being overridden elsewhere.&lt;br /&gt;
&lt;br /&gt;
== 📚 References ==&lt;br /&gt;
&lt;br /&gt;
* [OpenCV Official Website](https://opencv.org/)&lt;br /&gt;
* [Yocto Project Documentation](https://docs.yoctoproject.org/)&lt;br /&gt;
* [MediaTek Genio SDK](https://www.mediatek.com/iot/opensource/genio)&lt;br /&gt;
&lt;br /&gt;
== 🛟 Need Help? ==&lt;br /&gt;
&lt;br /&gt;
Need help integrating OpenCV and OpenCL on your custom Yocto build?&lt;br /&gt;
&lt;br /&gt;
💡 Contact [ProventusNova](https://proventusnova.com/contact-us) — we help teams customize BSPs, accelerate embedded AI development, and get production-ready faster.&lt;/div&gt;</summary>
		<author><name>Andres</name></author>
	</entry>
	<entry>
		<id>https://developerwiki.proventusnova.com/index.php?title=How_to_Run_GStreamer_in_a_Docker_Container&amp;diff=220</id>
		<title>How to Run GStreamer in a Docker Container</title>
		<link rel="alternate" type="text/html" href="https://developerwiki.proventusnova.com/index.php?title=How_to_Run_GStreamer_in_a_Docker_Container&amp;diff=220"/>
		<updated>2025-07-23T20:11:56Z</updated>

		<summary type="html">&lt;p&gt;Andres: Created page with &amp;quot;= How to Run GStreamer in Docker =  This tutorial shows you how to install and use &amp;#039;&amp;#039;&amp;#039;GStreamer&amp;#039;&amp;#039;&amp;#039; inside a &amp;#039;&amp;#039;&amp;#039;Docker container&amp;#039;&amp;#039;&amp;#039; on &amp;#039;&amp;#039;&amp;#039;Ubuntu 22.04&amp;#039;&amp;#039;&amp;#039;. We&amp;#039;ll build a minimal Docker image with support for &amp;#039;&amp;#039;&amp;#039;x264enc&amp;#039;&amp;#039;&amp;#039;, then run a simple test pipeline to encode video to an MP4 file.  == Step 1: Create a Dockerfile with GStreamer and x264enc ==  Create a file named &amp;lt;code&amp;gt;Dockerfile&amp;lt;/code&amp;gt; with the following contents:  &amp;lt;syntaxhighlight lang=&amp;quot;dockerfile&amp;quot;&amp;gt; FROM ubuntu:22.04...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= How to Run GStreamer in Docker =&lt;br /&gt;
&lt;br /&gt;
This tutorial shows you how to install and use &#039;&#039;&#039;GStreamer&#039;&#039;&#039; inside a &#039;&#039;&#039;Docker container&#039;&#039;&#039; on &#039;&#039;&#039;Ubuntu 22.04&#039;&#039;&#039;. We&#039;ll build a minimal Docker image with support for &#039;&#039;&#039;x264enc&#039;&#039;&#039;, then run a simple test pipeline to encode video to an MP4 file.&lt;br /&gt;
&lt;br /&gt;
== Step 1: Create a Dockerfile with GStreamer and x264enc ==&lt;br /&gt;
&lt;br /&gt;
Create a file named &amp;lt;code&amp;gt;Dockerfile&amp;lt;/code&amp;gt; with the following contents:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;dockerfile&amp;quot;&amp;gt;&lt;br /&gt;
FROM ubuntu:22.04&lt;br /&gt;
&lt;br /&gt;
ENV DEBIAN_FRONTEND=noninteractive&lt;br /&gt;
&lt;br /&gt;
# Install GStreamer with x264 support and minimal required tools&lt;br /&gt;
RUN apt-get update &amp;amp;&amp;amp; apt-get install -y \&lt;br /&gt;
    libgstreamer1.0-dev \&lt;br /&gt;
    libgstreamer-plugins-base1.0-dev \&lt;br /&gt;
    libgstreamer-plugins-bad1.0-dev \&lt;br /&gt;
    gstreamer1.0-plugins-base \&lt;br /&gt;
    gstreamer1.0-plugins-good \&lt;br /&gt;
    gstreamer1.0-plugins-bad \&lt;br /&gt;
    gstreamer1.0-plugins-ugly \&lt;br /&gt;
    gstreamer1.0-libav \&lt;br /&gt;
    gstreamer1.0-tools \&lt;br /&gt;
    gstreamer1.0-x \&lt;br /&gt;
    gstreamer1.0-alsa \&lt;br /&gt;
    gstreamer1.0-gl \&lt;br /&gt;
    gstreamer1.0-gtk3 \&lt;br /&gt;
    gstreamer1.0-qt5 \&lt;br /&gt;
    gstreamer1.0-pulseaudio \&lt;br /&gt;
    libx264-dev \&lt;br /&gt;
    &amp;amp;&amp;amp; rm -rf /var/lib/apt/lists/*&lt;br /&gt;
&lt;br /&gt;
CMD [ &amp;quot;tail&amp;quot;, &amp;quot;-F&amp;quot;, &amp;quot;/dev/null&amp;quot; ]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This Dockerfile installs a complete GStreamer stack along with the necessary packages to support &amp;lt;code&amp;gt;x264enc&amp;lt;/code&amp;gt;, allowing you to encode H.264 video streams.&lt;br /&gt;
&lt;br /&gt;
== Step 2: Build the Docker image ==&lt;br /&gt;
&lt;br /&gt;
Use the following command to build the Docker image and tag it as &amp;lt;code&amp;gt;gstreamer-test&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker build -t gstreamer-test .&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Step 3: Start the GStreamer container in the background ==&lt;br /&gt;
&lt;br /&gt;
Run the container in detached mode and give it a name:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d --name gstreamer-test gstreamer-test&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Step 4: Run a sample GStreamer pipeline inside the container ==&lt;br /&gt;
&lt;br /&gt;
Use the following GStreamer command to generate a test video, encode it with x264, and save it as an MP4 file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
gst-launch-1.0 videotestsrc num-buffers=300 is-live=true ! video/x-raw,width=640,height=480,framerate=30/1 ! x264enc ! mp4mux ! filesink location=output.mp4&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will create a short 10-second video called &amp;lt;code&amp;gt;output.mp4&amp;lt;/code&amp;gt; using GStreamer&#039;s built-in &amp;lt;code&amp;gt;videotestsrc&amp;lt;/code&amp;gt; source.&lt;br /&gt;
&lt;br /&gt;
== Step 5: Exit the container ==&lt;br /&gt;
&lt;br /&gt;
After the pipeline finishes, you can exit the container shell:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
exit&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Step 6: Copy the video output to the host system ==&lt;br /&gt;
&lt;br /&gt;
Transfer the generated MP4 file from the container to your local system:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker cp gstreamer-test:/output.mp4 ./output.mp4&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Step 7: Preview the video on your host machine ==&lt;br /&gt;
&lt;br /&gt;
Open &amp;lt;code&amp;gt;output.mp4&amp;lt;/code&amp;gt; with any media player that supports MP4 and H.264, such as VLC or your system&#039;s default video player.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
You&#039;ve successfully created a Dockerized GStreamer environment with x264 encoding support. This is useful for rapid prototyping of pipelines, isolated testing, or running GStreamer apps on systems without native installations.&lt;br /&gt;
&lt;br /&gt;
For more GStreamer examples, pipeline debugging tips, or Docker use cases in embedded systems, explore our other tutorials.&lt;br /&gt;
&lt;br /&gt;
{{Footer}}&lt;/div&gt;</summary>
		<author><name>Andres</name></author>
	</entry>
	<entry>
		<id>https://developerwiki.proventusnova.com/index.php?title=Create_custom_Yocto_meta_layer_for_MediaTek_G510_board&amp;diff=214</id>
		<title>Create custom Yocto meta layer for MediaTek G510 board</title>
		<link rel="alternate" type="text/html" href="https://developerwiki.proventusnova.com/index.php?title=Create_custom_Yocto_meta_layer_for_MediaTek_G510_board&amp;diff=214"/>
		<updated>2025-06-25T17:23:46Z</updated>

		<summary type="html">&lt;p&gt;Andres: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This wiki will provide a detailed guide on how to create a custom Yocto meta-layer for a MediaTek Genio 510 board.&lt;br /&gt;
&lt;br /&gt;
=Pre-requisites=&lt;br /&gt;
1. The host machine must have the following requirements:&lt;br /&gt;
*At least 90GB of space&lt;br /&gt;
*At least 8GB RAM&lt;br /&gt;
*Host OS must be a supported Linux distribution. (To see supported Linux Distributions, click [https://docs.yoctoproject.org/ref-manual/system-requirements.html#supported-linux-distributions supported distributions])&lt;br /&gt;
&lt;br /&gt;
2. The following packages must be present in the host machine:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apt install build-essential chrpath cpio debianutils diffstat file gawk gcc git iputils-ping libacl1 liblz4-tool locales python3 python3-git python3-jinja2 python3-pexpect python3-pip python3-subunit socat texinfo unzip wget xz-utils zstd&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Create Base Meta-Layer=&lt;br /&gt;
&lt;br /&gt;
This section contains steps to create the base custom meta-layer. &amp;lt;br&amp;gt;&lt;br /&gt;
Creating a layer can be done manually or automatically via bitbake. &amp;lt;br&amp;gt;&lt;br /&gt;
After completion, the custom base meta-layer will contain the following parts:&lt;br /&gt;
&lt;br /&gt;
* Custom layer configuration&lt;br /&gt;
* Custom distro configuration&lt;br /&gt;
* Custom machine&lt;br /&gt;
* Custom config template files&lt;br /&gt;
* Custom image recipe&lt;br /&gt;
&lt;br /&gt;
==Manually create layer==&lt;br /&gt;
&lt;br /&gt;
===Step 1. Add base layer.conf file===&lt;br /&gt;
&lt;br /&gt;
The layer configuration file provides Yocto with the configuration for the custom meta-layer.&lt;br /&gt;
It shall be stored in a directory called &#039;&#039;&#039;conf&#039;&#039;&#039; inside the base meta-layer directory, and it shall be named layer.conf.&lt;br /&gt;
According to the [https://docs.yoctoproject.org/dev/dev-manual/layers.html Yocto documentation] it is recommended to start from an existing layer.conf file from a different meta-layer and change it according to the custom requirements.&lt;br /&gt;
&lt;br /&gt;
For instance, here is an example of how the directory structure should look after creating the layer.conf file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-pn-mtk/&lt;br /&gt;
├── conf&lt;br /&gt;
│   └── layer.conf&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An example layer.conf file based on [https://gitlab.com/mediatek/aiot/rity/meta-rity/-/blob/rity-scarthgap-v25.0/meta-rity-demo/conf/layer.conf MediaTek RITY meta-rity-demo] is shown in the following code snipped.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# We have a conf and classes directory, add to BBPATH&lt;br /&gt;
BBPATH .= &amp;quot;:${LAYERDIR}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# We have recipes-* directories, add to BBFILES&lt;br /&gt;
BBFILES += &amp;quot;${LAYERDIR}/recipes-*/*/*.bb ${LAYERDIR}/recipes-*/*/*.bbappend&amp;quot;&lt;br /&gt;
&lt;br /&gt;
BBFILE_COLLECTIONS += &amp;quot;pn-mtk&amp;quot;&lt;br /&gt;
BBFILE_PATTERN_pn-mtk = &amp;quot;^${LAYERDIR}/&amp;quot;&lt;br /&gt;
BBFILE_PRIORITY_pn-mtk = &amp;quot;9&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# This should only be incremented on significant changes that will&lt;br /&gt;
# cause compatibility issues with other layers&lt;br /&gt;
LAYERVERSION_pn-mtk = &amp;quot;1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
LAYERDEPENDS_pn-mtk = &amp;quot; \&lt;br /&gt;
	core \&lt;br /&gt;
	mediatek-bsp \&lt;br /&gt;
	mediatek-tsn \&lt;br /&gt;
	mediatek-bluedroid \&lt;br /&gt;
	mediatek-demo \&lt;br /&gt;
	multimedia-layer \&lt;br /&gt;
	openembedded-layer \&lt;br /&gt;
	networking-layer \&lt;br /&gt;
	meta-python \&lt;br /&gt;
&amp;quot;&lt;br /&gt;
&lt;br /&gt;
LAYERSERIES_COMPAT_pn-mtk = &amp;quot;scarthgap&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 2. Add base distro config===&lt;br /&gt;
&lt;br /&gt;
In order to add the initial distro configuration, it is necessary to create distro configuration file inside the &#039;&#039;&#039;meta-layer/conf/distro&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
Here is an example of how the directory structure should look like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-pn-mtk/&lt;br /&gt;
├── conf&lt;br /&gt;
│   ├── distro&lt;br /&gt;
│   │   └── pn-mtk.conf&lt;br /&gt;
│   └── layer.conf&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The same as with the layer.conf, it is easier to start with an existing distro configuration file and modify it in order to fit the project requirements. For example, the following corresponds to a distro configuration file based on the [https://gitlab.com/mediatek/aiot/rity/meta-rity/-/blob/rity-scarthgap-v25.0/meta-rity-demo/conf/distro/rity-demo.conf MediaTek meta-rity-demo]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
require conf/distro/rity.inc&lt;br /&gt;
&lt;br /&gt;
DISTRO = &amp;quot;pn-mtk&amp;quot;&lt;br /&gt;
DISTRO_NAME = &amp;quot;PN MTK Layer&amp;quot;&lt;br /&gt;
&lt;br /&gt;
INIT_MANAGER = &amp;quot;systemd&amp;quot;&lt;br /&gt;
&lt;br /&gt;
DISTRO_FEATURES:append = &amp;quot; pipewire demo pam fwupdate expand-rootfs btf&amp;quot;&lt;br /&gt;
DISTRO_FEATURES_FILTER_NATIVESDK:append = &amp;quot; wayland&amp;quot;&lt;br /&gt;
VIRTUAL-RUNTIME_vim = &amp;quot;vim&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Mount /var/log/ in persistence storage,&lt;br /&gt;
# so it is possible to keep journalctl logs.&lt;br /&gt;
VOLATILE_LOG_DIR = &amp;quot;0&amp;quot;&lt;br /&gt;
&lt;br /&gt;
PACKAGECONFIG:append:pn-weston-init = &amp;quot; no-idle-timeout&amp;quot;&lt;br /&gt;
&lt;br /&gt;
PACKAGE_CLASSES ?= &amp;quot;package_deb&amp;quot;&lt;br /&gt;
PACKAGE_FEED_URIS ?= &amp;quot;http://192.168.96.20:9876&amp;quot;&lt;br /&gt;
EXTRA_IMAGE_FEATURES:append = &amp;quot; package-management &amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 3. Add base machine===&lt;br /&gt;
&lt;br /&gt;
This step might not be required, if there is already a machine that can be used from a different meta-layer.&lt;br /&gt;
However, it is still recommended to create a custom machine configuration based on that machine in order to keep better order of the machine used in the custom Yocto build.&lt;br /&gt;
&lt;br /&gt;
To create a custom machine, it is necessary to add a machine.conf file in the &#039;&#039;&#039;meta-layer/conf/machine&#039;&#039;&#039; directory.&lt;br /&gt;
For example, this is how the directory structure should look when adding a new machine to the custom meta-layer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-pn-mtk/&lt;br /&gt;
├── conf&lt;br /&gt;
│   ├── distro&lt;br /&gt;
│   │   └── pn-mtk.conf&lt;br /&gt;
│   ├── layer.conf&lt;br /&gt;
│   └── machine&lt;br /&gt;
│       └── mtk-g510.conf&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And, as a reference, here is a custom machine based on [https://gitlab.com/mediatek/aiot/rity/meta-mediatek-bsp/-/blob/rity-scarthgap-v25.0/conf/machine/mt8370-evk.conf MediaTek meta-mediatek-bsp  mt8370-evk.conf] machine.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
require conf/machine/include/mt8370.inc&lt;br /&gt;
require conf/machine/include/mt7921.inc&lt;br /&gt;
&lt;br /&gt;
# Kernel&lt;br /&gt;
KERNEL_DEVICETREE = &amp;quot;mediatek/mt8370-genio-510-evk.dtb&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# U-Boot&lt;br /&gt;
UBOOT_MACHINE = &amp;quot;genio_510_evk_defconfig&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# libdram&lt;br /&gt;
LIBDRAM_BOARD_NAME = &amp;quot;genio-700-evk&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# OP-TEE&lt;br /&gt;
OPTEE_DRAM_SIZE = &amp;quot;0x100000000&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# LK&lt;br /&gt;
LK_BOARD_NAME = &amp;quot;genio-510-evk&amp;quot;&lt;br /&gt;
&lt;br /&gt;
MACHINE_FEATURES:append = &amp;quot; alsa bluetooth pci usbgadget usbhost wifi tsn uc-fde&amp;quot;&lt;br /&gt;
&lt;br /&gt;
MACHINEOVERRIDES =. &amp;quot;mt8370-evk:genio-510-evk:&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# onsemi-firmware&lt;br /&gt;
ONSEMI_BOARD_NAME = &amp;quot;MediaTek_Genio&amp;quot;&lt;br /&gt;
MACHINE_EXTRA_RRECOMMENDS:append = &amp;quot; \&lt;br /&gt;
        onsemi-firmware-ap1302-ar0430 \&lt;br /&gt;
        onsemi-firmware-ap1302-ar0830 \&lt;br /&gt;
&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Drivers for external I2C device&lt;br /&gt;
MACHINE_EXTRA_RRECOMMENDS:append = &amp;quot; \&lt;br /&gt;
        ite-it6510-driver \&lt;br /&gt;
        lontium-lt6911-driver \&lt;br /&gt;
&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 4. Add initial config template files===&lt;br /&gt;
&lt;br /&gt;
Bitbake will require 2 configuration files for building an image:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;bblayers.conf&#039;&#039;&#039;: This file contains information about the location of the required meta-layers for the project.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;local.conf&#039;&#039;&#039;: This file contains general build configuration for bitbake. For instance, in this file it is possible to determine where to store downloads, cache and even which package management configuration to use.&lt;br /&gt;
&lt;br /&gt;
Now, in order to simplify the configuration of a custom Yocto build, it is possible to include template configuration files on the custom meta-layer. This practice is encouraged in order to increase build repeatability.&lt;br /&gt;
&lt;br /&gt;
These 2 files are generally created inside &#039;&#039;&#039;meta-layer/conf/templates/template-name&#039;&#039;&#039;.&lt;br /&gt;
For reference, this is how the directory structure would look like after the files are created:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-pn-mtk/&lt;br /&gt;
├── conf&lt;br /&gt;
│   ├── distro&lt;br /&gt;
│   │   └── pn-mtk.conf&lt;br /&gt;
│   ├── layer.conf&lt;br /&gt;
│   ├── machine&lt;br /&gt;
│   │   └── mtk-g510.conf&lt;br /&gt;
│   └── templates&lt;br /&gt;
│       └── default&lt;br /&gt;
│           ├── bblayers.conf.sample&lt;br /&gt;
│           └── local.conf.sample&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here is an example of a custom bblayers.conf.sample file based on [https://gitlab.com/mediatek/aiot/rity/meta-rity/-/blob/rity-scarthgap-v25.0/meta/conf/templates/default/bblayers.conf.sample MediaTek meta-rity]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# POKY_BBLAYERS_CONF_VERSION is increased each time build/conf/bblayers.conf&lt;br /&gt;
# changes incompatibly&lt;br /&gt;
POKY_BBLAYERS_CONF_VERSION = &amp;quot;2&amp;quot;&lt;br /&gt;
&lt;br /&gt;
BBPATH = &amp;quot;${TOPDIR}&amp;quot;&lt;br /&gt;
BBFILES ?= &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
BBLAYERS ?= &amp;quot; \&lt;br /&gt;
  ##OEROOT##/meta \&lt;br /&gt;
  ##OEROOT##/meta-poky \&lt;br /&gt;
  ##OEROOT##/meta-yocto-bsp \&lt;br /&gt;
  ##OEROOT##/../meta-arm/meta-arm \&lt;br /&gt;
  ##OEROOT##/../meta-arm/meta-arm-toolchain \&lt;br /&gt;
  ##OEROOT##/../meta-clang \&lt;br /&gt;
  ##OEROOT##/../meta-mediatek-bsp \&lt;br /&gt;
  ##OEROOT##/../meta-mediatek-tsn \&lt;br /&gt;
  ##OEROOT##/../meta-mediatek-bluedroid \&lt;br /&gt;
  ##OEROOT##/../meta-mediatek-demo \&lt;br /&gt;
  ##OEROOT##/../meta-nn \&lt;br /&gt;
  ##OEROOT##/../meta-security \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-multimedia \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-networking \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-oe \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-python \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-perl \&lt;br /&gt;
  ##OEROOT##/../meta-rity/meta \&lt;br /&gt;
  ##OEROOT##/../meta-rity/meta-rity-bringup \&lt;br /&gt;
  ##OEROOT##/../meta-rity/meta-rity-demo \&lt;br /&gt;
  ##OEROOT##/../../../meta-pn-mtk \&lt;br /&gt;
  &amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And, this is an example of a custom local.conf.sample file based on [https://gitlab.com/mediatek/aiot/rity/meta-rity/-/blob/rity-scarthgap-v25.0/meta/conf/templates/default/local.conf.sample MediaTek meta-rity]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# POKY_BBLAYERS_CONF_VERSION is increased each time build/conf/bblayers.conf&lt;br /&gt;
# changes incompatibly&lt;br /&gt;
POKY_BBLAYERS_CONF_VERSION = &amp;quot;2&amp;quot;&lt;br /&gt;
&lt;br /&gt;
BBPATH = &amp;quot;${TOPDIR}&amp;quot;&lt;br /&gt;
BBFILES ?= &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
BBLAYERS ?= &amp;quot; \&lt;br /&gt;
  ##OEROOT##/meta \&lt;br /&gt;
  ##OEROOT##/meta-poky \&lt;br /&gt;
  ##OEROOT##/meta-yocto-bsp \&lt;br /&gt;
  ##OEROOT##/../meta-arm/meta-arm \&lt;br /&gt;
  ##OEROOT##/../meta-arm/meta-arm-toolchain \&lt;br /&gt;
  ##OEROOT##/../meta-clang \&lt;br /&gt;
  ##OEROOT##/../meta-mediatek-bsp \&lt;br /&gt;
  ##OEROOT##/../meta-mediatek-tsn \&lt;br /&gt;
  ##OEROOT##/../meta-mediatek-bluedroid \&lt;br /&gt;
  ##OEROOT##/../meta-mediatek-demo \&lt;br /&gt;
  ##OEROOT##/../meta-nn \&lt;br /&gt;
  ##OEROOT##/../meta-security \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-multimedia \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-networking \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-oe \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-python \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-perl \&lt;br /&gt;
  ##OEROOT##/../meta-rity/meta \&lt;br /&gt;
  ##OEROOT##/../meta-rity/meta-rity-bringup \&lt;br /&gt;
  ##OEROOT##/../meta-rity/meta-rity-demo \&lt;br /&gt;
  ##OEROOT##/../../../meta-pn-mtk \&lt;br /&gt;
  &amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 5. Add base image recipe===&lt;br /&gt;
&lt;br /&gt;
In order to create a custom image, it is necessary to add a custom image recipe file.&lt;br /&gt;
This file is usually added inside the &#039;&#039;&#039;meta-layer/recipes-layer/images&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-pn-mtk/&lt;br /&gt;
├── conf&lt;br /&gt;
│   ├── distro&lt;br /&gt;
│   │   └── pn-mtk.conf&lt;br /&gt;
│   ├── layer.conf&lt;br /&gt;
│   ├── machine&lt;br /&gt;
│   │   └── mtk-g510.conf&lt;br /&gt;
│   └── templates&lt;br /&gt;
│       └── default&lt;br /&gt;
│           ├── bblayers.conf.sample&lt;br /&gt;
│           └── local.conf.sample&lt;br /&gt;
├── README.md&lt;br /&gt;
└── recipes-pn-mtk&lt;br /&gt;
    └── images&lt;br /&gt;
        └── pn-mtk-image-base.bb&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once again, a custom image recipe can be based on another image recipe. And, it can also import other image recipes in order to include their base configurations.&lt;br /&gt;
&lt;br /&gt;
As reference, the following image recipe was based on [https://gitlab.com/mediatek/aiot/rity/meta-rity/-/blob/rity-scarthgap-v25.0/meta-rity-demo/recipes-demo/images/rity-demo-image.bb MediaTek meta-rity rity-demo-image recipe]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
require rity-bsp-image.bb&lt;br /&gt;
&lt;br /&gt;
DESCRIPTION = &amp;quot;PN MTK Demo Image&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#FIXME: Removed pkggroups&lt;br /&gt;
IMAGE_INSTALL += &amp;quot;\&lt;br /&gt;
	packagegroup-rity-graphics \&lt;br /&gt;
	rity-demo-opencl \&lt;br /&gt;
	python3-pip \&lt;br /&gt;
	python3-opencv \&lt;br /&gt;
	opkg \&lt;br /&gt;
	benchmark-suite \&lt;br /&gt;
	ltp \&lt;br /&gt;
	stress-scripts \&lt;br /&gt;
	packagegroup-rity-ai-ml \&lt;br /&gt;
&amp;quot;&lt;br /&gt;
&lt;br /&gt;
IMAGE_INSTALL:append:genio-510 = &amp;quot; \&lt;br /&gt;
	packagegroup-rity-tsn \&lt;br /&gt;
&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Footer}}&lt;/div&gt;</summary>
		<author><name>Andres</name></author>
	</entry>
	<entry>
		<id>https://developerwiki.proventusnova.com/index.php?title=How_to_create_a_custom_yocto_meta_layer&amp;diff=205</id>
		<title>How to create a custom yocto meta layer</title>
		<link rel="alternate" type="text/html" href="https://developerwiki.proventusnova.com/index.php?title=How_to_create_a_custom_yocto_meta_layer&amp;diff=205"/>
		<updated>2025-06-14T18:45:55Z</updated>

		<summary type="html">&lt;p&gt;Andres: /* Pre-requisites */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This wiki will provide a detailed guide on how to create a custom Yocto meta-layer.&lt;br /&gt;
&lt;br /&gt;
=Pre-requisites=&lt;br /&gt;
1. The host machine must have the following requirements:&lt;br /&gt;
*At least 90GB of space&lt;br /&gt;
*At least 8GB RAM&lt;br /&gt;
*Host OS must be a supported Linux distribution. (To see supported Linux Distributions, click [https://docs.yoctoproject.org/ref-manual/system-requirements.html#supported-linux-distributions supported distributions])&lt;br /&gt;
&lt;br /&gt;
2. The following packages must be present in the host machine:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apt install build-essential chrpath cpio debianutils diffstat file gawk gcc git iputils-ping libacl1 liblz4-tool locales python3 python3-git python3-jinja2 python3-pexpect python3-pip python3-subunit socat texinfo unzip wget xz-utils zstd&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Create Base Meta-Layer=&lt;br /&gt;
&lt;br /&gt;
This section contains steps to create the base custom meta-layer. &amp;lt;br&amp;gt;&lt;br /&gt;
Creating a layer can be done manually or automatically via bitbake. &amp;lt;br&amp;gt;&lt;br /&gt;
After completion, the custom base meta-layer will contain the following parts:&lt;br /&gt;
&lt;br /&gt;
* Custom layer configuration&lt;br /&gt;
* Custom distro configuration&lt;br /&gt;
* Custom machine&lt;br /&gt;
* Custom config template files&lt;br /&gt;
* Custom image recipe&lt;br /&gt;
&lt;br /&gt;
==Manually create layer==&lt;br /&gt;
&lt;br /&gt;
===Step 1. Add base layer.conf file===&lt;br /&gt;
&lt;br /&gt;
The layer configuration file provides Yocto with the configuration for the custom meta-layer.&lt;br /&gt;
It shall be stored in a directory called &#039;&#039;&#039;conf&#039;&#039;&#039; inside the base meta-layer directory, and it shall be named layer.conf.&lt;br /&gt;
According to the [https://docs.yoctoproject.org/dev/dev-manual/layers.html Yocto documentation] it is recommended to start from an existing layer.conf file from a different meta-layer and change it according to the custom requirements.&lt;br /&gt;
&lt;br /&gt;
For instance, here is an example of how the directory structure should look after creating the layer.conf file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   └── layer.conf&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An example layer.conf file based on [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/conf/layer.conf NVIDIA OE4T tegra_demo_distro] is shown in the following code snipped.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
BBPATH =. &amp;quot;${LAYERDIR}:&amp;quot;&lt;br /&gt;
BBFILES += &amp;quot;${LAYERDIR}/recipes-*/*/*.bb ${LAYERDIR}/recipes-*/*/*.bbappend&amp;quot;&lt;br /&gt;
BBFILES_DYNAMIC += &amp;quot;swupdate:${LAYERDIR}/dynamic-layers/meta-swupdate/recipes-*/*/*.bb \&lt;br /&gt;
                    swupdate:${LAYERDIR}/dynamic-layers/meta-swupdate/recipes-*/*/*.bbappend&amp;quot;&lt;br /&gt;
&lt;br /&gt;
BBFILE_COLLECTIONS += &amp;quot;proventusnova&amp;quot;&lt;br /&gt;
BBFILE_PATTERN_proventusnova = &amp;quot;^${LAYERDIR}/&amp;quot;&lt;br /&gt;
BBFILE_PRIORITY_proventusnova = &amp;quot;50&amp;quot;&lt;br /&gt;
&lt;br /&gt;
LAYERVERSION_proventusnova = &amp;quot;4&amp;quot;&lt;br /&gt;
LAYERSERIES_COMPAT_proventusnova = &amp;quot;scarthgap&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# This is used by the tegra-distro-sanity bbclass&lt;br /&gt;
# to identify the distro layer directory during&lt;br /&gt;
# bblayers checks.&lt;br /&gt;
TD_DISTRO_LAYERDIR = &amp;quot;${LAYERDIR}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 2. Add base distro config===&lt;br /&gt;
&lt;br /&gt;
In order to add the initial distro configuration, it is necessary to create distro configuration file inside the &#039;&#039;&#039;meta-layer/conf/distro&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
Here is an example of how the directory structure should look like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   ├── distro&lt;br /&gt;
│   │   └── proventusnova.conf&lt;br /&gt;
│   └── layer.conf&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The same as with the layer.conf, it is easier to start with an existing distro configuration file and modify it in order to fit the project requirements. For example, the following corresponds to a distro configuration file based on the [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/conf/distro/tegrademo.conf NVIDIA tegra_demo_distro]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
DISTRO = &amp;quot;proventusnova&amp;quot;&lt;br /&gt;
DISTRO_NAME = &amp;quot;ProventusNova Custom Distro&amp;quot;&lt;br /&gt;
DISTRO_VERSION_BASE = &amp;quot;1.0&amp;quot;&lt;br /&gt;
DISTRO_VERSION = &amp;quot;${DISTRO_VERSION_BASE}+snapshot-${METADATA_REVISION}&amp;quot;&lt;br /&gt;
DISTRO_CODENAME = &amp;quot;proventusnova&amp;quot;&lt;br /&gt;
SDK_VENDOR = &amp;quot;-proventusnova&amp;quot;&lt;br /&gt;
SDK_VERSION := &amp;quot;${@&#039;${DISTRO_VERSION}&#039;.replace(&#039;snapshot-${METADATA_REVISION}&#039;,&#039;snapshot&#039;)}&amp;quot;&lt;br /&gt;
SDK_VERSION[vardepvalue] = &amp;quot;${SDK_VERSION}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
MAINTAINER = &amp;quot;ProventusNova team &amp;lt;support@proventusnova.com&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
TARGET_VENDOR = &amp;quot;-proventusnova&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# New ${DISTRO}-&amp;lt;version&amp;gt; setting for sanity checks.&lt;br /&gt;
# Increment version number (and the corresponding&lt;br /&gt;
# setting int the template bblayers.conf.sample file)&lt;br /&gt;
# each time the layer settings are changed.&lt;br /&gt;
REQUIRED_PROVENTUSNOVA_BBLAYERS_CONF_VERSION = &amp;quot;${DISTRO}-1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
LOCALCONF_VERSION = &amp;quot;2&amp;quot;&lt;br /&gt;
&lt;br /&gt;
PROVENTUSNOVA_DEFAULT_DISTRO_FEATURES = &amp;quot;largefile opengl ptest multiarch wayland vulkan systemd pam virtualization usrmerge&amp;quot;&lt;br /&gt;
&lt;br /&gt;
DISTRO_FEATURES ?= &amp;quot;${DISTRO_FEATURES_DEFAULT} ${PROVENTUSNOVA_DEFAULT_DISTRO_FEATURES}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Jetson platforms do not use linux-yocto, but for QEMU testing&lt;br /&gt;
# align with the poky distro.&lt;br /&gt;
PREFERRED_VERSION_linux-yocto ?= &amp;quot;5.19%&amp;quot;&lt;br /&gt;
PREFERRED_VERSION_linux-yocto-rt ?= &amp;quot;5.19%&amp;quot;&lt;br /&gt;
&lt;br /&gt;
SDK_NAME = &amp;quot;${DISTRO}-${TCLIBC}-${SDKMACHINE}-${IMAGE_BASENAME}-${TUNE_PKGARCH}-${MACHINE}&amp;quot;&lt;br /&gt;
SDKPATHINSTALL = &amp;quot;/opt/${DISTRO}/${SDK_VERSION}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
TCLIBCAPPEND = &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
PACKAGE_CLASSES ?= &amp;quot;package_rpm&amp;quot;&lt;br /&gt;
&lt;br /&gt;
SANITY_TESTED_DISTROS ?= &amp;quot; \&lt;br /&gt;
            ubuntu-20.04 \n \&lt;br /&gt;
            ubuntu-22.04 \n \&lt;br /&gt;
            ubuntu-24.04 \n \&lt;br /&gt;
            &amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Most NVIDIA-supplied services expect systemd&lt;br /&gt;
INIT_MANAGER = &amp;quot;systemd&amp;quot;&lt;br /&gt;
&lt;br /&gt;
require conf/distro/include/no-static-libs.inc&lt;br /&gt;
require conf/distro/include/yocto-uninative.inc&lt;br /&gt;
require conf/distro/include/security_flags.inc&lt;br /&gt;
INHERIT += &amp;quot;uninative&amp;quot;&lt;br /&gt;
&lt;br /&gt;
LICENSE_FLAGS_ACCEPTED += &amp;quot;commercial_faad2 commercial_x264&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 3. Add base machine===&lt;br /&gt;
&lt;br /&gt;
This step might not be required, if there is already a machine that can be used from a different meta-layer.&lt;br /&gt;
However, it is still recommended to create a custom machine configuration based on that machine in order to keep better order of the machine used in the custom Yocto build.&lt;br /&gt;
&lt;br /&gt;
To create a custom machine, it is necessary to add a machine.conf file in the &#039;&#039;&#039;meta-layer/conf/machine&#039;&#039;&#039; directory.&lt;br /&gt;
For example, this is how the directory structure should look when adding a new machine to the custom meta-layer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   ├── distro&lt;br /&gt;
│   │   └── proventusnova.conf&lt;br /&gt;
│   ├── layer.conf&lt;br /&gt;
│   └── machine&lt;br /&gt;
│       └── proventusnova-jetson-orin-nx-16-devkit.conf&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And, as a reference, here is a custom machine based on [https://github.com/OE4T/meta-tegra/blob/scarthgap/conf/machine/p3509-a02-p3767-0000.conf NVIDIA meta-tegra  p3509-a02-p3767-0000] machine.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#@TYPE: Machine&lt;br /&gt;
#@NAME: Nvidia Jetson Orin NX 16GB (P3767-0000)&lt;br /&gt;
#@DESCRIPTION: Nvidia Jetson Orin NX 16GB module in P3509 carrier&lt;br /&gt;
&lt;br /&gt;
TEGRA_FLASHVAR_PINMUX_CONFIG ?= &amp;quot;tegra234-mb1-bct-pinmux-p3767-hdmi-a03.dtsi&amp;quot;&lt;br /&gt;
TEGRA_FLASHVAR_PMC_CONFIG ?= &amp;quot;tegra234-mb1-bct-padvoltage-p3767-hdmi-a03.dtsi&amp;quot;&lt;br /&gt;
TEGRA_PLUGIN_MANAGER_OVERLAYS ?= &amp;quot;tegra234-carveouts.dtbo tegra-optee.dtbo tegra234-p3768-0000+p3767-0000-dynamic.dtbo tegra234-dcb-p3767-0000-hdmi.dtbo&amp;quot;&lt;br /&gt;
TEGRA_DCE_OVERLAY ?= &amp;quot;tegra234-dcb-p3767-0000-hdmi.dtbo&amp;quot;&lt;br /&gt;
&lt;br /&gt;
require conf/machine/include/orin-nx.inc&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 4. Add initial config template files===&lt;br /&gt;
&lt;br /&gt;
Bitbake will require 2 configuration files for building an image:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;bblayers.conf&#039;&#039;&#039;: This file contains information about the location of the required meta-layers for the project.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;local.conf&#039;&#039;&#039;: This file contains general build configuration for bitbake. For instance, in this file it is possible to determine where to store downloads, cache and even which package management configuration to use.&lt;br /&gt;
&lt;br /&gt;
Now, in order to simplify the configuration of a custom Yocto build, it is possible to include template configuration files on the custom meta-layer. This practice is encouraged in order to increase build repeatability.&lt;br /&gt;
&lt;br /&gt;
These 2 files are generally created inside &#039;&#039;&#039;meta-layer/conf/templates/template-name&#039;&#039;&#039;.&lt;br /&gt;
For reference, this is how the directory structure would look like after the files are created:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   ├── distro&lt;br /&gt;
│   │   └── proventusnova.conf&lt;br /&gt;
│   ├── layer.conf&lt;br /&gt;
│   ├── machine&lt;br /&gt;
│   │   └── proventusnova-jetson-orin-nx-16-devkit.conf&lt;br /&gt;
│   └── templates&lt;br /&gt;
│       └── proventusnova&lt;br /&gt;
│           ├── bblayers.conf.sample&lt;br /&gt;
│           └── local.conf.sample&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here is an example of a custom bblayers.conf.sample file based on [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/conf/templates/tegrademo/bblayers.conf.sample NVIDIA tegra-demo-distro]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Version of layers configuration, specific to&lt;br /&gt;
# each defined distro in the repository.&lt;br /&gt;
# Format: ${DISTRO}-&amp;lt;version&amp;gt;&lt;br /&gt;
TD_BBLAYERS_CONF_VERSION = &amp;quot;proventusnova-1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
BBPATH = &amp;quot;${TOPDIR}&amp;quot;&lt;br /&gt;
BBFILES ?= &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
BBLAYERS ?= &amp;quot; \&lt;br /&gt;
  ##OEROOT##/meta \&lt;br /&gt;
  ##OEROOT##/../meta-tegra \&lt;br /&gt;
  ##OEROOT##/../meta-tegra-community \&lt;br /&gt;
  ##OEROOT##/../meta-virtualization \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-oe \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-python \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-networking \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-filesystems \&lt;br /&gt;
  &amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And, this is an example of a custom local.conf.sample file based on [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/conf/templates/tegrademo/local.conf.sample NVIDIA tegra-demo-distro]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
# Machine Selection&lt;br /&gt;
#&lt;br /&gt;
MACHINE ??= &amp;quot;proventusnova-jetson-orin-nx-16-devkit.conf&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Where to place downloads&lt;br /&gt;
#&lt;br /&gt;
DL_DIR ?= &amp;quot;${TOPDIR}/../downloads&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Where to place shared-state files&lt;br /&gt;
#&lt;br /&gt;
SSTATE_DIR ?= &amp;quot;${TOPDIR}/../sstate-cache&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Where to place the build output&lt;br /&gt;
#&lt;br /&gt;
TMPDIR = &amp;quot;${TOPDIR}/tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Default policy (distro) config&lt;br /&gt;
#&lt;br /&gt;
DISTRO ?= &amp;quot;proventusnova&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Package Management configuration&lt;br /&gt;
#&lt;br /&gt;
PACKAGE_CLASSES ?= &amp;quot;package_deb&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# SDK target architecture&lt;br /&gt;
#&lt;br /&gt;
SDKMACHINE ?= &amp;quot;x86_64&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Extra image configuration defaults&lt;br /&gt;
#&lt;br /&gt;
EXTRA_IMAGE_FEATURES ?= &amp;quot;debug-tweaks&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Additional image features&lt;br /&gt;
#&lt;br /&gt;
USER_CLASSES ?= &amp;quot;buildstats&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Interactive shell configuration&lt;br /&gt;
#&lt;br /&gt;
PATCHRESOLVE = &amp;quot;noop&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Disk Space Monitoring during the build&lt;br /&gt;
#&lt;br /&gt;
BB_DISKMON_DIRS ??= &amp;quot;\&lt;br /&gt;
    STOPTASKS,${TMPDIR},1G,100K \&lt;br /&gt;
    STOPTASKS,${DL_DIR},1G,100K \&lt;br /&gt;
    STOPTASKS,${SSTATE_DIR},1G,100K \&lt;br /&gt;
    STOPTASKS,/tmp,100M,100K \&lt;br /&gt;
    HALT,${TMPDIR},100M,1K \&lt;br /&gt;
    HALT,${DL_DIR},100M,1K \&lt;br /&gt;
    HALT,${SSTATE_DIR},100M,1K \&lt;br /&gt;
    HALT,/tmp,10M,1K&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Qemu configuration&lt;br /&gt;
#&lt;br /&gt;
PACKAGECONFIG:append:pn-qemu-system-native = &amp;quot; sdl&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# CONF_VERSION is increased each time build/conf/ changes incompatibly and is used to&lt;br /&gt;
# track the version of this file when it was generated.&lt;br /&gt;
CONF_VERSION = &amp;quot;2&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 5. Add base image recipe===&lt;br /&gt;
&lt;br /&gt;
In order to create a custom image, it is necessary to add a custom image recipe file.&lt;br /&gt;
This file is usually added inside the &#039;&#039;&#039;meta-layer/recipes-layer/images&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   ├── distro&lt;br /&gt;
│   │   └── proventusnova.conf&lt;br /&gt;
│   ├── layer.conf&lt;br /&gt;
│   ├── machine&lt;br /&gt;
│   │   └── proventusnova-jetson-orin-nx-16-devkit.conf&lt;br /&gt;
│   └── templates&lt;br /&gt;
│       ├── bblayers.conf.sample&lt;br /&gt;
│       └── local.conf.sample&lt;br /&gt;
├── README.md&lt;br /&gt;
└── recipes-proventusnova&lt;br /&gt;
    └── images&lt;br /&gt;
        └── proventusnova-image-base.bb&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once again, a custom image recipe can be based on another image recipe. And, it can also import other image recipes in order to include their base configurations.&lt;br /&gt;
&lt;br /&gt;
As reference, the following image recipe was based on [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/recipes-demo/images/demo-image-base.bb NVIDIA tegra-demo-distro demo-image-base recipe]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
DESCRIPTION = &amp;quot;ProventusNova base image&amp;quot;&lt;br /&gt;
LICENSE = &amp;quot;CLOSED&amp;quot;&lt;br /&gt;
&lt;br /&gt;
inherit core-image&lt;br /&gt;
&lt;br /&gt;
IMAGE_FEATURES += &amp;quot;ssh-server-openssh debug-tweaks&amp;quot;&lt;br /&gt;
&lt;br /&gt;
CORE_IMAGE_BASE_INSTALL += &amp;quot;systemd&amp;quot;&lt;br /&gt;
TOOLCHAIN_HOST_TASK += &amp;quot;nativesdk-packagegroup-cuda-sdk-host&amp;quot;&lt;br /&gt;
&lt;br /&gt;
inherit nopackages&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Create layer via bitbake==&lt;br /&gt;
&lt;br /&gt;
===Step 1. Create custom layer===&lt;br /&gt;
&lt;br /&gt;
Run the following command to create a custom layer&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bitbake-layers create-layer meta-proventusnova&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This should automatically create a meta-proventusnova folder with the following structure&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   └──layer.conf&lt;br /&gt;
├── COPYING.MIT&lt;br /&gt;
├── recipes-example&lt;br /&gt;
│    └── example&lt;br /&gt;
│        └──example_0.1.bb&lt;br /&gt;
└── README.md&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 2. Add custom layer===&lt;br /&gt;
Next is to add the custom layer to the project.&amp;lt;br&amp;gt;&lt;br /&gt;
Run the following command to add the custom layer&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bitbake-layers add-layer meta-proventusnova&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This should add the meta-proventusnova to the build/conf/bblayers.conf file or where you set the build directory.&lt;br /&gt;
&lt;br /&gt;
{{Footer}}&lt;/div&gt;</summary>
		<author><name>Andres</name></author>
	</entry>
	<entry>
		<id>https://developerwiki.proventusnova.com/index.php?title=How_to_create_a_custom_yocto_meta_layer&amp;diff=204</id>
		<title>How to create a custom yocto meta layer</title>
		<link rel="alternate" type="text/html" href="https://developerwiki.proventusnova.com/index.php?title=How_to_create_a_custom_yocto_meta_layer&amp;diff=204"/>
		<updated>2025-06-14T18:45:27Z</updated>

		<summary type="html">&lt;p&gt;Andres: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This wiki will provide a detailed guide on how to create a custom Yocto meta-layer.&lt;br /&gt;
&lt;br /&gt;
=Pre-requisites=&lt;br /&gt;
1. The host machine must have the following requirements:&lt;br /&gt;
*At least 90GB of space&lt;br /&gt;
*At least 8GB RAM&lt;br /&gt;
*Host OS must be a supported Linux distribution. (To see supported Linux Distributions, click [https://docs.yoctoproject.org/ref-manual/system-requirements.html#supported-linux-distributions supported distributions])&lt;br /&gt;
&lt;br /&gt;
2. The following packages must be present in the host machine:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apt install build-essential chrpath cpio debianutils diffstat file gawk gcc git iputils-ping libacl1 liblz4-tool locales python3 python3-git python3-jinja2 python3-pexpect python3-pip python3-subunit socat texinfo unzip wget xz-utils zstd&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3. Get the latest copy of the [https://github.com/yoctoproject/poky Poky repository]. &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git clone git://git.yoctoproject.org/poky&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Create Base Meta-Layer=&lt;br /&gt;
&lt;br /&gt;
This section contains steps to create the base custom meta-layer. &amp;lt;br&amp;gt;&lt;br /&gt;
Creating a layer can be done manually or automatically via bitbake. &amp;lt;br&amp;gt;&lt;br /&gt;
After completion, the custom base meta-layer will contain the following parts:&lt;br /&gt;
&lt;br /&gt;
* Custom layer configuration&lt;br /&gt;
* Custom distro configuration&lt;br /&gt;
* Custom machine&lt;br /&gt;
* Custom config template files&lt;br /&gt;
* Custom image recipe&lt;br /&gt;
&lt;br /&gt;
==Manually create layer==&lt;br /&gt;
&lt;br /&gt;
===Step 1. Add base layer.conf file===&lt;br /&gt;
&lt;br /&gt;
The layer configuration file provides Yocto with the configuration for the custom meta-layer.&lt;br /&gt;
It shall be stored in a directory called &#039;&#039;&#039;conf&#039;&#039;&#039; inside the base meta-layer directory, and it shall be named layer.conf.&lt;br /&gt;
According to the [https://docs.yoctoproject.org/dev/dev-manual/layers.html Yocto documentation] it is recommended to start from an existing layer.conf file from a different meta-layer and change it according to the custom requirements.&lt;br /&gt;
&lt;br /&gt;
For instance, here is an example of how the directory structure should look after creating the layer.conf file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   └── layer.conf&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An example layer.conf file based on [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/conf/layer.conf NVIDIA OE4T tegra_demo_distro] is shown in the following code snipped.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
BBPATH =. &amp;quot;${LAYERDIR}:&amp;quot;&lt;br /&gt;
BBFILES += &amp;quot;${LAYERDIR}/recipes-*/*/*.bb ${LAYERDIR}/recipes-*/*/*.bbappend&amp;quot;&lt;br /&gt;
BBFILES_DYNAMIC += &amp;quot;swupdate:${LAYERDIR}/dynamic-layers/meta-swupdate/recipes-*/*/*.bb \&lt;br /&gt;
                    swupdate:${LAYERDIR}/dynamic-layers/meta-swupdate/recipes-*/*/*.bbappend&amp;quot;&lt;br /&gt;
&lt;br /&gt;
BBFILE_COLLECTIONS += &amp;quot;proventusnova&amp;quot;&lt;br /&gt;
BBFILE_PATTERN_proventusnova = &amp;quot;^${LAYERDIR}/&amp;quot;&lt;br /&gt;
BBFILE_PRIORITY_proventusnova = &amp;quot;50&amp;quot;&lt;br /&gt;
&lt;br /&gt;
LAYERVERSION_proventusnova = &amp;quot;4&amp;quot;&lt;br /&gt;
LAYERSERIES_COMPAT_proventusnova = &amp;quot;scarthgap&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# This is used by the tegra-distro-sanity bbclass&lt;br /&gt;
# to identify the distro layer directory during&lt;br /&gt;
# bblayers checks.&lt;br /&gt;
TD_DISTRO_LAYERDIR = &amp;quot;${LAYERDIR}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 2. Add base distro config===&lt;br /&gt;
&lt;br /&gt;
In order to add the initial distro configuration, it is necessary to create distro configuration file inside the &#039;&#039;&#039;meta-layer/conf/distro&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
Here is an example of how the directory structure should look like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   ├── distro&lt;br /&gt;
│   │   └── proventusnova.conf&lt;br /&gt;
│   └── layer.conf&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The same as with the layer.conf, it is easier to start with an existing distro configuration file and modify it in order to fit the project requirements. For example, the following corresponds to a distro configuration file based on the [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/conf/distro/tegrademo.conf NVIDIA tegra_demo_distro]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
DISTRO = &amp;quot;proventusnova&amp;quot;&lt;br /&gt;
DISTRO_NAME = &amp;quot;ProventusNova Custom Distro&amp;quot;&lt;br /&gt;
DISTRO_VERSION_BASE = &amp;quot;1.0&amp;quot;&lt;br /&gt;
DISTRO_VERSION = &amp;quot;${DISTRO_VERSION_BASE}+snapshot-${METADATA_REVISION}&amp;quot;&lt;br /&gt;
DISTRO_CODENAME = &amp;quot;proventusnova&amp;quot;&lt;br /&gt;
SDK_VENDOR = &amp;quot;-proventusnova&amp;quot;&lt;br /&gt;
SDK_VERSION := &amp;quot;${@&#039;${DISTRO_VERSION}&#039;.replace(&#039;snapshot-${METADATA_REVISION}&#039;,&#039;snapshot&#039;)}&amp;quot;&lt;br /&gt;
SDK_VERSION[vardepvalue] = &amp;quot;${SDK_VERSION}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
MAINTAINER = &amp;quot;ProventusNova team &amp;lt;support@proventusnova.com&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
TARGET_VENDOR = &amp;quot;-proventusnova&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# New ${DISTRO}-&amp;lt;version&amp;gt; setting for sanity checks.&lt;br /&gt;
# Increment version number (and the corresponding&lt;br /&gt;
# setting int the template bblayers.conf.sample file)&lt;br /&gt;
# each time the layer settings are changed.&lt;br /&gt;
REQUIRED_PROVENTUSNOVA_BBLAYERS_CONF_VERSION = &amp;quot;${DISTRO}-1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
LOCALCONF_VERSION = &amp;quot;2&amp;quot;&lt;br /&gt;
&lt;br /&gt;
PROVENTUSNOVA_DEFAULT_DISTRO_FEATURES = &amp;quot;largefile opengl ptest multiarch wayland vulkan systemd pam virtualization usrmerge&amp;quot;&lt;br /&gt;
&lt;br /&gt;
DISTRO_FEATURES ?= &amp;quot;${DISTRO_FEATURES_DEFAULT} ${PROVENTUSNOVA_DEFAULT_DISTRO_FEATURES}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Jetson platforms do not use linux-yocto, but for QEMU testing&lt;br /&gt;
# align with the poky distro.&lt;br /&gt;
PREFERRED_VERSION_linux-yocto ?= &amp;quot;5.19%&amp;quot;&lt;br /&gt;
PREFERRED_VERSION_linux-yocto-rt ?= &amp;quot;5.19%&amp;quot;&lt;br /&gt;
&lt;br /&gt;
SDK_NAME = &amp;quot;${DISTRO}-${TCLIBC}-${SDKMACHINE}-${IMAGE_BASENAME}-${TUNE_PKGARCH}-${MACHINE}&amp;quot;&lt;br /&gt;
SDKPATHINSTALL = &amp;quot;/opt/${DISTRO}/${SDK_VERSION}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
TCLIBCAPPEND = &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
PACKAGE_CLASSES ?= &amp;quot;package_rpm&amp;quot;&lt;br /&gt;
&lt;br /&gt;
SANITY_TESTED_DISTROS ?= &amp;quot; \&lt;br /&gt;
            ubuntu-20.04 \n \&lt;br /&gt;
            ubuntu-22.04 \n \&lt;br /&gt;
            ubuntu-24.04 \n \&lt;br /&gt;
            &amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Most NVIDIA-supplied services expect systemd&lt;br /&gt;
INIT_MANAGER = &amp;quot;systemd&amp;quot;&lt;br /&gt;
&lt;br /&gt;
require conf/distro/include/no-static-libs.inc&lt;br /&gt;
require conf/distro/include/yocto-uninative.inc&lt;br /&gt;
require conf/distro/include/security_flags.inc&lt;br /&gt;
INHERIT += &amp;quot;uninative&amp;quot;&lt;br /&gt;
&lt;br /&gt;
LICENSE_FLAGS_ACCEPTED += &amp;quot;commercial_faad2 commercial_x264&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 3. Add base machine===&lt;br /&gt;
&lt;br /&gt;
This step might not be required, if there is already a machine that can be used from a different meta-layer.&lt;br /&gt;
However, it is still recommended to create a custom machine configuration based on that machine in order to keep better order of the machine used in the custom Yocto build.&lt;br /&gt;
&lt;br /&gt;
To create a custom machine, it is necessary to add a machine.conf file in the &#039;&#039;&#039;meta-layer/conf/machine&#039;&#039;&#039; directory.&lt;br /&gt;
For example, this is how the directory structure should look when adding a new machine to the custom meta-layer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   ├── distro&lt;br /&gt;
│   │   └── proventusnova.conf&lt;br /&gt;
│   ├── layer.conf&lt;br /&gt;
│   └── machine&lt;br /&gt;
│       └── proventusnova-jetson-orin-nx-16-devkit.conf&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And, as a reference, here is a custom machine based on [https://github.com/OE4T/meta-tegra/blob/scarthgap/conf/machine/p3509-a02-p3767-0000.conf NVIDIA meta-tegra  p3509-a02-p3767-0000] machine.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#@TYPE: Machine&lt;br /&gt;
#@NAME: Nvidia Jetson Orin NX 16GB (P3767-0000)&lt;br /&gt;
#@DESCRIPTION: Nvidia Jetson Orin NX 16GB module in P3509 carrier&lt;br /&gt;
&lt;br /&gt;
TEGRA_FLASHVAR_PINMUX_CONFIG ?= &amp;quot;tegra234-mb1-bct-pinmux-p3767-hdmi-a03.dtsi&amp;quot;&lt;br /&gt;
TEGRA_FLASHVAR_PMC_CONFIG ?= &amp;quot;tegra234-mb1-bct-padvoltage-p3767-hdmi-a03.dtsi&amp;quot;&lt;br /&gt;
TEGRA_PLUGIN_MANAGER_OVERLAYS ?= &amp;quot;tegra234-carveouts.dtbo tegra-optee.dtbo tegra234-p3768-0000+p3767-0000-dynamic.dtbo tegra234-dcb-p3767-0000-hdmi.dtbo&amp;quot;&lt;br /&gt;
TEGRA_DCE_OVERLAY ?= &amp;quot;tegra234-dcb-p3767-0000-hdmi.dtbo&amp;quot;&lt;br /&gt;
&lt;br /&gt;
require conf/machine/include/orin-nx.inc&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 4. Add initial config template files===&lt;br /&gt;
&lt;br /&gt;
Bitbake will require 2 configuration files for building an image:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;bblayers.conf&#039;&#039;&#039;: This file contains information about the location of the required meta-layers for the project.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;local.conf&#039;&#039;&#039;: This file contains general build configuration for bitbake. For instance, in this file it is possible to determine where to store downloads, cache and even which package management configuration to use.&lt;br /&gt;
&lt;br /&gt;
Now, in order to simplify the configuration of a custom Yocto build, it is possible to include template configuration files on the custom meta-layer. This practice is encouraged in order to increase build repeatability.&lt;br /&gt;
&lt;br /&gt;
These 2 files are generally created inside &#039;&#039;&#039;meta-layer/conf/templates/template-name&#039;&#039;&#039;.&lt;br /&gt;
For reference, this is how the directory structure would look like after the files are created:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   ├── distro&lt;br /&gt;
│   │   └── proventusnova.conf&lt;br /&gt;
│   ├── layer.conf&lt;br /&gt;
│   ├── machine&lt;br /&gt;
│   │   └── proventusnova-jetson-orin-nx-16-devkit.conf&lt;br /&gt;
│   └── templates&lt;br /&gt;
│       └── proventusnova&lt;br /&gt;
│           ├── bblayers.conf.sample&lt;br /&gt;
│           └── local.conf.sample&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here is an example of a custom bblayers.conf.sample file based on [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/conf/templates/tegrademo/bblayers.conf.sample NVIDIA tegra-demo-distro]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Version of layers configuration, specific to&lt;br /&gt;
# each defined distro in the repository.&lt;br /&gt;
# Format: ${DISTRO}-&amp;lt;version&amp;gt;&lt;br /&gt;
TD_BBLAYERS_CONF_VERSION = &amp;quot;proventusnova-1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
BBPATH = &amp;quot;${TOPDIR}&amp;quot;&lt;br /&gt;
BBFILES ?= &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
BBLAYERS ?= &amp;quot; \&lt;br /&gt;
  ##OEROOT##/meta \&lt;br /&gt;
  ##OEROOT##/../meta-tegra \&lt;br /&gt;
  ##OEROOT##/../meta-tegra-community \&lt;br /&gt;
  ##OEROOT##/../meta-virtualization \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-oe \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-python \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-networking \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-filesystems \&lt;br /&gt;
  &amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And, this is an example of a custom local.conf.sample file based on [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/conf/templates/tegrademo/local.conf.sample NVIDIA tegra-demo-distro]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
# Machine Selection&lt;br /&gt;
#&lt;br /&gt;
MACHINE ??= &amp;quot;proventusnova-jetson-orin-nx-16-devkit.conf&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Where to place downloads&lt;br /&gt;
#&lt;br /&gt;
DL_DIR ?= &amp;quot;${TOPDIR}/../downloads&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Where to place shared-state files&lt;br /&gt;
#&lt;br /&gt;
SSTATE_DIR ?= &amp;quot;${TOPDIR}/../sstate-cache&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Where to place the build output&lt;br /&gt;
#&lt;br /&gt;
TMPDIR = &amp;quot;${TOPDIR}/tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Default policy (distro) config&lt;br /&gt;
#&lt;br /&gt;
DISTRO ?= &amp;quot;proventusnova&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Package Management configuration&lt;br /&gt;
#&lt;br /&gt;
PACKAGE_CLASSES ?= &amp;quot;package_deb&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# SDK target architecture&lt;br /&gt;
#&lt;br /&gt;
SDKMACHINE ?= &amp;quot;x86_64&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Extra image configuration defaults&lt;br /&gt;
#&lt;br /&gt;
EXTRA_IMAGE_FEATURES ?= &amp;quot;debug-tweaks&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Additional image features&lt;br /&gt;
#&lt;br /&gt;
USER_CLASSES ?= &amp;quot;buildstats&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Interactive shell configuration&lt;br /&gt;
#&lt;br /&gt;
PATCHRESOLVE = &amp;quot;noop&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Disk Space Monitoring during the build&lt;br /&gt;
#&lt;br /&gt;
BB_DISKMON_DIRS ??= &amp;quot;\&lt;br /&gt;
    STOPTASKS,${TMPDIR},1G,100K \&lt;br /&gt;
    STOPTASKS,${DL_DIR},1G,100K \&lt;br /&gt;
    STOPTASKS,${SSTATE_DIR},1G,100K \&lt;br /&gt;
    STOPTASKS,/tmp,100M,100K \&lt;br /&gt;
    HALT,${TMPDIR},100M,1K \&lt;br /&gt;
    HALT,${DL_DIR},100M,1K \&lt;br /&gt;
    HALT,${SSTATE_DIR},100M,1K \&lt;br /&gt;
    HALT,/tmp,10M,1K&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Qemu configuration&lt;br /&gt;
#&lt;br /&gt;
PACKAGECONFIG:append:pn-qemu-system-native = &amp;quot; sdl&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# CONF_VERSION is increased each time build/conf/ changes incompatibly and is used to&lt;br /&gt;
# track the version of this file when it was generated.&lt;br /&gt;
CONF_VERSION = &amp;quot;2&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 5. Add base image recipe===&lt;br /&gt;
&lt;br /&gt;
In order to create a custom image, it is necessary to add a custom image recipe file.&lt;br /&gt;
This file is usually added inside the &#039;&#039;&#039;meta-layer/recipes-layer/images&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   ├── distro&lt;br /&gt;
│   │   └── proventusnova.conf&lt;br /&gt;
│   ├── layer.conf&lt;br /&gt;
│   ├── machine&lt;br /&gt;
│   │   └── proventusnova-jetson-orin-nx-16-devkit.conf&lt;br /&gt;
│   └── templates&lt;br /&gt;
│       ├── bblayers.conf.sample&lt;br /&gt;
│       └── local.conf.sample&lt;br /&gt;
├── README.md&lt;br /&gt;
└── recipes-proventusnova&lt;br /&gt;
    └── images&lt;br /&gt;
        └── proventusnova-image-base.bb&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once again, a custom image recipe can be based on another image recipe. And, it can also import other image recipes in order to include their base configurations.&lt;br /&gt;
&lt;br /&gt;
As reference, the following image recipe was based on [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/recipes-demo/images/demo-image-base.bb NVIDIA tegra-demo-distro demo-image-base recipe]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
DESCRIPTION = &amp;quot;ProventusNova base image&amp;quot;&lt;br /&gt;
LICENSE = &amp;quot;CLOSED&amp;quot;&lt;br /&gt;
&lt;br /&gt;
inherit core-image&lt;br /&gt;
&lt;br /&gt;
IMAGE_FEATURES += &amp;quot;ssh-server-openssh debug-tweaks&amp;quot;&lt;br /&gt;
&lt;br /&gt;
CORE_IMAGE_BASE_INSTALL += &amp;quot;systemd&amp;quot;&lt;br /&gt;
TOOLCHAIN_HOST_TASK += &amp;quot;nativesdk-packagegroup-cuda-sdk-host&amp;quot;&lt;br /&gt;
&lt;br /&gt;
inherit nopackages&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Create layer via bitbake==&lt;br /&gt;
&lt;br /&gt;
===Step 1. Create custom layer===&lt;br /&gt;
&lt;br /&gt;
Run the following command to create a custom layer&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bitbake-layers create-layer meta-proventusnova&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This should automatically create a meta-proventusnova folder with the following structure&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   └──layer.conf&lt;br /&gt;
├── COPYING.MIT&lt;br /&gt;
├── recipes-example&lt;br /&gt;
│    └── example&lt;br /&gt;
│        └──example_0.1.bb&lt;br /&gt;
└── README.md&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 2. Add custom layer===&lt;br /&gt;
Next is to add the custom layer to the project.&amp;lt;br&amp;gt;&lt;br /&gt;
Run the following command to add the custom layer&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bitbake-layers add-layer meta-proventusnova&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This should add the meta-proventusnova to the build/conf/bblayers.conf file or where you set the build directory.&lt;br /&gt;
&lt;br /&gt;
{{Footer}}&lt;/div&gt;</summary>
		<author><name>Andres</name></author>
	</entry>
	<entry>
		<id>https://developerwiki.proventusnova.com/index.php?title=Template:Footer&amp;diff=203</id>
		<title>Template:Footer</title>
		<link rel="alternate" type="text/html" href="https://developerwiki.proventusnova.com/index.php?title=Template:Footer&amp;diff=203"/>
		<updated>2025-06-09T00:20:38Z</updated>

		<summary type="html">&lt;p&gt;Andres: /* 🏗 Customized Technology Solutions for Your Business */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Need Further Support? =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;📞 Book Consultation Call:&#039;&#039;&#039; [https://proventusnova.com/contact-us/ Show Calendar!]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;📩 Contact Via Email:&#039;&#039;&#039; [mailto:support@proventusnova.com support@proventusnova.com]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;🌐 Visit Our Website:&#039;&#039;&#039; [https://proventusnova.com ProventusNova.com]&lt;/div&gt;</summary>
		<author><name>Andres</name></author>
	</entry>
	<entry>
		<id>https://developerwiki.proventusnova.com/index.php?title=Https://www.google.com/How_to_start_camera_stream_on_boot_with_systemd_service_NVIDIA_Jetson_tutorial&amp;diff=202</id>
		<title>Https://www.google.com/How to start camera stream on boot with systemd service NVIDIA Jetson tutorial</title>
		<link rel="alternate" type="text/html" href="https://developerwiki.proventusnova.com/index.php?title=Https://www.google.com/How_to_start_camera_stream_on_boot_with_systemd_service_NVIDIA_Jetson_tutorial&amp;diff=202"/>
		<updated>2025-06-08T22:38:27Z</updated>

		<summary type="html">&lt;p&gt;Andres: Created page with &amp;quot;=How to start camera stream on boot with systemd service – NVIDIA Jetson Tutorial=  This tutorial demonstrates how to automatically launch a Python-based camera streaming application on boot using a &amp;lt;code&amp;gt;systemd&amp;lt;/code&amp;gt; service on NVIDIA Jetson devices.  == Prerequisites ==  * NVIDIA Jetson board (e.g., Orin NX, Nano, Xavier) * Your custom Python GStreamer/WebRTC camera application * Access to the terminal and root privileges  == Step 1: Prepare the Python Script ==  E...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=How to start camera stream on boot with systemd service – NVIDIA Jetson Tutorial=&lt;br /&gt;
&lt;br /&gt;
This tutorial demonstrates how to automatically launch a Python-based camera streaming application on boot using a &amp;lt;code&amp;gt;systemd&amp;lt;/code&amp;gt; service on NVIDIA Jetson devices.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
&lt;br /&gt;
* NVIDIA Jetson board (e.g., Orin NX, Nano, Xavier)&lt;br /&gt;
* Your custom Python GStreamer/WebRTC camera application&lt;br /&gt;
* Access to the terminal and root privileges&lt;br /&gt;
&lt;br /&gt;
== Step 1: Prepare the Python Script ==&lt;br /&gt;
&lt;br /&gt;
Ensure your Python streaming script is available on the Jetson device. Below is the exact script used in this tutorial &amp;lt;code&amp;gt;camera_stream.py&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
  &#039;&#039;&#039;Note:&#039;&#039;&#039; Make sure to set the correct IP address for the device that will be consuming the stream. In this case &#039;&#039;&#039;10.42.0.1&#039;&#039;&#039; is used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python3&lt;br /&gt;
&lt;br /&gt;
import gi&lt;br /&gt;
import signal&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
gi.require_version(&#039;Gst&#039;, &#039;1.0&#039;)&lt;br /&gt;
gi.require_version(&#039;GLib&#039;, &#039;2.0&#039;)&lt;br /&gt;
from gi.repository import Gst, GLib&lt;br /&gt;
&lt;br /&gt;
Gst.init(None)&lt;br /&gt;
loop = GLib.MainLoop()&lt;br /&gt;
&lt;br /&gt;
def on_message(bus, message, loop):&lt;br /&gt;
    msg_type = message.type&lt;br /&gt;
&lt;br /&gt;
    if msg_type == Gst.MessageType.ERROR:&lt;br /&gt;
        err, debug = message.parse_error()&lt;br /&gt;
        print(f&amp;quot;Error: {err}, Debug: {debug}&amp;quot;)&lt;br /&gt;
        loop.quit()&lt;br /&gt;
&lt;br /&gt;
def signal_handler(sig, frame):&lt;br /&gt;
    print(&amp;quot;Interrupt received, stopping pipeline...&amp;quot;)&lt;br /&gt;
    loop.quit()&lt;br /&gt;
&lt;br /&gt;
# Handle SIGINT (Ctrl+C) and SIGTERM (systemd stop)&lt;br /&gt;
signal.signal(signal.SIGINT, signal_handler)&lt;br /&gt;
signal.signal(signal.SIGTERM, signal_handler)&lt;br /&gt;
&lt;br /&gt;
pipeline = Gst.parse_launch(&lt;br /&gt;
    &amp;quot;nvarguscamerasrc sensor-id=0 ! &amp;quot;&lt;br /&gt;
    &amp;quot;nvv4l2h264enc bitrate=4000000 ! &amp;quot;&lt;br /&gt;
    &amp;quot;h264parse ! rtph264pay config-interval=1 pt=96 ! &amp;quot;&lt;br /&gt;
    &amp;quot;udpsink host=10.42.0.1 port=5000&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
bus = pipeline.get_bus()&lt;br /&gt;
bus.add_signal_watch()&lt;br /&gt;
bus.connect(&amp;quot;message&amp;quot;, on_message, loop)&lt;br /&gt;
&lt;br /&gt;
pipeline.set_state(Gst.State.PLAYING)&lt;br /&gt;
&lt;br /&gt;
try:&lt;br /&gt;
    print(&amp;quot;Pipeline started. Streaming...&amp;quot;)&lt;br /&gt;
    loop.run()&lt;br /&gt;
finally:&lt;br /&gt;
    print(&amp;quot;Shutting down pipeline.&amp;quot;)&lt;br /&gt;
    pipeline.set_state(Gst.State.NULL)&lt;br /&gt;
    bus.remove_signal_watch()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save this as &amp;lt;code&amp;gt;/usr/local/bin/camera_stream.py&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Make sure all required GStreamer plugins are installed and working. You can test this script manually before proceeding.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
python3 /usr/local/bin/camera_stream.py&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Step 2: Create a systemd Service File ==&lt;br /&gt;
&lt;br /&gt;
Use the following &amp;lt;code&amp;gt;systemd&amp;lt;/code&amp;gt; unit file to run the Python script at boot:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Jetson camera UDP stream on boot&lt;br /&gt;
After=nvargus-daemon.service&lt;br /&gt;
Requires=nvargus-daemon.service&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
ExecStart=/usr/bin/python3 /usr/local/bin/camera_stream.py&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
StandardOutput=journal&lt;br /&gt;
StandardError=journal&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save this file as &amp;lt;code&amp;gt;/etc/systemd/system/camera-stream.service&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Step 3: Enable and Start the Service ==&lt;br /&gt;
&lt;br /&gt;
To enable and start the service on boot, run the following commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo systemctl daemon-reload&lt;br /&gt;
sudo systemctl enable camera-stream.service&lt;br /&gt;
sudo systemctl start camera-stream.service&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To check the service status:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
systemctl status camera-stream.service&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To view logs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
journalctl -u camera-stream.service&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Step 4: Testing auto camera stream feature ==&lt;br /&gt;
&lt;br /&gt;
In order to test this feature, run the following GStreamer pipeline on the device that will preview the camera stream put by the NVIDIA Jetson device.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
gst-launch-1.0 -v udpsrc port=5000 ! application/x-rtp, encoding-name=H264, payload=96 ! rtph264depay ! avdec_h264 ! videoconvert ! autovideosink&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, reboot or power-cycle the board.&lt;br /&gt;
&lt;br /&gt;
Finally, make sure that the stream is shown as expected on the client device.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Footer}}&lt;/div&gt;</summary>
		<author><name>Andres</name></author>
	</entry>
	<entry>
		<id>https://developerwiki.proventusnova.com/index.php?title=How_to_Build_a_Video_Capture_Application_Using_GStreamer_and_OpenCV_in_Python&amp;diff=87</id>
		<title>How to Build a Video Capture Application Using GStreamer and OpenCV in Python</title>
		<link rel="alternate" type="text/html" href="https://developerwiki.proventusnova.com/index.php?title=How_to_Build_a_Video_Capture_Application_Using_GStreamer_and_OpenCV_in_Python&amp;diff=87"/>
		<updated>2025-03-23T23:18:25Z</updated>

		<summary type="html">&lt;p&gt;Andres: Created page with &amp;quot;= How to Build a Video Capture Application Using GStreamer and OpenCV in Python =  This guide explains how to create a basic video capture application using **GStreamer** and **OpenCV** in Python. The application captures video from a camera using GStreamer and processes it with OpenCV.  == Full Script == For those who just want the code, here is the complete script:  &amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt; import gi import cv2 import numpy as np import sys  gi.require_version(&amp;quot;...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= How to Build a Video Capture Application Using GStreamer and OpenCV in Python =&lt;br /&gt;
&lt;br /&gt;
This guide explains how to create a basic video capture application using **GStreamer** and **OpenCV** in Python. The application captures video from a camera using GStreamer and processes it with OpenCV.&lt;br /&gt;
&lt;br /&gt;
== Full Script ==&lt;br /&gt;
For those who just want the code, here is the complete script:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import gi&lt;br /&gt;
import cv2&lt;br /&gt;
import numpy as np&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
gi.require_version(&amp;quot;Gst&amp;quot;, &amp;quot;1.0&amp;quot;)&lt;br /&gt;
gi.require_version(&amp;quot;GLib&amp;quot;, &amp;quot;2.0&amp;quot;)&lt;br /&gt;
from gi.repository import Gst, GLib&lt;br /&gt;
&lt;br /&gt;
class Camera:&lt;br /&gt;
    def __init__(self, width=640, height=480, fps=30):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;Initialize the GStreamer pipeline and elements.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        Gst.init(None)  # Initialize GStreamer&lt;br /&gt;
&lt;br /&gt;
        self.width = width&lt;br /&gt;
        self.height = height&lt;br /&gt;
        self.fps = fps&lt;br /&gt;
        self.frame = None  # Placeholder for the latest frame&lt;br /&gt;
        self.running = True  # Flag to track if the loop should run&lt;br /&gt;
&lt;br /&gt;
        # Define GStreamer pipeline&lt;br /&gt;
        self.pipeline_str = (&lt;br /&gt;
            f&amp;quot;v4l2src device=/dev/video6 ! &amp;quot;&lt;br /&gt;
            f&amp;quot;image/jpeg, width={self.width}, height={self.height}, framerate={self.fps}/1 ! &amp;quot;&lt;br /&gt;
            &amp;quot;jpegdec ! &amp;quot;&lt;br /&gt;
            &amp;quot;videoconvert ! &amp;quot;&lt;br /&gt;
            &amp;quot;videoscale ! &amp;quot;&lt;br /&gt;
            f&amp;quot;video/x-raw,format=BGR,width={self.width},height={self.height} ! &amp;quot;&lt;br /&gt;
            &amp;quot;appsink name=sink emit-signals=true max-buffers=1 drop=true&amp;quot;&lt;br /&gt;
        )&lt;br /&gt;
&lt;br /&gt;
        # Create pipeline&lt;br /&gt;
        self.pipeline = Gst.parse_launch(self.pipeline_str)&lt;br /&gt;
        self.appsink = self.pipeline.get_by_name(&amp;quot;sink&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        if not self.appsink:&lt;br /&gt;
            print(&amp;quot;Error: Could not find appsink element.&amp;quot;)&lt;br /&gt;
            sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
        # Connect new-sample signal&lt;br /&gt;
        self.appsink.connect(&amp;quot;new-sample&amp;quot;, self.on_new_sample)&lt;br /&gt;
&lt;br /&gt;
        # Start pipeline&lt;br /&gt;
        self.pipeline.set_state(Gst.State.PLAYING)&lt;br /&gt;
&lt;br /&gt;
        # Start GLib main loop&lt;br /&gt;
        self.loop = GLib.MainLoop()&lt;br /&gt;
&lt;br /&gt;
        # Add a timer to update OpenCV display&lt;br /&gt;
        GLib.timeout_add(30, self.update_display)&lt;br /&gt;
&lt;br /&gt;
    def on_new_sample(self, sink):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;Callback function for processing new samples.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        sample = sink.emit(&amp;quot;pull-sample&amp;quot;)&lt;br /&gt;
        if sample is None:&lt;br /&gt;
            return Gst.FlowReturn.ERROR&lt;br /&gt;
&lt;br /&gt;
        buffer = sample.get_buffer()&lt;br /&gt;
        success, map_info = buffer.map(Gst.MapFlags.READ)&lt;br /&gt;
        if not success:&lt;br /&gt;
            return Gst.FlowReturn.ERROR&lt;br /&gt;
&lt;br /&gt;
        # Convert buffer to NumPy array&lt;br /&gt;
        frame_data = np.frombuffer(map_info.data, dtype=np.uint8)&lt;br /&gt;
        buffer.unmap(map_info)&lt;br /&gt;
&lt;br /&gt;
        try:&lt;br /&gt;
            self.frame = frame_data.reshape((self.height, self.width, 3))&lt;br /&gt;
        except ValueError:&lt;br /&gt;
            print(&amp;quot;Frame size mismatch, skipping frame.&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        return Gst.FlowReturn.OK&lt;br /&gt;
&lt;br /&gt;
    def update_display(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;Update OpenCV display and check if the window is closed.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        if self.frame is not None:&lt;br /&gt;
            cv2.imshow(&amp;quot;GStreamer Video&amp;quot;, self.frame)&lt;br /&gt;
            &lt;br /&gt;
            # Check if OpenCV window is closed&lt;br /&gt;
            if cv2.getWindowProperty(&amp;quot;GStreamer Video&amp;quot;, cv2.WND_PROP_VISIBLE) &amp;lt; 1:&lt;br /&gt;
                self.stop()&lt;br /&gt;
                return False  # Stop updating&lt;br /&gt;
&lt;br /&gt;
            if cv2.waitKey(1) &amp;amp; 0xFF == ord(&amp;quot;q&amp;quot;):&lt;br /&gt;
                self.stop()&lt;br /&gt;
                return False  # Stop updating&lt;br /&gt;
&lt;br /&gt;
        return True  # Continue updating&lt;br /&gt;
&lt;br /&gt;
    def start(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;Run the GStreamer pipeline loop.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        try:&lt;br /&gt;
            self.loop.run()&lt;br /&gt;
        except KeyboardInterrupt:&lt;br /&gt;
            self.stop()&lt;br /&gt;
&lt;br /&gt;
    def stop(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;Stop the GStreamer pipeline and cleanup.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        if self.running:&lt;br /&gt;
            self.running = False&lt;br /&gt;
            print(&amp;quot;Stopping camera...&amp;quot;)&lt;br /&gt;
            self.pipeline.set_state(Gst.State.NULL)&lt;br /&gt;
            cv2.destroyAllWindows()&lt;br /&gt;
            self.loop.quit()&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    camera = Camera(width=640, height=480, fps=30)&lt;br /&gt;
    camera.start()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Step-by-Step Guide ==&lt;br /&gt;
&lt;br /&gt;
=== 1. Install Dependencies ===&lt;br /&gt;
Before running the script, make sure you have the required dependencies installed.&lt;br /&gt;
&lt;br /&gt;
Run the following command to install them:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
pip install opencv-python numpy pygobject&lt;br /&gt;
sudo apt install gstreamer1.0-tools gstreamer1.0-plugins-base gstreamer1.0-plugins-good&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 2. Understand the GStreamer Pipeline ===&lt;br /&gt;
The script uses the following GStreamer pipeline:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
v4l2src device=/dev/video6 ! image/jpeg, width=640, height=480, framerate=30/1 ! &lt;br /&gt;
jpegdec ! videoconvert ! videoscale ! video/x-raw,format=BGR,width=640,height=480 ! appsink&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
- **v4l2src** → Captures video from a device (e.g., `/dev/video6`).&lt;br /&gt;
- **jpegdec** → Decodes JPEG frames.&lt;br /&gt;
- **videoconvert** → Converts to a format compatible with OpenCV.&lt;br /&gt;
- **appsink** → Sends frames to OpenCV for further processing.&lt;br /&gt;
&lt;br /&gt;
=== 3. Run the Script ===&lt;br /&gt;
Save the script as `camera.py` and run it:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
python camera.py&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Press **&#039;q&#039;** or close the OpenCV window to stop the program.&lt;br /&gt;
&lt;br /&gt;
=== 4. Modify for Your Camera ===&lt;br /&gt;
- To use a different camera, change the `device=/dev/video6` in the script.&lt;br /&gt;
- Modify `width`, `height`, and `fps` in the `Camera` class.&lt;br /&gt;
&lt;br /&gt;
== FAQ ==&lt;br /&gt;
&lt;br /&gt;
=== How can I change the camera source? ===&lt;br /&gt;
Modify the `v4l2src` device in the pipeline:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
self.pipeline_str = &amp;quot;v4l2src device=/dev/video0 ! ...&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Use `/dev/video0`, `/dev/video1`, etc., depending on your setup.&lt;br /&gt;
&lt;br /&gt;
=== Why is the video not displaying? ===&lt;br /&gt;
Possible issues:&lt;br /&gt;
1. **Camera is in use** → Close other applications using the camera.&lt;br /&gt;
2. **Wrong device path** → Check available devices using:&lt;br /&gt;
   &amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
   v4l2-ctl --list-devices&lt;br /&gt;
   &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
3. **Missing dependencies** → Ensure all required GStreamer plugins are installed.&lt;br /&gt;
&lt;br /&gt;
=== How do I exit the application? ===&lt;br /&gt;
Press **&#039;q&#039;** or close the OpenCV window to stop the script.&lt;br /&gt;
&lt;br /&gt;
=== How can I improve performance? ===&lt;br /&gt;
- Reduce `width` and `height` for better speed.&lt;br /&gt;
- Set `drop=true` in `appsink` to avoid frame buffering delays.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
You&#039;ve now built a basic **video capture application** using **GStreamer** and **OpenCV** in Python! 🚀  &lt;br /&gt;
Modify the script to suit your needs, such as adding **filters**, **recording**, or **streaming**.&lt;br /&gt;
&lt;br /&gt;
If you have any questions, feel free to ask in the comments. Happy coding! 🎥🖥️&lt;/div&gt;</summary>
		<author><name>Andres</name></author>
	</entry>
	<entry>
		<id>https://developerwiki.proventusnova.com/index.php?title=How_to_create_a_custom_yocto_meta_layer&amp;diff=81</id>
		<title>How to create a custom yocto meta layer</title>
		<link rel="alternate" type="text/html" href="https://developerwiki.proventusnova.com/index.php?title=How_to_create_a_custom_yocto_meta_layer&amp;diff=81"/>
		<updated>2025-03-11T22:12:20Z</updated>

		<summary type="html">&lt;p&gt;Andres: /* Step 2. Add base distro config */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This wiki will provide a detailed guide on how to create a custom Yocto meta-layer.&lt;br /&gt;
&lt;br /&gt;
==Create Base Meta-Layer==&lt;br /&gt;
&lt;br /&gt;
This section contains steps to create the base custom meta-layer.&lt;br /&gt;
After completion, the custom base meta-layer will contain the following parts:&lt;br /&gt;
&lt;br /&gt;
* Custom layer configuration&lt;br /&gt;
* Custom distro configuration&lt;br /&gt;
* Custom machine&lt;br /&gt;
* Custom config template files&lt;br /&gt;
* Custom image recipe&lt;br /&gt;
&lt;br /&gt;
===Step 1. Add base layer.conf file===&lt;br /&gt;
&lt;br /&gt;
The layer configuration file provides Yocto with the configuration for the custom meta-layer.&lt;br /&gt;
It shall be stored in a directory called &#039;&#039;&#039;conf&#039;&#039;&#039; inside the base meta-layer directory, and it shall be named layer.conf.&lt;br /&gt;
According to the [https://docs.yoctoproject.org/dev/dev-manual/layers.html Yocto documentation] it is recommended to start from an existing layer.conf file from a different meta-layer and change it according to the custom requirements.&lt;br /&gt;
&lt;br /&gt;
For instance, here is an example of how the directory structure should look after creating the layer.conf file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   └── layer.conf&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An example layer.conf file based on [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/conf/layer.conf NVIDIA OE4T tegra_demo_distro] is shown in the following code snipped.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
BBPATH =. &amp;quot;${LAYERDIR}:&amp;quot;&lt;br /&gt;
BBFILES += &amp;quot;${LAYERDIR}/recipes-*/*/*.bb ${LAYERDIR}/recipes-*/*/*.bbappend&amp;quot;&lt;br /&gt;
BBFILES_DYNAMIC += &amp;quot;swupdate:${LAYERDIR}/dynamic-layers/meta-swupdate/recipes-*/*/*.bb \&lt;br /&gt;
                    swupdate:${LAYERDIR}/dynamic-layers/meta-swupdate/recipes-*/*/*.bbappend&amp;quot;&lt;br /&gt;
&lt;br /&gt;
BBFILE_COLLECTIONS += &amp;quot;proventusnova&amp;quot;&lt;br /&gt;
BBFILE_PATTERN_proventusnova = &amp;quot;^${LAYERDIR}/&amp;quot;&lt;br /&gt;
BBFILE_PRIORITY_proventusnova = &amp;quot;50&amp;quot;&lt;br /&gt;
&lt;br /&gt;
LAYERVERSION_proventusnova = &amp;quot;4&amp;quot;&lt;br /&gt;
LAYERSERIES_COMPAT_proventusnova = &amp;quot;scarthgap&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# This is used by the tegra-distro-sanity bbclass&lt;br /&gt;
# to identify the distro layer directory during&lt;br /&gt;
# bblayers checks.&lt;br /&gt;
TD_DISTRO_LAYERDIR = &amp;quot;${LAYERDIR}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 2. Add base distro config===&lt;br /&gt;
&lt;br /&gt;
In order to add the initial distro configuration, it is necessary to create distro configuration file inside the &#039;&#039;&#039;meta-layer/conf/distro&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
Here is an example of how the directory structure should look like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   ├── distro&lt;br /&gt;
│   │   └── proventusnova.conf&lt;br /&gt;
│   └── layer.conf&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The same as with the layer.conf, it is easier to start with an existing distro configuration file and modify it in order to fit the project requirements. For example, the following corresponds to a distro configuration file based on the [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/conf/distro/tegrademo.conf NVIDIA tegra_demo_distro]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
DISTRO = &amp;quot;proventusnova&amp;quot;&lt;br /&gt;
DISTRO_NAME = &amp;quot;ProventusNova Custom Distro&amp;quot;&lt;br /&gt;
DISTRO_VERSION_BASE = &amp;quot;1.0&amp;quot;&lt;br /&gt;
DISTRO_VERSION = &amp;quot;${DISTRO_VERSION_BASE}+snapshot-${METADATA_REVISION}&amp;quot;&lt;br /&gt;
DISTRO_CODENAME = &amp;quot;proventusnova&amp;quot;&lt;br /&gt;
SDK_VENDOR = &amp;quot;-proventusnova&amp;quot;&lt;br /&gt;
SDK_VERSION := &amp;quot;${@&#039;${DISTRO_VERSION}&#039;.replace(&#039;snapshot-${METADATA_REVISION}&#039;,&#039;snapshot&#039;)}&amp;quot;&lt;br /&gt;
SDK_VERSION[vardepvalue] = &amp;quot;${SDK_VERSION}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
MAINTAINER = &amp;quot;ProventusNova team &amp;lt;support@proventusnova.com&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
TARGET_VENDOR = &amp;quot;-proventusnova&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# New ${DISTRO}-&amp;lt;version&amp;gt; setting for sanity checks.&lt;br /&gt;
# Increment version number (and the corresponding&lt;br /&gt;
# setting int the template bblayers.conf.sample file)&lt;br /&gt;
# each time the layer settings are changed.&lt;br /&gt;
REQUIRED_PROVENTUSNOVA_BBLAYERS_CONF_VERSION = &amp;quot;${DISTRO}-1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
LOCALCONF_VERSION = &amp;quot;2&amp;quot;&lt;br /&gt;
&lt;br /&gt;
PROVENTUSNOVA_DEFAULT_DISTRO_FEATURES = &amp;quot;largefile opengl ptest multiarch wayland vulkan systemd pam virtualization usrmerge&amp;quot;&lt;br /&gt;
&lt;br /&gt;
DISTRO_FEATURES ?= &amp;quot;${DISTRO_FEATURES_DEFAULT} ${PROVENTUSNOVA_DEFAULT_DISTRO_FEATURES}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Jetson platforms do not use linux-yocto, but for QEMU testing&lt;br /&gt;
# align with the poky distro.&lt;br /&gt;
PREFERRED_VERSION_linux-yocto ?= &amp;quot;5.19%&amp;quot;&lt;br /&gt;
PREFERRED_VERSION_linux-yocto-rt ?= &amp;quot;5.19%&amp;quot;&lt;br /&gt;
&lt;br /&gt;
SDK_NAME = &amp;quot;${DISTRO}-${TCLIBC}-${SDKMACHINE}-${IMAGE_BASENAME}-${TUNE_PKGARCH}-${MACHINE}&amp;quot;&lt;br /&gt;
SDKPATHINSTALL = &amp;quot;/opt/${DISTRO}/${SDK_VERSION}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
TCLIBCAPPEND = &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
PACKAGE_CLASSES ?= &amp;quot;package_rpm&amp;quot;&lt;br /&gt;
&lt;br /&gt;
SANITY_TESTED_DISTROS ?= &amp;quot; \&lt;br /&gt;
            ubuntu-20.04 \n \&lt;br /&gt;
            ubuntu-22.04 \n \&lt;br /&gt;
            ubuntu-24.04 \n \&lt;br /&gt;
            &amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Most NVIDIA-supplied services expect systemd&lt;br /&gt;
INIT_MANAGER = &amp;quot;systemd&amp;quot;&lt;br /&gt;
&lt;br /&gt;
require conf/distro/include/no-static-libs.inc&lt;br /&gt;
require conf/distro/include/yocto-uninative.inc&lt;br /&gt;
require conf/distro/include/security_flags.inc&lt;br /&gt;
INHERIT += &amp;quot;uninative&amp;quot;&lt;br /&gt;
&lt;br /&gt;
LICENSE_FLAGS_ACCEPTED += &amp;quot;commercial_faad2 commercial_x264&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 3. Add base machine===&lt;br /&gt;
&lt;br /&gt;
This step might not be required, if there is already a machine that can be used from a different meta-layer.&lt;br /&gt;
However, it is still recommended to create a custom machine configuration based on that machine in order to keep better order of the machine used in the custom Yocto build.&lt;br /&gt;
&lt;br /&gt;
To create a custom machine, it is necessary to add a machine.conf file in the &#039;&#039;&#039;meta-layer/conf/machine&#039;&#039;&#039; directory.&lt;br /&gt;
For example, this is how the directory structure should look when adding a new machine to the custom meta-layer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   ├── distro&lt;br /&gt;
│   │   └── proventusnova.conf&lt;br /&gt;
│   ├── layer.conf&lt;br /&gt;
│   └── machine&lt;br /&gt;
│       └── proventusnova-jetson-orin-nx-16-devkit.conf&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And, as a reference, here is a custom machine based on [https://github.com/OE4T/meta-tegra/blob/scarthgap/conf/machine/p3509-a02-p3767-0000.conf NVIDIA meta-tegra  p3509-a02-p3767-0000] machine.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#@TYPE: Machine&lt;br /&gt;
#@NAME: Nvidia Jetson Orin NX 16GB (P3767-0000)&lt;br /&gt;
#@DESCRIPTION: Nvidia Jetson Orin NX 16GB module in P3509 carrier&lt;br /&gt;
&lt;br /&gt;
TEGRA_FLASHVAR_PINMUX_CONFIG ?= &amp;quot;tegra234-mb1-bct-pinmux-p3767-hdmi-a03.dtsi&amp;quot;&lt;br /&gt;
TEGRA_FLASHVAR_PMC_CONFIG ?= &amp;quot;tegra234-mb1-bct-padvoltage-p3767-hdmi-a03.dtsi&amp;quot;&lt;br /&gt;
TEGRA_PLUGIN_MANAGER_OVERLAYS ?= &amp;quot;tegra234-carveouts.dtbo tegra-optee.dtbo tegra234-p3768-0000+p3767-0000-dynamic.dtbo tegra234-dcb-p3767-0000-hdmi.dtbo&amp;quot;&lt;br /&gt;
TEGRA_DCE_OVERLAY ?= &amp;quot;tegra234-dcb-p3767-0000-hdmi.dtbo&amp;quot;&lt;br /&gt;
&lt;br /&gt;
require conf/machine/include/orin-nx.inc&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 4. Add initial config template files===&lt;br /&gt;
&lt;br /&gt;
Bitbake will require 2 configuration files for building an image:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;bblayers.conf&#039;&#039;&#039;: This file contains information about the location of the required meta-layers for the project.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;local.conf&#039;&#039;&#039;: This file contains general build configuration for bitbake. For instance, in this file it is possible to determine where to store downloads, cache and even which package management configuration to use.&lt;br /&gt;
&lt;br /&gt;
Now, in order to simplify the configuration of a custom Yocto build, it is possible to include template configuration files on the custom meta-layer. This practice is encouraged in order to increase build repeatability.&lt;br /&gt;
&lt;br /&gt;
These 2 files are generally created inside &#039;&#039;&#039;meta-layer/conf/templates/template-name&#039;&#039;&#039;.&lt;br /&gt;
For reference, this is how the directory structure would look like after the files are created:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   ├── distro&lt;br /&gt;
│   │   └── proventusnova.conf&lt;br /&gt;
│   ├── layer.conf&lt;br /&gt;
│   ├── machine&lt;br /&gt;
│   │   └── proventusnova-jetson-orin-nx-16-devkit.conf&lt;br /&gt;
│   └── templates&lt;br /&gt;
│       └── proventusnova&lt;br /&gt;
│           ├── bblayers.conf.sample&lt;br /&gt;
│           └── local.conf.sample&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here is an example of a custom bblayers.conf.sample file based on [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/conf/templates/tegrademo/bblayers.conf.sample NVIDIA tegra-demo-distro]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Version of layers configuration, specific to&lt;br /&gt;
# each defined distro in the repository.&lt;br /&gt;
# Format: ${DISTRO}-&amp;lt;version&amp;gt;&lt;br /&gt;
TD_BBLAYERS_CONF_VERSION = &amp;quot;proventusnova-1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
BBPATH = &amp;quot;${TOPDIR}&amp;quot;&lt;br /&gt;
BBFILES ?= &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
BBLAYERS ?= &amp;quot; \&lt;br /&gt;
  ##OEROOT##/meta \&lt;br /&gt;
  ##OEROOT##/../meta-tegra \&lt;br /&gt;
  ##OEROOT##/../meta-tegra-community \&lt;br /&gt;
  ##OEROOT##/../meta-virtualization \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-oe \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-python \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-networking \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-filesystems \&lt;br /&gt;
  &amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And, this is an example of a custom local.conf.sample file based on [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/conf/templates/tegrademo/local.conf.sample NVIDIA tegra-demo-distro]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
# Machine Selection&lt;br /&gt;
#&lt;br /&gt;
MACHINE ??= &amp;quot;proventusnova-jetson-orin-nx-16-devkit.conf&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Where to place downloads&lt;br /&gt;
#&lt;br /&gt;
DL_DIR ?= &amp;quot;${TOPDIR}/../downloads&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Where to place shared-state files&lt;br /&gt;
#&lt;br /&gt;
SSTATE_DIR ?= &amp;quot;${TOPDIR}/../sstate-cache&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Where to place the build output&lt;br /&gt;
#&lt;br /&gt;
TMPDIR = &amp;quot;${TOPDIR}/tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Default policy (distro) config&lt;br /&gt;
#&lt;br /&gt;
DISTRO ?= &amp;quot;proventusnova&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Package Management configuration&lt;br /&gt;
#&lt;br /&gt;
PACKAGE_CLASSES ?= &amp;quot;package_deb&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# SDK target architecture&lt;br /&gt;
#&lt;br /&gt;
SDKMACHINE ?= &amp;quot;x86_64&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Extra image configuration defaults&lt;br /&gt;
#&lt;br /&gt;
EXTRA_IMAGE_FEATURES ?= &amp;quot;debug-tweaks&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Additional image features&lt;br /&gt;
#&lt;br /&gt;
USER_CLASSES ?= &amp;quot;buildstats&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Interactive shell configuration&lt;br /&gt;
#&lt;br /&gt;
PATCHRESOLVE = &amp;quot;noop&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Disk Space Monitoring during the build&lt;br /&gt;
#&lt;br /&gt;
BB_DISKMON_DIRS ??= &amp;quot;\&lt;br /&gt;
    STOPTASKS,${TMPDIR},1G,100K \&lt;br /&gt;
    STOPTASKS,${DL_DIR},1G,100K \&lt;br /&gt;
    STOPTASKS,${SSTATE_DIR},1G,100K \&lt;br /&gt;
    STOPTASKS,/tmp,100M,100K \&lt;br /&gt;
    HALT,${TMPDIR},100M,1K \&lt;br /&gt;
    HALT,${DL_DIR},100M,1K \&lt;br /&gt;
    HALT,${SSTATE_DIR},100M,1K \&lt;br /&gt;
    HALT,/tmp,10M,1K&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Qemu configuration&lt;br /&gt;
#&lt;br /&gt;
PACKAGECONFIG:append:pn-qemu-system-native = &amp;quot; sdl&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# CONF_VERSION is increased each time build/conf/ changes incompatibly and is used to&lt;br /&gt;
# track the version of this file when it was generated.&lt;br /&gt;
CONF_VERSION = &amp;quot;2&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 5. Add base image recipe===&lt;br /&gt;
&lt;br /&gt;
In order to create a custom image, it is necessary to add a custom image recipe file.&lt;br /&gt;
This file is usually added inside the &#039;&#039;&#039;meta-layer/recipes-layer/images&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   ├── distro&lt;br /&gt;
│   │   └── proventusnova.conf&lt;br /&gt;
│   ├── layer.conf&lt;br /&gt;
│   ├── machine&lt;br /&gt;
│   │   └── proventusnova-jetson-orin-nx-16-devkit.conf&lt;br /&gt;
│   └── templates&lt;br /&gt;
│       ├── bblayers.conf.sample&lt;br /&gt;
│       └── local.conf.sample&lt;br /&gt;
├── README.md&lt;br /&gt;
└── recipes-proventusnova&lt;br /&gt;
    └── images&lt;br /&gt;
        └── proventusnova-image-base.bb&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once again, a custom image recipe can be based on another image recipe. And, it can also import other image recipes in order to include their base configurations.&lt;br /&gt;
&lt;br /&gt;
As reference, the following image recipe was based on [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/recipes-demo/images/demo-image-base.bb NVIDIA tegra-demo-distro demo-image-base recipe]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
DESCRIPTION = &amp;quot;ProventusNova base image&amp;quot;&lt;br /&gt;
LICENSE = &amp;quot;CLOSED&amp;quot;&lt;br /&gt;
&lt;br /&gt;
inherit core-image&lt;br /&gt;
&lt;br /&gt;
IMAGE_FEATURES += &amp;quot;ssh-server-openssh debug-tweaks&amp;quot;&lt;br /&gt;
&lt;br /&gt;
CORE_IMAGE_BASE_INSTALL += &amp;quot;systemd&amp;quot;&lt;br /&gt;
TOOLCHAIN_HOST_TASK += &amp;quot;nativesdk-packagegroup-cuda-sdk-host&amp;quot;&lt;br /&gt;
&lt;br /&gt;
inherit nopackages&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Andres</name></author>
	</entry>
	<entry>
		<id>https://developerwiki.proventusnova.com/index.php?title=How_to_create_a_custom_yocto_meta_layer&amp;diff=80</id>
		<title>How to create a custom yocto meta layer</title>
		<link rel="alternate" type="text/html" href="https://developerwiki.proventusnova.com/index.php?title=How_to_create_a_custom_yocto_meta_layer&amp;diff=80"/>
		<updated>2025-03-11T22:12:04Z</updated>

		<summary type="html">&lt;p&gt;Andres: /* Step 4. Add initial config template files */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This wiki will provide a detailed guide on how to create a custom Yocto meta-layer.&lt;br /&gt;
&lt;br /&gt;
==Create Base Meta-Layer==&lt;br /&gt;
&lt;br /&gt;
This section contains steps to create the base custom meta-layer.&lt;br /&gt;
After completion, the custom base meta-layer will contain the following parts:&lt;br /&gt;
&lt;br /&gt;
* Custom layer configuration&lt;br /&gt;
* Custom distro configuration&lt;br /&gt;
* Custom machine&lt;br /&gt;
* Custom config template files&lt;br /&gt;
* Custom image recipe&lt;br /&gt;
&lt;br /&gt;
===Step 1. Add base layer.conf file===&lt;br /&gt;
&lt;br /&gt;
The layer configuration file provides Yocto with the configuration for the custom meta-layer.&lt;br /&gt;
It shall be stored in a directory called &#039;&#039;&#039;conf&#039;&#039;&#039; inside the base meta-layer directory, and it shall be named layer.conf.&lt;br /&gt;
According to the [https://docs.yoctoproject.org/dev/dev-manual/layers.html Yocto documentation] it is recommended to start from an existing layer.conf file from a different meta-layer and change it according to the custom requirements.&lt;br /&gt;
&lt;br /&gt;
For instance, here is an example of how the directory structure should look after creating the layer.conf file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   └── layer.conf&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An example layer.conf file based on [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/conf/layer.conf NVIDIA OE4T tegra_demo_distro] is shown in the following code snipped.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
BBPATH =. &amp;quot;${LAYERDIR}:&amp;quot;&lt;br /&gt;
BBFILES += &amp;quot;${LAYERDIR}/recipes-*/*/*.bb ${LAYERDIR}/recipes-*/*/*.bbappend&amp;quot;&lt;br /&gt;
BBFILES_DYNAMIC += &amp;quot;swupdate:${LAYERDIR}/dynamic-layers/meta-swupdate/recipes-*/*/*.bb \&lt;br /&gt;
                    swupdate:${LAYERDIR}/dynamic-layers/meta-swupdate/recipes-*/*/*.bbappend&amp;quot;&lt;br /&gt;
&lt;br /&gt;
BBFILE_COLLECTIONS += &amp;quot;proventusnova&amp;quot;&lt;br /&gt;
BBFILE_PATTERN_proventusnova = &amp;quot;^${LAYERDIR}/&amp;quot;&lt;br /&gt;
BBFILE_PRIORITY_proventusnova = &amp;quot;50&amp;quot;&lt;br /&gt;
&lt;br /&gt;
LAYERVERSION_proventusnova = &amp;quot;4&amp;quot;&lt;br /&gt;
LAYERSERIES_COMPAT_proventusnova = &amp;quot;scarthgap&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# This is used by the tegra-distro-sanity bbclass&lt;br /&gt;
# to identify the distro layer directory during&lt;br /&gt;
# bblayers checks.&lt;br /&gt;
TD_DISTRO_LAYERDIR = &amp;quot;${LAYERDIR}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 2. Add base distro config===&lt;br /&gt;
&lt;br /&gt;
In order to add the initial distro configuration, it is necessary to create distro configuration file inside the &#039;&#039;&#039;meta-layer/conf/distro&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
Here is an example of how the directory structure should look like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   ├── distro&lt;br /&gt;
│   │   └── proventusnova.conf&lt;br /&gt;
│   └── layer.conf&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The same as with the layer.conf, it is easier to start with an existing distro configuration file and modify it in order to fit the project requirements. For example, the following corresponds to a distro configuration file based on the [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/conf/distro/tegrademo.conf NVIDIA tegra_demo_distro]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
DISTRO = &amp;quot;proventusnova&amp;quot;&lt;br /&gt;
DISTRO_NAME = &amp;quot;ProventusNova Custom Distro&amp;quot;&lt;br /&gt;
DISTRO_VERSION_BASE = &amp;quot;1.0&amp;quot;&lt;br /&gt;
DISTRO_VERSION = &amp;quot;${DISTRO_VERSION_BASE}+snapshot-${METADATA_REVISION}&amp;quot;&lt;br /&gt;
DISTRO_CODENAME = &amp;quot;proventusnova&amp;quot;&lt;br /&gt;
SDK_VENDOR = &amp;quot;-proventusnova&amp;quot;&lt;br /&gt;
SDK_VERSION := &amp;quot;${@&#039;${DISTRO_VERSION}&#039;.replace(&#039;snapshot-${METADATA_REVISION}&#039;,&#039;snapshot&#039;)}&amp;quot;&lt;br /&gt;
SDK_VERSION[vardepvalue] = &amp;quot;${SDK_VERSION}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
MAINTAINER = &amp;quot;ProventusNova team &amp;lt;support@proventusnova.com&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
TARGET_VENDOR = &amp;quot;-proventusnova&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# New ${DISTRO}-&amp;lt;version&amp;gt; setting for sanity checks.&lt;br /&gt;
# Increment version number (and the corresponding&lt;br /&gt;
# setting int the template bblayers.conf.sample file)&lt;br /&gt;
# each time the layer settings are changed.&lt;br /&gt;
REQUIRED_PROVENTUSNOVA_BBLAYERS_CONF_VERSION = &amp;quot;${DISTRO}-1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
LOCALCONF_VERSION = &amp;quot;2&amp;quot;&lt;br /&gt;
&lt;br /&gt;
PROVENTUSNOVA_DEFAULT_DISTRO_FEATURES = &amp;quot;largefile opengl ptest multiarch wayland vulkan systemd pam virtualization usrmerge&amp;quot;&lt;br /&gt;
&lt;br /&gt;
DISTRO_FEATURES ?= &amp;quot;${DISTRO_FEATURES_DEFAULT} ${PROVENTUSNOVA_DEFAULT_DISTRO_FEATURES}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Jetson platforms do not use linux-yocto, but for QEMU testing&lt;br /&gt;
# align with the poky distro.&lt;br /&gt;
PREFERRED_VERSION_linux-yocto ?= &amp;quot;5.19%&amp;quot;&lt;br /&gt;
PREFERRED_VERSION_linux-yocto-rt ?= &amp;quot;5.19%&amp;quot;&lt;br /&gt;
&lt;br /&gt;
SDK_NAME = &amp;quot;${DISTRO}-${TCLIBC}-${SDKMACHINE}-${IMAGE_BASENAME}-${TUNE_PKGARCH}-${MACHINE}&amp;quot;&lt;br /&gt;
SDKPATHINSTALL = &amp;quot;/opt/${DISTRO}/${SDK_VERSION}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
TCLIBCAPPEND = &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
PACKAGE_CLASSES ?= &amp;quot;package_rpm&amp;quot;&lt;br /&gt;
&lt;br /&gt;
SANITY_TESTED_DISTROS ?= &amp;quot; \&lt;br /&gt;
            ubuntu-20.04 \n \&lt;br /&gt;
            ubuntu-22.04 \n \&lt;br /&gt;
            ubuntu-24.04 \n \&lt;br /&gt;
            &amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Most NVIDIA-supplied services expect systemd&lt;br /&gt;
INIT_MANAGER = &amp;quot;systemd&amp;quot;&lt;br /&gt;
&lt;br /&gt;
require conf/distro/include/no-static-libs.inc&lt;br /&gt;
require conf/distro/include/yocto-uninative.inc&lt;br /&gt;
require conf/distro/include/security_flags.inc&lt;br /&gt;
INHERIT += &amp;quot;uninative&amp;quot;&lt;br /&gt;
&lt;br /&gt;
LICENSE_FLAGS_ACCEPTED += &amp;quot;commercial_faad2 commercial_x264&amp;quot;&lt;br /&gt;
&lt;br /&gt;
USE_REDUNDANT_FLASH_LAYOUT_DEFAULT ?= &amp;quot;1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
INHERIT += &amp;quot;tegra-support-sanity&amp;quot;&lt;br /&gt;
ESDK_CLASS_INHERIT_DISABLE:append = &amp;quot; tegra-support-sanity&amp;quot;&lt;br /&gt;
&lt;br /&gt;
BB_SIGNATURE_HANDLER ?= &amp;quot;OEEquivHash&amp;quot;&lt;br /&gt;
BB_HASHSERVE ??= &amp;quot;auto&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 3. Add base machine===&lt;br /&gt;
&lt;br /&gt;
This step might not be required, if there is already a machine that can be used from a different meta-layer.&lt;br /&gt;
However, it is still recommended to create a custom machine configuration based on that machine in order to keep better order of the machine used in the custom Yocto build.&lt;br /&gt;
&lt;br /&gt;
To create a custom machine, it is necessary to add a machine.conf file in the &#039;&#039;&#039;meta-layer/conf/machine&#039;&#039;&#039; directory.&lt;br /&gt;
For example, this is how the directory structure should look when adding a new machine to the custom meta-layer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   ├── distro&lt;br /&gt;
│   │   └── proventusnova.conf&lt;br /&gt;
│   ├── layer.conf&lt;br /&gt;
│   └── machine&lt;br /&gt;
│       └── proventusnova-jetson-orin-nx-16-devkit.conf&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And, as a reference, here is a custom machine based on [https://github.com/OE4T/meta-tegra/blob/scarthgap/conf/machine/p3509-a02-p3767-0000.conf NVIDIA meta-tegra  p3509-a02-p3767-0000] machine.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#@TYPE: Machine&lt;br /&gt;
#@NAME: Nvidia Jetson Orin NX 16GB (P3767-0000)&lt;br /&gt;
#@DESCRIPTION: Nvidia Jetson Orin NX 16GB module in P3509 carrier&lt;br /&gt;
&lt;br /&gt;
TEGRA_FLASHVAR_PINMUX_CONFIG ?= &amp;quot;tegra234-mb1-bct-pinmux-p3767-hdmi-a03.dtsi&amp;quot;&lt;br /&gt;
TEGRA_FLASHVAR_PMC_CONFIG ?= &amp;quot;tegra234-mb1-bct-padvoltage-p3767-hdmi-a03.dtsi&amp;quot;&lt;br /&gt;
TEGRA_PLUGIN_MANAGER_OVERLAYS ?= &amp;quot;tegra234-carveouts.dtbo tegra-optee.dtbo tegra234-p3768-0000+p3767-0000-dynamic.dtbo tegra234-dcb-p3767-0000-hdmi.dtbo&amp;quot;&lt;br /&gt;
TEGRA_DCE_OVERLAY ?= &amp;quot;tegra234-dcb-p3767-0000-hdmi.dtbo&amp;quot;&lt;br /&gt;
&lt;br /&gt;
require conf/machine/include/orin-nx.inc&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 4. Add initial config template files===&lt;br /&gt;
&lt;br /&gt;
Bitbake will require 2 configuration files for building an image:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;bblayers.conf&#039;&#039;&#039;: This file contains information about the location of the required meta-layers for the project.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;local.conf&#039;&#039;&#039;: This file contains general build configuration for bitbake. For instance, in this file it is possible to determine where to store downloads, cache and even which package management configuration to use.&lt;br /&gt;
&lt;br /&gt;
Now, in order to simplify the configuration of a custom Yocto build, it is possible to include template configuration files on the custom meta-layer. This practice is encouraged in order to increase build repeatability.&lt;br /&gt;
&lt;br /&gt;
These 2 files are generally created inside &#039;&#039;&#039;meta-layer/conf/templates/template-name&#039;&#039;&#039;.&lt;br /&gt;
For reference, this is how the directory structure would look like after the files are created:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   ├── distro&lt;br /&gt;
│   │   └── proventusnova.conf&lt;br /&gt;
│   ├── layer.conf&lt;br /&gt;
│   ├── machine&lt;br /&gt;
│   │   └── proventusnova-jetson-orin-nx-16-devkit.conf&lt;br /&gt;
│   └── templates&lt;br /&gt;
│       └── proventusnova&lt;br /&gt;
│           ├── bblayers.conf.sample&lt;br /&gt;
│           └── local.conf.sample&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here is an example of a custom bblayers.conf.sample file based on [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/conf/templates/tegrademo/bblayers.conf.sample NVIDIA tegra-demo-distro]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Version of layers configuration, specific to&lt;br /&gt;
# each defined distro in the repository.&lt;br /&gt;
# Format: ${DISTRO}-&amp;lt;version&amp;gt;&lt;br /&gt;
TD_BBLAYERS_CONF_VERSION = &amp;quot;proventusnova-1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
BBPATH = &amp;quot;${TOPDIR}&amp;quot;&lt;br /&gt;
BBFILES ?= &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
BBLAYERS ?= &amp;quot; \&lt;br /&gt;
  ##OEROOT##/meta \&lt;br /&gt;
  ##OEROOT##/../meta-tegra \&lt;br /&gt;
  ##OEROOT##/../meta-tegra-community \&lt;br /&gt;
  ##OEROOT##/../meta-virtualization \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-oe \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-python \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-networking \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-filesystems \&lt;br /&gt;
  &amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And, this is an example of a custom local.conf.sample file based on [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/conf/templates/tegrademo/local.conf.sample NVIDIA tegra-demo-distro]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
# Machine Selection&lt;br /&gt;
#&lt;br /&gt;
MACHINE ??= &amp;quot;proventusnova-jetson-orin-nx-16-devkit.conf&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Where to place downloads&lt;br /&gt;
#&lt;br /&gt;
DL_DIR ?= &amp;quot;${TOPDIR}/../downloads&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Where to place shared-state files&lt;br /&gt;
#&lt;br /&gt;
SSTATE_DIR ?= &amp;quot;${TOPDIR}/../sstate-cache&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Where to place the build output&lt;br /&gt;
#&lt;br /&gt;
TMPDIR = &amp;quot;${TOPDIR}/tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Default policy (distro) config&lt;br /&gt;
#&lt;br /&gt;
DISTRO ?= &amp;quot;proventusnova&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Package Management configuration&lt;br /&gt;
#&lt;br /&gt;
PACKAGE_CLASSES ?= &amp;quot;package_deb&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# SDK target architecture&lt;br /&gt;
#&lt;br /&gt;
SDKMACHINE ?= &amp;quot;x86_64&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Extra image configuration defaults&lt;br /&gt;
#&lt;br /&gt;
EXTRA_IMAGE_FEATURES ?= &amp;quot;debug-tweaks&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Additional image features&lt;br /&gt;
#&lt;br /&gt;
USER_CLASSES ?= &amp;quot;buildstats&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Interactive shell configuration&lt;br /&gt;
#&lt;br /&gt;
PATCHRESOLVE = &amp;quot;noop&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Disk Space Monitoring during the build&lt;br /&gt;
#&lt;br /&gt;
BB_DISKMON_DIRS ??= &amp;quot;\&lt;br /&gt;
    STOPTASKS,${TMPDIR},1G,100K \&lt;br /&gt;
    STOPTASKS,${DL_DIR},1G,100K \&lt;br /&gt;
    STOPTASKS,${SSTATE_DIR},1G,100K \&lt;br /&gt;
    STOPTASKS,/tmp,100M,100K \&lt;br /&gt;
    HALT,${TMPDIR},100M,1K \&lt;br /&gt;
    HALT,${DL_DIR},100M,1K \&lt;br /&gt;
    HALT,${SSTATE_DIR},100M,1K \&lt;br /&gt;
    HALT,/tmp,10M,1K&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Qemu configuration&lt;br /&gt;
#&lt;br /&gt;
PACKAGECONFIG:append:pn-qemu-system-native = &amp;quot; sdl&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# CONF_VERSION is increased each time build/conf/ changes incompatibly and is used to&lt;br /&gt;
# track the version of this file when it was generated.&lt;br /&gt;
CONF_VERSION = &amp;quot;2&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 5. Add base image recipe===&lt;br /&gt;
&lt;br /&gt;
In order to create a custom image, it is necessary to add a custom image recipe file.&lt;br /&gt;
This file is usually added inside the &#039;&#039;&#039;meta-layer/recipes-layer/images&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   ├── distro&lt;br /&gt;
│   │   └── proventusnova.conf&lt;br /&gt;
│   ├── layer.conf&lt;br /&gt;
│   ├── machine&lt;br /&gt;
│   │   └── proventusnova-jetson-orin-nx-16-devkit.conf&lt;br /&gt;
│   └── templates&lt;br /&gt;
│       ├── bblayers.conf.sample&lt;br /&gt;
│       └── local.conf.sample&lt;br /&gt;
├── README.md&lt;br /&gt;
└── recipes-proventusnova&lt;br /&gt;
    └── images&lt;br /&gt;
        └── proventusnova-image-base.bb&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once again, a custom image recipe can be based on another image recipe. And, it can also import other image recipes in order to include their base configurations.&lt;br /&gt;
&lt;br /&gt;
As reference, the following image recipe was based on [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/recipes-demo/images/demo-image-base.bb NVIDIA tegra-demo-distro demo-image-base recipe]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
DESCRIPTION = &amp;quot;ProventusNova base image&amp;quot;&lt;br /&gt;
LICENSE = &amp;quot;CLOSED&amp;quot;&lt;br /&gt;
&lt;br /&gt;
inherit core-image&lt;br /&gt;
&lt;br /&gt;
IMAGE_FEATURES += &amp;quot;ssh-server-openssh debug-tweaks&amp;quot;&lt;br /&gt;
&lt;br /&gt;
CORE_IMAGE_BASE_INSTALL += &amp;quot;systemd&amp;quot;&lt;br /&gt;
TOOLCHAIN_HOST_TASK += &amp;quot;nativesdk-packagegroup-cuda-sdk-host&amp;quot;&lt;br /&gt;
&lt;br /&gt;
inherit nopackages&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Andres</name></author>
	</entry>
	<entry>
		<id>https://developerwiki.proventusnova.com/index.php?title=How_to_create_a_custom_yocto_meta_layer&amp;diff=79</id>
		<title>How to create a custom yocto meta layer</title>
		<link rel="alternate" type="text/html" href="https://developerwiki.proventusnova.com/index.php?title=How_to_create_a_custom_yocto_meta_layer&amp;diff=79"/>
		<updated>2025-03-11T20:28:22Z</updated>

		<summary type="html">&lt;p&gt;Andres: /* Step 4. Add initial config template files */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This wiki will provide a detailed guide on how to create a custom Yocto meta-layer.&lt;br /&gt;
&lt;br /&gt;
==Create Base Meta-Layer==&lt;br /&gt;
&lt;br /&gt;
This section contains steps to create the base custom meta-layer.&lt;br /&gt;
After completion, the custom base meta-layer will contain the following parts:&lt;br /&gt;
&lt;br /&gt;
* Custom layer configuration&lt;br /&gt;
* Custom distro configuration&lt;br /&gt;
* Custom machine&lt;br /&gt;
* Custom config template files&lt;br /&gt;
* Custom image recipe&lt;br /&gt;
&lt;br /&gt;
===Step 1. Add base layer.conf file===&lt;br /&gt;
&lt;br /&gt;
The layer configuration file provides Yocto with the configuration for the custom meta-layer.&lt;br /&gt;
It shall be stored in a directory called &#039;&#039;&#039;conf&#039;&#039;&#039; inside the base meta-layer directory, and it shall be named layer.conf.&lt;br /&gt;
According to the [https://docs.yoctoproject.org/dev/dev-manual/layers.html Yocto documentation] it is recommended to start from an existing layer.conf file from a different meta-layer and change it according to the custom requirements.&lt;br /&gt;
&lt;br /&gt;
For instance, here is an example of how the directory structure should look after creating the layer.conf file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   └── layer.conf&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An example layer.conf file based on [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/conf/layer.conf NVIDIA OE4T tegra_demo_distro] is shown in the following code snipped.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
BBPATH =. &amp;quot;${LAYERDIR}:&amp;quot;&lt;br /&gt;
BBFILES += &amp;quot;${LAYERDIR}/recipes-*/*/*.bb ${LAYERDIR}/recipes-*/*/*.bbappend&amp;quot;&lt;br /&gt;
BBFILES_DYNAMIC += &amp;quot;swupdate:${LAYERDIR}/dynamic-layers/meta-swupdate/recipes-*/*/*.bb \&lt;br /&gt;
                    swupdate:${LAYERDIR}/dynamic-layers/meta-swupdate/recipes-*/*/*.bbappend&amp;quot;&lt;br /&gt;
&lt;br /&gt;
BBFILE_COLLECTIONS += &amp;quot;proventusnova&amp;quot;&lt;br /&gt;
BBFILE_PATTERN_proventusnova = &amp;quot;^${LAYERDIR}/&amp;quot;&lt;br /&gt;
BBFILE_PRIORITY_proventusnova = &amp;quot;50&amp;quot;&lt;br /&gt;
&lt;br /&gt;
LAYERVERSION_proventusnova = &amp;quot;4&amp;quot;&lt;br /&gt;
LAYERSERIES_COMPAT_proventusnova = &amp;quot;scarthgap&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# This is used by the tegra-distro-sanity bbclass&lt;br /&gt;
# to identify the distro layer directory during&lt;br /&gt;
# bblayers checks.&lt;br /&gt;
TD_DISTRO_LAYERDIR = &amp;quot;${LAYERDIR}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 2. Add base distro config===&lt;br /&gt;
&lt;br /&gt;
In order to add the initial distro configuration, it is necessary to create distro configuration file inside the &#039;&#039;&#039;meta-layer/conf/distro&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
Here is an example of how the directory structure should look like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   ├── distro&lt;br /&gt;
│   │   └── proventusnova.conf&lt;br /&gt;
│   └── layer.conf&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The same as with the layer.conf, it is easier to start with an existing distro configuration file and modify it in order to fit the project requirements. For example, the following corresponds to a distro configuration file based on the [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/conf/distro/tegrademo.conf NVIDIA tegra_demo_distro]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
DISTRO = &amp;quot;proventusnova&amp;quot;&lt;br /&gt;
DISTRO_NAME = &amp;quot;ProventusNova Custom Distro&amp;quot;&lt;br /&gt;
DISTRO_VERSION_BASE = &amp;quot;1.0&amp;quot;&lt;br /&gt;
DISTRO_VERSION = &amp;quot;${DISTRO_VERSION_BASE}+snapshot-${METADATA_REVISION}&amp;quot;&lt;br /&gt;
DISTRO_CODENAME = &amp;quot;proventusnova&amp;quot;&lt;br /&gt;
SDK_VENDOR = &amp;quot;-proventusnova&amp;quot;&lt;br /&gt;
SDK_VERSION := &amp;quot;${@&#039;${DISTRO_VERSION}&#039;.replace(&#039;snapshot-${METADATA_REVISION}&#039;,&#039;snapshot&#039;)}&amp;quot;&lt;br /&gt;
SDK_VERSION[vardepvalue] = &amp;quot;${SDK_VERSION}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
MAINTAINER = &amp;quot;ProventusNova team &amp;lt;support@proventusnova.com&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
TARGET_VENDOR = &amp;quot;-proventusnova&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# New ${DISTRO}-&amp;lt;version&amp;gt; setting for sanity checks.&lt;br /&gt;
# Increment version number (and the corresponding&lt;br /&gt;
# setting int the template bblayers.conf.sample file)&lt;br /&gt;
# each time the layer settings are changed.&lt;br /&gt;
REQUIRED_PROVENTUSNOVA_BBLAYERS_CONF_VERSION = &amp;quot;${DISTRO}-1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
LOCALCONF_VERSION = &amp;quot;2&amp;quot;&lt;br /&gt;
&lt;br /&gt;
PROVENTUSNOVA_DEFAULT_DISTRO_FEATURES = &amp;quot;largefile opengl ptest multiarch wayland vulkan systemd pam virtualization usrmerge&amp;quot;&lt;br /&gt;
&lt;br /&gt;
DISTRO_FEATURES ?= &amp;quot;${DISTRO_FEATURES_DEFAULT} ${PROVENTUSNOVA_DEFAULT_DISTRO_FEATURES}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Jetson platforms do not use linux-yocto, but for QEMU testing&lt;br /&gt;
# align with the poky distro.&lt;br /&gt;
PREFERRED_VERSION_linux-yocto ?= &amp;quot;5.19%&amp;quot;&lt;br /&gt;
PREFERRED_VERSION_linux-yocto-rt ?= &amp;quot;5.19%&amp;quot;&lt;br /&gt;
&lt;br /&gt;
SDK_NAME = &amp;quot;${DISTRO}-${TCLIBC}-${SDKMACHINE}-${IMAGE_BASENAME}-${TUNE_PKGARCH}-${MACHINE}&amp;quot;&lt;br /&gt;
SDKPATHINSTALL = &amp;quot;/opt/${DISTRO}/${SDK_VERSION}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
TCLIBCAPPEND = &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
PACKAGE_CLASSES ?= &amp;quot;package_rpm&amp;quot;&lt;br /&gt;
&lt;br /&gt;
SANITY_TESTED_DISTROS ?= &amp;quot; \&lt;br /&gt;
            ubuntu-20.04 \n \&lt;br /&gt;
            ubuntu-22.04 \n \&lt;br /&gt;
            ubuntu-24.04 \n \&lt;br /&gt;
            &amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Most NVIDIA-supplied services expect systemd&lt;br /&gt;
INIT_MANAGER = &amp;quot;systemd&amp;quot;&lt;br /&gt;
&lt;br /&gt;
require conf/distro/include/no-static-libs.inc&lt;br /&gt;
require conf/distro/include/yocto-uninative.inc&lt;br /&gt;
require conf/distro/include/security_flags.inc&lt;br /&gt;
INHERIT += &amp;quot;uninative&amp;quot;&lt;br /&gt;
&lt;br /&gt;
LICENSE_FLAGS_ACCEPTED += &amp;quot;commercial_faad2 commercial_x264&amp;quot;&lt;br /&gt;
&lt;br /&gt;
USE_REDUNDANT_FLASH_LAYOUT_DEFAULT ?= &amp;quot;1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
INHERIT += &amp;quot;tegra-support-sanity&amp;quot;&lt;br /&gt;
ESDK_CLASS_INHERIT_DISABLE:append = &amp;quot; tegra-support-sanity&amp;quot;&lt;br /&gt;
&lt;br /&gt;
BB_SIGNATURE_HANDLER ?= &amp;quot;OEEquivHash&amp;quot;&lt;br /&gt;
BB_HASHSERVE ??= &amp;quot;auto&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 3. Add base machine===&lt;br /&gt;
&lt;br /&gt;
This step might not be required, if there is already a machine that can be used from a different meta-layer.&lt;br /&gt;
However, it is still recommended to create a custom machine configuration based on that machine in order to keep better order of the machine used in the custom Yocto build.&lt;br /&gt;
&lt;br /&gt;
To create a custom machine, it is necessary to add a machine.conf file in the &#039;&#039;&#039;meta-layer/conf/machine&#039;&#039;&#039; directory.&lt;br /&gt;
For example, this is how the directory structure should look when adding a new machine to the custom meta-layer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   ├── distro&lt;br /&gt;
│   │   └── proventusnova.conf&lt;br /&gt;
│   ├── layer.conf&lt;br /&gt;
│   └── machine&lt;br /&gt;
│       └── proventusnova-jetson-orin-nx-16-devkit.conf&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And, as a reference, here is a custom machine based on [https://github.com/OE4T/meta-tegra/blob/scarthgap/conf/machine/p3509-a02-p3767-0000.conf NVIDIA meta-tegra  p3509-a02-p3767-0000] machine.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#@TYPE: Machine&lt;br /&gt;
#@NAME: Nvidia Jetson Orin NX 16GB (P3767-0000)&lt;br /&gt;
#@DESCRIPTION: Nvidia Jetson Orin NX 16GB module in P3509 carrier&lt;br /&gt;
&lt;br /&gt;
TEGRA_FLASHVAR_PINMUX_CONFIG ?= &amp;quot;tegra234-mb1-bct-pinmux-p3767-hdmi-a03.dtsi&amp;quot;&lt;br /&gt;
TEGRA_FLASHVAR_PMC_CONFIG ?= &amp;quot;tegra234-mb1-bct-padvoltage-p3767-hdmi-a03.dtsi&amp;quot;&lt;br /&gt;
TEGRA_PLUGIN_MANAGER_OVERLAYS ?= &amp;quot;tegra234-carveouts.dtbo tegra-optee.dtbo tegra234-p3768-0000+p3767-0000-dynamic.dtbo tegra234-dcb-p3767-0000-hdmi.dtbo&amp;quot;&lt;br /&gt;
TEGRA_DCE_OVERLAY ?= &amp;quot;tegra234-dcb-p3767-0000-hdmi.dtbo&amp;quot;&lt;br /&gt;
&lt;br /&gt;
require conf/machine/include/orin-nx.inc&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 4. Add initial config template files===&lt;br /&gt;
&lt;br /&gt;
Bitbake will require 2 configuration files for building an image:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;bblayers.conf&#039;&#039;&#039;: This file contains information about the location of the required meta-layers for the project.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;local.conf&#039;&#039;&#039;: This file contains general build configuration for bitbake. For instance, in this file it is possible to determine where to store downloads, cache and even which package management configuration to use.&lt;br /&gt;
&lt;br /&gt;
Now, in order to simplify the configuration of a custom Yocto build, it is possible to include template configuration files on the custom meta-layer. This practice is encouraged in order to increase build repeatability.&lt;br /&gt;
&lt;br /&gt;
These 2 files are generally created inside &#039;&#039;&#039;meta-layer/conf/templates/template-name&#039;&#039;&#039;.&lt;br /&gt;
For reference, this is how the directory structure would look like after the files are created:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   ├── distro&lt;br /&gt;
│   │   └── proventusnova.conf&lt;br /&gt;
│   ├── layer.conf&lt;br /&gt;
│   ├── machine&lt;br /&gt;
│   │   └── proventusnova-jetson-orin-nx-16-devkit.conf&lt;br /&gt;
│   └── templates&lt;br /&gt;
│       └── proventusnova&lt;br /&gt;
│           ├── bblayers.conf.sample&lt;br /&gt;
│           └── local.conf.sample&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here is an example of a custom bblayers.conf.sample file based on [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/conf/templates/tegrademo/bblayers.conf.sample NVIDIA tegra-demo-distro]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Version of layers configuration, specific to&lt;br /&gt;
# each defined distro in the repository.&lt;br /&gt;
# Format: ${DISTRO}-&amp;lt;version&amp;gt;&lt;br /&gt;
TD_BBLAYERS_CONF_VERSION = &amp;quot;proventusnova-1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
BBPATH = &amp;quot;${TOPDIR}&amp;quot;&lt;br /&gt;
BBFILES ?= &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
BBLAYERS ?= &amp;quot; \&lt;br /&gt;
  ##OEROOT##/meta \&lt;br /&gt;
  ##OEROOT##/../meta-tegra \&lt;br /&gt;
  ##OEROOT##/../meta-tegra-community \&lt;br /&gt;
  ##OEROOT##/../meta-virtualization \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-oe \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-python \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-networking \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-filesystems \&lt;br /&gt;
  &amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And, this is an example of a custom local.conf.sample file based on [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/conf/templates/tegrademo/local.conf.sample NVIDIA tegra-demo-distro]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
# Machine Selection&lt;br /&gt;
#&lt;br /&gt;
MACHINE ??= &amp;quot;proventusnova-jetson-orin-nx-16-devkit.conf&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Where to place downloads&lt;br /&gt;
#&lt;br /&gt;
DL_DIR ?= &amp;quot;${TOPDIR}/../downloads&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Where to place shared-state files&lt;br /&gt;
#&lt;br /&gt;
SSTATE_DIR ?= &amp;quot;${TOPDIR}/../sstate-cache&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Where to place the build output&lt;br /&gt;
#&lt;br /&gt;
TMPDIR = &amp;quot;${TOPDIR}/tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Default policy (distro) config&lt;br /&gt;
#&lt;br /&gt;
DISTRO ?= &amp;quot;proventusnova&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Package Management configuration&lt;br /&gt;
#&lt;br /&gt;
PACKAGE_CLASSES ?= &amp;quot;package_deb&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# SDK target architecture&lt;br /&gt;
#&lt;br /&gt;
SDKMACHINE ?= &amp;quot;x86_64&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Extra image configuration defaults&lt;br /&gt;
#&lt;br /&gt;
EXTRA_IMAGE_FEATURES ?= &amp;quot;debug-tweaks&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Additional image features&lt;br /&gt;
#&lt;br /&gt;
USER_CLASSES ?= &amp;quot;buildstats&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Interactive shell configuration&lt;br /&gt;
#&lt;br /&gt;
PATCHRESOLVE = &amp;quot;noop&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Disk Space Monitoring during the build&lt;br /&gt;
#&lt;br /&gt;
BB_DISKMON_DIRS ??= &amp;quot;\&lt;br /&gt;
    STOPTASKS,${TMPDIR},1G,100K \&lt;br /&gt;
    STOPTASKS,${DL_DIR},1G,100K \&lt;br /&gt;
    STOPTASKS,${SSTATE_DIR},1G,100K \&lt;br /&gt;
    STOPTASKS,/tmp,100M,100K \&lt;br /&gt;
    HALT,${TMPDIR},100M,1K \&lt;br /&gt;
    HALT,${DL_DIR},100M,1K \&lt;br /&gt;
    HALT,${SSTATE_DIR},100M,1K \&lt;br /&gt;
    HALT,/tmp,10M,1K&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Qemu configuration&lt;br /&gt;
#&lt;br /&gt;
PACKAGECONFIG:append:pn-qemu-system-native = &amp;quot; sdl&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# CONF_VERSION is increased each time build/conf/ changes incompatibly and is used to&lt;br /&gt;
# track the version of this file when it was generated.&lt;br /&gt;
CONF_VERSION = &amp;quot;1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 5. Add base image recipe===&lt;br /&gt;
&lt;br /&gt;
In order to create a custom image, it is necessary to add a custom image recipe file.&lt;br /&gt;
This file is usually added inside the &#039;&#039;&#039;meta-layer/recipes-layer/images&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   ├── distro&lt;br /&gt;
│   │   └── proventusnova.conf&lt;br /&gt;
│   ├── layer.conf&lt;br /&gt;
│   ├── machine&lt;br /&gt;
│   │   └── proventusnova-jetson-orin-nx-16-devkit.conf&lt;br /&gt;
│   └── templates&lt;br /&gt;
│       ├── bblayers.conf.sample&lt;br /&gt;
│       └── local.conf.sample&lt;br /&gt;
├── README.md&lt;br /&gt;
└── recipes-proventusnova&lt;br /&gt;
    └── images&lt;br /&gt;
        └── proventusnova-image-base.bb&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once again, a custom image recipe can be based on another image recipe. And, it can also import other image recipes in order to include their base configurations.&lt;br /&gt;
&lt;br /&gt;
As reference, the following image recipe was based on [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/recipes-demo/images/demo-image-base.bb NVIDIA tegra-demo-distro demo-image-base recipe]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
DESCRIPTION = &amp;quot;ProventusNova base image&amp;quot;&lt;br /&gt;
LICENSE = &amp;quot;CLOSED&amp;quot;&lt;br /&gt;
&lt;br /&gt;
inherit core-image&lt;br /&gt;
&lt;br /&gt;
IMAGE_FEATURES += &amp;quot;ssh-server-openssh debug-tweaks&amp;quot;&lt;br /&gt;
&lt;br /&gt;
CORE_IMAGE_BASE_INSTALL += &amp;quot;systemd&amp;quot;&lt;br /&gt;
TOOLCHAIN_HOST_TASK += &amp;quot;nativesdk-packagegroup-cuda-sdk-host&amp;quot;&lt;br /&gt;
&lt;br /&gt;
inherit nopackages&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Andres</name></author>
	</entry>
	<entry>
		<id>https://developerwiki.proventusnova.com/index.php?title=How_to_create_a_custom_yocto_meta_layer&amp;diff=78</id>
		<title>How to create a custom yocto meta layer</title>
		<link rel="alternate" type="text/html" href="https://developerwiki.proventusnova.com/index.php?title=How_to_create_a_custom_yocto_meta_layer&amp;diff=78"/>
		<updated>2025-03-11T19:39:39Z</updated>

		<summary type="html">&lt;p&gt;Andres: /* Step 5. Add base image recipe */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This wiki will provide a detailed guide on how to create a custom Yocto meta-layer.&lt;br /&gt;
&lt;br /&gt;
==Create Base Meta-Layer==&lt;br /&gt;
&lt;br /&gt;
This section contains steps to create the base custom meta-layer.&lt;br /&gt;
After completion, the custom base meta-layer will contain the following parts:&lt;br /&gt;
&lt;br /&gt;
* Custom layer configuration&lt;br /&gt;
* Custom distro configuration&lt;br /&gt;
* Custom machine&lt;br /&gt;
* Custom config template files&lt;br /&gt;
* Custom image recipe&lt;br /&gt;
&lt;br /&gt;
===Step 1. Add base layer.conf file===&lt;br /&gt;
&lt;br /&gt;
The layer configuration file provides Yocto with the configuration for the custom meta-layer.&lt;br /&gt;
It shall be stored in a directory called &#039;&#039;&#039;conf&#039;&#039;&#039; inside the base meta-layer directory, and it shall be named layer.conf.&lt;br /&gt;
According to the [https://docs.yoctoproject.org/dev/dev-manual/layers.html Yocto documentation] it is recommended to start from an existing layer.conf file from a different meta-layer and change it according to the custom requirements.&lt;br /&gt;
&lt;br /&gt;
For instance, here is an example of how the directory structure should look after creating the layer.conf file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   └── layer.conf&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An example layer.conf file based on [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/conf/layer.conf NVIDIA OE4T tegra_demo_distro] is shown in the following code snipped.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
BBPATH =. &amp;quot;${LAYERDIR}:&amp;quot;&lt;br /&gt;
BBFILES += &amp;quot;${LAYERDIR}/recipes-*/*/*.bb ${LAYERDIR}/recipes-*/*/*.bbappend&amp;quot;&lt;br /&gt;
BBFILES_DYNAMIC += &amp;quot;swupdate:${LAYERDIR}/dynamic-layers/meta-swupdate/recipes-*/*/*.bb \&lt;br /&gt;
                    swupdate:${LAYERDIR}/dynamic-layers/meta-swupdate/recipes-*/*/*.bbappend&amp;quot;&lt;br /&gt;
&lt;br /&gt;
BBFILE_COLLECTIONS += &amp;quot;proventusnova&amp;quot;&lt;br /&gt;
BBFILE_PATTERN_proventusnova = &amp;quot;^${LAYERDIR}/&amp;quot;&lt;br /&gt;
BBFILE_PRIORITY_proventusnova = &amp;quot;50&amp;quot;&lt;br /&gt;
&lt;br /&gt;
LAYERVERSION_proventusnova = &amp;quot;4&amp;quot;&lt;br /&gt;
LAYERSERIES_COMPAT_proventusnova = &amp;quot;scarthgap&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# This is used by the tegra-distro-sanity bbclass&lt;br /&gt;
# to identify the distro layer directory during&lt;br /&gt;
# bblayers checks.&lt;br /&gt;
TD_DISTRO_LAYERDIR = &amp;quot;${LAYERDIR}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 2. Add base distro config===&lt;br /&gt;
&lt;br /&gt;
In order to add the initial distro configuration, it is necessary to create distro configuration file inside the &#039;&#039;&#039;meta-layer/conf/distro&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
Here is an example of how the directory structure should look like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   ├── distro&lt;br /&gt;
│   │   └── proventusnova.conf&lt;br /&gt;
│   └── layer.conf&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The same as with the layer.conf, it is easier to start with an existing distro configuration file and modify it in order to fit the project requirements. For example, the following corresponds to a distro configuration file based on the [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/conf/distro/tegrademo.conf NVIDIA tegra_demo_distro]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
DISTRO = &amp;quot;proventusnova&amp;quot;&lt;br /&gt;
DISTRO_NAME = &amp;quot;ProventusNova Custom Distro&amp;quot;&lt;br /&gt;
DISTRO_VERSION_BASE = &amp;quot;1.0&amp;quot;&lt;br /&gt;
DISTRO_VERSION = &amp;quot;${DISTRO_VERSION_BASE}+snapshot-${METADATA_REVISION}&amp;quot;&lt;br /&gt;
DISTRO_CODENAME = &amp;quot;proventusnova&amp;quot;&lt;br /&gt;
SDK_VENDOR = &amp;quot;-proventusnova&amp;quot;&lt;br /&gt;
SDK_VERSION := &amp;quot;${@&#039;${DISTRO_VERSION}&#039;.replace(&#039;snapshot-${METADATA_REVISION}&#039;,&#039;snapshot&#039;)}&amp;quot;&lt;br /&gt;
SDK_VERSION[vardepvalue] = &amp;quot;${SDK_VERSION}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
MAINTAINER = &amp;quot;ProventusNova team &amp;lt;support@proventusnova.com&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
TARGET_VENDOR = &amp;quot;-proventusnova&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# New ${DISTRO}-&amp;lt;version&amp;gt; setting for sanity checks.&lt;br /&gt;
# Increment version number (and the corresponding&lt;br /&gt;
# setting int the template bblayers.conf.sample file)&lt;br /&gt;
# each time the layer settings are changed.&lt;br /&gt;
REQUIRED_PROVENTUSNOVA_BBLAYERS_CONF_VERSION = &amp;quot;${DISTRO}-1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
LOCALCONF_VERSION = &amp;quot;2&amp;quot;&lt;br /&gt;
&lt;br /&gt;
PROVENTUSNOVA_DEFAULT_DISTRO_FEATURES = &amp;quot;largefile opengl ptest multiarch wayland vulkan systemd pam virtualization usrmerge&amp;quot;&lt;br /&gt;
&lt;br /&gt;
DISTRO_FEATURES ?= &amp;quot;${DISTRO_FEATURES_DEFAULT} ${PROVENTUSNOVA_DEFAULT_DISTRO_FEATURES}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Jetson platforms do not use linux-yocto, but for QEMU testing&lt;br /&gt;
# align with the poky distro.&lt;br /&gt;
PREFERRED_VERSION_linux-yocto ?= &amp;quot;5.19%&amp;quot;&lt;br /&gt;
PREFERRED_VERSION_linux-yocto-rt ?= &amp;quot;5.19%&amp;quot;&lt;br /&gt;
&lt;br /&gt;
SDK_NAME = &amp;quot;${DISTRO}-${TCLIBC}-${SDKMACHINE}-${IMAGE_BASENAME}-${TUNE_PKGARCH}-${MACHINE}&amp;quot;&lt;br /&gt;
SDKPATHINSTALL = &amp;quot;/opt/${DISTRO}/${SDK_VERSION}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
TCLIBCAPPEND = &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
PACKAGE_CLASSES ?= &amp;quot;package_rpm&amp;quot;&lt;br /&gt;
&lt;br /&gt;
SANITY_TESTED_DISTROS ?= &amp;quot; \&lt;br /&gt;
            ubuntu-20.04 \n \&lt;br /&gt;
            ubuntu-22.04 \n \&lt;br /&gt;
            ubuntu-24.04 \n \&lt;br /&gt;
            &amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Most NVIDIA-supplied services expect systemd&lt;br /&gt;
INIT_MANAGER = &amp;quot;systemd&amp;quot;&lt;br /&gt;
&lt;br /&gt;
require conf/distro/include/no-static-libs.inc&lt;br /&gt;
require conf/distro/include/yocto-uninative.inc&lt;br /&gt;
require conf/distro/include/security_flags.inc&lt;br /&gt;
INHERIT += &amp;quot;uninative&amp;quot;&lt;br /&gt;
&lt;br /&gt;
LICENSE_FLAGS_ACCEPTED += &amp;quot;commercial_faad2 commercial_x264&amp;quot;&lt;br /&gt;
&lt;br /&gt;
USE_REDUNDANT_FLASH_LAYOUT_DEFAULT ?= &amp;quot;1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
INHERIT += &amp;quot;tegra-support-sanity&amp;quot;&lt;br /&gt;
ESDK_CLASS_INHERIT_DISABLE:append = &amp;quot; tegra-support-sanity&amp;quot;&lt;br /&gt;
&lt;br /&gt;
BB_SIGNATURE_HANDLER ?= &amp;quot;OEEquivHash&amp;quot;&lt;br /&gt;
BB_HASHSERVE ??= &amp;quot;auto&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 3. Add base machine===&lt;br /&gt;
&lt;br /&gt;
This step might not be required, if there is already a machine that can be used from a different meta-layer.&lt;br /&gt;
However, it is still recommended to create a custom machine configuration based on that machine in order to keep better order of the machine used in the custom Yocto build.&lt;br /&gt;
&lt;br /&gt;
To create a custom machine, it is necessary to add a machine.conf file in the &#039;&#039;&#039;meta-layer/conf/machine&#039;&#039;&#039; directory.&lt;br /&gt;
For example, this is how the directory structure should look when adding a new machine to the custom meta-layer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   ├── distro&lt;br /&gt;
│   │   └── proventusnova.conf&lt;br /&gt;
│   ├── layer.conf&lt;br /&gt;
│   └── machine&lt;br /&gt;
│       └── proventusnova-jetson-orin-nx-16-devkit.conf&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And, as a reference, here is a custom machine based on [https://github.com/OE4T/meta-tegra/blob/scarthgap/conf/machine/p3509-a02-p3767-0000.conf NVIDIA meta-tegra  p3509-a02-p3767-0000] machine.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#@TYPE: Machine&lt;br /&gt;
#@NAME: Nvidia Jetson Orin NX 16GB (P3767-0000)&lt;br /&gt;
#@DESCRIPTION: Nvidia Jetson Orin NX 16GB module in P3509 carrier&lt;br /&gt;
&lt;br /&gt;
TEGRA_FLASHVAR_PINMUX_CONFIG ?= &amp;quot;tegra234-mb1-bct-pinmux-p3767-hdmi-a03.dtsi&amp;quot;&lt;br /&gt;
TEGRA_FLASHVAR_PMC_CONFIG ?= &amp;quot;tegra234-mb1-bct-padvoltage-p3767-hdmi-a03.dtsi&amp;quot;&lt;br /&gt;
TEGRA_PLUGIN_MANAGER_OVERLAYS ?= &amp;quot;tegra234-carveouts.dtbo tegra-optee.dtbo tegra234-p3768-0000+p3767-0000-dynamic.dtbo tegra234-dcb-p3767-0000-hdmi.dtbo&amp;quot;&lt;br /&gt;
TEGRA_DCE_OVERLAY ?= &amp;quot;tegra234-dcb-p3767-0000-hdmi.dtbo&amp;quot;&lt;br /&gt;
&lt;br /&gt;
require conf/machine/include/orin-nx.inc&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 4. Add initial config template files===&lt;br /&gt;
&lt;br /&gt;
Bitbake will require 2 configuration files for building an image:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;bblayers.conf&#039;&#039;&#039;: This file contains information about the location of the required meta-layers for the project.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;local.conf&#039;&#039;&#039;: This file contains general build configuration for bitbake. For instance, in this file it is possible to determine where to store downloads, cache and even which package management configuration to use.&lt;br /&gt;
&lt;br /&gt;
Now, in order to simplify the configuration of a custom Yocto build, it is possible to include template configuration files on the custom meta-layer. This practice is encouraged in order to increase build repeatability.&lt;br /&gt;
&lt;br /&gt;
These 2 files are generally created inside &#039;&#039;&#039;meta-layer/conf/templates&#039;&#039;&#039;.&lt;br /&gt;
For reference, this is how the directory structure would look like after the files are created:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   ├── distro&lt;br /&gt;
│   │   └── proventusnova.conf&lt;br /&gt;
│   ├── layer.conf&lt;br /&gt;
│   ├── machine&lt;br /&gt;
│   │   └── proventusnova-jetson-orin-nx-16-devkit.conf&lt;br /&gt;
│   └── templates&lt;br /&gt;
│       ├── bblayers.conf.sample&lt;br /&gt;
│       └── local.conf.sample&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here is an example of a custom bblayers.conf.sample file based on [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/conf/templates/tegrademo/bblayers.conf.sample NVIDIA tegra-demo-distro]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Version of layers configuration, specific to&lt;br /&gt;
# each defined distro in the repository.&lt;br /&gt;
# Format: ${DISTRO}-&amp;lt;version&amp;gt;&lt;br /&gt;
TD_BBLAYERS_CONF_VERSION = &amp;quot;proventusnova-1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
BBPATH = &amp;quot;${TOPDIR}&amp;quot;&lt;br /&gt;
BBFILES ?= &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
BBLAYERS ?= &amp;quot; \&lt;br /&gt;
  ##OEROOT##/meta \&lt;br /&gt;
  ##OEROOT##/../meta-tegra \&lt;br /&gt;
  ##OEROOT##/../meta-tegra-community \&lt;br /&gt;
  ##OEROOT##/../meta-virtualization \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-oe \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-python \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-networking \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-filesystems \&lt;br /&gt;
  &amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And, this is an example of a custom local.conf.sample file based on [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/conf/templates/tegrademo/local.conf.sample NVIDIA tegra-demo-distro]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
# Machine Selection&lt;br /&gt;
#&lt;br /&gt;
MACHINE ??= &amp;quot;proventusnova-jetson-orin-nx-16-devkit.conf&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Where to place downloads&lt;br /&gt;
#&lt;br /&gt;
DL_DIR ?= &amp;quot;${TOPDIR}/../downloads&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Where to place shared-state files&lt;br /&gt;
#&lt;br /&gt;
SSTATE_DIR ?= &amp;quot;${TOPDIR}/../sstate-cache&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Where to place the build output&lt;br /&gt;
#&lt;br /&gt;
TMPDIR = &amp;quot;${TOPDIR}/tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Default policy (distro) config&lt;br /&gt;
#&lt;br /&gt;
DISTRO ?= &amp;quot;proventusnova&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Package Management configuration&lt;br /&gt;
#&lt;br /&gt;
PACKAGE_CLASSES ?= &amp;quot;package_deb&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# SDK target architecture&lt;br /&gt;
#&lt;br /&gt;
SDKMACHINE ?= &amp;quot;x86_64&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Extra image configuration defaults&lt;br /&gt;
#&lt;br /&gt;
EXTRA_IMAGE_FEATURES ?= &amp;quot;debug-tweaks&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Additional image features&lt;br /&gt;
#&lt;br /&gt;
USER_CLASSES ?= &amp;quot;buildstats&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Interactive shell configuration&lt;br /&gt;
#&lt;br /&gt;
PATCHRESOLVE = &amp;quot;noop&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Disk Space Monitoring during the build&lt;br /&gt;
#&lt;br /&gt;
BB_DISKMON_DIRS ??= &amp;quot;\&lt;br /&gt;
    STOPTASKS,${TMPDIR},1G,100K \&lt;br /&gt;
    STOPTASKS,${DL_DIR},1G,100K \&lt;br /&gt;
    STOPTASKS,${SSTATE_DIR},1G,100K \&lt;br /&gt;
    STOPTASKS,/tmp,100M,100K \&lt;br /&gt;
    HALT,${TMPDIR},100M,1K \&lt;br /&gt;
    HALT,${DL_DIR},100M,1K \&lt;br /&gt;
    HALT,${SSTATE_DIR},100M,1K \&lt;br /&gt;
    HALT,/tmp,10M,1K&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Qemu configuration&lt;br /&gt;
#&lt;br /&gt;
PACKAGECONFIG:append:pn-qemu-system-native = &amp;quot; sdl&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# CONF_VERSION is increased each time build/conf/ changes incompatibly and is used to&lt;br /&gt;
# track the version of this file when it was generated.&lt;br /&gt;
CONF_VERSION = &amp;quot;1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 5. Add base image recipe===&lt;br /&gt;
&lt;br /&gt;
In order to create a custom image, it is necessary to add a custom image recipe file.&lt;br /&gt;
This file is usually added inside the &#039;&#039;&#039;meta-layer/recipes-layer/images&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   ├── distro&lt;br /&gt;
│   │   └── proventusnova.conf&lt;br /&gt;
│   ├── layer.conf&lt;br /&gt;
│   ├── machine&lt;br /&gt;
│   │   └── proventusnova-jetson-orin-nx-16-devkit.conf&lt;br /&gt;
│   └── templates&lt;br /&gt;
│       ├── bblayers.conf.sample&lt;br /&gt;
│       └── local.conf.sample&lt;br /&gt;
├── README.md&lt;br /&gt;
└── recipes-proventusnova&lt;br /&gt;
    └── images&lt;br /&gt;
        └── proventusnova-image-base.bb&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once again, a custom image recipe can be based on another image recipe. And, it can also import other image recipes in order to include their base configurations.&lt;br /&gt;
&lt;br /&gt;
As reference, the following image recipe was based on [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/recipes-demo/images/demo-image-base.bb NVIDIA tegra-demo-distro demo-image-base recipe]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
DESCRIPTION = &amp;quot;ProventusNova base image&amp;quot;&lt;br /&gt;
LICENSE = &amp;quot;CLOSED&amp;quot;&lt;br /&gt;
&lt;br /&gt;
inherit core-image&lt;br /&gt;
&lt;br /&gt;
IMAGE_FEATURES += &amp;quot;ssh-server-openssh debug-tweaks&amp;quot;&lt;br /&gt;
&lt;br /&gt;
CORE_IMAGE_BASE_INSTALL += &amp;quot;systemd&amp;quot;&lt;br /&gt;
TOOLCHAIN_HOST_TASK += &amp;quot;nativesdk-packagegroup-cuda-sdk-host&amp;quot;&lt;br /&gt;
&lt;br /&gt;
inherit nopackages&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Andres</name></author>
	</entry>
	<entry>
		<id>https://developerwiki.proventusnova.com/index.php?title=How_to_create_a_custom_yocto_meta_layer&amp;diff=77</id>
		<title>How to create a custom yocto meta layer</title>
		<link rel="alternate" type="text/html" href="https://developerwiki.proventusnova.com/index.php?title=How_to_create_a_custom_yocto_meta_layer&amp;diff=77"/>
		<updated>2025-03-11T19:24:43Z</updated>

		<summary type="html">&lt;p&gt;Andres: /* Step 4. Add initial config template files */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This wiki will provide a detailed guide on how to create a custom Yocto meta-layer.&lt;br /&gt;
&lt;br /&gt;
==Create Base Meta-Layer==&lt;br /&gt;
&lt;br /&gt;
This section contains steps to create the base custom meta-layer.&lt;br /&gt;
After completion, the custom base meta-layer will contain the following parts:&lt;br /&gt;
&lt;br /&gt;
* Custom layer configuration&lt;br /&gt;
* Custom distro configuration&lt;br /&gt;
* Custom machine&lt;br /&gt;
* Custom config template files&lt;br /&gt;
* Custom image recipe&lt;br /&gt;
&lt;br /&gt;
===Step 1. Add base layer.conf file===&lt;br /&gt;
&lt;br /&gt;
The layer configuration file provides Yocto with the configuration for the custom meta-layer.&lt;br /&gt;
It shall be stored in a directory called &#039;&#039;&#039;conf&#039;&#039;&#039; inside the base meta-layer directory, and it shall be named layer.conf.&lt;br /&gt;
According to the [https://docs.yoctoproject.org/dev/dev-manual/layers.html Yocto documentation] it is recommended to start from an existing layer.conf file from a different meta-layer and change it according to the custom requirements.&lt;br /&gt;
&lt;br /&gt;
For instance, here is an example of how the directory structure should look after creating the layer.conf file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   └── layer.conf&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An example layer.conf file based on [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/conf/layer.conf NVIDIA OE4T tegra_demo_distro] is shown in the following code snipped.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
BBPATH =. &amp;quot;${LAYERDIR}:&amp;quot;&lt;br /&gt;
BBFILES += &amp;quot;${LAYERDIR}/recipes-*/*/*.bb ${LAYERDIR}/recipes-*/*/*.bbappend&amp;quot;&lt;br /&gt;
BBFILES_DYNAMIC += &amp;quot;swupdate:${LAYERDIR}/dynamic-layers/meta-swupdate/recipes-*/*/*.bb \&lt;br /&gt;
                    swupdate:${LAYERDIR}/dynamic-layers/meta-swupdate/recipes-*/*/*.bbappend&amp;quot;&lt;br /&gt;
&lt;br /&gt;
BBFILE_COLLECTIONS += &amp;quot;proventusnova&amp;quot;&lt;br /&gt;
BBFILE_PATTERN_proventusnova = &amp;quot;^${LAYERDIR}/&amp;quot;&lt;br /&gt;
BBFILE_PRIORITY_proventusnova = &amp;quot;50&amp;quot;&lt;br /&gt;
&lt;br /&gt;
LAYERVERSION_proventusnova = &amp;quot;4&amp;quot;&lt;br /&gt;
LAYERSERIES_COMPAT_proventusnova = &amp;quot;scarthgap&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# This is used by the tegra-distro-sanity bbclass&lt;br /&gt;
# to identify the distro layer directory during&lt;br /&gt;
# bblayers checks.&lt;br /&gt;
TD_DISTRO_LAYERDIR = &amp;quot;${LAYERDIR}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 2. Add base distro config===&lt;br /&gt;
&lt;br /&gt;
In order to add the initial distro configuration, it is necessary to create distro configuration file inside the &#039;&#039;&#039;meta-layer/conf/distro&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
Here is an example of how the directory structure should look like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   ├── distro&lt;br /&gt;
│   │   └── proventusnova.conf&lt;br /&gt;
│   └── layer.conf&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The same as with the layer.conf, it is easier to start with an existing distro configuration file and modify it in order to fit the project requirements. For example, the following corresponds to a distro configuration file based on the [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/conf/distro/tegrademo.conf NVIDIA tegra_demo_distro]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
DISTRO = &amp;quot;proventusnova&amp;quot;&lt;br /&gt;
DISTRO_NAME = &amp;quot;ProventusNova Custom Distro&amp;quot;&lt;br /&gt;
DISTRO_VERSION_BASE = &amp;quot;1.0&amp;quot;&lt;br /&gt;
DISTRO_VERSION = &amp;quot;${DISTRO_VERSION_BASE}+snapshot-${METADATA_REVISION}&amp;quot;&lt;br /&gt;
DISTRO_CODENAME = &amp;quot;proventusnova&amp;quot;&lt;br /&gt;
SDK_VENDOR = &amp;quot;-proventusnova&amp;quot;&lt;br /&gt;
SDK_VERSION := &amp;quot;${@&#039;${DISTRO_VERSION}&#039;.replace(&#039;snapshot-${METADATA_REVISION}&#039;,&#039;snapshot&#039;)}&amp;quot;&lt;br /&gt;
SDK_VERSION[vardepvalue] = &amp;quot;${SDK_VERSION}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
MAINTAINER = &amp;quot;ProventusNova team &amp;lt;support@proventusnova.com&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
TARGET_VENDOR = &amp;quot;-proventusnova&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# New ${DISTRO}-&amp;lt;version&amp;gt; setting for sanity checks.&lt;br /&gt;
# Increment version number (and the corresponding&lt;br /&gt;
# setting int the template bblayers.conf.sample file)&lt;br /&gt;
# each time the layer settings are changed.&lt;br /&gt;
REQUIRED_PROVENTUSNOVA_BBLAYERS_CONF_VERSION = &amp;quot;${DISTRO}-1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
LOCALCONF_VERSION = &amp;quot;2&amp;quot;&lt;br /&gt;
&lt;br /&gt;
PROVENTUSNOVA_DEFAULT_DISTRO_FEATURES = &amp;quot;largefile opengl ptest multiarch wayland vulkan systemd pam virtualization usrmerge&amp;quot;&lt;br /&gt;
&lt;br /&gt;
DISTRO_FEATURES ?= &amp;quot;${DISTRO_FEATURES_DEFAULT} ${PROVENTUSNOVA_DEFAULT_DISTRO_FEATURES}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Jetson platforms do not use linux-yocto, but for QEMU testing&lt;br /&gt;
# align with the poky distro.&lt;br /&gt;
PREFERRED_VERSION_linux-yocto ?= &amp;quot;5.19%&amp;quot;&lt;br /&gt;
PREFERRED_VERSION_linux-yocto-rt ?= &amp;quot;5.19%&amp;quot;&lt;br /&gt;
&lt;br /&gt;
SDK_NAME = &amp;quot;${DISTRO}-${TCLIBC}-${SDKMACHINE}-${IMAGE_BASENAME}-${TUNE_PKGARCH}-${MACHINE}&amp;quot;&lt;br /&gt;
SDKPATHINSTALL = &amp;quot;/opt/${DISTRO}/${SDK_VERSION}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
TCLIBCAPPEND = &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
PACKAGE_CLASSES ?= &amp;quot;package_rpm&amp;quot;&lt;br /&gt;
&lt;br /&gt;
SANITY_TESTED_DISTROS ?= &amp;quot; \&lt;br /&gt;
            ubuntu-20.04 \n \&lt;br /&gt;
            ubuntu-22.04 \n \&lt;br /&gt;
            ubuntu-24.04 \n \&lt;br /&gt;
            &amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Most NVIDIA-supplied services expect systemd&lt;br /&gt;
INIT_MANAGER = &amp;quot;systemd&amp;quot;&lt;br /&gt;
&lt;br /&gt;
require conf/distro/include/no-static-libs.inc&lt;br /&gt;
require conf/distro/include/yocto-uninative.inc&lt;br /&gt;
require conf/distro/include/security_flags.inc&lt;br /&gt;
INHERIT += &amp;quot;uninative&amp;quot;&lt;br /&gt;
&lt;br /&gt;
LICENSE_FLAGS_ACCEPTED += &amp;quot;commercial_faad2 commercial_x264&amp;quot;&lt;br /&gt;
&lt;br /&gt;
USE_REDUNDANT_FLASH_LAYOUT_DEFAULT ?= &amp;quot;1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
INHERIT += &amp;quot;tegra-support-sanity&amp;quot;&lt;br /&gt;
ESDK_CLASS_INHERIT_DISABLE:append = &amp;quot; tegra-support-sanity&amp;quot;&lt;br /&gt;
&lt;br /&gt;
BB_SIGNATURE_HANDLER ?= &amp;quot;OEEquivHash&amp;quot;&lt;br /&gt;
BB_HASHSERVE ??= &amp;quot;auto&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 3. Add base machine===&lt;br /&gt;
&lt;br /&gt;
This step might not be required, if there is already a machine that can be used from a different meta-layer.&lt;br /&gt;
However, it is still recommended to create a custom machine configuration based on that machine in order to keep better order of the machine used in the custom Yocto build.&lt;br /&gt;
&lt;br /&gt;
To create a custom machine, it is necessary to add a machine.conf file in the &#039;&#039;&#039;meta-layer/conf/machine&#039;&#039;&#039; directory.&lt;br /&gt;
For example, this is how the directory structure should look when adding a new machine to the custom meta-layer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   ├── distro&lt;br /&gt;
│   │   └── proventusnova.conf&lt;br /&gt;
│   ├── layer.conf&lt;br /&gt;
│   └── machine&lt;br /&gt;
│       └── proventusnova-jetson-orin-nx-16-devkit.conf&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And, as a reference, here is a custom machine based on [https://github.com/OE4T/meta-tegra/blob/scarthgap/conf/machine/p3509-a02-p3767-0000.conf NVIDIA meta-tegra  p3509-a02-p3767-0000] machine.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#@TYPE: Machine&lt;br /&gt;
#@NAME: Nvidia Jetson Orin NX 16GB (P3767-0000)&lt;br /&gt;
#@DESCRIPTION: Nvidia Jetson Orin NX 16GB module in P3509 carrier&lt;br /&gt;
&lt;br /&gt;
TEGRA_FLASHVAR_PINMUX_CONFIG ?= &amp;quot;tegra234-mb1-bct-pinmux-p3767-hdmi-a03.dtsi&amp;quot;&lt;br /&gt;
TEGRA_FLASHVAR_PMC_CONFIG ?= &amp;quot;tegra234-mb1-bct-padvoltage-p3767-hdmi-a03.dtsi&amp;quot;&lt;br /&gt;
TEGRA_PLUGIN_MANAGER_OVERLAYS ?= &amp;quot;tegra234-carveouts.dtbo tegra-optee.dtbo tegra234-p3768-0000+p3767-0000-dynamic.dtbo tegra234-dcb-p3767-0000-hdmi.dtbo&amp;quot;&lt;br /&gt;
TEGRA_DCE_OVERLAY ?= &amp;quot;tegra234-dcb-p3767-0000-hdmi.dtbo&amp;quot;&lt;br /&gt;
&lt;br /&gt;
require conf/machine/include/orin-nx.inc&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 4. Add initial config template files===&lt;br /&gt;
&lt;br /&gt;
Bitbake will require 2 configuration files for building an image:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;bblayers.conf&#039;&#039;&#039;: This file contains information about the location of the required meta-layers for the project.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;local.conf&#039;&#039;&#039;: This file contains general build configuration for bitbake. For instance, in this file it is possible to determine where to store downloads, cache and even which package management configuration to use.&lt;br /&gt;
&lt;br /&gt;
Now, in order to simplify the configuration of a custom Yocto build, it is possible to include template configuration files on the custom meta-layer. This practice is encouraged in order to increase build repeatability.&lt;br /&gt;
&lt;br /&gt;
These 2 files are generally created inside &#039;&#039;&#039;meta-layer/conf/templates&#039;&#039;&#039;.&lt;br /&gt;
For reference, this is how the directory structure would look like after the files are created:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   ├── distro&lt;br /&gt;
│   │   └── proventusnova.conf&lt;br /&gt;
│   ├── layer.conf&lt;br /&gt;
│   ├── machine&lt;br /&gt;
│   │   └── proventusnova-jetson-orin-nx-16-devkit.conf&lt;br /&gt;
│   └── templates&lt;br /&gt;
│       ├── bblayers.conf.sample&lt;br /&gt;
│       └── local.conf.sample&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here is an example of a custom bblayers.conf.sample file based on [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/conf/templates/tegrademo/bblayers.conf.sample NVIDIA tegra-demo-distro]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Version of layers configuration, specific to&lt;br /&gt;
# each defined distro in the repository.&lt;br /&gt;
# Format: ${DISTRO}-&amp;lt;version&amp;gt;&lt;br /&gt;
TD_BBLAYERS_CONF_VERSION = &amp;quot;proventusnova-1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
BBPATH = &amp;quot;${TOPDIR}&amp;quot;&lt;br /&gt;
BBFILES ?= &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
BBLAYERS ?= &amp;quot; \&lt;br /&gt;
  ##OEROOT##/meta \&lt;br /&gt;
  ##OEROOT##/../meta-tegra \&lt;br /&gt;
  ##OEROOT##/../meta-tegra-community \&lt;br /&gt;
  ##OEROOT##/../meta-virtualization \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-oe \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-python \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-networking \&lt;br /&gt;
  ##OEROOT##/../meta-openembedded/meta-filesystems \&lt;br /&gt;
  &amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And, this is an example of a custom local.conf.sample file based on [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/conf/templates/tegrademo/local.conf.sample NVIDIA tegra-demo-distro]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
# Machine Selection&lt;br /&gt;
#&lt;br /&gt;
MACHINE ??= &amp;quot;proventusnova-jetson-orin-nx-16-devkit.conf&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Where to place downloads&lt;br /&gt;
#&lt;br /&gt;
DL_DIR ?= &amp;quot;${TOPDIR}/../downloads&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Where to place shared-state files&lt;br /&gt;
#&lt;br /&gt;
SSTATE_DIR ?= &amp;quot;${TOPDIR}/../sstate-cache&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Where to place the build output&lt;br /&gt;
#&lt;br /&gt;
TMPDIR = &amp;quot;${TOPDIR}/tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Default policy (distro) config&lt;br /&gt;
#&lt;br /&gt;
DISTRO ?= &amp;quot;proventusnova&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Package Management configuration&lt;br /&gt;
#&lt;br /&gt;
PACKAGE_CLASSES ?= &amp;quot;package_deb&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# SDK target architecture&lt;br /&gt;
#&lt;br /&gt;
SDKMACHINE ?= &amp;quot;x86_64&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Extra image configuration defaults&lt;br /&gt;
#&lt;br /&gt;
EXTRA_IMAGE_FEATURES ?= &amp;quot;debug-tweaks&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Additional image features&lt;br /&gt;
#&lt;br /&gt;
USER_CLASSES ?= &amp;quot;buildstats&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Interactive shell configuration&lt;br /&gt;
#&lt;br /&gt;
PATCHRESOLVE = &amp;quot;noop&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Disk Space Monitoring during the build&lt;br /&gt;
#&lt;br /&gt;
BB_DISKMON_DIRS ??= &amp;quot;\&lt;br /&gt;
    STOPTASKS,${TMPDIR},1G,100K \&lt;br /&gt;
    STOPTASKS,${DL_DIR},1G,100K \&lt;br /&gt;
    STOPTASKS,${SSTATE_DIR},1G,100K \&lt;br /&gt;
    STOPTASKS,/tmp,100M,100K \&lt;br /&gt;
    HALT,${TMPDIR},100M,1K \&lt;br /&gt;
    HALT,${DL_DIR},100M,1K \&lt;br /&gt;
    HALT,${SSTATE_DIR},100M,1K \&lt;br /&gt;
    HALT,/tmp,10M,1K&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Qemu configuration&lt;br /&gt;
#&lt;br /&gt;
PACKAGECONFIG:append:pn-qemu-system-native = &amp;quot; sdl&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# CONF_VERSION is increased each time build/conf/ changes incompatibly and is used to&lt;br /&gt;
# track the version of this file when it was generated.&lt;br /&gt;
CONF_VERSION = &amp;quot;1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 5. Add base image recipe===&lt;/div&gt;</summary>
		<author><name>Andres</name></author>
	</entry>
	<entry>
		<id>https://developerwiki.proventusnova.com/index.php?title=How_to_create_a_custom_yocto_meta_layer&amp;diff=76</id>
		<title>How to create a custom yocto meta layer</title>
		<link rel="alternate" type="text/html" href="https://developerwiki.proventusnova.com/index.php?title=How_to_create_a_custom_yocto_meta_layer&amp;diff=76"/>
		<updated>2025-03-11T18:36:07Z</updated>

		<summary type="html">&lt;p&gt;Andres: /* Step 3. Add base machine */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This wiki will provide a detailed guide on how to create a custom Yocto meta-layer.&lt;br /&gt;
&lt;br /&gt;
==Create Base Meta-Layer==&lt;br /&gt;
&lt;br /&gt;
This section contains steps to create the base custom meta-layer.&lt;br /&gt;
After completion, the custom base meta-layer will contain the following parts:&lt;br /&gt;
&lt;br /&gt;
* Custom layer configuration&lt;br /&gt;
* Custom distro configuration&lt;br /&gt;
* Custom machine&lt;br /&gt;
* Custom config template files&lt;br /&gt;
* Custom image recipe&lt;br /&gt;
&lt;br /&gt;
===Step 1. Add base layer.conf file===&lt;br /&gt;
&lt;br /&gt;
The layer configuration file provides Yocto with the configuration for the custom meta-layer.&lt;br /&gt;
It shall be stored in a directory called &#039;&#039;&#039;conf&#039;&#039;&#039; inside the base meta-layer directory, and it shall be named layer.conf.&lt;br /&gt;
According to the [https://docs.yoctoproject.org/dev/dev-manual/layers.html Yocto documentation] it is recommended to start from an existing layer.conf file from a different meta-layer and change it according to the custom requirements.&lt;br /&gt;
&lt;br /&gt;
For instance, here is an example of how the directory structure should look after creating the layer.conf file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   └── layer.conf&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An example layer.conf file based on [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/conf/layer.conf NVIDIA OE4T tegra_demo_distro] is shown in the following code snipped.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
BBPATH =. &amp;quot;${LAYERDIR}:&amp;quot;&lt;br /&gt;
BBFILES += &amp;quot;${LAYERDIR}/recipes-*/*/*.bb ${LAYERDIR}/recipes-*/*/*.bbappend&amp;quot;&lt;br /&gt;
BBFILES_DYNAMIC += &amp;quot;swupdate:${LAYERDIR}/dynamic-layers/meta-swupdate/recipes-*/*/*.bb \&lt;br /&gt;
                    swupdate:${LAYERDIR}/dynamic-layers/meta-swupdate/recipes-*/*/*.bbappend&amp;quot;&lt;br /&gt;
&lt;br /&gt;
BBFILE_COLLECTIONS += &amp;quot;proventusnova&amp;quot;&lt;br /&gt;
BBFILE_PATTERN_proventusnova = &amp;quot;^${LAYERDIR}/&amp;quot;&lt;br /&gt;
BBFILE_PRIORITY_proventusnova = &amp;quot;50&amp;quot;&lt;br /&gt;
&lt;br /&gt;
LAYERVERSION_proventusnova = &amp;quot;4&amp;quot;&lt;br /&gt;
LAYERSERIES_COMPAT_proventusnova = &amp;quot;scarthgap&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# This is used by the tegra-distro-sanity bbclass&lt;br /&gt;
# to identify the distro layer directory during&lt;br /&gt;
# bblayers checks.&lt;br /&gt;
TD_DISTRO_LAYERDIR = &amp;quot;${LAYERDIR}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 2. Add base distro config===&lt;br /&gt;
&lt;br /&gt;
In order to add the initial distro configuration, it is necessary to create distro configuration file inside the &#039;&#039;&#039;meta-layer/conf/distro&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
Here is an example of how the directory structure should look like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   ├── distro&lt;br /&gt;
│   │   └── proventusnova.conf&lt;br /&gt;
│   └── layer.conf&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The same as with the layer.conf, it is easier to start with an existing distro configuration file and modify it in order to fit the project requirements. For example, the following corresponds to a distro configuration file based on the [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/conf/distro/tegrademo.conf NVIDIA tegra_demo_distro]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
DISTRO = &amp;quot;proventusnova&amp;quot;&lt;br /&gt;
DISTRO_NAME = &amp;quot;ProventusNova Custom Distro&amp;quot;&lt;br /&gt;
DISTRO_VERSION_BASE = &amp;quot;1.0&amp;quot;&lt;br /&gt;
DISTRO_VERSION = &amp;quot;${DISTRO_VERSION_BASE}+snapshot-${METADATA_REVISION}&amp;quot;&lt;br /&gt;
DISTRO_CODENAME = &amp;quot;proventusnova&amp;quot;&lt;br /&gt;
SDK_VENDOR = &amp;quot;-proventusnova&amp;quot;&lt;br /&gt;
SDK_VERSION := &amp;quot;${@&#039;${DISTRO_VERSION}&#039;.replace(&#039;snapshot-${METADATA_REVISION}&#039;,&#039;snapshot&#039;)}&amp;quot;&lt;br /&gt;
SDK_VERSION[vardepvalue] = &amp;quot;${SDK_VERSION}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
MAINTAINER = &amp;quot;ProventusNova team &amp;lt;support@proventusnova.com&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
TARGET_VENDOR = &amp;quot;-proventusnova&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# New ${DISTRO}-&amp;lt;version&amp;gt; setting for sanity checks.&lt;br /&gt;
# Increment version number (and the corresponding&lt;br /&gt;
# setting int the template bblayers.conf.sample file)&lt;br /&gt;
# each time the layer settings are changed.&lt;br /&gt;
REQUIRED_PROVENTUSNOVA_BBLAYERS_CONF_VERSION = &amp;quot;${DISTRO}-1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
LOCALCONF_VERSION = &amp;quot;2&amp;quot;&lt;br /&gt;
&lt;br /&gt;
PROVENTUSNOVA_DEFAULT_DISTRO_FEATURES = &amp;quot;largefile opengl ptest multiarch wayland vulkan systemd pam virtualization usrmerge&amp;quot;&lt;br /&gt;
&lt;br /&gt;
DISTRO_FEATURES ?= &amp;quot;${DISTRO_FEATURES_DEFAULT} ${PROVENTUSNOVA_DEFAULT_DISTRO_FEATURES}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Jetson platforms do not use linux-yocto, but for QEMU testing&lt;br /&gt;
# align with the poky distro.&lt;br /&gt;
PREFERRED_VERSION_linux-yocto ?= &amp;quot;5.19%&amp;quot;&lt;br /&gt;
PREFERRED_VERSION_linux-yocto-rt ?= &amp;quot;5.19%&amp;quot;&lt;br /&gt;
&lt;br /&gt;
SDK_NAME = &amp;quot;${DISTRO}-${TCLIBC}-${SDKMACHINE}-${IMAGE_BASENAME}-${TUNE_PKGARCH}-${MACHINE}&amp;quot;&lt;br /&gt;
SDKPATHINSTALL = &amp;quot;/opt/${DISTRO}/${SDK_VERSION}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
TCLIBCAPPEND = &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
PACKAGE_CLASSES ?= &amp;quot;package_rpm&amp;quot;&lt;br /&gt;
&lt;br /&gt;
SANITY_TESTED_DISTROS ?= &amp;quot; \&lt;br /&gt;
            ubuntu-20.04 \n \&lt;br /&gt;
            ubuntu-22.04 \n \&lt;br /&gt;
            ubuntu-24.04 \n \&lt;br /&gt;
            &amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Most NVIDIA-supplied services expect systemd&lt;br /&gt;
INIT_MANAGER = &amp;quot;systemd&amp;quot;&lt;br /&gt;
&lt;br /&gt;
require conf/distro/include/no-static-libs.inc&lt;br /&gt;
require conf/distro/include/yocto-uninative.inc&lt;br /&gt;
require conf/distro/include/security_flags.inc&lt;br /&gt;
INHERIT += &amp;quot;uninative&amp;quot;&lt;br /&gt;
&lt;br /&gt;
LICENSE_FLAGS_ACCEPTED += &amp;quot;commercial_faad2 commercial_x264&amp;quot;&lt;br /&gt;
&lt;br /&gt;
USE_REDUNDANT_FLASH_LAYOUT_DEFAULT ?= &amp;quot;1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
INHERIT += &amp;quot;tegra-support-sanity&amp;quot;&lt;br /&gt;
ESDK_CLASS_INHERIT_DISABLE:append = &amp;quot; tegra-support-sanity&amp;quot;&lt;br /&gt;
&lt;br /&gt;
BB_SIGNATURE_HANDLER ?= &amp;quot;OEEquivHash&amp;quot;&lt;br /&gt;
BB_HASHSERVE ??= &amp;quot;auto&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 3. Add base machine===&lt;br /&gt;
&lt;br /&gt;
This step might not be required, if there is already a machine that can be used from a different meta-layer.&lt;br /&gt;
However, it is still recommended to create a custom machine configuration based on that machine in order to keep better order of the machine used in the custom Yocto build.&lt;br /&gt;
&lt;br /&gt;
To create a custom machine, it is necessary to add a machine.conf file in the &#039;&#039;&#039;meta-layer/conf/machine&#039;&#039;&#039; directory.&lt;br /&gt;
For example, this is how the directory structure should look when adding a new machine to the custom meta-layer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   ├── distro&lt;br /&gt;
│   │   └── proventusnova.conf&lt;br /&gt;
│   ├── layer.conf&lt;br /&gt;
│   └── machine&lt;br /&gt;
│       └── proventusnova-jetson-orin-nx-16-devkit.conf&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And, as a reference, here is a custom machine based on [https://github.com/OE4T/meta-tegra/blob/scarthgap/conf/machine/p3509-a02-p3767-0000.conf NVIDIA meta-tegra  p3509-a02-p3767-0000] machine.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#@TYPE: Machine&lt;br /&gt;
#@NAME: Nvidia Jetson Orin NX 16GB (P3767-0000)&lt;br /&gt;
#@DESCRIPTION: Nvidia Jetson Orin NX 16GB module in P3509 carrier&lt;br /&gt;
&lt;br /&gt;
TEGRA_FLASHVAR_PINMUX_CONFIG ?= &amp;quot;tegra234-mb1-bct-pinmux-p3767-hdmi-a03.dtsi&amp;quot;&lt;br /&gt;
TEGRA_FLASHVAR_PMC_CONFIG ?= &amp;quot;tegra234-mb1-bct-padvoltage-p3767-hdmi-a03.dtsi&amp;quot;&lt;br /&gt;
TEGRA_PLUGIN_MANAGER_OVERLAYS ?= &amp;quot;tegra234-carveouts.dtbo tegra-optee.dtbo tegra234-p3768-0000+p3767-0000-dynamic.dtbo tegra234-dcb-p3767-0000-hdmi.dtbo&amp;quot;&lt;br /&gt;
TEGRA_DCE_OVERLAY ?= &amp;quot;tegra234-dcb-p3767-0000-hdmi.dtbo&amp;quot;&lt;br /&gt;
&lt;br /&gt;
require conf/machine/include/orin-nx.inc&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 4. Add initial config template files===&lt;br /&gt;
&lt;br /&gt;
===Step 5. Add base image recipe===&lt;/div&gt;</summary>
		<author><name>Andres</name></author>
	</entry>
	<entry>
		<id>https://developerwiki.proventusnova.com/index.php?title=How_to_create_a_custom_yocto_meta_layer&amp;diff=75</id>
		<title>How to create a custom yocto meta layer</title>
		<link rel="alternate" type="text/html" href="https://developerwiki.proventusnova.com/index.php?title=How_to_create_a_custom_yocto_meta_layer&amp;diff=75"/>
		<updated>2025-03-11T18:04:25Z</updated>

		<summary type="html">&lt;p&gt;Andres: /* Step 2. Add base distro config */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This wiki will provide a detailed guide on how to create a custom Yocto meta-layer.&lt;br /&gt;
&lt;br /&gt;
==Create Base Meta-Layer==&lt;br /&gt;
&lt;br /&gt;
This section contains steps to create the base custom meta-layer.&lt;br /&gt;
After completion, the custom base meta-layer will contain the following parts:&lt;br /&gt;
&lt;br /&gt;
* Custom layer configuration&lt;br /&gt;
* Custom distro configuration&lt;br /&gt;
* Custom machine&lt;br /&gt;
* Custom config template files&lt;br /&gt;
* Custom image recipe&lt;br /&gt;
&lt;br /&gt;
===Step 1. Add base layer.conf file===&lt;br /&gt;
&lt;br /&gt;
The layer configuration file provides Yocto with the configuration for the custom meta-layer.&lt;br /&gt;
It shall be stored in a directory called &#039;&#039;&#039;conf&#039;&#039;&#039; inside the base meta-layer directory, and it shall be named layer.conf.&lt;br /&gt;
According to the [https://docs.yoctoproject.org/dev/dev-manual/layers.html Yocto documentation] it is recommended to start from an existing layer.conf file from a different meta-layer and change it according to the custom requirements.&lt;br /&gt;
&lt;br /&gt;
For instance, here is an example of how the directory structure should look after creating the layer.conf file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   └── layer.conf&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An example layer.conf file based on [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/conf/layer.conf NVIDIA OE4T tegra_demo_distro] is shown in the following code snipped.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
BBPATH =. &amp;quot;${LAYERDIR}:&amp;quot;&lt;br /&gt;
BBFILES += &amp;quot;${LAYERDIR}/recipes-*/*/*.bb ${LAYERDIR}/recipes-*/*/*.bbappend&amp;quot;&lt;br /&gt;
BBFILES_DYNAMIC += &amp;quot;swupdate:${LAYERDIR}/dynamic-layers/meta-swupdate/recipes-*/*/*.bb \&lt;br /&gt;
                    swupdate:${LAYERDIR}/dynamic-layers/meta-swupdate/recipes-*/*/*.bbappend&amp;quot;&lt;br /&gt;
&lt;br /&gt;
BBFILE_COLLECTIONS += &amp;quot;proventusnova&amp;quot;&lt;br /&gt;
BBFILE_PATTERN_proventusnova = &amp;quot;^${LAYERDIR}/&amp;quot;&lt;br /&gt;
BBFILE_PRIORITY_proventusnova = &amp;quot;50&amp;quot;&lt;br /&gt;
&lt;br /&gt;
LAYERVERSION_proventusnova = &amp;quot;4&amp;quot;&lt;br /&gt;
LAYERSERIES_COMPAT_proventusnova = &amp;quot;scarthgap&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# This is used by the tegra-distro-sanity bbclass&lt;br /&gt;
# to identify the distro layer directory during&lt;br /&gt;
# bblayers checks.&lt;br /&gt;
TD_DISTRO_LAYERDIR = &amp;quot;${LAYERDIR}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 2. Add base distro config===&lt;br /&gt;
&lt;br /&gt;
In order to add the initial distro configuration, it is necessary to create distro configuration file inside the &#039;&#039;&#039;meta-layer/conf/distro&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
Here is an example of how the directory structure should look like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   ├── distro&lt;br /&gt;
│   │   └── proventusnova.conf&lt;br /&gt;
│   └── layer.conf&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The same as with the layer.conf, it is easier to start with an existing distro configuration file and modify it in order to fit the project requirements. For example, the following corresponds to a distro configuration file based on the [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/conf/distro/tegrademo.conf NVIDIA tegra_demo_distro]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
DISTRO = &amp;quot;proventusnova&amp;quot;&lt;br /&gt;
DISTRO_NAME = &amp;quot;ProventusNova Custom Distro&amp;quot;&lt;br /&gt;
DISTRO_VERSION_BASE = &amp;quot;1.0&amp;quot;&lt;br /&gt;
DISTRO_VERSION = &amp;quot;${DISTRO_VERSION_BASE}+snapshot-${METADATA_REVISION}&amp;quot;&lt;br /&gt;
DISTRO_CODENAME = &amp;quot;proventusnova&amp;quot;&lt;br /&gt;
SDK_VENDOR = &amp;quot;-proventusnova&amp;quot;&lt;br /&gt;
SDK_VERSION := &amp;quot;${@&#039;${DISTRO_VERSION}&#039;.replace(&#039;snapshot-${METADATA_REVISION}&#039;,&#039;snapshot&#039;)}&amp;quot;&lt;br /&gt;
SDK_VERSION[vardepvalue] = &amp;quot;${SDK_VERSION}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
MAINTAINER = &amp;quot;ProventusNova team &amp;lt;support@proventusnova.com&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
TARGET_VENDOR = &amp;quot;-proventusnova&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# New ${DISTRO}-&amp;lt;version&amp;gt; setting for sanity checks.&lt;br /&gt;
# Increment version number (and the corresponding&lt;br /&gt;
# setting int the template bblayers.conf.sample file)&lt;br /&gt;
# each time the layer settings are changed.&lt;br /&gt;
REQUIRED_PROVENTUSNOVA_BBLAYERS_CONF_VERSION = &amp;quot;${DISTRO}-1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
LOCALCONF_VERSION = &amp;quot;2&amp;quot;&lt;br /&gt;
&lt;br /&gt;
PROVENTUSNOVA_DEFAULT_DISTRO_FEATURES = &amp;quot;largefile opengl ptest multiarch wayland vulkan systemd pam virtualization usrmerge&amp;quot;&lt;br /&gt;
&lt;br /&gt;
DISTRO_FEATURES ?= &amp;quot;${DISTRO_FEATURES_DEFAULT} ${PROVENTUSNOVA_DEFAULT_DISTRO_FEATURES}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Jetson platforms do not use linux-yocto, but for QEMU testing&lt;br /&gt;
# align with the poky distro.&lt;br /&gt;
PREFERRED_VERSION_linux-yocto ?= &amp;quot;5.19%&amp;quot;&lt;br /&gt;
PREFERRED_VERSION_linux-yocto-rt ?= &amp;quot;5.19%&amp;quot;&lt;br /&gt;
&lt;br /&gt;
SDK_NAME = &amp;quot;${DISTRO}-${TCLIBC}-${SDKMACHINE}-${IMAGE_BASENAME}-${TUNE_PKGARCH}-${MACHINE}&amp;quot;&lt;br /&gt;
SDKPATHINSTALL = &amp;quot;/opt/${DISTRO}/${SDK_VERSION}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
TCLIBCAPPEND = &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
PACKAGE_CLASSES ?= &amp;quot;package_rpm&amp;quot;&lt;br /&gt;
&lt;br /&gt;
SANITY_TESTED_DISTROS ?= &amp;quot; \&lt;br /&gt;
            ubuntu-20.04 \n \&lt;br /&gt;
            ubuntu-22.04 \n \&lt;br /&gt;
            ubuntu-24.04 \n \&lt;br /&gt;
            &amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Most NVIDIA-supplied services expect systemd&lt;br /&gt;
INIT_MANAGER = &amp;quot;systemd&amp;quot;&lt;br /&gt;
&lt;br /&gt;
require conf/distro/include/no-static-libs.inc&lt;br /&gt;
require conf/distro/include/yocto-uninative.inc&lt;br /&gt;
require conf/distro/include/security_flags.inc&lt;br /&gt;
INHERIT += &amp;quot;uninative&amp;quot;&lt;br /&gt;
&lt;br /&gt;
LICENSE_FLAGS_ACCEPTED += &amp;quot;commercial_faad2 commercial_x264&amp;quot;&lt;br /&gt;
&lt;br /&gt;
USE_REDUNDANT_FLASH_LAYOUT_DEFAULT ?= &amp;quot;1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
INHERIT += &amp;quot;tegra-support-sanity&amp;quot;&lt;br /&gt;
ESDK_CLASS_INHERIT_DISABLE:append = &amp;quot; tegra-support-sanity&amp;quot;&lt;br /&gt;
&lt;br /&gt;
BB_SIGNATURE_HANDLER ?= &amp;quot;OEEquivHash&amp;quot;&lt;br /&gt;
BB_HASHSERVE ??= &amp;quot;auto&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 3. Add base machine===&lt;br /&gt;
&lt;br /&gt;
===Step 4. Add initial config template files===&lt;br /&gt;
&lt;br /&gt;
===Step 5. Add base image recipe===&lt;/div&gt;</summary>
		<author><name>Andres</name></author>
	</entry>
	<entry>
		<id>https://developerwiki.proventusnova.com/index.php?title=How_to_create_a_custom_yocto_meta_layer&amp;diff=74</id>
		<title>How to create a custom yocto meta layer</title>
		<link rel="alternate" type="text/html" href="https://developerwiki.proventusnova.com/index.php?title=How_to_create_a_custom_yocto_meta_layer&amp;diff=74"/>
		<updated>2025-03-11T18:00:20Z</updated>

		<summary type="html">&lt;p&gt;Andres: /* Step 2. Add base distro config */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This wiki will provide a detailed guide on how to create a custom Yocto meta-layer.&lt;br /&gt;
&lt;br /&gt;
==Create Base Meta-Layer==&lt;br /&gt;
&lt;br /&gt;
This section contains steps to create the base custom meta-layer.&lt;br /&gt;
After completion, the custom base meta-layer will contain the following parts:&lt;br /&gt;
&lt;br /&gt;
* Custom layer configuration&lt;br /&gt;
* Custom distro configuration&lt;br /&gt;
* Custom machine&lt;br /&gt;
* Custom config template files&lt;br /&gt;
* Custom image recipe&lt;br /&gt;
&lt;br /&gt;
===Step 1. Add base layer.conf file===&lt;br /&gt;
&lt;br /&gt;
The layer configuration file provides Yocto with the configuration for the custom meta-layer.&lt;br /&gt;
It shall be stored in a directory called &#039;&#039;&#039;conf&#039;&#039;&#039; inside the base meta-layer directory, and it shall be named layer.conf.&lt;br /&gt;
According to the [https://docs.yoctoproject.org/dev/dev-manual/layers.html Yocto documentation] it is recommended to start from an existing layer.conf file from a different meta-layer and change it according to the custom requirements.&lt;br /&gt;
&lt;br /&gt;
For instance, here is an example of how the directory structure should look after creating the layer.conf file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   └── layer.conf&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An example layer.conf file based on [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/conf/layer.conf NVIDIA OE4T tegra_demo_distro] is shown in the following code snipped.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
BBPATH =. &amp;quot;${LAYERDIR}:&amp;quot;&lt;br /&gt;
BBFILES += &amp;quot;${LAYERDIR}/recipes-*/*/*.bb ${LAYERDIR}/recipes-*/*/*.bbappend&amp;quot;&lt;br /&gt;
BBFILES_DYNAMIC += &amp;quot;swupdate:${LAYERDIR}/dynamic-layers/meta-swupdate/recipes-*/*/*.bb \&lt;br /&gt;
                    swupdate:${LAYERDIR}/dynamic-layers/meta-swupdate/recipes-*/*/*.bbappend&amp;quot;&lt;br /&gt;
&lt;br /&gt;
BBFILE_COLLECTIONS += &amp;quot;proventusnova&amp;quot;&lt;br /&gt;
BBFILE_PATTERN_proventusnova = &amp;quot;^${LAYERDIR}/&amp;quot;&lt;br /&gt;
BBFILE_PRIORITY_proventusnova = &amp;quot;50&amp;quot;&lt;br /&gt;
&lt;br /&gt;
LAYERVERSION_proventusnova = &amp;quot;4&amp;quot;&lt;br /&gt;
LAYERSERIES_COMPAT_proventusnova = &amp;quot;scarthgap&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# This is used by the tegra-distro-sanity bbclass&lt;br /&gt;
# to identify the distro layer directory during&lt;br /&gt;
# bblayers checks.&lt;br /&gt;
TD_DISTRO_LAYERDIR = &amp;quot;${LAYERDIR}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 2. Add base distro config===&lt;br /&gt;
&lt;br /&gt;
In order to add the initial distro configuration, it is necessary to create distro configuration file inside the &#039;&#039;&#039;meta-layer/conf/distro&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
Here is an example of how the directory structure should look like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   ├── distro&lt;br /&gt;
│   │   └── proventusnova.conf&lt;br /&gt;
│   └── layer.conf&lt;br /&gt;
└── README.md&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 3. Add base machine===&lt;br /&gt;
&lt;br /&gt;
===Step 4. Add initial config template files===&lt;br /&gt;
&lt;br /&gt;
===Step 5. Add base image recipe===&lt;/div&gt;</summary>
		<author><name>Andres</name></author>
	</entry>
	<entry>
		<id>https://developerwiki.proventusnova.com/index.php?title=How_to_create_a_custom_yocto_meta_layer&amp;diff=73</id>
		<title>How to create a custom yocto meta layer</title>
		<link rel="alternate" type="text/html" href="https://developerwiki.proventusnova.com/index.php?title=How_to_create_a_custom_yocto_meta_layer&amp;diff=73"/>
		<updated>2025-03-11T17:35:18Z</updated>

		<summary type="html">&lt;p&gt;Andres: /* Step 1. Add base layer.conf file */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This wiki will provide a detailed guide on how to create a custom Yocto meta-layer.&lt;br /&gt;
&lt;br /&gt;
==Create Base Meta-Layer==&lt;br /&gt;
&lt;br /&gt;
This section contains steps to create the base custom meta-layer.&lt;br /&gt;
After completion, the custom base meta-layer will contain the following parts:&lt;br /&gt;
&lt;br /&gt;
* Custom layer configuration&lt;br /&gt;
* Custom distro configuration&lt;br /&gt;
* Custom machine&lt;br /&gt;
* Custom config template files&lt;br /&gt;
* Custom image recipe&lt;br /&gt;
&lt;br /&gt;
===Step 1. Add base layer.conf file===&lt;br /&gt;
&lt;br /&gt;
The layer configuration file provides Yocto with the configuration for the custom meta-layer.&lt;br /&gt;
It shall be stored in a directory called &#039;&#039;&#039;conf&#039;&#039;&#039; inside the base meta-layer directory, and it shall be named layer.conf.&lt;br /&gt;
According to the [https://docs.yoctoproject.org/dev/dev-manual/layers.html Yocto documentation] it is recommended to start from an existing layer.conf file from a different meta-layer and change it according to the custom requirements.&lt;br /&gt;
&lt;br /&gt;
For instance, here is an example of how the directory structure should look after creating the layer.conf file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-proventusnova/&lt;br /&gt;
├── conf&lt;br /&gt;
│   └── layer.conf&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An example layer.conf file based on [https://github.com/OE4T/tegra-demo-distro/blob/scarthgap-l4t-r35.x/layers/meta-tegrademo/conf/layer.conf NVIDIA OE4T tegra_demo_distro] is shown in the following code snipped.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
BBPATH =. &amp;quot;${LAYERDIR}:&amp;quot;&lt;br /&gt;
BBFILES += &amp;quot;${LAYERDIR}/recipes-*/*/*.bb ${LAYERDIR}/recipes-*/*/*.bbappend&amp;quot;&lt;br /&gt;
BBFILES_DYNAMIC += &amp;quot;swupdate:${LAYERDIR}/dynamic-layers/meta-swupdate/recipes-*/*/*.bb \&lt;br /&gt;
                    swupdate:${LAYERDIR}/dynamic-layers/meta-swupdate/recipes-*/*/*.bbappend&amp;quot;&lt;br /&gt;
&lt;br /&gt;
BBFILE_COLLECTIONS += &amp;quot;proventusnova&amp;quot;&lt;br /&gt;
BBFILE_PATTERN_proventusnova = &amp;quot;^${LAYERDIR}/&amp;quot;&lt;br /&gt;
BBFILE_PRIORITY_proventusnova = &amp;quot;50&amp;quot;&lt;br /&gt;
&lt;br /&gt;
LAYERVERSION_proventusnova = &amp;quot;4&amp;quot;&lt;br /&gt;
LAYERSERIES_COMPAT_proventusnova = &amp;quot;scarthgap&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# This is used by the tegra-distro-sanity bbclass&lt;br /&gt;
# to identify the distro layer directory during&lt;br /&gt;
# bblayers checks.&lt;br /&gt;
TD_DISTRO_LAYERDIR = &amp;quot;${LAYERDIR}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 2. Add base distro config===&lt;br /&gt;
&lt;br /&gt;
===Step 3. Add base machine===&lt;br /&gt;
&lt;br /&gt;
===Step 4. Add initial config template files===&lt;br /&gt;
&lt;br /&gt;
===Step 5. Add base image recipe===&lt;/div&gt;</summary>
		<author><name>Andres</name></author>
	</entry>
	<entry>
		<id>https://developerwiki.proventusnova.com/index.php?title=How_to_create_a_custom_yocto_meta_layer&amp;diff=72</id>
		<title>How to create a custom yocto meta layer</title>
		<link rel="alternate" type="text/html" href="https://developerwiki.proventusnova.com/index.php?title=How_to_create_a_custom_yocto_meta_layer&amp;diff=72"/>
		<updated>2025-03-11T17:30:21Z</updated>

		<summary type="html">&lt;p&gt;Andres: /* Step 1. Add base layer.conf file */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This wiki will provide a detailed guide on how to create a custom Yocto meta-layer.&lt;br /&gt;
&lt;br /&gt;
==Create Base Meta-Layer==&lt;br /&gt;
&lt;br /&gt;
This section contains steps to create the base custom meta-layer.&lt;br /&gt;
After completion, the custom base meta-layer will contain the following parts:&lt;br /&gt;
&lt;br /&gt;
* Custom layer configuration&lt;br /&gt;
* Custom distro configuration&lt;br /&gt;
* Custom machine&lt;br /&gt;
* Custom config template files&lt;br /&gt;
* Custom image recipe&lt;br /&gt;
&lt;br /&gt;
===Step 1. Add base layer.conf file===&lt;br /&gt;
&lt;br /&gt;
The layer configuration file provides Yocto with the configuration for the custom meta-layer.&lt;br /&gt;
It shall be stored in a directory called &#039;&#039;&#039;conf&#039;&#039;&#039; inside the base meta-layer directory, and it shall be named layer.conf.&lt;br /&gt;
According to the [https://docs.yoctoproject.org/dev/dev-manual/layers.html Yocto documentation] it is recommended to start from an existing layer.conf file from a different meta-layer and change it according to the custom requirements.&lt;br /&gt;
&lt;br /&gt;
For instance, here is an example of how the directory structure should look after creating the layer.conf file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta-layer/&lt;br /&gt;
├── conf&lt;br /&gt;
│   └── layer.conf&lt;br /&gt;
└── README.md&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 2. Add base distro config===&lt;br /&gt;
&lt;br /&gt;
===Step 3. Add base machine===&lt;br /&gt;
&lt;br /&gt;
===Step 4. Add initial config template files===&lt;br /&gt;
&lt;br /&gt;
===Step 5. Add base image recipe===&lt;/div&gt;</summary>
		<author><name>Andres</name></author>
	</entry>
	<entry>
		<id>https://developerwiki.proventusnova.com/index.php?title=How_to_create_a_custom_yocto_meta_layer&amp;diff=71</id>
		<title>How to create a custom yocto meta layer</title>
		<link rel="alternate" type="text/html" href="https://developerwiki.proventusnova.com/index.php?title=How_to_create_a_custom_yocto_meta_layer&amp;diff=71"/>
		<updated>2025-03-11T16:23:28Z</updated>

		<summary type="html">&lt;p&gt;Andres: /* Step 1. Add base layer.conf file */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This wiki will provide a detailed guide on how to create a custom Yocto meta-layer.&lt;br /&gt;
&lt;br /&gt;
==Create Base Meta-Layer==&lt;br /&gt;
&lt;br /&gt;
This section contains steps to create the base custom meta-layer.&lt;br /&gt;
After completion, the custom base meta-layer will contain the following parts:&lt;br /&gt;
&lt;br /&gt;
* Custom layer configuration&lt;br /&gt;
* Custom distro configuration&lt;br /&gt;
* Custom machine&lt;br /&gt;
* Custom config template files&lt;br /&gt;
* Custom image recipe&lt;br /&gt;
&lt;br /&gt;
===Step 1. Add base layer.conf file===&lt;br /&gt;
&lt;br /&gt;
The layer configuration file provides Yocto with the configuration for the custom meta-layer.&lt;br /&gt;
It shall be stored in a directory called &#039;&#039;&#039;conf&#039;&#039;&#039; inside the base meta-layer directory, and it shall be named layer.conf.&lt;br /&gt;
According to the [https://docs.yoctoproject.org/dev/dev-manual/layers.html Yocto documentation] it is recommended to start from an existing layer.conf file from a different meta-layer and change it according to the custom requirements.&lt;br /&gt;
&lt;br /&gt;
For instance, here is an example of how the directory structure should look after creating the layer.conf file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
echo &amp;quot;Hello, World!&amp;quot;&lt;br /&gt;
ls -l /home/user&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Step 2. Add base distro config===&lt;br /&gt;
&lt;br /&gt;
===Step 3. Add base machine===&lt;br /&gt;
&lt;br /&gt;
===Step 4. Add initial config template files===&lt;br /&gt;
&lt;br /&gt;
===Step 5. Add base image recipe===&lt;/div&gt;</summary>
		<author><name>Andres</name></author>
	</entry>
	<entry>
		<id>https://developerwiki.proventusnova.com/index.php?title=How_to_create_a_custom_yocto_meta_layer&amp;diff=70</id>
		<title>How to create a custom yocto meta layer</title>
		<link rel="alternate" type="text/html" href="https://developerwiki.proventusnova.com/index.php?title=How_to_create_a_custom_yocto_meta_layer&amp;diff=70"/>
		<updated>2025-03-11T15:53:57Z</updated>

		<summary type="html">&lt;p&gt;Andres: /* Create Base Meta-Layer */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This wiki will provide a detailed guide on how to create a custom Yocto meta-layer.&lt;br /&gt;
&lt;br /&gt;
==Create Base Meta-Layer==&lt;br /&gt;
&lt;br /&gt;
This section contains steps to create the base custom meta-layer.&lt;br /&gt;
After completion, the custom base meta-layer will contain the following parts:&lt;br /&gt;
&lt;br /&gt;
* Custom layer configuration&lt;br /&gt;
* Custom distro configuration&lt;br /&gt;
* Custom machine&lt;br /&gt;
* Custom config template files&lt;br /&gt;
* Custom image recipe&lt;br /&gt;
&lt;br /&gt;
===Step 1. Add base layer.conf file===&lt;br /&gt;
&lt;br /&gt;
===Step 2. Add base distro config===&lt;br /&gt;
&lt;br /&gt;
===Step 3. Add base machine===&lt;br /&gt;
&lt;br /&gt;
===Step 4. Add initial config template files===&lt;br /&gt;
&lt;br /&gt;
===Step 5. Add base image recipe===&lt;/div&gt;</summary>
		<author><name>Andres</name></author>
	</entry>
	<entry>
		<id>https://developerwiki.proventusnova.com/index.php?title=How_to_create_a_custom_yocto_meta_layer&amp;diff=69</id>
		<title>How to create a custom yocto meta layer</title>
		<link rel="alternate" type="text/html" href="https://developerwiki.proventusnova.com/index.php?title=How_to_create_a_custom_yocto_meta_layer&amp;diff=69"/>
		<updated>2025-03-11T15:51:46Z</updated>

		<summary type="html">&lt;p&gt;Andres: Created page with &amp;quot;=Introduction=  This wiki will provide a detailed guide on how to create a custom Yocto meta-layer.  ==Create Base Meta-Layer==  This section contains steps to create the base custom meta-layer. After completion, the custom base meta-layer will contain the following parts:  * Custom layer configuration * Custom distro configuration * Custom machine * Custom config template files * Custom image recipe  &amp;#039;&amp;#039;&amp;#039;Step 1. Add base layer.conf file&amp;#039;&amp;#039;&amp;#039;  &amp;#039;&amp;#039;&amp;#039;Step 2. Add base distro con...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This wiki will provide a detailed guide on how to create a custom Yocto meta-layer.&lt;br /&gt;
&lt;br /&gt;
==Create Base Meta-Layer==&lt;br /&gt;
&lt;br /&gt;
This section contains steps to create the base custom meta-layer.&lt;br /&gt;
After completion, the custom base meta-layer will contain the following parts:&lt;br /&gt;
&lt;br /&gt;
* Custom layer configuration&lt;br /&gt;
* Custom distro configuration&lt;br /&gt;
* Custom machine&lt;br /&gt;
* Custom config template files&lt;br /&gt;
* Custom image recipe&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Step 1. Add base layer.conf file&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Step 2. Add base distro config&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Step 3. Add base machine&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Step 4. Add initial config template files&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Step 5. Add base image recipe&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Andres</name></author>
	</entry>
	<entry>
		<id>https://developerwiki.proventusnova.com/index.php?title=Main_Page&amp;diff=2</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://developerwiki.proventusnova.com/index.php?title=Main_Page&amp;diff=2"/>
		<updated>2025-02-15T19:06:48Z</updated>

		<summary type="html">&lt;p&gt;Andres: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Welcome to the ProventusNova Developer Wiki =&lt;br /&gt;
&#039;&#039;&#039;Expert knowledge for Embedded Systems, AI, and Software Development.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Looking to build high-performance embedded systems, optimize AI models, or streamline multimedia processing? This wiki is a &#039;&#039;&#039;public knowledge hub&#039;&#039;&#039; designed to help engineers, developers, and businesses solve real-world technical challenges.  &lt;br /&gt;
&lt;br /&gt;
Here, you’ll find &#039;&#039;&#039;step-by-step tutorials, best practices, and deep technical insights&#039;&#039;&#039; to help you bring your projects to life.  &lt;br /&gt;
&lt;br /&gt;
== 🚀 What You’ll Find Here ==&lt;br /&gt;
* &#039;&#039;&#039;Hands-on Tutorials&#039;&#039;&#039; – Practical guides to get you started quickly.  &lt;br /&gt;
* &#039;&#039;&#039;Industry Best Practices&#039;&#039;&#039; – Proven workflows and methodologies.  &lt;br /&gt;
* &#039;&#039;&#039;Optimized Solutions&#039;&#039;&#039; – Performance tuning for embedded, AI, and multimedia applications.  &lt;br /&gt;
* &#039;&#039;&#039;Open-Source Resources&#039;&#039;&#039; – Code samples, frameworks, and tools to accelerate development.  &lt;br /&gt;
&lt;br /&gt;
Whether you&#039;re an individual developer, a startup, or an enterprise, you’ll find resources here to &#039;&#039;&#039;enhance your expertise and improve your products&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
== 💡 Featured Tutorials ==&lt;br /&gt;
🔧 **[Building a Custom Linux OS with Yocto](Yocto-Project-Tutorial)** – Tailor an operating system for your hardware.  &lt;br /&gt;
🤖 **[Deploying AI for Real-Time Video Analytics](AI-Video-Analytics)** – Use machine learning for intelligent decision-making.  &lt;br /&gt;
🎥 **[Optimizing GStreamer Pipelines](GStreamer-Optimization)** – Improve multimedia processing efficiency.  &lt;br /&gt;
🌐 **[Scaling Web Applications](Django-Web-Development)** – Design backends for performance and reliability.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- For more topics, explore the **[[Tutorials Index]]**. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ⚙️ Technical Resources ==&lt;br /&gt;
* [[Embedded Systems Development]] – BSPs, firmware, and real-time processing.  &lt;br /&gt;
* [[AI &amp;amp; Computer Vision]] – Edge AI, model training, and deployment.  &lt;br /&gt;
* [[GStreamer Development]] – High-performance video and audio streaming.  &lt;br /&gt;
* [[Web &amp;amp; Cloud Solutions]] – Scalable, production-ready applications.  &lt;br /&gt;
&lt;br /&gt;
== 🏗 Need a Solution for Your Project? ==&lt;br /&gt;
Are you looking for ways to:  &lt;br /&gt;
✅ Optimize your &#039;&#039;&#039;embedded system&#039;&#039;&#039; for better performance?  &lt;br /&gt;
✅ Integrate &#039;&#039;&#039;AI and computer vision&#039;&#039;&#039; into your products?  &lt;br /&gt;
✅ Improve &#039;&#039;&#039;multimedia processing&#039;&#039;&#039; for real-time applications?  &lt;br /&gt;
✅ Develop a &#039;&#039;&#039;robust and scalable&#039;&#039;&#039; web platform?  &lt;br /&gt;
&lt;br /&gt;
Our team has helped businesses across multiple industries solve these challenges.  &lt;br /&gt;
&lt;br /&gt;
📩 &#039;&#039;&#039;Let’s collaborate!&#039;&#039;&#039; Contact us at &#039;&#039;&#039;[support@proventusnova.com](mailto:support@proventusnova.com)&#039;&#039;&#039; or visit &#039;&#039;&#039;[ProventusNova.com](https://proventusnova.com)&#039;&#039;&#039; to discuss your project.&lt;/div&gt;</summary>
		<author><name>Andres</name></author>
	</entry>
</feed>