realm / realm-cpp

Realm C++
Apache License 2.0
74 stars 17 forks source link

mismatch detected for 'RuntimeLibrary' on windows #155

Open MHebes opened 10 months ago

MHebes commented 10 months ago

I am trying to build a basic hello world program, and am getting some linker errors.

I'm on windows with visual studio 2022 (cl.exe version is Microsoft (R) C/C++ Optimizing Compiler Version 19.38.33130 for x86).

Just tons of static/dynamic linking errors, e.g.

realm-dbg.lib(spec.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MTd_StaticDebug' doesn't match value 'MDd_DynamicDebug' in main.obj

Here's a MRE:

// main.cpp
#include <cpprealm/sdk.hpp>
#include <iostream>

namespace realm {
struct Todo {
  realm::primary_key<realm::object_id> _id{realm::object_id::generate()};
  std::string name;
  std::string status;
  // The ownerId property stores the user.identifier() of a
  // logged-in user. Omit this property for the non-sync example.
  std::string ownerId;
};
REALM_SCHEMA(Todo, _id, name, status, ownerId);
}  // namespace realm

int main() {
  auto config = realm::db_config();
  auto realm = realm::db(std::move(config));

  auto todo = realm::Todo{.name = "Hello", .status = "In Progress"};
  realm.write([&] { realm.add(std::move(todo)); });

  auto todos = realm.objects<realm::Todo>();

  for (const auto& t : todos) {
    std::cout << t.name.detach();
  }

  return 0;
}
cmake_minimum_required(VERSION 3.25.2)

set(BIN cpprealmtest)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

project(${BIN})

if(MSVC)
   set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zc:preprocessor /bigobj")
endif()

message(STATUS "Fetching mongodb realm/atlas device sdk...")
include(FetchContent)
FetchContent_Declare(
  cpprealm
  GIT_REPOSITORY https://github.com/realm/realm-cpp.git
  GIT_TAG        v1.0.0
  GIT_SHALLOW    TRUE
)
FetchContent_MakeAvailable(cpprealm)

add_executable(${BIN} main.cpp)
target_link_libraries(${BIN} PRIVATE cpprealm)

Commands:

$ mkdir build
$ cd build
$ cmake ..
$ cmake --build . -j -t cpprealmtest --config debug # release, relwithdebinfo have the same issues

There's a slightly suspicious line in the CMakeLists that may be related to the issue:

https://github.com/realm/realm-cpp/blob/43a68815c11eb7fdd8010eef91157419d2e17b64/CMakeLists.txt#L120

Any thoughts on how I should fix this issue?

fealebenpae commented 9 months ago

Hey @MHebes,

Right now we've hardcoded static linking to the MSVC runtime libraries, but we're working on removing the limitation. Until we've merged those changes the temporary work around is to opt in for static linking of the runtime libraries yourself by similarly setting the MSVC_RUNTIME_LIBRARY target property in your project.

MHebes commented 9 months ago

I gotcha @fealebenpae—thanks so much for the link and info!

Would you happen to have a sense of how hard it would be for me to monkey patch to build with dynamic linking? Assuming I didn't care about any platforms other than desktop windows (my project produces many binaries so static linking would be pretty burdensome).

In other words, do you think that removing the set_property(...MSVC_RUNTIME_LIBRARY) lines from realm-cpp/CMakeLists.txt like you do in that PR draft be good enough or is there a deeper reason for the static linking other than "simplicity in deployment"?

fealebenpae commented 9 months ago

You can certainly edit the listfile - there is a similar change in a submodule you have to make, but that's about it. However, there is the added complication of our dependencies on Windows - we rely on OpenSSL and zlib and the prebuilt copies we host and link against are also built to statically link the runtime libraries. You would need to provide your own copies of OpenSSL and zlib that satisfy CMake's find_package and call find_package(OpenSSL REQUIRED), find_package(zlib REQUIRED), and set(REALM_USE_SYSTEM_OPENSSL ON) in your project's CMakeLists.txt prior to including realm-cpp.

The vcpkg integration PR I originally linked to is supposed to solve this generally, as we'll be pulling OpenSSL and zlib as vcpkg dependencies and vcpkg can build with the correct RuntimeLibrary setting. It's definitely possible to achieve the same yourself if you're handy with CMake, but my suggestion would be to wait for the vcpkg integration to land and consume the library that way.