MySQL 连接器/C++ 8.0 开发人员指南  / 第 5 章构建连接器/C++ 应用程序  /  5.1 构建连接器/C++ 应用程序:一般注意事项

5.1 构建连接器/C++ 应用程序:一般注意事项

本节讨论构建连接器/C++ 应用程序时要牢记的一般注意事项。有关适用于特定平台的信息,请参阅 第 5.2 节“构建连接器/C++ 应用程序:特定于平台的注意事项”中适用于您的平台的部分。

此处显示的命令是从命令行给出的(例如,从 a 调用Makefile)。这些命令适用于支持 make和命令行构建工具(例如 g++ccclang )的任何平台,但可能需要针对您的构建环境进行调整。

构建工具和配置设置

用于构建 Connector/C++ 应用程序的工具与用于构建 Connector/C++ 本身的工具兼容非常重要。理想情况下,使用用于构建连接器/C++ 二进制文件的相同工具构建您的应用程序。

为避免出现问题,请确保这些因素对于您的应用程序和连接器/C++ 本身是相同的:

  • 编译器版本。

  • 运行时库。

  • 运行时链接器配置设置。

为避免潜在的崩溃,Connector/C++ 的构建配置应与使用它的应用程序的构建配置相匹配。例如,不要将 Connector/C++ 的发布版本与客户端应用程序的调试版本一起使用。

要使用不同的编译器版本、发布配置或运行时库,首先使用所需设置从源代码构建 Connector/C++(请参阅 第 4 章,从源代码安装 Connector/C++),然后使用相同的设置构建您的应用程序。

连接器/C++ 二进制分发包括一个 INFO_BIN文件,该文件描述用于构建分发的环境和配置选项。如果您从二进制分发版安装 Connector/C++ 并在某个平台上遇到与构建相关的问题,那么检查用于在该平台上构建分发版的设置可能会有所帮助。二进制发行版还包括一个 INFO_SRC文件,该文件提供有关产品版本和生成发行版的源存储库的信息。(在 Connector/C++ 8.0.14 之前,查找 BUILDINFO.txt而不是 INFO_BINand INFO_SRC。)

C++11 支持

X DevAPI 使用 C++11 语言特性。要编译使用 X DevAPI 的连接器/C++ 应用程序,请使用该-std=c++11选项在编译器中启用 C++11 支持。使用 X DevAPI for C(纯 C API)或遗留 JDBC API(基于纯 C++)的应用程序不需要此选项,除非应用程序代码使用 C++11。

连接器/C++ 头文件

