Search code examples
c++cdevice-tree

Linker error: undefined reference to fdt_path_offset


I am trying to leverage libfdt for parsing device tree blob files.

You can install libfdt on any Ubuntu by: sudo apt-get install libfdt-dev

I write simple test program to use one of the APIs:

#include <vector>
#include <iostream>
#include <libfdt.h>
#include <fstream>

std::vector<char>
read_binary(const std::string& fnm)
{
  if (fnm.empty())
    throw std::runtime_error("No file specified");

  // load the file
  std::ifstream stream(fnm);
  if (!stream)
    throw std::runtime_error("Failed to open file '" + fnm + "' for reading");

  stream.seekg(0, stream.end);
  size_t size = stream.tellg();
  stream.seekg(0, stream.beg);

  std::vector<char> binary(size);
  stream.read(binary.data(), size);
  return binary;
}

int main ()
{
  std::vector<char> binary = read_binary("metadata.dtb");
  const void* fdt = binary.data();
  int offset = fdt_path_offset(fdt,"/interfaces");
  std::cout << offset << std::endl;
  return 0;
}

I compile/link with:

g++ main.cpp -lfdt

Compiling succeeds, but linking fails. I don't understand why. I can see the library has the symbols. The library exists in the default search path. The linker is able to find the library.

Linker Error:

main.cpp: undefined reference to `fdt_path_offset(void const*, char const*)'

Solution

  • libfdt is C software that doesn't care about C++.

    Functions written in C should be declared with extern "C" in order to be usable in C++. A lot of C libraries have their user-facing headers wrapped in

    #ifdef __cplusplus
    extern "C" {
    #endif
    
    // declarations ...
    
    #ifdef __cplusplus
    }
    #endif
    

    as a convenience for C++ developers.

    However libfdt apparently doesn't do that, so you have to do it yourself.

    extern "C" {
        #include <libfdt.h>
    }
    

    should do the trick.