Reputation: 159
I decided to use mysql as part of a project to teach myself C++ so let me apologise in advance for the lack of knowledge. The concept of linking, dynamic and static libraries are still very new to me. With this out of the way, let's proceed.
I'm trying to query a mysql server from C++. Ideally, I'd like the end product to run on any architecture with as little dependencies on libraries as possible. I don't want the user of my code to have to install any libraries themselves (i.e. Connector/C++). I also want to use cmake to compile my project.
In order to do this, I used binaries for
I built Boost from source and I used brew to install openssl even though ssl and crypto dynamic libraries came with the connector binary.
I used https://dev.mysql.com/doc/connector-cpp/8.0/en/connector-cpp-apps-macos-notes.html and https://dev.mysql.com/doc/connector-cpp/8.0/en/connector-cpp-apps-general-considerations.html#connector-cpp-apps-link-libraries as reference for my CmakeLists.txt
cmake_minimum_required(VERSION 3.1)
project(SQL VERSION 0.1.0)
# enable c++17
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(MYSQL_DIR "/usr/local/mysql-connector-c++-8.0.19")
find_package(Threads REQUIRED)
find_package(Boost REQUIRED)
add_executable(${PROJECT_NAME} main.cpp)
target_include_directories(
${PROJECT_NAME}
PUBLIC
${MYSQL_DIR}/include
${Boost_INCLUDE_DIRS}
)
find_library(SSL_LIB NAMES ssl PATHS ${MYSQL_DIR}/lib64 NO_DEFAULT_PATH)
find_library(CRYPTO_LIB NAMES crypto PATHS ${MYSQL_DIR}/lib64 NO_DEFAULT_PATH)
find_library(MYSQL_LIBS NAMES mysqlcppconn PATHS ${MYSQL_DIR}/lib64)
target_link_libraries(${PROJECT_NAME} ${MYSQL_LIBS} ${SSL_LIB} ${CRYPTO_LIB} Threads::Threads)
#define STATIC_CONCPP
#include <mysql/jdbc.h>
#include <iostream>
#include <vector>
#include <stdexcept>
int main(){
std::cout << "Connector/C++ standalone program example..." << '\n';
sql::Connection *con;
sql::Statement *stmt;
sql::mysql::MySQL_Driver * driver = sql::mysql::get_driver_instance();
con = driver->connect(URI, USER, PASS);
con->setSchema(EXAMPLE_DB);
stmt = con->createStatement();
sql::ResultSet *res = stmt->executeQuery("SELECT * FROM TICKERS");
std::cout << "\t... running " << "SELECT * FROM TICKERS" << "..." <<'\n';
sql::ResultSetMetaData *mtd = res->getMetaData();
while (res->next()){
std::cout << res->getString(1) <<'\t' <<res->getString(2) << '\n';
}
}
I use cmake ..; cmake --build .
to build my project.
Using the above, at first I got
Scanning dependencies of target SQL
[ 50%] Building CXX object CMakeFiles/SQL.dir/main.cpp.o
[100%] Linking CXX executable SQL
[100%] Built target SQL
However, why I try and run the executable I get
dyld: Library not loaded: libssl.1.1.dylib
Referenced from: /Users/paperino/dev/cpp/learn/mysql/build/./SQL
Reason: image not found
Abort trap: 6
If I copy libssl and libcrypto from /usr/local/mysql-connector-c++-8.0.19/lib64
to my build folder then I'm able to run the executable. Why is this necessary, even though I've specified the paths to both ssl and crypto libraries using find_library
?
It is possible to link your application with the Connector/C++ static library. This way there is no runtime dependency on the connector, and the resulting binary can run on systems where Connector/C++ is not installed.
Reading this, I thought this sounds exactly like what I want.
I made the following change to my CmakeLists.txt
find_library(MYSQL_LIBS NAMES mysqlcppconn-static PATHS ${MYSQL_DIR}/lib64)
However, trying to build with the static connector library I get the following errors about missing symbols. Any ideas why this is happening and how to fix it?
Scanning dependencies of target SQL
[ 50%] Building CXX object CMakeFiles/SQL.dir/main.cpp.o
[100%] Linking CXX executable SQL
Undefined symbols for architecture x86_64:
"_res_9_dn_expand", referenced from:
sql::mysql::srv_list(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short&) in libmysqlcppconn-static.a(mysql_connection.cpp.o)
"_res_9_nclose", referenced from:
sql::mysql::srv_list(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short&) in libmysqlcppconn-static.a(mysql_connection.cpp.o)
"_res_9_ninit", referenced from:
sql::mysql::srv_list(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short&) in libmysqlcppconn-static.a(mysql_connection.cpp.o)
"_res_9_ns_initparse", referenced from:
sql::mysql::srv_list(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short&) in libmysqlcppconn-static.a(mysql_connection.cpp.o)
"_res_9_ns_parserr", referenced from:
sql::mysql::srv_list(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short&) in libmysqlcppconn-static.a(mysql_connection.cpp.o)
"_res_9_nsearch", referenced from:
sql::mysql::srv_list(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short&) in libmysqlcppconn-static.a(mysql_connection.cpp.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [SQL] Error 1
make[1]: *** [CMakeFiles/SQL.dir/all] Error 2
make: *** [all] Error 2
Thank you all for your time.
Upvotes: 4
Views: 2341
Reputation: 43
As for the _res_9_dn_expand and associated errors, you also need to link with the "resolv" libraries. Add "-lresolv" to the linker command line. Try that before reading the rest of this.
As you correctly stated, if you want to build your application so that no extra files are necessary, you must link to the static libraries of MySQL, as well as the static libraries of everything MySQL needs. And to link properly, you will need to use the same OpenSSL libraries that were used to build the MySQL libraries.
There are two roads to take. Either get the same version of the static libraries of OpenSSL that MySQL used to build their ready-made libraries, or compile the MySQL libraries again with the version of OpenSSL that you have.
Just to add more confusion to the mix, the last time I did this the MySQL C++ Connector depends on the MySQL runtime 'C' libraries. I believe that is where the OpenSSL comes in to play. So if you go the "recompile everything" route, you may need to recompile more than just the C++ connector.
Upvotes: 1