应用程序使用的 API 决定了它应该包含哪些连接器/C++ 头文件。以下包含指令在包含路径包含 的假设下工作 $MYSQL_CPPCONN_DIR/include,其中 $MYSQL_CPPCONN_DIR是 Connector/C++ 安装位置。在编译器调用命令上传递一个-I $MYSQL_CPPCONN_DIR/include 选项以确保这一点。

  • 对于使用 X DevAPI 的应用程序:

    #include <mysqlx/xdevapi.h>
  • 对于使用 X DevAPI for C 的应用程序:

    #include <mysqlx/xapi.h>
  • 对于使用遗留 JDBC API 的应用程序,头文件依赖于版本:

    • 从 Connector/C++ 8.0.16 开始,一个 #include指令就足够了:

      #include <mysql/jdbc.h>
    • 在 Connector/C++ 8.0.16 之前,使用这组 #include指令:

      #include <jdbc/mysql_driver.h>
      #include <jdbc/mysql_connection.h>
      #include <jdbc/cppconn/*.h>

      该表示法<jdbc/cppconn/*.h> 意味着您应该包括 jdbc/cppconn应用程序所需的目录中的所有头文件。所需的特定文件取决于应用程序。

    • 使用 Connector/C++ 1.1 的遗留代码具有 #include以下形式的指令:

      #include <mysql_driver.h>
      #include <mysql_connection.h>
      #include <cppconn/*.h>

      要使用 Connector/C++ 8.0 构建此类代码而不修改它,请添加$MYSQL_CPPCONN_DIR/include/jdbc 到包含路径。

要编译您打算静态链接到 Connector/C++ 的代码,请定义一个宏来调整头文件中的 API 声明,以便与静态库一起使用。有关详细信息,请参阅 使用连接器/C++ 静态库

连接器/C++ 版本宏

从 Connector/C++ 8.0.30 开始,版本相关的宏定义在公共头文件中。宏的目的是提供一种系统地和可预测地维护连接器/C++ 产品版本编号的方法。下表描述了与版本相关的宏。

宏名称 描述
MYSQL_CONCPP_VERSION_MAJOR 产品版本号;目前 8
MYSQL_CONCPP_VERSION_MINOR 产品版本号;目前 00
MYSQL_CONCPP_VERSION_MICRO 产品版本微号;最初 30
MYSQL_CONCPP_VERSION_NUMBER 完整的连接器/C++ 版本号,其中包含主要、次要和微编号。例如,组合版本号 8000030表示 Connector/C++ 8.0.30。
笔记

这些宏维护的版本号仅适用于 Connector/C++ 产品,与单独处理的 API 或 ABI 版本无关。

使用 X DevAPI、X DevAPI for C 或遗留 JDBC API 的连接器/C++ 应用程序可以指定 MYSQL_CONCPP_VERSION_NUMBER宏以添加条件测试,以确定包含或排除功能依赖性,基于哪个连接器/C++ 版本引入了依赖性。例如,可以 MYSQL_CONCPP_VERSION_NUMBER在以下情况下使用宏:

  • 当 Connector/C++ 应用程序需要一个守卫来检查在指定版本之后引入的功能时。以下示例指定版本 8.0.32,它在公共头文件中定义了宏。当宏未定义时(使用 8.0.30 之前的头文件),相同的条件编译指令也有效,因为该值被视为 0。

    #if MYSQL_CONCPP_VERSION_NUMBER > 8000032
      // use some 8.0.32+ feature
    #endif
  • 当连接器/C++ 应用程序需要在指定版本之前引入的所有功能时。

    #if MYSQL_CONCPP_VERSION_NUMBER < 8000032
      // this usage is OK; it compiles with 8.0.31 and all previous versions
    #endif
  • 当使用 X DevAPI 的连接器/C++ 应用程序也使用 CharacterSet::utf8mb3枚举常量或任何新的utf8mb4 归类成员时。如果应用程序使用 8.0.30 之前的连接器编译,则可以保护这些新 API 元素的使用。

    #if MYSQL_CONCPP_VERSION_NUMBER >= 8000030
      if (CharacterSet::utf8mb3 == cs)
    #else
      if (CharacterSet::utf8 == cs)
    #endif
      {
        // cs is the id of the utf8 character set
      }
  • 当使用 X DevAPI 的连接器/C++ 应用程序需要检查utf8mb3字符集的名称或其任何排序规则时,还必须使用 8.0.30 之前的连接器进行编译。

    #if MYSQL_CONCPP_VERSION_NUMBER >= 8000030
      if ("utf8mb3" == characterSetName(cs))
    #else
      if ("utf8" == characterSetName(cs))
    #endif
      {
        // cs is the id of the utf8 character set
      }
    笔记

    或者,您可以与数字枚举常量值进行比较,无论连接器版本如何,它都应该有效。

  • 当使用遗留 JDBC API 的连接器/C++ 应用程序需要检查utf8mb3 字符集的名称或其任何排序规则时,它还必须使用 8.0.30 之前的连接器进行编译。

    #if MYSQL_CONCPP_VERSION_NUMBER >= 8000030
      if ("utf8mb3" == metadata->getColumnCharset(column))
    #else
      if ("utf8" == metadata->getColumnCharset(column))
    #endif
      {
        // column is the column index using the utf8 character set
      }

不要使用MYSQL_CONCPP_VERSION_NUMBER 宏来检查早于 Connector/C++ 8.0.30 的版本,这会产生不可靠的结果。例如:

#if MYSQL_CONCPP_VERSION_NUMBER > 8000028
  // this does not compile the with 8.0.29 connector!
#endif

#if MYSQL_CONCPP_VERSION_NUMBER < 8000028
  // this compiles with the 8.0.29 connector!
#endif

升压头文件

在这些情况下需要 Boost 头文件:

  • 在 Connector/C++ 8.0.16 之前,在 Unix 和类 Unix 平台上使用 X DevAPI 或 X DevAPI for C 的应用程序,如果您使用gcc构建并且系统上的 C++ 标准库版本未实现 UTF8 转换器( codecvt_utf8).

  • 在 Connector/C++ 8.0.23 之前,编译使用遗留 JDBC API 的 Connector/C++ 应用程序。

如果需要 Boost 头文件,则必须安装 Boost 1.59.0 或更新版本,并且必须将头文件的位置添加到包含路径中。要获取 Boost 及其安装说明,请访问官方 Boost 站点

链接库

使用 OpenSSL 构建连接器/C++ 使连接器库依赖于 OpenSSL 动态库。在这种情况下:

  • 将应用程序动态链接到 Connector/C++ 时,此依赖项仅在运行时相关。

  • 将应用程序静态链接到 Connector/C++ 时,还要链接到 OpenSSL 库。在 Linux 上,这意味着 -lssl -lcrypto显式添加到编译/链接命令。在 Windows 上,这是自动处理的。

在 Windows 上,链接到 C++ 运行时库的动态版本。

运行库

X DevAPI for C 应用程序libstdc++在运行时需要。根据您的平台或构建工具,可能会应用不同的库。例如,库 libc++在 macOS 上;参见 第 5.2.2 节,“macOS 注释”

如果应用程序是使用动态链接库构建的,那么这些库不仅必须存在于构建主机上,还必须存在于应用程序运行的目标主机上。必须正确配置动态链接器以查找这些库及其运行时依赖项,以及查找连接器/C++ 库及其运行时依赖项。

Oracle 构建的连接器/C++ 库依赖于 OpenSSL 库。后者必须安装在系统上才能运行链接到连接器/C++ 库的代码。另一种选择是将 OpenSSL 库放在与连接器/C++ 相同的位置,在这种情况下,动态链接器应该在连接器库旁边找到它们。另见 第 5.2.1 节,“Windows 注释”第 5.2.2 节,“macOS 注释”

笔记

从 Connector/C++ 8.0.28 开始不再支持 TLSv1 和 TLSv1.1 连接协议,这使得 TLSv1.2 成为最早支持的连接协议。

使用连接器/C++ 动态库

Connector/C++ 动态库名称取决于平台。这些库为 C 实现 X DevAPI 和 X DevAPI,其中 A库名称代表 ABI 版本:

  • libmysqlcppconn8.so.A (Unix)

  • libmysqlcppconn8.A.dylib (苹果系统)

  • mysqlcppconn8-A-vsNN.dll, 带导入库 (Windows) vsNN/mysqlcppconn8.lib

对于遗留的 JDBC API,动态库的命名方式如下,其中B库名代表 ABI 版本:

  • libmysqlcppconn.so.B (Unix)

  • libmysqlcppconn.B.dylib (苹果系统)

  • mysqlcppconn-B-vsNN.dll, 带导入库 (Windows) vsNN/mysqlcppconn-static.lib

在 Windows 上, 库名称中的值取决于用于构建库的 MSVC 工具链版本。(Oracle 提供的连接器/C++ 库使用 ,它们与 MSVC 2019 和 2017 兼容。)此约定允许在同一系统上使用使用不同版本的 MSVC 构建的库。另见 第 5.2.1 节,“Windows 注释”vsNNvs14

要构建使用 X DevAPI 或 X DevAPI for C 的代码,请添加 -lmysqlcppconn8到链接器选项。要构建使用遗留 JDBC API 的代码,请添加 -lmysqlcppconn.

您还必须通过指定适当的库目录来指示是使用 64 位库还是 32 位库。使用-L链接器选项指定 $MYSQL_CONCPP_DIR/lib64(64 位库)或 $MYSQL_CONCPP_DIR/lib(32 位库),$MYSQL_CPPCONN_DIRConnector/C++ 安装位置在哪里。在 FreeBSD 上,/lib64 不使用。库名称始终以 /lib.

要构建使用 X DevAPI 的连接器/C++ 应用程序,源代码位于 中app.cc,并动态链接到连接器库,Makefile可能如下所示:

MYSQL_CONCPP_DIR = Connector/C++ installation location
CPPFLAGS = -I $(MYSQL_CONCPP_DIR)/include -L $(MYSQL_CONCPP_DIR)/lib64
LDLIBS = -lmysqlcppconn8
CXXFLAGS = -std=c++11
app : app.cc

这样Makefile,命令 make app生成以下编译器调用:

g++ -std=c++11 -I .../include -L .../lib64 app.cc -lmysqlcppconn8 -o app

要构建一个使用 C 的 X DevAPI 的纯 C 应用程序,源代码位于 中app.c,并动态链接到连接器库,Makefile可能如下所示:

MYSQL_CONCPP_DIR = Connector/C++ installation location
CPPFLAGS = -I $(MYSQL_CONCPP_DIR)/include -L $(MYSQL_CONCPP_DIR)/lib64
LDLIBS = -lmysqlcppconn8
app : app.c

这样Makefile,命令 make app生成以下编译器调用:

cc -I .../include -L .../lib64 app.c -lmysqlcppconn8 -o app
笔记

生成的代码,即使它被编译为纯 C,也取决于 C++ 运行时(通常 libstdc++,这可能因平台或构建工具而异;请参阅 运行时库)。

要构建一个使用遗留 JDBC API 的纯 C++ 应用程序,源代码位于 中app.c,并动态链接到连接器库,Makefile 可能如下所示:

MYSQL_CONCPP_DIR = Connector/C++ installation location
CPPFLAGS = -I $(MYSQL_CONCPP_DIR)/include -L $(MYSQL_CONCPP_DIR)/lib64
LDLIBS = -lmysqlcppconn
app : app.c

在这种情况下,库选项是 -lmysqlcppcon,而不是 -lmysqlcppcon8X DevAPI 或 X DevAPI for C 应用程序。

这样Makefile,命令 make app生成以下编译器调用:

cc -I .../include -L .../lib64 app.c -lmysqlcppconn -o app
笔记

运行使用 Connector/C++ 动态库的应用程序时,动态链接器必须找到该库及其运行时依赖项。请参阅 运行时库

使用连接器/C++ 静态库

可以将您的应用程序与连接器/C++ 静态库链接起来。这样,连接器就没有运行时依赖性,生成的二进制文件可以在未安装连接器/C++ 的系统上运行。

笔记

即使在静态链接时,生成的代码仍然依赖于连接器/C++ 库的所有运行时依赖项。例如,如果 Connector/C++ 是使用 OpenSSL 构建的,则代码对 OpenSSL 库具有运行时依赖性。请参阅 运行时库

Connector/C++ 静态库名称取决于平台。这些库为 C 实现了 X DevAPI 和 X DevAPI:

  • libmysqlcppconn8-static.a(Unix、macOS)

  • vsNN/mysqlcppconn8-static.lib (视窗)

对于旧版 JDBC API,静态库的命名方式如下:

  • libmysqlcppconn-static.a(Unix、macOS)

  • vsNN/mysqlcppconn-static.lib (视窗)

在 Windows 上, 库名称中的值取决于用于构建库的 MSVC 工具链版本。(Oracle 提供的连接器/C++ 库使用 ,它们与 MSVC 2019 和 2017 兼容。)此约定允许在同一系统上使用使用不同版本的 MSVC 构建的库。另见 第 5.2.1 节,“Windows 注释”vsNNvs14

要编译您打算静态链接到 Connector/C++ 的代码,请定义一个宏来调整头文件中的 API 声明,以便与静态库一起使用。定义宏的一种方法是-D在编译器调用命令上传递一个选项:

  • 对于使用 X DevAPI、X DevAPI for C 或(自 Connector/C++ 8.0.16 起)遗留 JDBC API 的应用程序,定义 STATIC_CONCPP宏。重要的是你定义它;值无关紧要。例如: -DSTATIC_CONCPP

  • 在 Connector/C++ 8.0.16 之前,对于使用遗留 JDBC API 的应用程序,将CPPCONN_PUBLIC_FUNC 宏定义为空字符串。为确保这一点,请将宏定义为CPPCONN_PUBLIC_FUNC=,而不是 CPPCONN_PUBLIC_FUNC。例如: -DCPPCONN_PUBLIC_FUNC=

要构建使用 X DevAPI 的连接器/C++ 应用程序,源代码位于 中app.cc,并静态链接到连接器库,Makefile可能如下所示:

MYSQL_CONCPP_DIR = Connector/C++ installation location
CPPFLAGS = -DSTATIC_CONCPP -I $(MYSQL_CONCPP_DIR)/include
LDLIBS = $(MYSQL_CONCPP_DIR)/lib64/libmysqlcppconn8-static.a -lssl -lcrypto -lpthread
CXXFLAGS = -std=c++11
app : app.cc

这样Makefile,命令 make app生成以下编译器调用:

g++ -std=c++11 -DSTATIC_CONCPP -I .../include app.cc
  .../lib64/libmysqlcppconn8-static.a -lssl -lcrypto -lpthread -o app
笔记

为避免链接器报告未解析的符号,编译行必须包括 OpenSSL 库和 pthread连接器/C++ 代码所依赖的库。

如果在没有 OpenSSL 库的情况下构建 Connector/C++,则不需要它们,但 Oracle 构建的 Connector/C++ 分发版确实依赖于 OpenSSL。

连接器/C++ 库所需的库的确切列表取决于平台。例如,在 Solaris 上, socket可能需要 rt、 和 库。nsl

要构建一个使用 C 的 X DevAPI 的纯 C 应用程序,源代码位于 中app.c,并静态链接到连接器库,Makefile可能如下所示:

MYSQL_CONCPP_DIR = Connector/C++ installation location
CPPFLAGS = -DSTATIC_CONCPP -I $(MYSQL_CONCPP_DIR)/include
LDLIBS = $(MYSQL_CONCPP_DIR)/lib64/libmysqlcppconn8-static.a -lssl -lcrypto -lpthread
app : app.c

这样Makefile,命令 make app生成以下编译器调用:

cc -DSTATIC_CONCPP -I .../include app.c
  .../lib64/libmysqlcppconn8-static.a -lssl -lcrypto -lpthread -o app

要构建一个使用遗留 JDBC API 的纯 C 应用程序,源代码位于 中app.c,并静态链接到连接器库,Makefile 可能如下所示:

MYSQL_CONCPP_DIR = Connector/C++ installation location
CPPFLAGS = -DCPPCONN_PUBLIC_FUNC= -I $(MYSQL_CONCPP_DIR)/include
LDLIBS = $(MYSQL_CONCPP_DIR)/lib64/libmysqlcppconn-static.a -lssl -lcrypto -lpthread
app : app.c

本例中的库选项命名 为libmysqlcppcon-static.a,而不是 libmysqlcppcon8-static.aX DevAPI 或 X DevAPI for C 应用程序。

这样Makefile,命令 make app生成以下编译器调用:

cc -std=c++11 --DCPPCONN_PUBLIC_FUNC= -I .../include app.c
  .../lib64/libmysqlcppconn-static.a -lssl -lcrypto -lpthread -o app

在构建纯 C 代码时,重要的是要注意连接器对 C++ 运行时的依赖性,这是由连接器库引入的,即使使用它的代码是纯 C:

  • 一种方法是确保使用 C++ 链接器来构建最终代码。此处显示的采用了这种方法 Makefile

    MYSQL_CONCPP_DIR = Connector/C++ installation location
    CPPFLAGS = -DSTATIC_CONCPP -I $(MYSQL_CONCPP_DIR)/include
    LDLIBS = $(MYSQL_CONCPP_DIR)/lib64/libmysqlcppconn8-static.a -lssl -lcrypto -lpthread
    LINK.o = $(LINK.cc) # use C++ linker
    app : app.o

    这样Makefile,构建过程有两个步骤:首先 app.c使用普通 C 编译器编译应用程序源代码以生成app.o,然后使用 C++ 链接器链接最终的可执行文件 ( app),它负责处理对 C++ 运行时的依赖性。命令看起来像这样:

    cc -DSTATIC_CONCPP -I .../include -c -o app.o app.c
    g++ -DSTATIC_CONCPP -I .../include app.o
      .../libmysqlcppconn8-static.a -lssl -lcrypto -lpthread -o app
  • 另一种方法是使用普通的 C 编译器和链接器,但将libstdc++C++ 运行时库作为显式选项添加到链接器。此处显示的采用了这种方法Makefile

    MYSQL_CONCPP_DIR = Connector/C++ installation location
    CPPFLAGS = -DSTATIC_CONCPP -I $(MYSQL_CONCPP_DIR)/include
    LDLIBS = $(MYSQL_CONCPP_DIR)/lib64/libmysqlcppconn8-static.a -lssl -lcrypto -lpthread -lstdc++
    app : app.c

    有了它Makefile,编译器被调用如下:

    cc -DSTATIC_CONCPP -I .../include app.c
      .../libmysqlcppconn8-static.a -lssl -lcrypto -lpthread -lstdc++ -o app
笔记

即使使用 Connector/C++ 的应用程序是用普通 C 编写的,最终的可执行文件也取决于 C++ 运行时,它必须安装在应用程序运行的目标计算机上。