介绍

我决定将mysql作为一个自学C++的项目的一部分,因此由于缺乏知识,让我提前道歉。对我来说,链接,动态和静态库的概念仍然很新。顺便说一句,让我们继续。

我正在尝试从C++查询mysql服务器。理想情况下,我希望最终产品可以在任何架构上运行,并且对库的依赖关系尽可能少。我不希望我的代码的用户必须自己安装任何库(即Connector / C++)。我也想使用cmake来编译我的项目。

制备

为此,我将二进制文件用于

  • mysql-connector-c++-8.0.19-macos10.15-x86-64bit
  • mysql-8.0.19-macos10.15-x86_64(不确定是否有必要,但是mysql文档说使用JDBC连接到服务器需要mysqlserver附带的mysql-client)

  • 我从源代码构建了Boost,即使连接器二进制文件附带了ssl和crypto动态库,我还是使用brew来安装openssl。

    CmakeLists.txt

    我使用https://dev.mysql.com/doc/connector-cpp/8.0/en/connector-cpp-apps-macos-notes.htmlhttps://dev.mysql.com/doc/connector-cpp/8.0/en/connector-cpp-apps-general-considerations.html#connector-cpp-apps-link-libraries作为我的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)
    

    C++代码

    #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';
        }
    }
    

    结果与问题

    我使用cmake ..; cmake --build .构建我的项目。
    使用上面的内容,首先我得到了
    Scanning dependencies of target SQL
    [ 50%] Building CXX object CMakeFiles/SQL.dir/main.cpp.o
    [100%] Linking CXX executable SQL
    [100%] Built target SQL
    

    但是,为什么我尝试运行可执行文件却得到了
    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
    

    问题1

    如果将libssl和libcrypto从/usr/local/mysql-connector-c++-8.0.19/lib64复制到构建文件夹,则能够运行可执行文件。即使我已经使用find_library指定了ssl和crypto库的路径,为什么仍需要这样做呢?

    问题2



    读这篇文章,我认为这听起来完全像我想要的。

    我对CmakeLists.txt进行了以下更改find_library(MYSQL_LIBS NAMES mysqlcppconn-static PATHS ${MYSQL_DIR}/lib64)
    但是,尝试使用静态连接器库进行构建时,遇到有关丢失符号的以下错误。有什么想法为什么会发生以及如何解决?
    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
    

    谢谢您的时间。

    最佳答案

    至于_res_9_dn_expand和相关的错误,您还需要链接“resolv”库。在链接器命令行中添加“-lresolv”。在阅读其余内容之前,请先尝试一下。
    正确地说,如果要构建应用程序以使不需要其他文件,则必须链接到MySQL的静态库以及MySQL所需的所有静态库。为了正确链接,您将需要使用与构建MySQL库相同的OpenSSL库。
    有两条路可走。要么获得与MySQL用于构建其现成库的OpenSSL静态库相同的版本,要么使用您拥有的OpenSSL版本再次编译MySQL库。
    只是为了增加混乱,我上次执行此操作时,MySQL C++ Connector取决于MySQL运行时“C”库。我相信这就是OpenSSL发挥作用的地方。因此,如果您采用“重新编译所有内容”的方法,则可能不仅需要C++连接器,还需要重新编译。

    关于c++ - 在MacOS Catalina上使用CMake编译/链接mysql-connector-c++,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/60749953/

    10-11 06:45
    查看更多