Search code examples
c++opencvheaderyocto

Yocto recipe for an application that uses opencv and cpp


I created a recipe for a cpp application using opencv to stream an image. But The build fails with following error :

Log data follows:

| DEBUG: Executing shell function do_compile
| shot.cpp:1:10: fatal error: core.hpp: No such file or directory
|     1 | #include "core.hpp"
|       |          ^~~~~~~~~~
| compilation terminated.
| WARNING: exit code 1 from a shell command.

Although, I added the meta-openembedded/meta-oe that includes opencv folder in which I found core.hpp to bblayers.

Here is the recipe:

DESCRIPTION   = " this is an application display an image"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"

SRC_URI = "file://shot.cpp"


DEPENDS = "opencv"

S = "${WORKDIR}"

do_compile () {
    ${CXX} shot.cpp -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_videoio
}

do_install () {

        install -d 0755 ${D}/${bindir}
    install -m 0755  ${D}/${bindir}
}

When I ran the application using the opencv I installed on my ubuntu 18.04. it works fine (using cmake).

I tried adding manually the core folder next to the recipe and it didn't work of course, I also added the path of the core.hpp to the recipe in the SRC_URI variable but no luck whatsoever I don't know what to do specially that I'm new to both yocto and opencv; help please

Here is the source code of the application:

#include "core.hpp"
#include "highgui.hpp"
#include <iostream>

using namespace cv;
using namespace std;

int main( )
{

      Mat image;

      // LOAD image
      image = imread("image1.jpg");   // Read the file "image.jpg".

      if(! image.data )  // Check for invalid input
      {
             cout <<  "Could not open or find the image" << std::endl ;
             return -1;
      }

      //DISPLAY image
      namedWindow( "window"); // Create a window for display.
      imshow( "window", image ); // Show our image inside it.

      waitKey(0);                       // Wait for a keystroke in the window
      return 0;
}

Solution

  • I think you need some modifications on your recipe:

    [...]
    inherit pkgconfig
    DEPENDS = "opencv"
    [...]
    

    And you will need to add a RDEPENDS and FILES variable:

    [...]
    DEPENDS = "opencv"
    # Add the runtime dependencies
    RDEPENDS_${PN} = "libopencv-core libopencv-imgproc libopencv-highgui libopencv-videoio libopencv-imgcodecs"
    
    [...]
    # At the end, ship the files
    FILES_${PN} = "${bindir}"
    

    RDEPENDS_${PN} will tell Yocto that your recipe package ${PN} needs a list a runtime dependencies. These dependencies are requiered to run your application on your board (typically libraries).

    FILES_${PN} will tell Yocto that your recipe package ${PN} will contains files. Without this line, Yocto will tell you that

    ${PN} is by default your recipe file name (without the version and .bb)


    There is also some errors.

    The compilation had some issues, lopencv_imgcodecs was not added, and there was no output name of your binary (I have named it shot):

    do_compile () {
        ${CXX} ${WORKDIR}/shot.cpp -o ${WORKDIR}/shot -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_imgcodecs ${LDFLAGS}
    }
    

    The second install command is not right:

    install -m 0755 ${WORKDIR}/shot ${D}/${bindir}
    

    Your application does not have the correct headers:

    #include "opencv2/opencv.hpp"
    #include "opencv2/highgui/highgui.hpp"
    

    At the end, the recipe looks like:

    DESCRIPTION   = " this is an application display an image"
    LICENSE = "MIT"
    LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
    
    SRC_URI = "file://shot.cpp"
    
    inherit pkgconfig
    DEPENDS = "opencv"
    RDEPENDS_${PN} = "libopencv-core libopencv-imgproc libopencv-highgui libopencv-videoio libopencv-imgcodecs"
    S = "${WORKDIR}"
    
    do_compile () {
        ${CXX} ${WORKDIR}/shot.cpp -o ${WORKDIR}/shot -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_imgcodecs ${LDFLAGS}
    }
    
    do_install () {
        install -d 0755 ${D}/${bindir}
        install -m 0755 ${WORKDIR}/shot ${D}/${bindir}
    }
    
    FILES_${PN} = "${bindir}"
    

    And the application:

    #include "opencv2/opencv.hpp"
    #include "opencv2/highgui/highgui.hpp"
    #include <iostream>
    
    using namespace cv;
    using namespace std;
    
    int main( )
    {
    
          Mat image;
    
          // LOAD image
          image = imread("image1.jpg");   // Read the file "image.jpg".
    
          if(! image.data )  // Check for invalid input
          {
                 cout <<  "Could not open or find the image" << std::endl ;
                 return -1;
          }
    
          //DISPLAY image
          namedWindow( "window"); // Create a window for display.
          imshow( "window", image ); // Show our image inside it.
    
          waitKey(0);                       // Wait for a keystroke in the window
          return 0;
    }
    

    The recipe was working on my Yocto warrior meta.