Skip to content

Commit

Permalink
Better support for building on Windows
Browse files Browse the repository at this point in the history
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`.
  • Loading branch information
sparkyb committed Mar 8, 2021
1 parent 24aaa72 commit e9dc5d4
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 8 deletions.
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
56 changes: 49 additions & 7 deletions setup_windows.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,60 @@
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",
Expand All @@ -29,14 +68,17 @@ 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"]

Expand Down
3 changes: 2 additions & 1 deletion site.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -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 =

0 comments on commit e9dc5d4

Please sign in to comment.