From 83ce6317adb57265db9bba73e65f940f1f65e007 Mon Sep 17 00:00:00 2001 From: Ben Buchwald Date: Sun, 7 Mar 2021 23:41:04 -0500 Subject: [PATCH 1/2] Better support for building on Windows mysqlclient can be built against either the MySQL Connector/C or the MariaDB Connector/C. Previously, which library was used was hardcoded in setup_windows.py while the path to the library was in site.cfg. Now both settings can be specified in site.cfg, as environment variables, or auto-detected. If a client isn't specified but a connector path is, that path will be searched for either mariadbclient.lib or mysqlclient.lib to set the client type. If a client is specified but a connector path isn't, the default path used by the pre-built .msi installers will be assumed. This will probably be "C:\Program Files\MariaDB\MariaDB Connector C" for mariadbclient and "C:\Program Files\MySQL\MySQL Connector C 6.1" for mysqlclient ("C:\Program Files (x86)" will be used on 32-bit builds). If neither client nor connector are specified, both client types will be checked to see if the appropriate .lib file exists in the default connector directory. These changes will allow users to install from source via pip (if binary wheels aren't available) without having to clone this repo to edit site.cfg. They can either install one of the connectors in the default location or install it somewhere else and set the path in the `MYSQLCLIENT_CONNECTOR` environment variable before installing. One other slight change was to add additional install and library directories for mariadbclient. This is because the pre-built connector binaries install the needed files in `include` and `lib` whereas building from source (like this repo's workflow does) leaves them in `include/mariadb` and `lib/mariadb`. --- README.md | 16 +++++++++++++ setup_windows.py | 61 ++++++++++++++++++++++++++++++++++++++++++------ site.cfg | 3 ++- 3 files changed, 72 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 79617fd0..4dbc54d7 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,22 @@ Or when you have question about MySQL: Building mysqlclient on Windows is very hard. But there are some binary wheels you can install easily. +If binary wheels do not exist for your version of Python, it may be possible to +build from source, but if this does not work, **do not come asking for support.** +To build from source, download the +[MariaDB C Connector](https://mariadb.com/downloads/#connectors) and install +it. It must be installed in the default location +(usually "C:\Program Files\MariaDB\MariaDB Connector C" or +"C:\Program Files (x86)\MariaDB\MariaDB Connector C" for 32-bit). If you +build the connector yourself or install it in a different location, set the +environment variable `MYSQLCLIENT_CONNECTOR` before installing. Once you have +the connector installed and an appropriate version of Visual Studio for your +version of Python: + +``` +$ pip install mysqlclient +``` + ### macOS (Homebrew) Install MySQL and mysqlclient: diff --git a/setup_windows.py b/setup_windows.py index c25cc52b..6e50e0ac 100644 --- a/setup_windows.py +++ b/setup_windows.py @@ -3,21 +3,63 @@ from distutils.msvccompiler import get_build_version +def get_default_connector(client): + if client == "mariadbclient": + return os.path.join( + os.environ["ProgramFiles"], "MariaDB", "MariaDB Connector C" + ) + elif client == "mysqlclient": + return os.path.join( + os.environ["ProgramFiles"], "MySQL", "MySQL Connector C 6.1" + ) + else: + raise ValueError("Unknown client library") + + +def find_library(client, connector=None): + if not connector: + connector = get_default_connector(client) + paths = [] + if client == "mariadbclient": + paths.append(os.path.join(connector, "lib", "mariadb", client + ".lib")) + paths.append(os.path.join(connector, "lib", client + ".lib")) + elif client == "mysqlclient": + vcversion = int(get_build_version()) + paths.append(os.path.join(connector, "lib", "vs%d" % vcversion)) + else: + raise ValueError("Unknown client library") + for path in paths: + if os.path.exists(path): + return path + return None + + def get_config(): from setup_common import get_metadata_and_options, create_release_file metadata, options = get_metadata_and_options() - connector = options["connector"] + client = os.environ.get("MYSQLCLIENT_CLIENT", options.get("client")) + connector = os.environ.get("MYSQLCLIENT_CONNECTOR", options.get("connector")) - extra_objects = [] + if not client: + for client in ("mariadbclient", "mysqlclient"): + if find_library(client, connector): + break + else: + raise RuntimeError("Couldn't find MySQL or MariaDB Connector") - # client = "mysqlclient" - client = "mariadbclient" + if not connector: + connector = get_default_connector(client) + + extra_objects = [] vcversion = int(get_build_version()) if client == "mariadbclient": - library_dirs = [os.path.join(connector, "lib", "mariadb")] + library_dirs = [ + os.path.join(connector, "lib", "mariadb"), + os.path.join(connector, "lib"), + ] libraries = [ "kernel32", "advapi32", @@ -29,14 +71,19 @@ def get_config(): "bcrypt", client, ] - include_dirs = [os.path.join(connector, "include", "mariadb")] - else: + include_dirs = [ + os.path.join(connector, "include", "mariadb"), + os.path.join(connector, "include"), + ] + elif client == "mysqlclient": library_dirs = [ os.path.join(connector, r"lib\vs%d" % vcversion), os.path.join(connector, "lib"), ] libraries = ["kernel32", "advapi32", "wsock32", client] include_dirs = [os.path.join(connector, r"include")] + else: + raise ValueError("Unknown client library") extra_link_args = ["/MANIFEST"] diff --git a/site.cfg b/site.cfg index 6b4596a4..e9cbeb03 100644 --- a/site.cfg +++ b/site.cfg @@ -9,4 +9,5 @@ static = False # http://stackoverflow.com/questions/1972259/mysql-python-install-problem-using-virtualenv-windows-pip # Windows connector libs for MySQL. You need a 32-bit connector for your 32-bit Python build. -connector = C:\Program Files (x86)\MySQL\MySQL Connector C 6.1 +client = +connector = From 8d4929744e4b51f3b2b2d9e817feed858d9dcfb1 Mon Sep 17 00:00:00 2001 From: Ben Buchwald Date: Mon, 8 Mar 2021 00:26:14 -0500 Subject: [PATCH 2/2] Remove support for building against MySQL Connector/C on Windows MySQL Connector/C is not longer published since 2017. New builds are always done against MariaDB Connector/C. Dropping support for the deprecated MySQL Connector simplifies the Windows build process. --- setup_windows.py | 95 ++++++++++++------------------------------------ site.cfg | 1 - 2 files changed, 23 insertions(+), 73 deletions(-) diff --git a/setup_windows.py b/setup_windows.py index 6e50e0ac..b2feb7d2 100644 --- a/setup_windows.py +++ b/setup_windows.py @@ -1,37 +1,5 @@ import os import sys -from distutils.msvccompiler import get_build_version - - -def get_default_connector(client): - if client == "mariadbclient": - return os.path.join( - os.environ["ProgramFiles"], "MariaDB", "MariaDB Connector C" - ) - elif client == "mysqlclient": - return os.path.join( - os.environ["ProgramFiles"], "MySQL", "MySQL Connector C 6.1" - ) - else: - raise ValueError("Unknown client library") - - -def find_library(client, connector=None): - if not connector: - connector = get_default_connector(client) - paths = [] - if client == "mariadbclient": - paths.append(os.path.join(connector, "lib", "mariadb", client + ".lib")) - paths.append(os.path.join(connector, "lib", client + ".lib")) - elif client == "mysqlclient": - vcversion = int(get_build_version()) - paths.append(os.path.join(connector, "lib", "vs%d" % vcversion)) - else: - raise ValueError("Unknown client library") - for path in paths: - if os.path.exists(path): - return path - return None def get_config(): @@ -39,51 +7,34 @@ def get_config(): metadata, options = get_metadata_and_options() - client = os.environ.get("MYSQLCLIENT_CLIENT", options.get("client")) + client = "mariadbclient" connector = os.environ.get("MYSQLCLIENT_CONNECTOR", options.get("connector")) - - if not client: - for client in ("mariadbclient", "mysqlclient"): - if find_library(client, connector): - break - else: - raise RuntimeError("Couldn't find MySQL or MariaDB Connector") - if not connector: - connector = get_default_connector(client) + connector = os.path.join( + os.environ["ProgramFiles"], "MariaDB", "MariaDB Connector C" + ) extra_objects = [] - vcversion = int(get_build_version()) - if client == "mariadbclient": - library_dirs = [ - os.path.join(connector, "lib", "mariadb"), - os.path.join(connector, "lib"), - ] - libraries = [ - "kernel32", - "advapi32", - "wsock32", - "shlwapi", - "Ws2_32", - "crypt32", - "secur32", - "bcrypt", - client, - ] - include_dirs = [ - os.path.join(connector, "include", "mariadb"), - os.path.join(connector, "include"), - ] - elif client == "mysqlclient": - library_dirs = [ - os.path.join(connector, r"lib\vs%d" % vcversion), - os.path.join(connector, "lib"), - ] - libraries = ["kernel32", "advapi32", "wsock32", client] - include_dirs = [os.path.join(connector, r"include")] - else: - raise ValueError("Unknown client library") + library_dirs = [ + os.path.join(connector, "lib", "mariadb"), + os.path.join(connector, "lib"), + ] + libraries = [ + "kernel32", + "advapi32", + "wsock32", + "shlwapi", + "Ws2_32", + "crypt32", + "secur32", + "bcrypt", + client, + ] + include_dirs = [ + os.path.join(connector, "include", "mariadb"), + os.path.join(connector, "include"), + ] extra_link_args = ["/MANIFEST"] diff --git a/site.cfg b/site.cfg index e9cbeb03..08a14b0e 100644 --- a/site.cfg +++ b/site.cfg @@ -9,5 +9,4 @@ static = False # http://stackoverflow.com/questions/1972259/mysql-python-install-problem-using-virtualenv-windows-pip # Windows connector libs for MySQL. You need a 32-bit connector for your 32-bit Python build. -client = connector =