SRombauts/SQLiteCpp

unresolved external symbol error

tt376 opened this issue ยท 13 comments

tt376 commented

vcpkg package management program version 2023-06-15-8c254a5fb6c503615834fc66bd0717664a339a2e
Microsoft Visual Studio Community 2022 (64-bit) - CurrentVersion 17.6.4
msvc console project
sqlitecpp 3.3.0

When I install the library using vcpkg and run the test code in VisualStudio, I get the following unresolved external symbol error.

********.obj error LNK2001: The external symbol "int const SQLite::OPEN_READONLY" (?OPEN_READONLY@SQLite@@@3HB) is unresolved
********.exe : fatal error LNK1120: 1 unresolved external reference

How can I resolve this?

If only the sqlite3 library is used from vcpkg, there is no error.

managed to replicate it, seems to be related to SQLiteCppExport.h
Visual Studio shows that is not detecting properly windows
image

I am not much familiar with CMake, however seems that under CMakeLists.txt

target_compile_definitions(SQLiteCpp PRIVATE "SQLITECPP_DLL_EXPORT")

should be

target_compile_definitions(SQLiteCpp PUBLIC "SQLITECPP_DLL_EXPORT")

managed to run the project using cmake with visual studio generator, I tried to patch it using vcpkg but it did not work

sadly there is nothing else I can think of for vcpkg+visual studio, as a workarround you can set the preprocessor definition manually for your project like this

image

I think it could be a good idea to open an Issue in vcpkg to check if they know a way how to set that definition

this is the patch I used in case anyone wants to check it out

diff --git a/CMakeLists.txt b/CMakeLists.txt
index df5693d..0a24924 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -216,7 +216,7 @@ endif (SQLITE_USE_LEGACY_STRUCT)
 if(BUILD_SHARED_LIBS)
     if(WIN32)
         add_definitions("-DSQLITECPP_COMPILE_DLL")
-        target_compile_definitions(SQLiteCpp PRIVATE "SQLITECPP_DLL_EXPORT")
+        target_compile_definitions(SQLiteCpp PUBLIC "SQLITECPP_DLL_EXPORT")
     endif()
 endif()
 
@@ -295,9 +295,9 @@ else (SQLITECPP_INTERNAL_SQLITE)
             target_link_libraries(SQLiteCpp PRIVATE ${sqlcipher_LIBRARY})
         endif()
     else()
-        find_package (SQLite3 REQUIRED)
+        find_package (unofficial-sqlite3 CONFIG)
         message(STATUS "Link to sqlite3 system library")
-        target_link_libraries(SQLiteCpp PUBLIC SQLite::SQLite3)
+        target_link_libraries(SQLiteCpp PRIVATE unofficial::sqlite3::sqlite3)
         if(SQLite3_VERSION VERSION_LESS "3.19")
             set_target_properties(SQLiteCpp PROPERTIES COMPILE_FLAGS "-DSQLITECPP_HAS_MEM_STRUCT")
         endif()
diff --git a/cmake/SQLiteCppConfig.cmake.in b/cmake/SQLiteCppConfig.cmake.in
index 2b48df4..d0feda9 100644
--- a/cmake/SQLiteCppConfig.cmake.in
+++ b/cmake/SQLiteCppConfig.cmake.in
@@ -1,6 +1,6 @@
 include(CMakeFindDependencyMacro)
 if(NOT @SQLITECPP_INTERNAL_SQLITE@)
-    find_dependency(SQLite3 REQUIRED)
+    find_dependency(unofficial-sqlite3 REQUIRED)
 endif()
 if(@UNIX@)
     set(THREADS_PREFER_PTHREAD_FLAG @THREADS_PREFER_PTHREAD_FLAG@)
tt376 commented

@ninjaoflight
Thank you for your detailed explanation.

I am not familiar with C++ and compilation and am not sure if I understand it correctly.
Is the following interpretation correct?

  • The problem occurs with respect to the output handling of the DLL.

  • Essentially, this is a problem that should be addressed by modifying "CMakeLists.txt".

  • By manually adding "SQLITECPP_COMPILE_DLL" to the last line of the "preprocessor definition", the DLL can be output and the project can be executed.

  • There may be a way to automatically resolve the "preprocessor definition" from vcpkg.

@tt376 I cannot speak for VCPKG+Visual Studio integration.

the issue happens because SQLITECPP_COMPILE_DLL is not defined, this definition is used by SQLiteCpp to check if it was compiled as a DLL or a static library, for vcpkg it is compiled as DLL however seems that the definition is not exported to the visual studio project

so the solution would be to include a patch for vcpkg in its port and test it so it exports correctly the definition, if is an error from the main Cmakelists of this repo it can be changed, if it requires a change for the port it has to be changed on the port.

also I found that in microsoft/vcpkg#8879 they have a similar issue for this

as an alternative workarround besides the other I mention you can modify the source code that includes SQlitecpp and define SQLITECPP_COMPILE_DLL before the include statement like this

#define SQLITECPP_COMPILE_DLL
#include <SQLiteCpp/SQLiteCpp.h>

it may not be the best solution but will work until someone finds a better solution

tt376 commented

@ninjaoflight
Thank you again for your detailed explanation.

I did not fully understand it with my knowledge, but I now have a better understanding.
My project compiled successfully and worked fine with both of the two methods you mentioned above.

If there is nothing to fix in this repository, I am willing to close this issue.

Finally, I would like to thank the developers of this repository and the people who worked on this issue.

calumr commented

I think #434 fixes this as we need SQLITECPP_COMPILE_DLL defined for all users of the library. add_definitions doesn't do this in cmake, it just defines it for SQLiteCpp and nothing else.

