Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue with backend include directories & DLL requirement even when linked statically #1015

Open
rasikhq opened this issue Nov 9, 2022 · 5 comments · May be fixed by #1118
Open

Issue with backend include directories & DLL requirement even when linked statically #1015

rasikhq opened this issue Nov 9, 2022 · 5 comments · May be fixed by #1118

Comments

@rasikhq
Copy link

rasikhq commented Nov 9, 2022

Hi, after several hours of going through documentation, github issues and CMakeLists.txt files I've finally given up in figuring out what I'm doing wrong to use Soci to connect to MySQL backend statically.

There are two parts to my issue, issue (2) only is reached when I manually fix issue (1) which in-itself I'm not sure why isn't already working on its own.

Environment:

  • Visual Studio 2022
  • Windows 10
  • CMake version 3.25.0-rc3

Issue (1):

This is my configuration that is relevant for SOCI:

set(BUILD_SHARED_LIBS OFF CACHE INTERNAL "Static Build" FORCE)

set(SOCI_SHARED OFF CACHE INTERNAL "SOCI Shared" FORCE)
set(SOCI_STATIC ON CACHE INTERNAL "SOCI Static" FORCE)
set(SOCI_TESTS OFF CACHE INTERNAL "SOCI Tests" FORCE)
set(WITH_BOOST OFF CACHE INTERNAL "SOCI use Boost" FORCE)
set(SOCI_EMPTY OFF CACHE INTERNAL "SOCI Backend" FORCE)
set(WITH_DB2 OFF CACHE INTERNAL "SOCI Backend" FORCE)
set(WITH_FIREBIRD OFF CACHE INTERNAL "SOCI Backend" FORCE)
set(WITH_MYSQL ON CACHE INTERNAL "SOCI Backend" FORCE)
set(WITH_ODBC OFF CACHE INTERNAL "SOCI Backend" FORCE)
set(WITH_ORACLE OFF CACHE INTERNAL "SOCI Backend" FORCE)
set(WITH_POSTGRESQL OFF CACHE INTERNAL "SOCI Backend" FORCE)
set(WITH_SQLITE3 OFF CACHE INTERNAL "SOCI Backend" FORCE)

# (... Other configurations and options ...)

target_link_libraries(myTarget PUBLIC soci_core_static)
target_link_libraries(myTarget PUBLIC soci_mysql_static)

CMake generates the solution files successfully and then I try to include the following:

#include <soci/soci.h>
#include <soci/soci-config.h>
#include <soci/mysql/soci-mysql.h>

and I get this error in every cpp file where these headers are included:

path\...\vendor\soci\include\soci/mysql/soci-mysql.h(37,10): fatal  error C1083: Cannot open include file: 'mysql.h': No such file or directory

Issue (2):

To overcome the above Issue I added following:

find_package(MySQL REQUIRED)
target_include_directories(myTarget PUBLIC ${MYSQL_INCLUDE_DIR})

This solves issue (1) and everything compiles with a test code like so:

soci::register_factory_mysql();
soci::session session(soci::mysql, "...");

Everything builds, but when I run the program, I get missing dependencies for libmysql.dll and if I copy paste that dll from my MySQL installation, the program runs fine, so then what was the point of going through static build if dll is still a requirement at the end?

Conclusion

I'm not sure what I'm doing wrong, at what step am I linking incorrectly or configuring incorrectly which is causing this, any help would be appreciated.

@vadz
Copy link
Member

vadz commented Nov 9, 2022

For (1) I think it's normal that you need to use MySQL options explicitly if you include the MySQL-specific SOCI header. The alternative would be to always include all backend-specific include paths into SOCI target itself, but this doesn't seem right, i.e. why would people not using MySQL at all need to have MySQL include paths in their build?

For (2) I'm sure that this behaves as expected: SOCI static build only refers to static libraries of SOCI itself, not the backend-specific libraries. The point of using it is not to have dependencies on SOCI DLLs.

@rasikhq
Copy link
Author

rasikhq commented Nov 9, 2022

So basically there is no way to statically link libmysqlclient that means? I really wanted to avoid having a .dll 😋

If that is the case then I guess I have everything configured correctly, this can be closed. Thank you

@vadz
Copy link
Member

vadz commented Nov 9, 2022

Does MySQL even come with static libraries in the first place (I don't use it myself, so I don't know)? If yes, it should be possible to convince CMake to use them, I guess... but e.g. libpq for PostgreSQL is only distributed in the shared form normally and even though you could rebuild it as a static library yourself, you wouldn't be able to do it for e.g. Oracle. So I just don't think you can avoid using DLLs in all cases, even though it might be possible with MySQL.

@rasikhq
Copy link
Author

rasikhq commented Nov 9, 2022

It seems like MySQL has a mysqlclient.lib (and libmysqlclient.so on linux) that can be used for static linking, however when I do that I get this during CMake generation:

CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake files:
MYSQL_EMBEDDED_LIBRARIES
    linked by target "cmTC_da6ba" in directory path-to-my-project/build/CMakeFiles/CMakeScratch/TryCompile-y7yx45

Also I tried goofing around by first linking with libmysql.lib (which is how linking is being performed now) and invoked cmake, it generated successfully, then I changed the linking library from libmysql to mysqlclient.lib manually in visual studio > Linker settings and compiled, and now I didn't need the .dll. So if there's a way to get rid of the embedded libraries error then surely it can work, however to my knowledge (I could be wrong here) the embedded mysql libraries are related to bundling the entire mysql server so not sure

Edit

So I took your FindMySQL.cmake and added this after the include(...) line at the very top

set(CLIENT_LIB "libmysql")
if(NOT ${BUILD_SHARED_LIBS})
	set(CLIENT_LIB "mysqlclient")
endif()

...

# Both for if(WIN32) and else(WIN32)
find_library(MYSQL_LIBRARIES NAMES ${CLIENT_LIB}
      PATHS
      ${MYSQL_LIB_PATHS}
   )

and modified following

if(${BUILD_SHARED_LIBS})
   set( CMAKE_REQUIRED_LIBRARIES ${MYSQL_EMBEDDED_LIBRARIES} )
   check_cxx_source_compiles( "#include <mysql.h>\nint main() { int i = MYSQL_OPT_USE_EMBEDDED_CONNECTION; }" HAVE_MYSQL_OPT_EMBEDDED_CONNECTION )
endif()

Got a completely static build of mysql, I have no idea how bad, broken or plain stupid this is, but it works atleast on windows. I haven't tried on Linux yet (I have to build my project on linux as well)

Edit 2

Works on linux as well (Debian 10)

@Krzmbrzl
Copy link
Contributor

Krzmbrzl commented Feb 2, 2025

This should be fixed via #1118

@Krzmbrzl Krzmbrzl linked a pull request Feb 2, 2025 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants