Kernel issue and make fail

Hello NV Team,

I currently use JP6.2 L4T:36.4.3
And refer to the kernel customization steps in detail to simplify the process into a script

There were no errors in the build and flash steps.

But when I was on AGX and wanted to do other projects, an error occurred when executing make:

nvidia@tegra-ubuntu:~/F75111/driver$ make
dtc -@ -I dts -O dtb -o f75111.dtbo f75111.dts
make -C /lib/modules/5.15.148-tegra/build M="/home/nvidia/F75111/driver" modules
make[1]: *** /lib/modules/5.15.148-tegra/build: No such file or directory.  Stop.
make: *** [Makefile:26: default] Error 2

I checked /lib/modules/5.15.148-tegra/build, but it points to my host side, is this correct?

nvidia@tegra-ubuntu:~/F75111/driver$ ls -al /lib/modules/5.15.148-tegra/build
lrwxrwxrwx 1 root root 77 Apr 15 15:43 /lib/modules/5.15.148-tegra/build -> /home/gbt/project/nvidia/JP6.2/Linux_for_Tegra/source/kernel/kernel-jammy-src

Or am I missing a step or setting when building the kernel? This causes /lib/modules/5.15.148-tegra/build to point to an error.

Here is my current script for running a custom kernel:

#!/bin/bash

echo "Building the Jetson Linux Kernel"
CURRENT_DIR=$PWD
cp defconfig JP6.2/Linux_for_Tegra/source/kernel/kernel-jammy-src/arch/arm64/configs/defconfig
cd JP6.2/Linux_for_Tegra/source
./generic_rt_build.sh "disable"
export CROSS_COMPILE=$HOME/l4t-gcc/aarch64--glibc--stable-2022.08-1/bin/aarch64-buildroot-linux-gnu-
make -C kernel
export INSTALL_MOD_PATH=$CURRENT_DIR/JP6.2/Linux_for_Tegra/rootfs/
sudo -E make install -C kernel
cp kernel/kernel-jammy-src/arch/arm64/boot/Image $CURRENT_DIR/JP6.2/Linux_for_Tegra/kernel/Image
cd -

