diff --git a/.appveyor.yml b/.appveyor.yml index 4d2cb81d2..8602293f7 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -48,8 +48,7 @@ install: } else { - $env:PILLOW_DEPS = "C:\pillow-depends\" - c:\python37\python.exe c:\pillow\winbuild\build_prepare.py + c:\python37\python.exe c:\pillow\winbuild\build_prepare.py -v --depends=C:\pillow-depends\ c:\pillow\winbuild\build\build_dep_all.cmd $host.SetShouldExit(0) } diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml index fe958ad5a..fe0fdc04c 100644 --- a/.github/workflows/test-windows.yml +++ b/.github/workflows/test-windows.yml @@ -66,12 +66,9 @@ jobs: ..\pillow-depends\gs950w32.exe /S Write-Host "::add-path::C:\Program Files (x86)\gs\gs9.50\bin" - $env:PILLOW_DEPS = "$env:RUNNER_WORKSPACE\pillow-depends\" xcopy /s ..\pillow-depends\test_images\* $env:GITHUB_WORKSPACE\tests\images\ - $env:PYTHON=$env:pythonLocation - cd $env:GITHUB_WORKSPACE/winbuild/ - & python.exe $env:GITHUB_WORKSPACE\winbuild\build_prepare.py + & python.exe $env:GITHUB_WORKSPACE\winbuild\build_prepare.py -v --depends=$env:RUNNER_WORKSPACE\pillow-depends\ --python=$env:pythonLocation shell: pwsh - name: Build dependencies / libjpeg-turbo diff --git a/setup.py b/setup.py index b55b1de62..1236b5df5 100755 --- a/setup.py +++ b/setup.py @@ -120,7 +120,7 @@ _LIB_IMAGING = ( "codec_fd", ) -DEBUG = True +DEBUG = False class DependencyException(Exception): diff --git a/winbuild/README.md b/winbuild/README.md index dabbc359a..45c37e4cb 100644 --- a/winbuild/README.md +++ b/winbuild/README.md @@ -19,7 +19,7 @@ The following is a simplified version of the script used on AppVeyor: ``` set PYTHON=C:\Python35\bin cd /D C:\Pillow\winbuild -C:\Python37\bin\python.exe build_prepare.py +C:\Python37\bin\python.exe build_prepare.py -v --depends=C:\pillow-depends build\build_dep_all.cmd build\build_pillow.cmd install cd .. diff --git a/winbuild/build.rst b/winbuild/build.rst index f47efb363..465bc2591 100644 --- a/winbuild/build.rst +++ b/winbuild/build.rst @@ -23,18 +23,20 @@ Compilers Download and install: -* `Microsoft Visual Studio 2017 or newer (with C++ component) - `_ +* `Microsoft Visual Studio 2017 or newer or Build Tools for Visual Studio 2017 or newer + `_ + (MSVC C++ build tools, and any Windows SDK version required) -* `CMake 3.13 or newer - `_ +* `CMake 3.13 or newer `_ + (also available as Visual Studio component C++ CMake tools for Windows) * `NASM `_ Any version of Visual Studio 2017 or newer should be supported, -including Visual Studio 2017 Community. +including Visual Studio 2017 Community, or Build Tools for Visual Studio 2019. -Paths to CMake and NASM must be added to the ``PATH`` environment variable. +Paths to CMake (if standalone) and NASM must be added to the ``PATH`` environment variable. +Visual Studio is found automatically with ``vswhere.exe``. Build configuration ------------------- @@ -47,7 +49,7 @@ behaviour of ``build_prepare.py``: ``build_prepare.py`` will be used. If only ``PYTHON`` is set, ``EXECUTABLE`` defaults to ``python.exe``. * ``ARCHITECTURE`` is used to select a ``x86`` or ``x64`` build. By default, - ``x86`` is used, unless ``PYTHON`` contains ``x64``, in which case ``x64`` + uses same architecture as the version of Python used to run ``build_prepare.py``. is used. * ``PILLOW_BUILD`` can be used to override the ``winbuild\build`` directory path, used to store generated build scripts and compiled libraries. @@ -55,6 +57,17 @@ behaviour of ``build_prepare.py``: * ``PILLOW_DEPS`` points to the directory used to store downloaded dependencies. By default ``winbuild\depends`` is used. +``build_prepare.py`` also supports the following command line parameters: + +* ``-v`` will print generated scripts. +* ``--no-imagequant`` will skip GPL-licensed ``libimagequant`` optional dependency +* ``--no-raqm`` will skip optional dependency Raqm (which itself depends on + LGPL-licensed ``fribidi``). +* ``--python=`` and ``--executable=`` override ``PYTHON`` and ``EXECUTABLE``. +* ``--architecture=`` overrides ``ARCHITECTURE``. +* ``--dir=`` and ``--depends=`` override ``PILLOW_BUILD`` + and ``PILLOW_DEPS``. + Dependencies ------------ @@ -93,7 +106,7 @@ The following is a simplified version of the script used on AppVeyor: set PYTHON=C:\Python35\bin cd /D C:\Pillow\winbuild - C:\Python37\bin\python.exe build_prepare.py + C:\Python37\bin\python.exe build_prepare.py -v --depends=C:\pillow-depends build\build_dep_all.cmd build\build_pillow.cmd install cd .. diff --git a/winbuild/build_prepare.py b/winbuild/build_prepare.py index e56b71eb4..475982da2 100644 --- a/winbuild/build_prepare.py +++ b/winbuild/build_prepare.py @@ -1,5 +1,6 @@ import os import shutil +import struct import subprocess import sys @@ -176,6 +177,8 @@ deps = { r"builds\windows\vc2010\freetype.vcxproj": { # freetype setting is /MD for .dll and /MT for .lib, we need /MD "MultiThreaded": "MultiThreadedDLL", # noqa E501 + # freetype doesn't specify SDK version, MSBuild may guess incorrectly + '': '\n $(WindowsSDKVersion)', # noqa E501 } }, "build": [ @@ -389,8 +392,9 @@ def write_script(name, lines): print("Writing " + name) with open(name, "w") as f: f.write("\n\r".join(lines)) - for line in lines: - print(" " + line) + if verbose: + for line in lines: + print(" " + line) def get_footer(dep): @@ -438,6 +442,8 @@ def build_dep(name): def build_dep_all(): lines = ["@echo on"] for dep_name in deps: + if dep_name in disabled: + continue lines.append(r'cmd.exe /c "{{build_dir}}\{}"'.format(build_dep(dep_name))) lines.append("if errorlevel 1 echo Build failed! && exit /B 1") lines.append("@echo All Pillow dependencies built successfully!") @@ -459,6 +465,28 @@ def build_pillow(): if __name__ == "__main__": + verbose = False + disabled = [] + for arg in sys.argv[1:]: + if arg == "-v": + verbose = True + elif arg == "--no-imagequant": + disabled += ["libimagequant"] + elif arg == "--no-raqm": + disabled += ["harfbuzz", "fribidi", "libraqm"] + elif arg.startswith("--depends="): + os.environ["PILLOW_DEPS"] = arg[10:] + elif arg.startswith("--python="): + os.environ["PYTHON"] = arg[9:] + elif arg.startswith("--executable="): + os.environ["EXECUTABLE"] = arg[13:] + elif arg.startswith("--architecture="): + os.environ["ARCHITECTURE"] = arg[15:] + elif arg.startswith("--dir="): + os.environ["PILLOW_BUILD"] = arg[6:] + else: + raise ValueError("Unknown parameter: " + arg) + # winbuild directory winbuild_dir = os.path.dirname(os.path.realpath(__file__)) @@ -477,7 +505,7 @@ if __name__ == "__main__": # use ARCHITECTURE or PYTHON to select architecture architecture = os.environ.get( - "ARCHITECTURE", "x64" if "x64" in python_dir else "x86" + "ARCHITECTURE", "x86" if struct.calcsize("P") == 4 else "x64" ) arch_prefs = architectures[architecture] print("Target Architecture:", architecture) @@ -528,5 +556,7 @@ if __name__ == "__main__": "header": sum([header, msvs["header"], ["@echo on"]], []), } + print() + build_dep_all() build_pillow()