Search code examples
embedded-linuxbuildrootmeson-build

Buildroot build error: `ERROR: Dependency "nlohmann_json" not found, tried pkgconfig and cmake`


I'm trying to add the header-only library https://github.com/nlohmann/json "JSON for Modern C++" to my Buildroot package for use both on the target embedded Linux board, as well as on my host build machine in unit tests.

However, I keep getting a variety of errors no matter what I do, including ERROR: Dependency "nlohmann_json" not found, tried pkgconfig and cmake.

What's the proper way to add this library package to be used by my package?

Details about my setup:

That JSON library is known as json-for-modern-cpp in the Buildroot source code, and is located here: https://github.com/buildroot/buildroot/tree/master/package/json-for-modern-cpp

My buildroot/package/json-for-modern-cpp/json-for-modern-cpp.mk file straight from Buildroot looks like this:

################################################################################
#
# json-for-modern-cpp
#
################################################################################

JSON_FOR_MODERN_CPP_VERSION = 3.10.5
JSON_FOR_MODERN_CPP_SOURCE = json-$(JSON_FOR_MODERN_CPP_VERSION).tar.gz
JSON_FOR_MODERN_CPP_SITE = $(call github,nlohmann,json,v$(JSON_FOR_MODERN_CPP_VERSION))
JSON_FOR_MODERN_CPP_LICENSE = MIT
JSON_FOR_MODERN_CPP_LICENSE_FILES = LICENSE.MIT
JSON_FOR_MODERN_CPP_CPE_ID_VENDOR = json-for-modern-cpp_project

JSON_FOR_MODERN_CPP_INSTALL_STAGING = YES
# header only library
JSON_FOR_MODERN_CPP_INSTALL_TARGET = NO
JSON_FOR_MODERN_CPP_CONF_OPTS = -DJSON_BuildTests=OFF -DJSON_MultipleHeaders=ON

$(eval $(cmake-package))

My package's br2-external/package/my-module-name/my-module-name.mk makefile has these dependencies in it (notice I added json-for-modern-cpp to both the MY_MODULE_NAME_DEPENDENCIES target board dependencies, as well as to the HOST_MY_MODULE_NAME_DEPENDENCIES host build system dependencies:

MY_MODULE_NAME_DEPENDENCIES += \
    some-other-lib1 \
    some-other-lib2 \
    json-for-modern-cpp

HOST_MY_MODULE_NAME_DEPENDENCIES += \
    host-some-other-lib1 \
    host-some-other-lib2 \
    json-for-modern-cpp

Solution

  • How to add a Buildroot package to your package, and to your meson.build file

    I figured it out. I've documented what I learned in my eRCaGuy_dotfiles/git & Linux cmds, help, tips & tricks - Gabriel.txt notes file. Search that document for "Adding dependencies from other meson.build files" and for "nlohmann" for details and notes.

    Here's the solution:

    If you need to add a dependency on a 3rd-party library or something, such as JSON for Modern C++ (https://github.com/nlohmann/json), simply do this:

    1. Find that project's meson.build file. Ex: https://github.com/nlohmann/json/blob/develop/meson.build Notice the 'nlohmann_json' project name at the top. Use that in your module's meson.build file:

      all_deps = [
          # NB: this `nlohmann_json` meson.build name can be identified from its public repo's 
          # meson.build file here: https://github.com/nlohmann/json/blob/develop/meson.build#L1
          dependency('nlohmann_json')
          dependency('some_other_lib2'),
          dependency('some_other_lib3'),
          dependency('some_other_lib4'),
      ]
      

      all_deps will then be used in your meson.build file to build your executable and specify your library dependencies--something like this, for example:

      my_lib = static_library(
          'my_module_name',
          include_directories : [include_dirs],
          sources: [library_sources],
          dependencies: all_deps,
          cpp_args: compiler_options,
          install: true,
      )
      
    2. Add $(eval $(host-cmake-package)) to the bottom of the json-for-modern-cpp.mk file in Buildroot here: https://github.com/buildroot/buildroot/blob/master/package/json-for-modern-cpp/json-for-modern-cpp.mk. This requires adding your own commit to your own custom fork of that repo.

      That changes that file from this:

      ################################################################################
      #
      # json-for-modern-cpp
      #
      ################################################################################
      
      JSON_FOR_MODERN_CPP_VERSION = 3.10.5
      JSON_FOR_MODERN_CPP_SOURCE = json-$(JSON_FOR_MODERN_CPP_VERSION).tar.gz
      JSON_FOR_MODERN_CPP_SITE = $(call github,nlohmann,json,v$(JSON_FOR_MODERN_CPP_VERSION))
      JSON_FOR_MODERN_CPP_LICENSE = MIT
      JSON_FOR_MODERN_CPP_LICENSE_FILES = LICENSE.MIT
      JSON_FOR_MODERN_CPP_CPE_ID_VENDOR = json-for-modern-cpp_project
      
      JSON_FOR_MODERN_CPP_INSTALL_STAGING = YES
      # header only library
      JSON_FOR_MODERN_CPP_INSTALL_TARGET = NO
      JSON_FOR_MODERN_CPP_CONF_OPTS = -DJSON_BuildTests=OFF -DJSON_MultipleHeaders=ON
      
      $(eval $(cmake-package))
      

      to this:

      ################################################################################
      #
      # json-for-modern-cpp
      #
      ################################################################################
      
      JSON_FOR_MODERN_CPP_VERSION = 3.10.5
      JSON_FOR_MODERN_CPP_SOURCE = json-$(JSON_FOR_MODERN_CPP_VERSION).tar.gz
      JSON_FOR_MODERN_CPP_SITE = $(call github,nlohmann,json,v$(JSON_FOR_MODERN_CPP_VERSION))
      JSON_FOR_MODERN_CPP_LICENSE = MIT
      JSON_FOR_MODERN_CPP_LICENSE_FILES = LICENSE.MIT
      JSON_FOR_MODERN_CPP_CPE_ID_VENDOR = json-for-modern-cpp_project
      
      JSON_FOR_MODERN_CPP_INSTALL_STAGING = YES
      # header only library
      JSON_FOR_MODERN_CPP_INSTALL_TARGET = NO
      JSON_FOR_MODERN_CPP_CONF_OPTS = -DJSON_BuildTests=OFF -DJSON_MultipleHeaders=ON
      
      $(eval $(cmake-package))
      $(eval $(host-cmake-package))
      

      Again, the only line added was the last one above. That causes cmake to bring in the necessary dependencies for the host build computer too, for your unit tests, and not just for the target embedded Linux board, which is what the $(eval $(cmake-package)) line does.

    3. Use the proper dependencies in your module's Buildroot br2-external/package/my-module-name/my-module-name.mk makefile. For the host it should be host-json-for-modern-cpp, not json-for-modern-cpp, since the latter is for the target board only. Note that the json-for-modern-cpp name seems to be defined in the config file here, by the way: https://github.com/buildroot/buildroot/blob/master/package/json-for-modern-cpp/Config.in#L2.

      MY_MODULE_NAME_DEPENDENCIES += \
          some-other-lib1 \
          some-other-lib2 \
          json-for-modern-cpp
      
      HOST_MY_MODULE_NAME_DEPENDENCIES += \
          host-some-other-lib1 \
          host-some-other-lib2 \
          host-json-for-modern-cpp
          # This last line just above is now **fixed**!
      

    That's it! It works now.

    I'm not sure why I had to add $(eval $(host-cmake-package)) to the buildroot file, as it seems like that should be something in the json-for-modern-cpp.mk file in the Buildroot repo by default, no?