jsoncpp icon indicating copy to clipboard operation
jsoncpp copied to clipboard

Linker error after string_view commit

Open vai-terokinnunen opened this issue 11 months ago • 7 comments

Describe the bug Since commit 60ccc1f5deb671e95d2a6cc761f6d03f3c8ade07 ("feat: support std::string_view in Value API"), simple example fails to linker error.

To Reproduce Steps to reproduce the behavior:

  1. Install latest jsoncpp (using Ubuntu:24.04 Docker image in this test)
git clone https://github.com/open-source-parsers/jsoncpp.git
cmake -B build-jsoncpp jsoncpp
cmake --build build-jsoncpp --target install
  1. Example project:

CMakeLists.txt

project("Example")
add_executable(example main.cpp)
target_link_libraries(example jsoncpp)

main.cpp

#include <iostream>
#include <json/json.h>
int main()
{
    Json::Value root;
    root["key"] = "value";
    std::cout << root.isMember("key") << '\n';
    root.removeMember("key");
    return 0;
}
  1. Try build cmake -B build-example example && cmake --build build-example
  2. Build fails with linker error
: && /usr/bin/c++  -rdynamic CMakeFiles/example.dir/main.cpp.o -o example  -ljsoncpp && :
/usr/bin/ld: CMakeFiles/example.dir/main.cpp.o: in function `main':
main.cpp:(.text+0x6c): undefined reference to `Json::Value::operator[](std::basic_string_view<char, std::char_traits<char> >)'
/usr/bin/ld: main.cpp:(.text+0xb7): undefined reference to `Json::Value::isMember(std::basic_string_view<char, std::char_traits<char> >) const'
/usr/bin/ld: main.cpp:(.text+0x105): undefined reference to `Json::Value::removeMember(std::basic_string_view<char, std::char_traits<char> >)'
collect2: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.

Expected behavior

  • Build successful. Works before commit 60ccc1f

Desktop (please complete the following information):

  • OS: Ubuntu 24.04
  • Meson version 1.3.2 (repeats with both meson and cmake builds)
  • Ninja version 1.11.1

Additional context

  • Extracting "key" to std::string, std::string_view or char* constant does not resolve the issue.

vai-terokinnunen avatar Jan 13 '25 13:01 vai-terokinnunen

I am getting the same problem on MacOS. I can work around it by removing the check in json/value.h to always set JSONCPP_HAS_STRING_VIEW to 1

or

A better fix is to modify CMakeLists.txt to set CMAKE_CXX_STANDARD to 17 (NOTE: setting it to 20 runs into problems with char8_t)

jmjatlanta avatar Feb 19 '25 14:02 jmjatlanta

Started messing around with this locally and was able to reproduce.

This looks to me like a library version mismatch. If JsonCpp is compiled with C++11, but the example project is compiled with C++17, then this error reproduces for me locally. If the example project is compiled with C++11 as well, I don't receive this error.

Being compatible with different versions of C++ is a big value add for JsonCpp, at least historically. I am reluctant to move to C++17 as a requirement in general.

This bug shouldn't impact most production use cases, AFAIK. I think what is probably the best answer at this point is to ensure that the headers that get installed to the system actually match the library that get installed to the system.

baylesj avatar Mar 12 '25 23:03 baylesj

As CMAKE_CXX_STANDARD is forced to be 11, JSONCPP_HAS_STRING_VIEW seems to be always undefined when building the library itself, because of the __cplusplus version check.

One possible approach may be omitting CMAKE_CXX_STANDARD, but using target_compile_features() to specify cxx_std_11 instead. As I see it is already there for lib_json there.

de1acr0ix avatar May 19 '25 21:05 de1acr0ix

I had the same problem on Ubuntu 24.04, but I set neither CMAKE_CXX_STANDARD nor JSONCPP_HAS_STRING_VIEW to solve the problem

Nana5aki avatar May 24 '25 16:05 Nana5aki

same as me, consider that:

if(CMAKE_CXX_STANDARD EQUAL 98) set(CMAKE_CXX_STANDARD 11) endif()

the cxx standard value is one of that: 98 11 14 17 20 23 26 Ref: https://cmake.org/cmake/help/latest/prop_tgt/CXX_STANDARD.html#prop_tgt:CXX_STANDARD

RonxBulld avatar Aug 27 '25 03:08 RonxBulld

Was about to report the same. (Actually prepared a bug report yesterday, for some reason I didn't find this issue). Given that the CMakeFile now forces a downgrade, it will lead to link errors later down the line.

EDIT: To be clear where the issue is. If a user of the library builds his program without any special args and jsoncpp without any special args, it won't link. Simply because the users build will NOT downgrade to C++11.

This can either be fixed adding a define to the emitted CMake Config file ("-DJSONCPP_HAS_STRINGVIEW" or whatever it was called), to allow users of the library to see and use the change, or in my opinion, preferably just omit setting the standard version by default. As that also prevents users from having to recompile potentially larger projects due to that change.

EDIT2: Also, how would one go about building the project with C++17 and newer? There's no way to undefine the CMAKE_CXX_STANDARD at configuration. At least set it only if it's not set in my opinion.

EDIT3: I "fixed" this problem in my build system by patching the CMakeLists.txt and uncommenting CMAKE_CXX_STANDARD and CMAKE_CXX_STANDARD_REQUIRED and letting it use whatever's GCC's current default (probably C++17).

EDIT4: Never mind, that also breaks other software that's using C++11, so the only "real" solution would be to include either a config.h file (or appropriate settings in config files, like pkgconfig and CMake) including the info about how the library has been built. Like this you can't use the C++11 build and then use it with a C++17 project.

Fighter19 avatar Nov 25 '25 09:11 Fighter19

Actually, this issue goes even deeper. We compile external libraries separately from our main project and link against them later. For libraries, we use CMake, as that's what they often provide (just like JsonCpp). For our main project, we use Sharpmake. The environments are set up with similar configurations (the same Visual Studio version, the same C++ standard, ...), but both Sharpmake and CMake obviously generate these projects differently.

The biggest (and surprising!) difference is that CMake does not define __cplusplus for Visual Studio projects. This is apparently a known issue and has not been addressed for nearly seven years: https://gitlab.kitware.com/cmake/cmake/-/issues/18837

This can be seen via Intellisense popups, too:

Image

I believe that whether this library uses string views should be an additional setting that gives users the power to control their environment. This not only addresses our use case but also all the issues mentioned above.

ShawnCZek avatar Nov 25 '25 19:11 ShawnCZek