diff --git a/.gitignore b/.gitignore index 1f4b237cf7e..e2ee588a11b 100644 --- a/.gitignore +++ b/.gitignore @@ -81,3 +81,5 @@ cover/ # Conda files # ############### __conda_version__.txt +lib/png.lib +lib/z.lib diff --git a/README.win.md b/README.win.md new file mode 100644 index 00000000000..6eab53d343c --- /dev/null +++ b/README.win.md @@ -0,0 +1,64 @@ +# Building on Windows + +There are a few possibilities to build matplotlib on Windows: + +* Wheels via [matplotlib-winbuild](https://github.com/jbmohler/matplotlib-winbuild) +* Wheels by using conda packages +* Conda packages + +## Wheel builds using conda packages + +This is a wheel build, but we use conda packages to get all the requirements. The binary +requirements (png, freetype,...) are statically linked and therefore not needed during the wheel +install. + +The commands below assume that you can compile a native python lib for the python version of your +choice. See [this howto](http://blog.ionelmc.ro/2014/12/21/compiling-python-extensions-on-windows/) +how to install and setup such environments. If in doubt: use python 3.5 as it mostly works +without fiddling with environment variables. + +``` sh +# create a new environment with the required packages +conda create -n "matplotlib_build" python=3.4 numpy python-dateutil pyparsing pytz tornado pyqt cycler tk libpng zlib freetype +activate matplotlib_build +# this package is only available in the conda-forge channel +conda install -c conda-forge msinttypes +# for python 2.7 +conda install -c conda-forge functools32 + +# copy the libs which have "wrong" names +set LIBRARY_LIB=%CONDA_DEFAULT_ENV%\Library\lib +mkdir lib || cmd /c "exit /b 0" +copy %LIBRARY_LIB%\zlibstatic.lib lib\z.lib +copy %LIBRARY_LIB%\libpng_static.lib lib\png.lib + +# Make the header files and the rest of the static libs available during the build +# CONDA_DEFAULT_ENV is a env variable which is set to the currently active environment path +set MPLBASEDIRLIST=%CONDA_DEFAULT_ENV%\Library\;. + +# build the wheel +python setup.py bdist_wheel +``` + +The `build_alllocal.cmd` script automates these steps if you already created and activated the conda environment. + + +## Conda packages + +This needs a [working installed C compiler](http://blog.ionelmc.ro/2014/12/21/compiling-python-extensions-on-windows/) +for the version of python you are compiling the package for but you don't need to setup the +environment variables. + +```sh +# only the first time... +conda install conda-build + +# the python version you want a package for... +set CONDA_PY=3.5 + +# builds the package, using a clean build environment +conda build ci\conda_recipe + +# install the new package +conda install --use-local matplotlib +``` diff --git a/appveyor.yml b/appveyor.yml index 202e26cb4d2..8f67174b668 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -# With infos from +# With infos from # http://tjelvarolsson.com/blog/how-to-continuously-test-your-python-code-on-windows-using-appveyor/ # https://packaging.python.org/en/latest/appveyor/ # https://github.com/rmcgibbo/python-appveyor-conda-example @@ -11,33 +11,31 @@ environment: # SDK v7.0 MSVC Express 2008's SetEnv.cmd script will fail if the # /E:ON and /V:ON options are not enabled in the batch script intepreter # See: http://stackoverflow.com/a/13751649/163740 - CMD_IN_ENV: "cmd /E:ON /V:ON /C .\\ci\\appveyor\\run_with_env.cmd" + CMD_IN_ENV: "cmd /E:ON /V:ON /C obvci_appveyor_python_build_env.cmd" + CONDA_INSTALL_LOCN: "C:\\conda" + # Workaround for https://github.com/conda/conda-build/issues/636 + PYTHONIOENCODING: "UTF-8" matrix: - - PYTHON: "C:\\Python34_64" - PYTHON_VERSION: "3.4" - PYTHON_ARCH: "64" - CONDA_PY: "34" - CONDA_NPY: "110" - - - PYTHON: "C:\\Python35_64" - PYTHON_VERSION: "3.5" - PYTHON_ARCH: "64" - CONDA_PY: "35" - CONDA_NPY: "110" - - - PYTHON: "C:\\Python27_64" - PYTHON_VERSION: "2.7" - PYTHON_ARCH: "64" + # for testing purpose: numpy 1.8 on py2.7, for the rest use 1.10/latest + - TARGET_ARCH: "x86" CONDA_PY: "27" CONDA_NPY: "18" - - - PYTHON: "C:\\Python27_32" PYTHON_VERSION: "2.7" - PYTHON_ARCH: "32" + - TARGET_ARCH: "x64" CONDA_PY: "27" CONDA_NPY: "18" - + PYTHON_VERSION: "2.7" + - TARGET_ARCH: "x64" + CONDA_PY: "34" + CONDA_NPY: "110" + PYTHON_VERSION: "3.4" + - TARGET_ARCH: "x64" + CONDA_PY: "35" + CONDA_NPY: "110" + PYTHON_VERSION: "3.5" + + # We always use a 64-bit machine, but can build x86 distributions # with the PYTHON_ARCH variable (which is used by CMD_IN_ENV). platform: @@ -47,25 +45,42 @@ platform: build: false init: - - "ECHO %PYTHON_VERSION% %PYTHON%" + - cmd: "ECHO %PYTHON_VERSION% %CONDA_INSTALL_LOCN%" install: - - powershell .\ci\appveyor\install.ps1 - - SET PATH=%PYTHON%;%PYTHON%\Scripts;%PATH% + - appveyor DownloadFile "https://raw.githubusercontent.com/pelson/Obvious-CI/master/bootstrap-obvious-ci-and-miniconda.py" + - cmd: python bootstrap-obvious-ci-and-miniconda.py %CONDA_INSTALL_LOCN% %TARGET_ARCH% %CONDA_PY:~0,1% --without-obvci + - cmd: set PATH=%CONDA_INSTALL_LOCN%;%CONDA_INSTALL_LOCN%\scripts;%PATH%; + - cmd: set PYTHONUNBUFFERED=1 + - cmd: conda install -c http://conda.anaconda.org/pelson/channel/development --yes --quiet obvious-ci + - cmd: obvci_install_conda_build_tools.py - cmd: conda config --set show_channel_urls yes # for msinttypes - cmd: conda config --add channels conda-forge # this is now the downloaded conda... - conda info -a - # same things as in tools/conda_recipe - - cmd: conda create -y -q -n test-environment python=%PYTHON_VERSION% pip setuptools numpy python-dateutil freetype=2.5 msinttypes tk pyparsing pytz tornado libpng zlib pyqt cycler nose mock + + # Fix the appveyor build environment to work with conda build + # workaround for missing vcvars64.bat in py34 64bit + - cmd: copy ci\appveyor\vcvars64.bat "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\amd64" + # workaround for conda build on py27 prefering the normal installed + # VS tools instead of the also installed Py27 VS compiler (which wouldn't need this workarounds...) + - cmd: copy "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\vcvars64.bat" "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\amd64\vcvarsamd64.bat" + + # same things as the requirements in ci/conda_recipe/meta.yaml + - cmd: conda create -y -q -n test-environment python=%PYTHON_VERSION% pip setuptools numpy python-dateutil freetype msinttypes tk pyparsing pytz tornado libpng zlib pyqt cycler nose mock - activate test-environment - # This is needed for the installer to find the dlls... + - cmd: echo %PYTHON_VERSION% %TARGET_ARCH% + - cmd: IF %PYTHON_VERSION% == 2.7 conda install -y functools32 + + # Let the install prefer the static builds of the libs - set LIBRARY_LIB=%CONDA_DEFAULT_ENV%\Library\lib - cmd: 'mkdir lib || cmd /c "exit /b 0"' - - copy %LIBRARY_LIB%\zlibstatic.lib lib\z.lib + - copy %LIBRARY_LIB%\zlibstatic.lib lib\z.lib - copy %LIBRARY_LIB%\libpng_static.lib lib\png.lib - set MPLBASEDIRLIST=%CONDA_DEFAULT_ENV%\Library\;. + # enables the local freetype build + - copy ci\travis\setup.cfg . # Show the installed packages + versions - conda list @@ -78,27 +93,39 @@ test_script: after_test: # After the tests were a success, build packages (wheels and conda) - - # There is a bug in wheels which prevents building wheels when the package uses namespaces - - cmd: '%CMD_IN_ENV% python setup.py bdist_wheel' - # Note also that our setup.py script, which is called by conda-build, writes - # a __conda_version__.txt file, so the version number on the binary package - # is set dynamically. This unfortunately mean that conda build --output - # doesn't really work. + + # Build the wheel + # Hide the output, the copied files really clutter the build log... + - cmd: '%CMD_IN_ENV% python setup.py bdist_wheel > NUL:' + + # And now the conda build after a cleanup... + # cleanup build files so that they don't pollute the conda build but keep the wheel in dist... + - cmd: git clean -d -x -f -e dist/ + # cleanup the environment so that the test-environment does not leak into the conda build... + - cmd: set MPLBASEDIRLIST= + - cmd: set LIBRARY_LIB= + - cmd: deactivate + - cmd: path + - cmd: where python - cmd: '%CMD_IN_ENV% conda config --get channels' - # we can't build conda packages on 27 due to missing functools32, which is a recent - # additional dependency for matplotlib - - cmd: if [%CONDA_PY%] NEQ [27] %CMD_IN_ENV% conda build .\ci\conda_recipe + - cmd: '%CMD_IN_ENV% conda build .\ci\conda_recipe' + # Move the conda package into the dist directory, to register it - # as an "artifact" for Appveyor. - - cmd: 'copy /Y %PYTHON%\conda-bld\win-32\*.bz2 dist || cmd /c "exit /b 0"' - - cmd: 'copy /Y %PYTHON%\conda-bld\win-64\*.bz2 dist || cmd /c "exit /b 0"' - - cmd: dir .\dist\ + # as an "artifact" for Appveyor. + - cmd: 'copy /Y %CONDA_INSTALL_LOCN%\conda-bld\win-32\*.bz2 dist || cmd /c "exit /b 0"' + - cmd: 'copy /Y %CONDA_INSTALL_LOCN%\conda-bld\win-64\*.bz2 dist || cmd /c "exit /b 0"' + - cmd: dir dist\ + - cmd: echo finished... artifacts: - path: dist\* name: packages - + - path: result_images\* - name: test result images + name: result_images type: zip + +on_failure: + - echo zipping images after a failure... + - 7z a result_images.zip result_images\ >NUL: + - appveyor PushArtifact result_images.zip diff --git a/build_alllocal.cmd b/build_alllocal.cmd new file mode 100644 index 00000000000..37560d1830d --- /dev/null +++ b/build_alllocal.cmd @@ -0,0 +1,34 @@ +:: This assumes you have installed all the dependencies via conda packages: +:: # create a new environment with the required packages +:: conda create -n "matplotlib_build" python=3.4 numpy python-dateutil pyparsing pytz tornado pyqt cycler tk libpng zlib freetype +:: activate matplotlib_build +:: # this package is only available in the conda-forge channel +:: conda install -c conda-forge msinttypes +:: if you build on py2.7: +:: conda install -c conda-forge functools32 + +set TARGET=bdist_wheel +IF [%1]==[] ( + echo Using default target: %TARGET% +) else ( + set TARGET=%1 + echo Using user supplied target: %TARGET% +) + +IF NOT DEFINED CONDA_DEFAULT_ENV ( + echo No Conda env activated: you need to create a conda env with the right packages and activate it! + GOTO:eof +) + +:: copy the libs which have "wrong" names +set LIBRARY_LIB=%CONDA_DEFAULT_ENV%\Library\lib +mkdir lib || cmd /c "exit /b 0" +copy %LIBRARY_LIB%\zlibstatic.lib lib\z.lib +copy %LIBRARY_LIB%\libpng_static.lib lib\png.lib + +:: Make the header files and the rest of the static libs available during the build +:: CONDA_DEFAULT_ENV is a env variable which is set to the currently active environment path +set MPLBASEDIRLIST=%CONDA_DEFAULT_ENV%\Library\;. + +:: build the target +python setup.py %TARGET% diff --git a/ci/appveyor/install.ps1 b/ci/appveyor/install.ps1 deleted file mode 100644 index c964973c676..00000000000 --- a/ci/appveyor/install.ps1 +++ /dev/null @@ -1,96 +0,0 @@ -# Sample script to install Miniconda under Windows -# Authors: Olivier Grisel, Jonathan Helmus and Kyle Kastner, Robert McGibbon -# License: CC0 1.0 Universal: http://creativecommons.org/publicdomain/zero/1.0/ - -$MINICONDA_URL = "http://repo.continuum.io/miniconda/" - - -function DownloadMiniconda ($python_version, $platform_suffix) { - $webclient = New-Object System.Net.WebClient - if ($python_version -match "3.4") { - $filename = "Miniconda3-latest-Windows-" + $platform_suffix + ".exe" - } else { - $filename = "Miniconda-latest-Windows-" + $platform_suffix + ".exe" - } - $url = $MINICONDA_URL + $filename - - $basedir = $pwd.Path + "\" - $filepath = $basedir + $filename - if (Test-Path $filename) { - Write-Host "Reusing" $filepath - return $filepath - } - - # Download and retry up to 3 times in case of network transient errors. - Write-Host "Downloading" $filename "from" $url - $retry_attempts = 2 - for($i=0; $i -lt $retry_attempts; $i++){ - try { - $webclient.DownloadFile($url, $filepath) - break - } - Catch [Exception]{ - Start-Sleep 1 - } - } - if (Test-Path $filepath) { - Write-Host "File saved at" $filepath - } else { - # Retry once to get the error message if any at the last try - $webclient.DownloadFile($url, $filepath) - } - return $filepath -} - - -function InstallMiniconda ($python_version, $architecture, $python_home) { - Write-Host "Installing Python" $python_version "for" $architecture "bit architecture to" $python_home - if (Test-Path $python_home) { - Write-Host $python_home "already exists, skipping." - return $false - } - if ($architecture -match "32") { - $platform_suffix = "x86" - } else { - $platform_suffix = "x86_64" - } - - $filepath = DownloadMiniconda $python_version $platform_suffix - Write-Host "Installing" $filepath "to" $python_home - $install_log = $python_home + ".log" - $args = "/S /D=$python_home" - Write-Host $filepath $args - Start-Process -FilePath $filepath -ArgumentList $args -Wait -Passthru - if (Test-Path $python_home) { - Write-Host "Python $python_version ($architecture) installation complete" - } else { - Write-Host "Failed to install Python in $python_home" - Get-Content -Path $install_log - Exit 1 - } -} - - -function InstallCondaPackages ($python_home, $spec) { - $conda_path = $python_home + "\Scripts\conda.exe" - $args = "install --yes " + $spec - Write-Host ("conda " + $args) - Start-Process -FilePath "$conda_path" -ArgumentList $args -Wait -Passthru -} - -function UpdateConda ($python_home) { - $conda_path = $python_home + "\Scripts\conda.exe" - Write-Host "Updating conda..." - $args = "update --yes conda" - Write-Host $conda_path $args - Start-Process -FilePath "$conda_path" -ArgumentList $args -Wait -Passthru -} - - -function main () { - InstallMiniconda $env:PYTHON_VERSION $env:PYTHON_ARCH $env:PYTHON - UpdateConda $env:PYTHON - InstallCondaPackages $env:PYTHON "conda-build jinja2 anaconda-client" -} - -main diff --git a/ci/appveyor/run_with_env.cmd b/ci/appveyor/run_with_env.cmd deleted file mode 100644 index 848f4608c86..00000000000 --- a/ci/appveyor/run_with_env.cmd +++ /dev/null @@ -1,95 +0,0 @@ -:: EXPECTED ENV VARS: PYTHON_ARCH (either x86 or x64) -:: CONDA_PY (either 27, 33, 35 etc. - only major version is extracted) -:: -:: -:: To build extensions for 64 bit Python 3, we need to configure environment -:: variables to use the MSVC 2010 C++ compilers from GRMSDKX_EN_DVD.iso of: -:: MS Windows SDK for Windows 7 and .NET Framework 4 (SDK v7.1) -:: -:: To build extensions for 64 bit Python 2, we need to configure environment -:: variables to use the MSVC 2008 C++ compilers from GRMSDKX_EN_DVD.iso of: -:: MS Windows SDK for Windows 7 and .NET Framework 3.5 (SDK v7.0) -:: -:: 32 bit builds, and 64-bit builds for 3.5 and beyond, do not require specific -:: environment configurations. -:: -:: Note: this script needs to be run with the /E:ON and /V:ON flags for the -:: cmd interpreter, at least for (SDK v7.0) -:: -:: More details at: -:: https://github.com/cython/cython/wiki/64BitCythonExtensionsOnWindows -:: http://stackoverflow.com/a/13751649/163740 -:: -:: Author: Phil Elson -:: Original Author: Olivier Grisel (https://github.com/ogrisel/python-appveyor-demo) -:: License: CC0 1.0 Universal: http://creativecommons.org/publicdomain/zero/1.0/ -:: -:: Notes about batch files for Python people: -:: -:: Quotes in values are literally part of the values: -:: SET FOO="bar" -:: FOO is now five characters long: " b a r " -:: If you don't want quotes, don't include them on the right-hand side. -:: -:: The CALL lines at the end of this file look redundant, but if you move them -:: outside of the IF clauses, they do not run properly in the SET_SDK_64==Y -:: case, I don't know why. -:: originally from https://github.com/pelson/Obvious-CI/blob/master/scripts/obvci_appveyor_python_build_env.cmd -@ECHO OFF - -SET COMMAND_TO_RUN=%* -SET WIN_SDK_ROOT=C:\Program Files\Microsoft SDKs\Windows - -:: Extract the major and minor versions, and allow for the minor version to be -:: more than 9. This requires the version number to have two dots in it. -SET MAJOR_PYTHON_VERSION=%CONDA_PY:~0,1% - -IF "%CONDA_PY:~2,1%" == "" ( - :: CONDA_PY style, such as 27, 34 etc. - SET MINOR_PYTHON_VERSION=%CONDA_PY:~1,1% -) ELSE ( - IF "%CONDA_PY:~3,1%" == "." ( - SET MINOR_PYTHON_VERSION=%CONDA_PY:~2,1% - ) ELSE ( - SET MINOR_PYTHON_VERSION=%CONDA_PY:~2,2% - ) -) - -:: Based on the Python version, determine what SDK version to use, and whether -:: to set the SDK for 64-bit. -IF %MAJOR_PYTHON_VERSION% == 2 ( - SET WINDOWS_SDK_VERSION="v7.0" - SET SET_SDK_64=Y -) ELSE ( - IF %MAJOR_PYTHON_VERSION% == 3 ( - SET WINDOWS_SDK_VERSION="v7.1" - IF %MINOR_PYTHON_VERSION% LEQ 4 ( - SET SET_SDK_64=Y - ) ELSE ( - SET SET_SDK_64=N - ) - ) ELSE ( - ECHO Unsupported Python version: "%MAJOR_PYTHON_VERSION%" - EXIT /B 1 - ) -) - -IF "%PYTHON_ARCH%"=="64" ( - IF %SET_SDK_64% == Y ( - ECHO Configuring Windows SDK %WINDOWS_SDK_VERSION% for Python %MAJOR_PYTHON_VERSION% on a 64 bit architecture - SET DISTUTILS_USE_SDK=1 - SET MSSdk=1 - "%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Setup\WindowsSdkVer.exe" -q -version:%WINDOWS_SDK_VERSION% - "%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Bin\SetEnv.cmd" /x64 /release - ECHO Executing: %COMMAND_TO_RUN% - call %COMMAND_TO_RUN% || EXIT /B 1 - ) ELSE ( - ECHO Using default MSVC build environment for 64 bit architecture - ECHO Executing: %COMMAND_TO_RUN% - call %COMMAND_TO_RUN% || EXIT /B 1 - ) -) ELSE ( - ECHO Using default MSVC build environment for 32 bit architecture - ECHO Executing: %COMMAND_TO_RUN% - call %COMMAND_TO_RUN% || EXIT /B 1 -) diff --git a/ci/appveyor/vcvars64.bat b/ci/appveyor/vcvars64.bat new file mode 100644 index 00000000000..c4659becc3a --- /dev/null +++ b/ci/appveyor/vcvars64.bat @@ -0,0 +1 @@ +CALL "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x64 \ No newline at end of file diff --git a/ci/conda_recipe/bld.bat b/ci/conda_recipe/bld.bat index fb7909de336..bd38d0bb372 100644 --- a/ci/conda_recipe/bld.bat +++ b/ci/conda_recipe/bld.bat @@ -1,19 +1,12 @@ -mkdir lib -copy %LIBRARY_LIB%\zlibstatic.lib lib\z.lib -if errorlevel 1 exit 1 -copy %LIBRARY_LIB%\libpng_static.lib lib\png.lib -if errorlevel 1 exit 1 - -set MPLBASEDIRLIST=%LIBRARY_PREFIX%;. +set LIBPATH=%LIBRARY_LIB%; +set INCLUDE=%INCLUDE%;%PREFIX%\Library\include\freetype2 -:: debug... -set +ECHO [directories] > setup.cfg +ECHO basedirlist = %LIBRARY_PREFIX% >> setup.cfg +ECHO [packages] >> setup.cfg +ECHO tests = False >> setup.cfg +ECHO sample_data = False >> setup.cfg +ECHO toolkits_tests = False >> setup.cfg -copy setup.cfg.template setup.cfg +%PYTHON% setup.py install if errorlevel 1 exit 1 - -python setup.py install -if errorlevel 1 exit 1 - -rd /s /q %SP_DIR%\dateutil -rd /s /q %SP_DIR%\numpy diff --git a/ci/conda_recipe/build.sh b/ci/conda_recipe/build.sh index c9ff280da80..d4d2f60fab2 100644 --- a/ci/conda_recipe/build.sh +++ b/ci/conda_recipe/build.sh @@ -7,17 +7,31 @@ if [ `uname` == Linux ]; then popd fi +cat < setup.cfg +[directories] +basedirlist = $PREFIX + +[packages] +tests = False +toolkit_tests = False +sample_data = False + +EOF + +# The macosx backend isn't building with conda at this stage. if [ `uname` == Darwin ]; then - sed s:'#ifdef WITH_NEXT_FRAMEWORK':'#if 1':g -i src/_macosx.m +cat << EOF >> setup.cfg + +[gui_support] +tkagg = true +macosx = false + +EOF fi -cp setup.cfg.template setup.cfg || exit 1 +cat setup.cfg +sed -i.bak "s|/usr/local|$PREFIX|" setupext.py -sed s:/usr/local:$PREFIX:g -i setupext.py $PYTHON setup.py install -rm -rf $SP_DIR/PySide -rm -rf $SP_DIR/__pycache__ -rm -rf $PREFIX/bin/nose* - diff --git a/ci/conda_recipe/cfg_notests.patch b/ci/conda_recipe/cfg_notests.patch deleted file mode 100644 index e47f9d1619d..00000000000 --- a/ci/conda_recipe/cfg_notests.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git setup.cfg.template setup.cfg.template -index 09fd92f..2085832 100644 ---- setup.cfg.template -+++ setup.cfg.template -@@ -18,7 +18,7 @@ - # optional. They are all installed by default, but they may be turned - # off here. - # --#tests = True -+tests = False - #sample_data = True - #toolkits = True - # Tests for the toolkits are only automatically installed \ No newline at end of file diff --git a/ci/conda_recipe/cfg_qt4agg.patch b/ci/conda_recipe/cfg_qt4agg.patch index 2403b9149fd..16e6fc6c393 100644 --- a/ci/conda_recipe/cfg_qt4agg.patch +++ b/ci/conda_recipe/cfg_qt4agg.patch @@ -1,11 +1,13 @@ diff --git setup.cfg.template setup.cfg.template -index 8af8b6d..4e4f9d2 100644 +index cae6f67..fd11c79 100644 --- setup.cfg.template +++ setup.cfg.template -@@ -78,5 +78,5 @@ +@@ -88,7 +88,7 @@ # if you have disabled the relevent extension modules. Agg will be used # by default. # -#backend = Agg +backend = Qt4Agg # + + [package_data] diff --git a/ci/conda_recipe/meta.yaml b/ci/conda_recipe/meta.yaml index 16101f30131..21f275de3da 100644 --- a/ci/conda_recipe/meta.yaml +++ b/ci/conda_recipe/meta.yaml @@ -1,61 +1,73 @@ -# stolen from https://github.com/conda/conda-recipes/tree/master/matplotlib -# selectors [py27] and comments need to be `# [selector] comment` not `[sel] # comment` +# Full credit goes to https://github.com/conda/conda-recipes for providing this recipe. +# It has been subsequently adapted for automated building with conda-forge and matplotlib. package: - name: matplotlib-test - version: 1.5.0.9 + name: matplotlib + version: 1.5.1.9 source: path: ../../ patches: - # don't run nosetest - - cfg_notests.patch - # nake Qt4Agg the default backend - - cfg_qt4agg.patch [not osx] - - rctmp_pyside.patch [not osx] - # tk work on OSX - - osx-tk.patch [osx] + # A patch to make Qt4Agg the default backend. + - cfg_qt4agg.patch # [linux] + # Patches the matplotlibrc template to default to Qt4. + - rctmp_pyside.patch # [not osx] + # Patches setupext to look in PREFIX for the tcl/tk headers. + - osx-tk.patch # [osx] # dynamic version from git + # we can't use condas usual dynamic versions as setup.py uses a guard + # around the setup call against importing, which is done internaly + # by conda build to get the version. + # https://github.com/matplotlib/matplotlib/pull/5629#issuecomment-167243654 - condaversion.patch requirements: build: - python - setuptools - - numpy + - numpy x.x - python-dateutil - - freetype >=2.5,<2.6 + - freetype + - msinttypes # [win] + - cycler + - nose - pyparsing - pytz - - py2cairo [linux and py2k] +# - py2cairo # [linux and py2k] - tornado - libpng - - zlib [win] - - msinttypes # this package is from the conda-forge channel! - - pyqt [not osx] - - cycler - - tk - #- functools32 [py27] # this is currently not available + - zlib # [win] + - pyqt # [not osx] + - tk # [linux and win] + - functools32 # [py2k] run: - python - - numpy + - numpy x.x + - cycler - python-dateutil - - freetype [unix] + - freetype - pytz - pyparsing - - py2cairo [linux and py2k] - - libpng [unix] - - pyqt [not osx] - - cycler - - tk +# - py2cairo # [linux and py2k] + - libpng # [unix] + - pyqt # [not osx] + - tk # [linux and win] + - functools32 # [py2k] test: - requires: - - nose - - mock + imports: + - matplotlib + - matplotlib.pyplot about: - home: http://matplotlib.sourceforge.net/ - license: PSF-based (http://matplotlib.sourceforge.net/users/license.html) + home: http://matplotlib.org/ + license: PSF-based (http://matplotlib.org/users/license.html) + summary: Publication quality figures in Python + +extra: + recipe-maintainers: + - pelson + - tacaswell + - JanSchulz diff --git a/ci/conda_recipe/osx-tk.patch b/ci/conda_recipe/osx-tk.patch index e950b328482..1411225550e 100644 --- a/ci/conda_recipe/osx-tk.patch +++ b/ci/conda_recipe/osx-tk.patch @@ -1,9 +1,9 @@ diff --git setupext.py setupext.py -index 9219c88..e3a9653 100644 +index ddf2ca1..b9e0729 100755 --- setupext.py +++ setupext.py -@@ -1334,52 +1334,11 @@ class BackendTkAgg(OptionalBackendPackage): - ext.library_dirs.extend([os.path.join(sys.prefix, 'dlls')]) +@@ -1659,52 +1659,11 @@ class BackendTkAgg(OptionalBackendPackage): + ext.library_dirs.extend([os.path.join(sys.prefix, 'dlls')]) elif sys.platform == 'darwin': - # this config section lifted directly from Imaging - thanks to @@ -16,7 +16,7 @@ index 9219c88..e3a9653 100644 - '/Library/Frameworks', - '/System/Library/Frameworks/', - ] -- + - # Find the directory that contains the Tcl.framework and - # Tk.framework bundles. - tk_framework_found = 0 @@ -46,7 +46,7 @@ index 9219c88..e3a9653 100644 - # than include a complicated search, this is a - # hard-coded path. It could bail out if X11 libs are - # not found... - +- - # tk_include_dirs.append('/usr/X11R6/include') - frameworks = ['-framework', 'Tcl', '-framework', 'Tk'] - ext.include_dirs.extend(tk_include_dirs) diff --git a/ci/conda_recipe/rctmp_pyside.patch b/ci/conda_recipe/rctmp_pyside.patch index 15e97de6454..906803575a9 100644 --- a/ci/conda_recipe/rctmp_pyside.patch +++ b/ci/conda_recipe/rctmp_pyside.patch @@ -6,7 +6,7 @@ index fdbbf26..6902fe9 100644 # You can also deploy your own backend outside of matplotlib by # referring to the module name (which must be in the PYTHONPATH) as # 'module://my_backend'. --backend : %(backend)s +-backend : $TEMPLATE_BACKEND +backend : Qt4Agg # If you are using the Qt4Agg backend, you can choose here diff --git a/ci/conda_recipe/run_test.py b/ci/conda_recipe/run_test.py index 37c11af85bf..fba57d981e5 100644 --- a/ci/conda_recipe/run_test.py +++ b/ci/conda_recipe/run_test.py @@ -1,4 +1,5 @@ import os +import platform import sys import matplotlib @@ -12,7 +13,8 @@ import matplotlib.backends._backend_agg import matplotlib.ft2font import matplotlib.ttconv -import matplotlib.backends._tkagg +if platform.system() not in ['Windows']: + import matplotlib.backends._tkagg import pylab import mpl_toolkits diff --git a/setup_external_compile.py b/setup_external_compile.py new file mode 100644 index 00000000000..c6a13c86829 --- /dev/null +++ b/setup_external_compile.py @@ -0,0 +1,69 @@ +# This file is coppied from https://github.com/jbmohler/matplotlib-winbuild +# Only the needed functions were kept. +""" +This file extracts and builds library dependencies libpng, zlib, & freetype2 on +MS Windows. It also extract tcl/tk for the header files. + +There are four possible build targets -- one for each permutation of VS 2008, +2010 and 32/64 bit. This builds the configuration that matches the Python +install that is executing. + +For Python 2.6, 2.7, 3.2: + +- VS 2008, 32 bit -- Windows SDK v7.0 +- VS 2008, 64 bit -- Windows SDK v7.0 + +For Python 3.3, 3.4: + +- VS 2010, 32 bit -- Windows SDK v7.1 +- VS 2010, 64 bit -- Windows SDK v7.1 +""" + +from __future__ import print_function, absolute_import +import sys +import platform +import os +import glob +import shutil +import zipfile +import tarfile +import distutils.msvc9compiler as msvc + +def fixproj(project_file, bit_target): + """ + :param bit_target: one of 'Win32' or 'x64' + """ + with open(project_file, 'r') as fd: + content = '\n'.join(line.strip() for line in fd if line.strip()) + content = content.replace('Win32', bit_target).replace('x64', bit_target) + with open(project_file, 'w') as fd: + fd.write(content) + +def tar_extract(tar_file, target): + with tarfile.open(tar_file, 'r:gz') as tgz: + tgz.extractall(target) + +def zip_extract(zip_file, target): + with zipfile.ZipFile(zip_file) as zf: + zf.extractall(target) + +# Configuration selection & declaration: +DEPSSRC = os.path.join(os.path.dirname(os.path.normpath(__file__)), 'deps_source') +DEPSBUILD = os.path.join(os.path.dirname(os.path.normpath(__file__)), 'build') +X64 = platform.architecture()[0] == '64bit' +PYVER = sys.version_info[:2] +VS2010 = PYVER >= (3, 3) +# If not VS2010, then use VS2008 + +VCVARSALL = None + +def prepare_build_cmd(build_cmd, **kwargs): + global VCVARSALL + if VCVARSALL == None: + candidate = msvc.find_vcvarsall(10.0 if VS2010 else 9.0) + if candidate == None: + raise RuntimeError('Microsoft VS {} required'.format('2010' if VS2010 else '2008')) + else: + VCVARSALL = candidate + + return build_cmd.format(vcvarsall=VCVARSALL, xXX='x64' if X64 else 'x86', **kwargs) diff --git a/setupext.py b/setupext.py index bf97b7e8253..b130679ce9f 100755 --- a/setupext.py +++ b/setupext.py @@ -23,7 +23,8 @@ # This is the version of FreeType to use when building a local # version. It must match the value in -# lib/matplotlib.__init__.py +# lib/matplotlib.__init__.py and also needs to be changed below in the +# embedded windows build script (grep for "REMINDER" in this file) LOCAL_FREETYPE_VERSION = '2.6.1' # md5 hash of the freetype tarball LOCAL_FREETYPE_HASH = '348e667d728c597360e4a87c16556597' @@ -130,16 +131,16 @@ def get_base_dirs(): """ if options['basedirlist']: return options['basedirlist'] - + if os.environ.get('MPLBASEDIRLIST'): return os.environ.get('MPLBASEDIRLIST').split(os.pathsep) win_bases = ['win32_static', ] - # on conda windows, we also add the \Library of the local interperter, + # on conda windows, we also add the \Library of the local interperter, # as conda installs libs/includes there if os.getenv('CONDA_DEFAULT_ENV'): win_bases.append(os.path.join(os.getenv('CONDA_DEFAULT_ENV'), "Library")) - + basedir_map = { 'win32': win_bases, 'darwin': ['/usr/local/', '/usr', '/usr/X11', @@ -157,7 +158,7 @@ def get_include_dirs(): """ include_dirs = [os.path.join(d, 'include') for d in get_base_dirs()] if sys.platform != 'win32': - # gcc includes this dir automatically, so also look for headers in + # gcc includes this dir automatically, so also look for headers in # these dirs include_dirs.extend( os.environ.get('CPLUS_INCLUDE_PATH', '').split(os.pathsep)) @@ -969,8 +970,12 @@ def add_flags(self, ext): # Statically link to the locally-built freetype. # This is certainly broken on Windows. ext.include_dirs.insert(0, os.path.join(src_path, 'include')) + if sys.platform == 'win32': + libfreetype = 'libfreetype.lib' + else: + libfreetype = 'libfreetype.a' ext.extra_objects.insert( - 0, os.path.join(src_path, 'objs', '.libs', 'libfreetype.a')) + 0, os.path.join(src_path, 'objs', '.libs', libfreetype)) ext.define_macros.append(('FREETYPE_BUILD_TYPE', 'local')) else: pkg_config.setup_extension( @@ -993,7 +998,12 @@ def do_custom_build(self): 'build', 'freetype-{0}'.format(LOCAL_FREETYPE_VERSION)) # We've already built freetype - if os.path.isfile(os.path.join(src_path, 'objs', '.libs', 'libfreetype.a')): + if sys.platform == 'win32': + libfreetype = 'libfreetype.lib' + else: + libfreetype = 'libfreetype.a' + + if os.path.isfile(os.path.join(src_path, 'objs', '.libs', libfreetype)): return tarball = 'freetype-{0}.tar.gz'.format(LOCAL_FREETYPE_VERSION) @@ -1015,15 +1025,52 @@ def do_custom_build(self): raise IOError("{0} does not match expected hash.".format(tarball)) print("Building {0}".format(tarball)) - cflags = 'CFLAGS="{0} -fPIC" '.format(os.environ.get('CFLAGS', '')) - - subprocess.check_call( - ['tar', 'zxf', tarball], cwd='build') - subprocess.check_call( - [cflags + './configure --with-zlib=no --with-bzip2=no ' - '--with-png=no --with-harfbuzz=no'], shell=True, cwd=src_path) - subprocess.check_call( - [cflags + 'make'], shell=True, cwd=src_path) + if sys.platform != 'win32': + # compilation on all other platforms than windows + cflags = 'CFLAGS="{0} -fPIC" '.format(os.environ.get('CFLAGS', '')) + + subprocess.check_call( + ['tar', 'zxf', tarball], cwd='build') + subprocess.check_call( + [cflags + './configure --with-zlib=no --with-bzip2=no ' + '--with-png=no --with-harfbuzz=no'], shell=True, cwd=src_path) + subprocess.check_call( + [cflags + 'make'], shell=True, cwd=src_path) + else: + # compilation on windows + FREETYPE_BUILD_CMD = """\ +call "%ProgramFiles%\\Microsoft SDKs\\Windows\\v7.0\\Bin\\SetEnv.Cmd" /Release /{xXX} /xp +call "{vcvarsall}" {xXX} +set MSBUILD=C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\MSBuild.exe +rd /S /Q %FREETYPE%\\objs +%MSBUILD% %FREETYPE%\\builds\\windows\\{vc20xx}\\freetype.sln /t:Clean;Build /p:Configuration="{config}";Platform={WinXX} +echo Build completed, moving result" +:: move to the "normal" path for the unix builds... +mkdir %FREETYPE%\\objs\\.libs +:: REMINDER: fix when changing the version +copy %FREETYPE%\\objs\\{vc20xx}\\{xXX}\\freetype261.lib %FREETYPE%\\objs\\.libs\\libfreetype.lib +if errorlevel 1 ( + rem This is a py27 version, which has a different location for the lib file :-/ + copy %FREETYPE%\\objs\\win32\\{vc20xx}\\freetype261.lib %FREETYPE%\\objs\\.libs\\libfreetype.lib +) +""" + from setup_external_compile import fixproj, prepare_build_cmd, VS2010, X64, tar_extract + # Note: freetype has no build profile for 2014, so we don't bother... + vc = 'vc2010' if VS2010 else 'vc2008' + WinXX = 'x64' if X64 else 'Win32' + tar_extract(tarball_path, "build") + # This is only false for py2.7, even on py3.5... + if not VS2010: + fixproj(os.path.join(src_path, 'builds', 'windows', vc, 'freetype.sln'), WinXX) + fixproj(os.path.join(src_path, 'builds', 'windows', vc, 'freetype.vcproj'), WinXX) + + cmdfile = os.path.join("build", 'build_freetype.cmd') + with open(cmdfile, 'w') as cmd: + cmd.write(prepare_build_cmd(FREETYPE_BUILD_CMD, vc20xx=vc, WinXX=WinXX, + config='Release' if VS2010 else 'LIB Release')) + + os.environ['FREETYPE'] = src_path + subprocess.check_call([cmdfile], shell=True) class FT2Font(SetupPackage): @@ -1597,7 +1644,7 @@ def add_flags(self, ext): if os.getenv('CONDA_DEFAULT_ENV'): # We are in conda and conda builds against tcl85 for all versions # includes are directly in the conda\library\include dir and - # libs in DLL or lib + # libs in DLL or lib ext.include_dirs.extend(['include']) ext.libraries.extend(['tk85', 'tcl85']) ext.library_dirs.extend(['dlls']) # or lib?