Defining this means that users of the library get #define SQLITECPP_API __declspec(dllimport), which is correct as dllexport should only be used when building the library itself:

https://stackoverflow.com/questions/57999/what-is-the-difference-between-dllexport-and-dllimport

I have tested this on our code (we use vcpkg with dynamic libs) and it seems to fix the linker errors.

I think #434 fixes this as we need SQLITECPP_COMPILE_DLL defined for all users of the library. add_definitions doesn't do this in cmake, it just defines it for SQLiteCpp and nothing else.

Defining this means that users of the library get #define SQLITECPP_API __declspec(dllimport), which is correct as dllexport should only be used when building the library itself:

https://stackoverflow.com/questions/57999/what-is-the-difference-between-dllexport-and-dllimport

I have tested this on our code (we use vcpkg with dynamic libs) and it seems to fix the linker errors.

good insight, I know this change works with cmake+vcpkg works, however I do not know if it works under vsbuild+vcpkg, I think the patch would need an additional command but I am not sure

edit: I also think that is a good Idea to use target_compile_definitions which is more clean in modern cmake

BA7LYA commented

I got the same problem and more error.

vcpkg+vscode+sqlitecpp

warning LNK4098: defaultlib 'MSVCRT' conflicts with use of other libs; use /NODEFAULTLIB:library
error LNK2001: The external symbol "int const SQLite::OPEN_READONLY" (?OPEN_READONLY@SQLite@@@3HB) is unresolved
error LNK2001: The external symbol "int const SQLite::OPEN_READWRITE" (?OPEN_READWRITE@SQLite@@3HB) is unresolved
error LNK1120: The external symbol "int const SQLite::OPEN_CREATE" (?OPEN_CREATE@SQLite@@3HB) is unresolved

managed to run the project using cmake with visual studio generator, I tried to patch it using vcpkg but it did not work

sadly there is nothing else I can think of for vcpkg+visual studio, as a workarround you can set the preprocessor definition manually for your project like this

image

I think it could be a good idea to open an Issue in vcpkg to check if they know a way how to set that definition

this is the patch I used in case anyone wants to check it out

diff --git a/CMakeLists.txt b/CMakeLists.txt
index df5693d..0a24924 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -216,7 +216,7 @@ endif (SQLITE_USE_LEGACY_STRUCT)
 if(BUILD_SHARED_LIBS)
     if(WIN32)
         add_definitions("-DSQLITECPP_COMPILE_DLL")
-        target_compile_definitions(SQLiteCpp PRIVATE "SQLITECPP_DLL_EXPORT")
+        target_compile_definitions(SQLiteCpp PUBLIC "SQLITECPP_DLL_EXPORT")
     endif()
 endif()
 
@@ -295,9 +295,9 @@ else (SQLITECPP_INTERNAL_SQLITE)
             target_link_libraries(SQLiteCpp PRIVATE ${sqlcipher_LIBRARY})
         endif()
     else()
-        find_package (SQLite3 REQUIRED)
+        find_package (unofficial-sqlite3 CONFIG)
         message(STATUS "Link to sqlite3 system library")
-        target_link_libraries(SQLiteCpp PUBLIC SQLite::SQLite3)
+        target_link_libraries(SQLiteCpp PRIVATE unofficial::sqlite3::sqlite3)
         if(SQLite3_VERSION VERSION_LESS "3.19")
             set_target_properties(SQLiteCpp PROPERTIES COMPILE_FLAGS "-DSQLITECPP_HAS_MEM_STRUCT")
         endif()
diff --git a/cmake/SQLiteCppConfig.cmake.in b/cmake/SQLiteCppConfig.cmake.in
index 2b48df4..d0feda9 100644
--- a/cmake/SQLiteCppConfig.cmake.in
+++ b/cmake/SQLiteCppConfig.cmake.in
@@ -1,6 +1,6 @@
 include(CMakeFindDependencyMacro)
 if(NOT @SQLITECPP_INTERNAL_SQLITE@)
-    find_dependency(SQLite3 REQUIRED)
+    find_dependency(unofficial-sqlite3 REQUIRED)
 endif()
 if(@UNIX@)
     set(THREADS_PREFER_PTHREAD_FLAG @THREADS_PREFER_PTHREAD_FLAG@)

You're a savior!
I wasted 1 hour (if not more) trying to understand what I was doing wrong. Turns out it was not my fault...
Works fine as a temporary solution, I guess. Thanks!

dpieve commented

Vcpkg + Visual studio 17.7. Errors:

error LNK2001: The external symbol "int const SQLite::OPEN_READONLY" (?OPEN_READONLY@SQLite@@@3HB) is unresolved
error LNK2001: The external symbol "int const SQLite::OPEN_READWRITE" (?OPEN_READWRITE@SQLite@@3HB) is unresolved

If I define SQLITECPP_COMPILE_DLL, it gives LNK2001 too.
Why is this issue closed? Is there a solution for it?

Vcpkg + Visual studio 17.7. Errors:

error LNK2001: The external symbol "int const SQLite::OPEN_READONLY" (?OPEN_READONLY@SQLite@@@3HB) is unresolved
error LNK2001: The external symbol "int const SQLite::OPEN_READWRITE" (?OPEN_READWRITE@SQLite@@3HB) is unresolved

If I define SQLITECPP_COMPILE_DLL, it gives LNK2001 too. Why is this issue closed? Is there a solution for it?

can you give a sample code?, SQLITECPP_COMPILE_DLL should be defined at project level or before any #include of the library

edit: I recommend reporting in vcpkg for any project that is not meson or cmake that cannot be replicated here

dpieve commented

@ninjaoflight I figure out that it works for me if I use an old vcpkg commit. So, for now it's fine, if I have more problems I will open an issue or report it to vcpkg as suggested. Thank you for the answer!