echo "Building the DTBs"
cd JP6.2/Linux_for_Tegra/source
export CROSS_COMPILE=$HOME/l4t-gcc/aarch64--glibc--stable-2022.08-1/bin/aarch64-buildroot-linux-gnu-
export KERNEL_HEADERS=$PWD/kernel/kernel-jammy-src
make dtbs
cp kernel-devicetree/generic-dts/dtbs/* $CURRENT_DIR/JP6.2/Linux_for_Tegra/kernel/dtb/

You can build the kernel and apply it well. Then what’s your problem? Please make it clear.

Thanks

Why does this error occur when executing make?

make[1]: *** /lib/modules/5.15.148-tegra/build: No such file or directory.  Stop.
make: *** [Makefile:26: default] Error 2

What is the solution?

This is incorrect:

The above is also why you see:

FYI, unlike many software projects, you should not just use “make” without arguments in a kernel compile. The error is an attempt to deal with a lack of configuration. Normally the build file in question is a symbolic link to a location which has configuration, but it doesn’t quite work this way with Jetsons.

To start with you want pristine kernel source. If the kernel source itself has been configured (hopefully it is not), then you can revert to pristine with:
make mrproper

Regarding this last point, you will find many instructions with a kernel build having the “O=/some/where” option in the command line. This is for create a separate location for any configuration or editing such that the original source is left pristine. This is a very good idea to use.

As an example, if you go to where the source code itself is, you can do this:
export TOP=$pwd

If you happen to have this at “~/some/source”, then “echo $TOP” would reply with that path.

If you then create an empty directory, e.g. “~/kernel”, the following would make sure both the source and that location are pristine:

cd $TOP
make mrproper
make O=~/kernel mrproper

It might be easier to export that output location via an environment variable. An optional name to use (and is in documentation) is TEGRA_KERNEL_OUT. Then you could do this:

cd ~/kernel
export TEGRA_KERNEL_OUT=$pwd
echo $TEGRA_KERNEL_OUT
cd $TOP
make O=$TEGRA_KERNEL_OUT mrproper

Once you have pristine source code you should never actually make changes there. The default configuration to start with in JetPack 5.x/L4T R35.x is “tegra_defconfig”. I will assume you have set up “TOP” and “TEGRA_KERNEL_OUT”:

cd $TOP
make O=$TEGRA_KERNEL_OUT tegra_defconfig

If you are only building modules and intend to keep the original kernel Image, then you would also need to keep the CONFIG_LOCALVERSION as “-tegra”. An example for editing the existing tegra_defconfig to set up CONFIG_LOCALVERSION would be via either the menuconfig target or the nconfig target (I prefer nconfig because it has symbol search; otherwise it is exactly the same thing as menuconfig; CONFIG_LOCALVERSION is one symbol):

cd $TOP
make O=$TEGRA_DEFCONFIG nconfig

If you are changing a non-module feature, then you probably need a new CONFIG_LOCALVERSION and complete install of modules, kernel Image, and any initrd.

Once you have the base configuration it must be propagated. One such method:

cd $TOP
# ...do config stuff...
make O=$TEGRA_KERNEL_OUT modules_prepare

In the case of the base kernel build this is done for you:

cd $TOP
# ...do config stuff....
make O=$TEGRA_KERNEL_OUT Image

In the case of building modules without building Image:

cd $TOP
# ...do config stuff....
make O=$TEGRA_KERNEL_OUT modules_prepare
make O=$TEGRA_KERNEL_OUT modules

In the case of building both Image and modules:

cd $TOP
# ...do config stuff....
make O=$TEGRA_KERNEL_OUT Image
# Note that the Image target would have done the equivalent of modules_prepare.
make O=$TEGRA_KERNEL_OUT modules

It is quite unlikely you need to build the device tree (dtbs target).

It is a really good idea to not overwrite your existing modules or kernel Image. It is usually a "bad idea"™ to just install the Image and modules while overwriting the originals and not saving them. For modules you can install them to an empty location and then later copy them over:

# Assuming you've already built modules.
mkdir ~/modules_out
cd ~/modules_out
export TEGRA_MODULES_OUT=$pwd
cd $TOP
make O=$TEGRA_KERNEL_OUT INSTALL_MOD_PATH=$TEGRA_MODULES_OUT modules_install

After that you would find a lot of content in “$TEGRA_MODULES_OUT” mirroring where the files would go if you were to manually copy them. I will emphasize that you would only be copying new or changed modules and not everything.

When you just run “make” you are building everything. When you don’t configure first, then you have a lot of configuration which is just plain wrong or conflicting. For example, you’re probably building for an old IBM mainframe, specialized hardware only found in an Internet backbone router, old style sound cards…everything. And hardly any of it would be relevant or correct for the Jetson.

The official docs are for cross compile, and much of this is the same on native compile. Find your L4T release via “head -n 1 /etc/nv_tegra_release”, and then go to the proper docs and source here:
https://developer.nvidia.com/linux-tegra

Just beware that the installation steps in the docs are about installing the content for flash and not for use with an existing installation. You can always ask more questions.

1 Like

But if I execute the following two instructions, I can execute make on the AGX device.

sudo rm /lib/modules/5.15.148-tegra/build
sudo ln -s /usr/src/linux-headers-5.15.148-tegra-ubuntu22.04_aarch64/3rdparty/canonical/linux-jammy/kernel-source/ /lib/modules/5.15.148-tegra/build

That’s true, but it is only useful if the software being linked has a starting config which matches the running system (which in turn began with make target tegra_defconfig for L4T R35.x and earlier, or defconfig for L4T R36.x; the latter change is when Jetsons go to mainline kernel).

This also is still wrong because you want to build only subsets. You shouldn’t be building everything in most cases. The firmware for example depends mostly on the carrier board and not the kernel config. There is the case that firmware more or less presents an argument to drivers as they load, and so new drivers means the possibility of new firmware…but that is exceedingly rare unless you develop your own carrier board and have a new component or layout of the carrier board which that driver applies to.

Just start with pristine source, configure it (including CONFIG_LOCALVERSION, which depends on what changes you might be making), and then use make on one target at a time for the targets you want.

You don’t need to build Image if you are only adding new modules, but you would then need the make target modules_prepare. I usually recommend that you build Image first even if you don’t need it as a kind of “acid test”; this does the modules_prepare for you as well.

And of course if you do use the build symbolic link, then it only applies when building natively on the Jetson itself. I still recommend against using that. There is a file which is something of a better choice which you can copy somewhere and save and preserve:
/proc/config.gz

That isn’t a real file, it lives in RAM and is the kernel telling you what its current configuration is. One part which is not saved in that is the CONFIG_LOCALVERSION, so you still need to save the output of “uname -r” to see the suffix to set CONFIG_LOCALVERSION to if you plan to reuse the current Image file.

Once you either build Image or modules_prepare, then build the modules target. Don’t build dtbs or other content unless you actually need it, and if you think you need it, then ask yourself why you need it because often this is going to cause problems rather than solve problems. The existing device tree is already correct for your module+carrier board combination. Yes, it is possible you might have added a new driver, but the new driver won’t care unless the component is some non-plug-n-play part of the carrier board which did not previously exist.