pboettch / json-schema-validator

JSON schema validator for JSON for Modern C++
Other
470 stars 135 forks source link

Linking issue ("undefined reference") when using nlohmann_json/3.9.1 #180

Closed gmclay closed 1 year ago

gmclay commented 2 years ago

Build OS: Ubuntu 18.04 Compiler: GCC (g++ 9.4.0) Using CMake and Conan

I've been using nlohmann_json 3.7.3 for 2+ years but wanted to add a schema validator. Link below says json-schema-validator has a dependency on nlohmann_json 3.9.1.

https://conan.io/center/json-schema-validator?version=2.1.0&tab=dependencies

I switched to nlohmann_json 3.9.1 and my build / unit tests passed as expected. However, once json-schema-validator/2.1.0 was added and the json_validator was called, there is an "undefined reference" error.

Note, I see nlohmann_json/3.7.3 is used in the conanfile.py (link below) so I switched back to that and the undefined reference goes away.

https://github.com/pboettch/json-schema-validator/blob/master/conanfile.py

Is this a documentation issue on conan.io? Or is json-schema-validator/2.1.0 supposed to be compatible with nlohmann_json/3.9.1?

Linker error

CMakeFiles/project.dir/JsonSchemaValidator.cpp.o: In function `JsonSchemaValidator::JsonSchemaValidator()':
JsonSchemaValidator.cpp:(.text+0x398): undefined reference to `nlohmann::json_schema::json_validator::json_validator(std::function<void (nlohmann::json_uri const&, nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> > >&)>, std::function<void (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)>)'
JsonSchemaValidator.cpp:(.text+0x3d5): undefined reference to `nlohmann::json_schema::json_validator::set_root_schema(nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> > > const&)'
JsonSchemaValidator.cpp:(.text+0x3e9): undefined reference to `nlohmann::json_schema::json_validator::validate(nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> > > const&) const'
JsonSchemaValidator.cpp:(.text+0x40c): undefined reference to `nlohmann::json_schema::json_validator::validate(nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> > > const&) const'
collect2: error: ld returned 1 exit status

JsonSchemaValidator.cpp -- essentially a copy of the sample code for json-schema-validator. Reference to JsonSchemaValidator.hpp removed for brevity.

#include <iostream>
#include <nlohmann/json-schema.hpp>
#include <nlohmann/json.hpp>

using nlohmann::json;
using nlohmann::json_schema::json_validator;

// The schema is defined based upon a string literal
static json uri_schema = R"(
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "myUri": {
      "type":"string",
      "format": "uri"
    }
  }
})"_json;

// The people are defined with brace initialization
static json good_uri = {{"myUri", "http://hostname.com/"}};
static json bad_uri = {{"myUri", "http:/hostname.com/"}};

static void uri_format_checker(const std::string& format,
                               const std::string& value)
{
    if (format == "uri")
    {
        if (value.find("://") == std::string::npos)
            throw std::invalid_argument("URI does not contain :// - invalid");
    }
    else
    {
        throw std::logic_error("Don't know how to validate " + format);
    }
}

JsonSchemaValidator::JsonSchemaValidator()
{
    json_validator validator(nullptr, uri_format_checker); // create validator

    try
    {
        validator.set_root_schema(uri_schema); // insert root-schema
    }
    catch (const std::exception& e)
    {
        std::cerr << "Validation of schema failed, here is why: " << e.what()
                  << "\n";
        // return EXIT_FAILURE;
    }

    validator.validate(good_uri);

    try
    {
        validator.validate(bad_uri);
    }
    catch (const std::exception& e)
    {
        std::cerr << "Validation expectedly failed, here is why: " << e.what()
                  << "\n";
    }
}

JsonSchemaValidator::~JsonSchemaValidator()
{
}
pboettch commented 2 years ago

I'm not using Conan so I can't really help. Is there an issue-database on their side, because I think it should be handled there.

iksemyonov commented 2 years ago

@gmclay Can you please show the complete cmake code that you use to: a) add the json-schema-validator package to your conan dependencies b) link json-schema-validator to your target? I use json-schema-validator 2.1.0 via conan, with the same package from conan.io that you've linked in the OP, and it works just fine.

gmclay commented 2 years ago

@pboettch thanks for the prompt response. I'm uncertain where the issue belongs but if you can confirm nlohmann_json/3.9.1 works with json-schema-validator/2.1.0 for you without conan then it is probably safe to say conan is related to the issue I'm seeing. Please confirm.

Please note that the conan file in this project (link below) references nlohmann_json/3.7.3 (old version -- works for me) and not nlohmann_json/3.9.1 (new version -- does not work for me). Is this file used in any testing? If so, you may see the issue if you use 3.9.1.

https://github.com/pboettch/json-schema-validator/blob/master/conanfile.py

@iksemyonov thanks for sharing that this is working for you. To be clear, are you using nlohmann_json/3.7.3 or nlohmann_json/3.9.1 with json-schema-validator/2.1.0?

Below are the conanfile and the src/CMakeList.txt. Note, I only included CMakeList.txt relevant lines since it is a large project with a couple CMake files. I think I included the relevant pieces but please let me know if there is a specific cmake command you'd like to see.

Could you also share how you're building / linking json-schema-validator/2.1.0 using cmake and conan?

conanfile.py

from sys import platform
from conans import ConanFile, CMake, tools

class PROJECTConan(ConanFile):
    settings = "os", "compiler", "build_type", "arch"

    requires = ["gtest/1.10.0",
                "nlohmann_json/3.7.3",
                "zlib/1.2.11",
                "boost/1.71.0",
                "b2/4.5.0",
                "json-schema-validator/2.1.0"]

    generators = "cmake"

      # gtest options
    default_options = {"gtest:no_main": True, "b2:use_cxx_env": True, "b2:toolset": "gcc"}

    def imports(self):
        self.copy("license*", dst="licenses", folder=True, ignore_case=True)
        self.copy("copying*", dst="licenses", folder=True, ignore_case=True)
        self.copy("*.dll", "bin", "bin")
        self.copy("*.dll", "bin", "lib")
        self.copy("*.so", "lib", "lib")
        self.copy("*.so.*", "lib", "lib")
        self.copy("*.a", "lib", "lib")
        self.copy("*.o", "lib", "lib")

src/CMakeList.txt

target_link_libraries(project PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${PROJECT_LINK_LIBS} ${CMAKE_DL_LIBS} ${CONAN_LIBS_JSON-SCHEMA-VALIDATOR})

include_directories(${PROJECT_INCLUDE_DIR} ${CONAN_INCLUDE_DIRS_JSON-SCHEMA-VALIDATOR})

if (UNIX)
    include_directories(SYSTEM ${CONAN_INCLUDE_DIRS_NLOHMANN_JSON} ${CONAN_INCLUDE_DIRS_BOOST} ${TASKFLOW_INCLUDE_DIR})
endif()
pboettch commented 1 year ago

Is this still a problem or did you find a solution?

gmclay commented 1 year ago

@pboettch this problem still exists but I have been using nlohmann_json/3.7.3 and json-schema-validator/2.1.0 to avoid the issue. I don't have a solution.

pboettch commented 1 year ago

When linking the final binary could you get the whole compiler/linker line? Would be interesting to see where it put the validator-lib.

Maybe compare with the working version.