cmake:用于搜索mysql的FindMySQL.cmake及bug溯源及修复
最近设计一个需要mysql的项目,构建项目的时候需要find_package
查找mysql 库安装位置,cmake默认没有提供mysql的find_package
支持.好在mysql官方是提供了,在github上mysql-connector-odbc
项目找到了FindMySQL.cmake
:
https://github.com/mysql/mysql-connector-odbc/blob/master/cmake/FindMySQL.cmake
有它就好办了。
CMakeLists中添加mysql库支持
在CMakeLists.txt 添加如下代码
# 查找 MySQL SDK
#set(MYSQLCLIENT_STATIC_LINKING true)
#set(FINDMYSQL_DEBUG true)
find_package(MySQL MODULE REQUIRED)
设置环境变量MYSQL_DIR
如下是FindMySQL.cmake源码中关于可选参数的说明:
##########################################################################
#
# Configuration variables, all optional, are
#
# MYSQL_DIR - Set in environment or as parameter to "cmake",
# this is the top directory of the MySQL Server or
# Connector/C install
# MYSQL_INCLUDE_DIR - Set in environment or as parameter to "cmake",
# this is the include directory where to find
# the client library
# MYSQL_LIB_DIR - Set in environment or as parameter to "cmake",
# this is the library directory where to find
# the client library
# MYSQLCLIENT_STATIC_LINKING
# - Specify that you want static linking, dynamic
# linking is the default
# MYSQLCLIENT_NO_THREADS
# - Specify to link against the single threaded
# library, "libmysqlclient". Note that in 5.5
# and up "libmysqlclient" is multithreaded and
# "libmysqlclient_r" just a soft link to it
# MYSQL_CONFIG_EXECUTABLE
# - "mysql_config" executable to use
# MYSQL_CXX_LINKAGE - Specify that client library needs C++ linking
# MYSQL_EXTRA_LIBRARIES
# - Libraries to add to the linkage
# MYSQL_CFLAGS - C compiler flags
# MYSQL_CXXFLAGS - C++ compiler flags
# MYSQL_LINK_FLAGS - User defined extra linkage flags
# FINDMYSQL_DEBUG - Set if want debug output from this script
通过上面的代码可知,FindMySQL
允许通过环境变量或参数MYSQL_DIR
来指定MySQL Server的安装位置。所以windows下可以通过如下脚本查找mysqld,计算mysql-server的安装位置,并设置MYSQL_DIR
环境变量,然后
where mysqld
if errorlevel 1 (echo mysqld NOT FOUND.exit /B -1
)
echo mysqld found
:: 获取mysql安装路径
FOR /F "delims=*" %%i in ('where mysqld') do set mysqld_bin=%%~dpi
::echo mysqld_bin=%mysqld_bin%
:: 删除最后的 '\'
set mysqld_bin=%mysqld_bin:~0,-1%
::echo mysqld_bin=%mysqld_bin%
for /f "delims=*" %%i in ("%mysqld_bin%") DO set MYSQL_DIR=%%~dpi
::echo MYSQL_DIR=%MYSQL_DIR%
:: 设置MYSQL_DIR环境变量
set MYSQL_DIR=%MYSQL_DIR:~0,-1%
echo MYSQL_DIR=%MYSQL_DIR%
执行
:: 生成Visual Studio 2015工程
cmake . -G "Visual Studio 14 2015 Win64"
如果执行成功就会看到如下输出
-- You will link dynamically to the MySQL client library (set with -DMYSQLCLIENT_STATIC_LINKING=<bool>)
-- Searching for dynamic libraries with the base name(s) "libmysql"
-- MYSQL_LIB_DIR_LIST =
-- MySQL client environment/cmake variables set that the user can override
-- MYSQL_DIR : D:/mysql-5.6.37-winx64
-- MYSQL_INCLUDE_DIR : D:/mysql-5.6.37-winx64/include
-- MYSQL_LIB_DIR : D:/mysql-5.6.37-winx64/lib
-- MYSQL_PLUGIN_DIR : D:/mysql-5.6.37-winx64/lib/plugin
-- MYSQL_CONFIG_EXECUTABLE :
-- MYSQL_CXX_LINKAGE :
-- MYSQL_CFLAGS :
-- MYSQL_CXXFLAGS :
-- MYSQLCLIENT_STATIC_LINKING :
-- MYSQLCLIENT_NO_THREADS :
-- MySQL client optional environment/cmake variables set by the user
-- MYSQL_EXTRA_LIBRARIES :
-- MYSQL_LINK_FLAGS :
-- MySQL client settings that the user can't override
-- MYSQL_VERSION : 5.6.37
-- MYSQL_VERSION_ID : 50637
-- MYSQL_LIB : D:/mysql-5.6.37-winx64/lib/libmysql.lib
-- MYSQL_LIBRARIES : mysql_sys;mysql_strings;D:/mysql-5.6.37-winx64/lib/libmysql.lib
BUG
然而事实上你会看到如下输出:
-- You will link dynamically to the MySQL client library (set with -DMYSQLCLIENT
_STATIC_LINKING=<bool>)
-- Searching for dynamic libraries with the base name(s) "libmysql"
CMake Error at cmake/Modules/FindMySQL.cmake:824 (message):Could not determine the MySQL Server version
Call Stack (most recent call first):src/CMakeLists.txt:8 (find_package)
Could not determine the MySQL Server version
出错啦!
同样的代码在linux下却是正常的。
这可是官方提供的FindMySQL.cmake
脚本哦,难道有Bug?
问题溯源
进一步阅读FindMySQL.cmake
的源码,找到如下位置
if(MYSQL_INCLUDE_DIR AND NOT MYSQL_VERSION)# Write the C source file that will include the MySQL headersset(GETMYSQLVERSION_SOURCEFILE "${CMAKE_CURRENT_BINARY_DIR}/getmysqlversion.c")file(WRITE "${GETMYSQLVERSION_SOURCEFILE}""#include <mysql.h>\n""#include <stdio.h>\n""int main() {\n"" printf(\"%s\", MYSQL_SERVER_VERSION);\n""}\n")# Compile and run the created executable, store output in MYSQL_VERSIONtry_run(_run_result _compile_result"${CMAKE_BINARY_DIR}""${GETMYSQLVERSION_SOURCEFILE}"CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${MYSQL_INCLUDE_DIR}"RUN_OUTPUT_VARIABLE MYSQL_VERSION)if(FINDMYSQL_DEBUG)if(NOT _compile_result)message("DBG: Could not compile \"getmysqlversion.c\"")endif()if(_run_result)message("DBG: Running \"getmysqlversion\" returned ${_run_result}")endif()endif()endif()
可以看到FindMySQL.cmake
为了获取mysql版本号,临时生成了一个getmysqlversion.c文件编译并执行它,通过getmysqlversion.exe的输出获取msyql.h
中定义的MYSQL_SERVER_VERSION
。
getmysqlversion.c
#include <mysql.h>
#include <stdio.h>
int main() {printf("%s", MYSQL_SERVER_VERSION);
}
于是我在cmake生成的工程文件中找到getmysqlversion.c,在命令行对它用MSVC的cl编译器进行编译
cl getmysqlversion.c /I d:\mysql-5.6.37-winx64\include
果然报错了
用于 x64 的 Microsoft (R) C/C++ 优化编译器 19.00.24215.1 版
版权所有(C) Microsoft Corporation。保留所有权利。getmysqlversion.c
d:\mysql-5.6.37-winx64\include\mysql_com.h(321): error C2061: 语法错误: 标识符“
SOCKET”
d:\mysql-5.6.37-winx64\include\mysql_com.h(365): error C2059: 语法错误:“}”
d:\mysql-5.6.37-winx64\include\mysql_com.h(482): error C2143: 语法错误: 缺少“)”(在“*”的前面)
d:\mysql-5.6.37-winx64\include\mysql_com.h(482): error C2143: 语法错误: 缺少“{”(在“*”的前面)
d:\mysql-5.6.37-winx64\include\mysql_com.h(482): error C2371: “Vio”: 重定义;不同的基类型
d:\mysql-5.6.37-winx64\include\mysql_com.h(307): note: 参见“Vio”的声明
d:\mysql-5.6.37-winx64\include\mysql_com.h(482): error C2143: 语法错误: 缺少“;”(在“*”的前面)
d:\mysql-5.6.37-winx64\include\mysql_com.h(482): error C2059: 语法错误:“)”
d:\mysql-5.6.37-winx64\include\mysql_com.h(483): error C2143: 语法错误: 缺少“)”(在“*”的前面)
d:\mysql-5.6.37-winx64\include\mysql_com.h(483): error C2143: 语法错误: 缺少“{”(在“*”的前面)
....
d:\mysql-5.6.37-winx64\include\mysql.h(404): fatal error C1003: 错误计数超过 100;正在停止编译
进一步分析mysql.h
的源码,及MYSQL_SERVER_VERSION
宏定义的位置,发现MYSQL_SERVER_VERSION
其实定义在mysq_version.h
中,而报错则与mysql_version.h
不相关的mysql_com.h
。所以实际上只需要include mysql_version.h
将#include <mysql.h>
改为#include <mysql_version.h>
则编译成功
getmysqlversion.c
#include <mysql_version.h>
#include <stdio.h>
int main() {printf("%s", MYSQL_SERVER_VERSION);
}
>cl getmysqlversion.c /I d:\mysql-5.6.37-winx64\include
用于 x64 的 Microsoft (R) C/C++ 优化编译器 19.00.24215.1 版
版权所有(C) Microsoft Corporation。保留所有权利。getmysqlversion.c
Microsoft (R) Incremental Linker Version 14.00.24215.1
Copyright (C) Microsoft Corporation. All rights reserved./out:getmysqlversion.exe
getmysqlversion.objJ:\mysql-listener\project.vs2015\src>getmysqlversion.exe
5.6.37
哈哈,果然是个bug,于是将FindMySQL.cmake
中对应的代码修改为,
file(WRITE "${GETMYSQLVERSION_SOURCEFILE}""#include <mysql_version.h>\n""#include <stdio.h>\n""int main() {\n"" printf(\"%s\", MYSQL_SERVER_VERSION);\n""}\n")
再执行就会看到成功输出了
:: 生成Visual Studio 2015工程
cmake . -G "Visual Studio 14 2015 Win64"
Pull Request
上面的修改已经向mysql-connector-odbc官方提交PR:
https://github.com/mysql/mysql-connector-odbc/pull/8
如果被批准,则你可以从https://github.com/mysql/mysql-connector-odbc/blob/master/cmake/FindMySQL.cmake下载修复后的脚本,
否则要自己修改,或从https://gitee.com/l0km/mysql-listener/blob/master/cmake/Modules/FindMySQL.cmake下载修复后的脚本
cmake:用于搜索mysql的FindMySQL.cmake及bug溯源及修复相关推荐
- centos cmake安装mysql_CentOS下使用cmake编译安装mysql
一.下载安装所必需的依赖包 1.因为高版本mysql都用cmake安装,所以下载cmake wget http://www.cmake.org/files/v3.0/cmake-3.0.1.tar.g ...
- linux启动mysql1820_linux mysql二进制不用Cmake安装方法
二进制安装 (先用yum 安装一下 numactl.本人用虚拟机的时候会如果没有安装 numactl 在初始化的时候出错 所有会先执行一下yum install numactl ) 1.添加mysql ...
- cmake 编译mysql_CentOS5.6下使用cmake编译MySQL5.5.13源码和安装
一.准备环境 1. 安装确保以下系统相关库文件 gcc gcc-c++ autoconf automake zlib* libxml* ncurses-devel libmcrypt* libt ...
- 【CMake】Android Studio 中使用 CMake 编译单个 C++ 源文件 ( 常用的 CMake 命令解析 )
文章目录 一.Android Studio 中使用 CMake 编译单个 C++ 源文件 二.cmake_minimum_required 命令设置最小 CMake 版本 三.project 命令设置 ...
- 现代 CMake 简明教程(一)- CMake 基础
系列文章目录 现代 CMake 简明教程(一)- CMake 基础 现代 CMake 简明教程(二)- 设计理念与使用 文章目录 系列文章目录 前言 CMake 基础 1. Modern CMake ...
- android cmake 打印_Android NDK 开发:CMake 使用
1. 前言 当在做 Android NDK 开发时,如果不熟悉用 CMake 来构建,读不懂 CMakeLists.txt 的配置脚本,很容易就会踩坑,遇到编译失败,一个很小的配置问题都会浪费很多时间 ...
- C++ CMake入门和进阶(二):CMake语法
CMake也是有语法的,这里总结一些.CMake系列学习个人笔记: C++ CMake入门和进阶(一):使用CMake编译项目 文章目录 输出 message 分支 if/elseif/else/en ...
- cmake:在各级目录之间共享变量(cmake cache变量)
摘要: 本文记录一下 CMake 变量的定义.原理及其使用.CMake 变量包含 Normal Variables.Cache Variables.通过 set 指令可以设置两种不同的变量.也可以在 ...
- cmake could not find openssl_使用CMake构建C++项目
背景 现代CMake如今开始转向使用targets和properties,比如下面文章介绍的这样: https://pabloariasal.github.io/2018/02/19/its-time ...
最新文章
- 2019年,人工智能要落地,更要小心被“摔死”
- androidexternal目录下新增一个可执行应用及编译
- 8、 IS NULL:空值查询
- MySQL创建索引跳过redo_明明我建了索引,为什么sql执行的还是这么慢?
- C# datetime 操作
- php poi,GitHub - satthi/poi-php: poi-php
- python打印九九加法表_Python小脚本
- php getfullyear,getYear、getFullYear和getUTCFullYear三者的区别
- 运行gclient一直没反应_安川变频器通电没反应维修措施分享
- JAVA minaio模型_Mina的线程模型
- 矩阵乘法c语言蓝桥杯,[蓝桥杯]ALGO-86.算法训练_矩阵乘法
- selenium的三种等待方式
- STM32F103ZET6+红外温度传感器mlx90614芯片
- Navcat无法连接mysql报错1449
- 自制模仿谷歌搜索UI的网页
- JavaScript通过extend和super实现继承
- Jupyter内的文件保存
- Android中百度地图基础实现,定位
- Spring Boot配置(一)
- C指针之指针与数组的天生姻缘