Search code examples
gitcmakeyoctobitbake

What is the "S" variable in a Yocto Bitbake recipe, and when do I need to set it?


I just added a new Bitbake recipe to wrap my CMake git repo, that's also in development. But I get an error saying that it can't find the CMakeLists.txt file. I can confirm that the latest git repo/branch is getting cloned, and it has the CMakeLists.txt file there, so I'm at a loss on what to do. I'm using Dunfell Yocto.

I looked at some other CMake example recipes. One suggested adding this S line to the recipe:

SRC_URI = "git://github.com/zafrullahsyed/cameracapture.git;protocol=https;tag=v0.1"

S = "${WORKDIR}/git"

inherit pkgconfig cmake

What does this Svariable do? And when do you generally need to set it?


Solution

  • S is used to point to source files that are unpacked with do_unpack into the recipe's WORKDIR. Check this for source fetching and unpacking process details.

    The default value of S is ${WORKDIR}/${BPN}-${PV}:

    Example: example_0.1.bb , S would be: example-0.1 folder inside WORKDIR.

    Now, what you MUST keep in mind that sources are not usually unpacked in S by default, unless you are unpacking a compressed file that has the same name value as S, example:

    SRC_URI = "https://somewebsite/example-0.1.zip"
    

    Default unpacking destination differs with each source type (SRC_URI input type):

    • git://repo will be unpacked under ${WORKDIR}/git
    • file://somefile will be unpacked directly under ${WORKDIR}

    These are the default values of course, Yocto provides parameters to control the unpacking process. Parameters are set in SRC_URI as follows:

    SRC_URI = "scheme://URL;param1=val1;param2=val2;..."
    

    For example if you want to change that you can use:

    • subdir: to specify another folder to unpack the sources in
    • destsuffix: for git this is the path to use for git checkout, default is git/ as I mentioned above.

    In your case you don't need to set these parameters.

    Now, the other important part that you need to understand is:

    • Every bitbake task works in some one or more directories and it is specified with the dirs flag.

    So, in your case, do_configure that is inherited from cmake.bbclass needs to find CMakeLists.txt from S.

    Here is a snipped of cmake.bbclass:do_configure:

    # Path to the CMake file to process.
    OECMAKE_SOURCEPATH ??= "${S}"
    ...
    
    cmake_do_configure() {
          ...
          cmake \
              ${OECMAKE_GENERATOR_ARGS} \
              $oecmake_sitefile \
              ${OECMAKE_SOURCEPATH} \   <======== AS YOU CAN SEE HERE
              ...
    

    As you can notice, OECMAKE_SOURCEPATH points to where CMakeLists.txt is. Bitbake assumes that it is under S. So if you have your CMakeLists.txt under subdirectory in your project (example: yourproject/sources/CMakeLists.txt) then imagine that yourproject's content will be unpacked under S which is ${WORKDIR}/git so you can change OECMAKE_SOURCEPATH as follows:

    inherit cmake
    OECMAKE_SOURCEPATH = "${S}/sources"
    

    That was just an example to understand more cmake.bbclass

    So, your git project will be unpacked under ${WORKDIR}/git, that's why you need to change the default value of S to that new location where your CMakeLists.txt is located.

    Another side point here to mention is that, there is another value called ${B} that points to the build directory that will hold the build output, because some projects support generating the output in different directory like cmake and some advanced Makefile projects like the Linux kernel.

    By default: S = "${B}", so the build will happen in the same directory. That's why in the base.bbclass which is the class that is inherited automatically for all recipes to provide all recipe's tasks from do_fetch to do_deploy sets the directory for main tasks as B:

    do_configure[dirs] = "${B}"
    do_compile[dirs] = "${B}"
    do_install[dirs] = "${B}"
    

    In your case, cmake.bbclass changes B to: ${WORKDIR}/build as follows:

    B = "${WORKDIR}/build"
    

    So, now let's print the big picture:

    • You inherit cmake: this will override the orignal base.bbclass:do_configure, do_compile and do_install with the new ones to support cmake project
    • do_configure by default work in B
    • cmake class changes B to ${WORKDIR}/build to separate the output
    • cmake's do_configure runs cmake command on OECMAKE_SOURCEPATH which points to S
    • Since do_configure works in B, then it will find CMakeLists.txt in S and uses it to generate output in B
    • do_compile works as well in B so it will continue with the compilation process
    • and so on ...

    To understand more with a practical example, check my workshop on that here:

    Side note: my TLS certificate expired so https will warn you :))