unresolved external symbol error
tt376 opened this issue ยท 13 comments
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.
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
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@)
@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
@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.
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 asdllexport
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
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
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!
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
@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!