diff --git a/.appveyor.yml b/.appveyor.yml
index e395f2ae6f6..c0a8a023717 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -1,4 +1,5 @@
version: '{build}'
+image: Visual Studio 2017
clone_folder: c:\pillow
init:
- ECHO %PYTHON%
@@ -6,40 +7,33 @@ init:
# Uncomment previous line to get RDP access during the build.
environment:
- X64_EXT: -x64
EXECUTABLE: python.exe
PIP_DIR: Scripts
- VENV: NO
TEST_OPTIONS:
DEPLOY: YES
matrix:
- PYTHON: C:/Python38
- - PYTHON: C:/Python38-x64
- - PYTHON: C:/Python35
+ ARCHITECTURE: x86
- PYTHON: C:/Python35-x64
+ ARCHITECTURE: x64
- PYTHON: C:/msys64/mingw32
EXECUTABLE: bin/python3
+ ARCHITECTURE: x86
PIP_DIR: bin
TEST_OPTIONS: --processes=0
DEPLOY: NO
- - PYTHON: C:/vp/pypy3
- EXECUTABLE: bin/pypy.exe
- VENV: YES
install:
- curl -fsSL -o pillow-depends.zip https://github.com/python-pillow/pillow-depends/archive/master.zip
- 7z x pillow-depends.zip -oc:\
- mv c:\pillow-depends-master c:\pillow-depends
-- xcopy c:\pillow-depends\*.zip c:\pillow\winbuild\
-- xcopy c:\pillow-depends\*.tar.gz c:\pillow\winbuild\
- xcopy /s c:\pillow-depends\test_images\* c:\pillow\tests\images
+- 7z x ..\pillow-depends\nasm-2.14.02-win64.zip -oc:\
+- curl -fsSL -o gs952.exe https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs952/gs952w32.exe
+- gs952.exe /S
+- path c:\nasm-2.14.02;C:\Program Files (x86)\gs\gs9.52\bin;%PATH%
- cd c:\pillow\winbuild\
-- ps: |
- if ($env:PYTHON -eq "c:/vp/pypy3")
- {
- c:\pillow\winbuild\appveyor_install_pypy3.cmd
- }
- ps: |
if ($env:PYTHON -eq "c:/msys64/mingw32")
{
@@ -47,13 +41,11 @@ install:
}
else
{
- c:\python37\python.exe c:\pillow\winbuild\build_dep.py
- c:\pillow\winbuild\build_deps.cmd
+ 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)
}
-- curl -fsSL -o gs952.exe https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs952/gs952w32.exe
-- gs952.exe /S
-- path %path%;C:\Program Files (x86)\gs\gs9.52\bin
+- path C:\pillow\winbuild\build\bin;%PATH%
build_script:
- ps: |
@@ -65,7 +57,7 @@ build_script:
}
else
{
- & $env:PYTHON/$env:EXECUTABLE c:\pillow\winbuild\build.py
+ c:\pillow\winbuild\build\build_pillow.cmd install
$host.SetShouldExit(0)
}
- cd c:\pillow
@@ -98,7 +90,7 @@ before_deploy:
- cd c:\pillow
- '%PYTHON%\%PIP_DIR%\pip.exe install wheel'
- cd c:\pillow\winbuild\
- - '%PYTHON%\%EXECUTABLE% c:\pillow\winbuild\build.py --wheel'
+ - c:\pillow\winbuild\build\build_pillow.cmd bdist_wheel
- cd c:\pillow
- ps: Get-ChildItem .\dist\*.* | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name }
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 3cad8d4170b..6c5d81ac44d 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -13,7 +13,7 @@ jobs:
name: Python ${{ matrix.python-version }}
steps:
- - uses: actions/checkout@v1
+ - uses: actions/checkout@v2
- name: pip cache
uses: actions/cache@v1
diff --git a/.github/workflows/test-docker.yml b/.github/workflows/test-docker.yml
index 8d1c2e24c08..f168304bc87 100644
--- a/.github/workflows/test-docker.yml
+++ b/.github/workflows/test-docker.yml
@@ -30,7 +30,7 @@ jobs:
name: ${{ matrix.docker }}
steps:
- - uses: actions/checkout@v1
+ - uses: actions/checkout@v2
- name: Build system information
run: python .github/workflows/system-info.py
diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml
index d45dc946769..24f8406bcfa 100644
--- a/.github/workflows/test-windows.yml
+++ b/.github/workflows/test-windows.yml
@@ -4,7 +4,6 @@ on: [push, pull_request]
jobs:
build:
-
runs-on: windows-2019
strategy:
fail-fast: false
@@ -27,14 +26,16 @@ jobs:
name: Python ${{ matrix.python-version }} ${{ matrix.architecture }}
steps:
- - uses: actions/checkout@v1
+ - name: Checkout Pillow
+ uses: actions/checkout@v2
- - uses: actions/checkout@v1
+ - name: Checkout cached dependencies
+ uses: actions/checkout@v2
with:
repository: python-pillow/pillow-depends
- ref: master
+ path: winbuild\depends
- - name: Cache
+ - name: Cache pip
uses: actions/cache@v1
with:
path: ~\AppData\Local\pip\Cache
@@ -51,291 +52,68 @@ jobs:
python-version: ${{ matrix.python-version }}
architecture: ${{ matrix.architecture }}
- - name: Build system information
+ - name: Print build system information
run: python .github/workflows/system-info.py
- name: pip install wheel pytest pytest-cov
- run: |
- "%pythonLocation%\python.exe" -m pip install wheel pytest pytest-cov
- shell: cmd
+ run: python -m pip install wheel pytest pytest-cov
- - name: Fetch dependencies
+ - name: Prepare dependencies
run: |
- 7z x ..\pillow-depends\nasm-2.14.02-win64.zip "-o$env:RUNNER_WORKSPACE\"
- Write-Host "`#`#[add-path]$env:RUNNER_WORKSPACE\nasm-2.14.02"
+ 7z x winbuild\depends\nasm-2.14.02-win64.zip "-o$env:RUNNER_WORKSPACE\"
Write-Host "::add-path::$env:RUNNER_WORKSPACE\nasm-2.14.02"
- ..\pillow-depends\gs950w32.exe /S
- Write-Host "`#`#[add-path]C:\Program Files (x86)\gs\gs9.50\bin"
+ winbuild\depends\gs950w32.exe /S
Write-Host "::add-path::C:\Program Files (x86)\gs\gs9.50\bin"
- $env:PYTHON=$env:pythonLocation
- xcopy ..\pillow-depends\*.zip $env:GITHUB_WORKSPACE\winbuild\
- xcopy ..\pillow-depends\*.tar.gz $env:GITHUB_WORKSPACE\winbuild\
- xcopy /s ..\pillow-depends\test_images\* $env:GITHUB_WORKSPACE\tests\images\
- cd $env:GITHUB_WORKSPACE/winbuild/
- python.exe $env:GITHUB_WORKSPACE\winbuild\build_dep.py
- env:
- EXECUTABLE: bin\python.exe
- shell: pwsh
-
- - name: Build dependencies / libjpeg
- if: false
- run: |
- REM FIXME uses /MT not /MD, see makefile.vc and win32.mak for more info
+ xcopy /s winbuild\depends\test_images\* Tests\images\
- set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include
- set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32
- set BUILD=%GITHUB_WORKSPACE%\winbuild\build
- cd /D %BUILD%\jpeg-9d
- call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.platform-vcvars }}
- echo on
- nmake -nologo -f makefile.vc setup-vc6
- nmake -nologo -f makefile.vc clean
- nmake -nologo -f makefile.vc nodebug=1 libjpeg.lib cjpeg.exe djpeg.exe
- copy /Y /B j*.h %INCLIB%
- copy /Y /B *.lib %INCLIB%
- copy /Y /B *.exe %INCLIB%
- shell: cmd
+ & python.exe winbuild\build_prepare.py -v --python=$env:pythonLocation
+ shell: pwsh
- name: Build dependencies / libjpeg-turbo
- run: |
- set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include
- set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32
- set BUILD=%GITHUB_WORKSPACE%\winbuild\build
- cd /D %BUILD%\libjpeg-turbo-2.0.3
- call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.platform-vcvars }}
- echo on
- set CMAKE=cmake.exe -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_RULE_MESSAGES:BOOL=OFF
- set CMAKE=%CMAKE% -DENABLE_SHARED:BOOL=OFF -DWITH_JPEG8:BOOL=TRUE -DWITH_CRT_DLL:BOOL=TRUE -DCMAKE_BUILD_TYPE=Release
- %CMAKE% -G "NMake Makefiles" .
- nmake -nologo -f Makefile clean
- nmake -nologo -f Makefile jpeg-static cjpeg-static djpeg-static
- copy /Y /B j*.h %INCLIB%
- copy /Y /B jpeg-static.lib %INCLIB%\libjpeg.lib
- copy /Y /B cjpeg-static.exe %INCLIB%\cjpeg.exe
- copy /Y /B djpeg-static.exe %INCLIB%\djpeg.exe
- shell: cmd
-
+ run: "& winbuild\\build\\build_dep_libjpeg.cmd"
- name: Build dependencies / zlib
- run: |
- set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include
- set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32
- set BUILD=%GITHUB_WORKSPACE%\winbuild\build
- cd /D %BUILD%\zlib-1.2.11
- call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.platform-vcvars }}
- echo on
- nmake -nologo -f win32\Makefile.msc clean
- nmake -nologo -f win32\Makefile.msc zlib.lib
- copy /Y /B z*.h %INCLIB%
- copy /Y /B *.lib %INCLIB%
- copy /Y /B zlib.lib %INCLIB%\z.lib
- shell: cmd
-
- - name: Build dependencies / LibTIFF
- run: |
- set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include
- set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32
- set BUILD=%GITHUB_WORKSPACE%\winbuild\build
- cd /D %BUILD%\tiff-4.1.0
- call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.platform-vcvars }}
- echo on
- copy %GITHUB_WORKSPACE%\winbuild\tiff.opt nmake.opt
- nmake -nologo -f makefile.vc clean
- nmake -nologo -f makefile.vc lib
- copy /Y /B libtiff\tiff*.h %INCLIB%
- copy /Y /B libtiff\*.dll %INCLIB%
- copy /Y /B libtiff\*.lib %INCLIB%
- shell: cmd
-
+ run: "& winbuild\\build\\build_dep_zlib.cmd"
+ - name: Build dependencies / LibTiff
+ run: "& winbuild\\build\\build_dep_libtiff.cmd"
- name: Build dependencies / WebP
- run: |
- set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include
- set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32
- set BUILD=%GITHUB_WORKSPACE%\winbuild\build
- cd /D %BUILD%\libwebp-1.1.0
- call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.platform-vcvars }}
- echo on
- rmdir /S /Q output\release-static
- nmake -nologo -f Makefile.vc CFG=release-static OBJDIR=output ARCH=${{ matrix.architecture }} all
- mkdir %INCLIB%\webp
- copy /Y /B src\webp\*.h %INCLIB%\webp
- copy /Y /B output\release-static\${{ matrix.architecture }}\lib\* %INCLIB%
- shell: cmd
-
+ run: "& winbuild\\build\\build_dep_libwebp.cmd"
- name: Build dependencies / FreeType
- run: |
- REM Toolkit v100 not available; missing VCTargetsPath; Clean fails
-
- set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include
- set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32
- set BUILD=%GITHUB_WORKSPACE%\winbuild\build
- cd /D %BUILD%\freetype-2.10.2
- call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.platform-vcvars }}
- echo on
- rmdir /S /Q objs
- set DefaultPlatformToolset=v142
- set VCTargetsPath=C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Microsoft\VC\v160\
- set MSBUILD="C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\MSBuild.exe"
- powershell -Command "(gc builds\windows\vc2010\freetype.vcxproj) -replace 'MultiThreaded<', 'MultiThreadedDLL<' | Out-File -encoding ASCII builds\windows\vc2010\freetype.vcxproj"
- %MSBUILD% builds\windows\vc2010\freetype.sln /t:Build /p:Configuration="Release Static" /p:Platform=${{ matrix.platform-msbuild }} /m
- xcopy /Y /E /Q include %INCLIB%
- copy /Y /B "objs\${{ matrix.platform-msbuild }}\Release Static\freetype.lib" %INCLIB%
- shell: cmd
-
+ run: "& winbuild\\build\\build_dep_freetype.cmd"
- name: Build dependencies / LCMS2
- run: |
- set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include
- set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32
- set BUILD=%GITHUB_WORKSPACE%\winbuild\build
- cd /D %BUILD%\lcms2-2.8
- call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.platform-vcvars }}
- echo on
- rmdir /S /Q Lib
- rmdir /S /Q Projects\VC2015\Release
- set VCTargetsPath=C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Microsoft\VC\v160\
- set MSBUILD="C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\MSBuild.exe"
- powershell %GITHUB_WORKSPACE%\winbuild\lcms2_patch.ps1
- %MSBUILD% Projects\VC2015\lcms2.sln /t:Clean;lcms2_static /p:Configuration="Release" /p:Platform=${{ matrix.platform-msbuild }} /m
- xcopy /Y /E /Q include %INCLIB%
- copy /Y /B Lib\MS\*.lib %INCLIB%
- shell: cmd
-
+ run: "& winbuild\\build\\build_dep_lcms2.cmd"
- name: Build dependencies / OpenJPEG
- run: |
- set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include
- set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32
- set BUILD=%GITHUB_WORKSPACE%\winbuild\build
- cd /D %BUILD%\openjpeg-2.3.1msvcr10-x32
- call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.platform-vcvars }}
- echo on
- set CMAKE=cmake.exe -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_RULE_MESSAGES:BOOL=OFF
- set CMAKE=%CMAKE% -DBUILD_THIRDPARTY:BOOL=OFF -DBUILD_SHARED_LIBS:BOOL=OFF
- set CMAKE=%CMAKE% -DCMAKE_BUILD_TYPE=Release
- %CMAKE% -G "NMake Makefiles" .
- nmake -nologo -f Makefile clean
- nmake -nologo -f Makefile
- mkdir %INCLIB%\openjpeg-2.3.1
- copy /Y /B src\lib\openjp2\*.h %INCLIB%\openjpeg-2.3.1
- copy /Y /B bin\*.lib %INCLIB%
- shell: cmd
+ run: "& winbuild\\build\\build_dep_openjpeg.cmd"
# GPL licensed; skip if building wheels
- name: Build dependencies / libimagequant
- if: "github.event_name != 'push' || contains(matrix.python-version, 'pypy')"
- run: |
- set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include
- set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32
- set BUILD=%GITHUB_WORKSPACE%\winbuild\build
- rem e5d454b: Merge tag '2.12.6' into msvc
- cd /D %BUILD%\libimagequant-e5d454bc7f5eb63ee50c84a83a7fa5ac94f68ec4
- call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.platform-vcvars }}
- echo on
- echo (gc CMakeLists.txt) -replace 'add_library', "add_compile_options(-openmp-)`r`nadd_library" ^| Out-File -encoding ASCII CMakeLists.txt > patch.ps1
- echo (gc CMakeLists.txt) -replace ' SHARED', ' STATIC' ^| Out-File -encoding ASCII CMakeLists.txt >> patch.ps1
- powershell .\patch.ps1
- set CMAKE=cmake.exe -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_RULE_MESSAGES:BOOL=OFF
- set CMAKE=%CMAKE% -DCMAKE_BUILD_TYPE=Release
- %CMAKE% -G "NMake Makefiles" .
- nmake -nologo -f Makefile clean
- nmake -nologo -f Makefile
- copy /Y /B *.h %INCLIB%
- copy /Y /B *.lib %INCLIB%
- shell: cmd
+ if: "github.event_name != 'push'"
+ run: "& winbuild\\build\\build_dep_libimagequant.cmd"
- # for Raqm
+ # Raqm dependencies
- name: Build dependencies / HarfBuzz
- run: |
- set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include
- set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32
- set BUILD=%GITHUB_WORKSPACE%\winbuild\build
- set INCLUDE=%INCLUDE%;%INCLIB%
- set LIB=%LIB%;%INCLIB%
- cd /D %BUILD%\harfbuzz-2.6.4
- call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.platform-vcvars }}
- echo on
- set CMAKE=cmake.exe -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_RULE_MESSAGES:BOOL=OFF
- set CMAKE=%CMAKE% -DHB_HAVE_FREETYPE:BOOL=ON -DCMAKE_BUILD_TYPE=Release
- %CMAKE% -G "NMake Makefiles" .
- nmake -nologo -f Makefile clean
- nmake -nologo -f Makefile harfbuzz
- copy /Y /B src\*.h %INCLIB%
- copy /Y /B *.lib %INCLIB%
- shell: cmd
-
- # for Raqm
+ run: "& winbuild\\build\\build_dep_harfbuzz.cmd"
- name: Build dependencies / FriBidi
- run: |
- set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include
- set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32
- set BUILD=%GITHUB_WORKSPACE%\winbuild\build
- cd /D %BUILD%\fribidi-1.0.9
- call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.platform-vcvars }}
- echo on
- copy /Y /B %GITHUB_WORKSPACE%\winbuild\fribidi.cmake CMakeLists.txt
- set CMAKE=cmake.exe -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_RULE_MESSAGES:BOOL=OFF
- set CMAKE=%CMAKE% -DCMAKE_BUILD_TYPE=Release
- %CMAKE% -G "NMake Makefiles" .
- nmake -nologo -f Makefile clean
- nmake -nologo -f Makefile fribidi
- copy /Y /B lib\*.h %INCLIB%
- copy /Y /B *.lib %INCLIB%
- shell: cmd
-
+ run: "& winbuild\\build\\build_dep_fribidi.cmd"
- name: Build dependencies / Raqm
- run: |
- set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include
- set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32
- set BUILD=%GITHUB_WORKSPACE%\winbuild\build
- set INCLUDE=%INCLUDE%;%INCLIB%
- set LIB=%LIB%;%INCLIB%
- cd /D %BUILD%\libraqm-0.7.0
- call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.platform-vcvars }}
- echo on
- copy /Y /B %GITHUB_WORKSPACE%\winbuild\raqm.cmake CMakeLists.txt
- set CMAKE=cmake.exe -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_RULE_MESSAGES:BOOL=OFF
- set CMAKE=%CMAKE% -DCMAKE_BUILD_TYPE=Release
- %CMAKE% -G "NMake Makefiles" .
- nmake -nologo -f Makefile clean
- nmake -nologo -f Makefile libraqm
- copy /Y /B src\*.h %INCLIB%
- copy /Y /B libraqm.dll %INCLIB%
- shell: cmd
+ run: "& winbuild\\build\\build_dep_libraqm.cmd"
- name: Build Pillow
run: |
- set PYTHON=%pythonLocation%
- set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include
- set MPLSRC=%GITHUB_WORKSPACE%
- set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32
- cd /D %GITHUB_WORKSPACE%
- set LIB=%INCLIB%;%PYTHON%\tcl
- set INCLUDE=%INCLIB%;%GITHUB_WORKSPACE%\depends\tcl86\include;%INCLUDE%
- call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.platform-vcvars }}
- set MSSdk=1
- set DISTUTILS_USE_SDK=1
- set py_vcruntime_redist=true
- %PYTHON%\python.exe setup.py build_ext install
- rem Add libraqm.dll (copied to INCLIB) to PATH.
- path %INCLIB%;%PATH%
- %PYTHON%\python.exe selftest.py --installed
- shell: cmd
+ & winbuild\build\build_pillow.cmd install
+ & $env:pythonLocation\python.exe selftest.py --installed
+ shell: pwsh
# failing with PyPy3
- name: Enable heap verification
if: "!contains(matrix.python-version, 'pypy')"
- run: |
- c:\"Program Files (x86)"\"Windows Kits"\10\Debuggers\x86\gflags.exe /p /enable %PYTHON%\python.exe
- shell: cmd
+ run: "& 'C:\\Program Files (x86)\\Windows Kits\\10\\Debuggers\\x86\\gflags.exe' /p /enable $env:pythonLocation\\python.exe"
- name: Test Pillow
run: |
- set PYTHON=%pythonLocation%
- set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32
- rem Add libraqm.dll (copied to INCLIB) to PATH.
- path %INCLIB%;%PATH%
- cd /D %GITHUB_WORKSPACE%
- %PYTHON%\python.exe -m pytest -vx -W always --cov PIL --cov Tests --cov-report term --cov-report xml Tests
+ path %GITHUB_WORKSPACE%\\winbuild\\build\\bin;%PATH%
+ python.exe -m pytest -vx -W always --cov PIL --cov Tests --cov-report term --cov-report xml Tests
shell: cmd
- name: Prepare to upload errors
@@ -359,29 +137,20 @@ jobs:
- name: Upload coverage
uses: codecov/codecov-action@v1
with:
- file: ./coverage.xml
- flags: GHA_Windows
- name: ${{ runner.os }} Python ${{ matrix.python-version }}
+ file: ./coverage.xml
+ flags: GHA_Windows
+ name: ${{ runner.os }} Python ${{ matrix.python-version }} ${{ matrix.architecture }}
- name: Build wheel
id: wheel
- if: "github.event_name == 'push' && !contains(matrix.python-version, 'pypy')"
+ if: "github.event_name == 'push'"
run: |
- for /f "tokens=3 delims=/" %%a in ("${{ github.ref }}") do echo ##[set-output name=dist;]dist-%%a
for /f "tokens=3 delims=/" %%a in ("${{ github.ref }}") do echo ::set-output name=dist::dist-%%a
- set PYTHON=%pythonLocation%
- set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include
- set MPLSRC=%GITHUB_WORKSPACE%
- set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32
- cd /D %GITHUB_WORKSPACE%
- set LIB=%INCLIB%;%PYTHON%\tcl
- set INCLUDE=%INCLIB%;%GITHUB_WORKSPACE%\depends\tcl86\include;%INCLUDE%
- call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.platform-vcvars }}
- %PYTHON%\python.exe setup.py bdist_wheel
+ winbuild\\build\\build_pillow.cmd bdist_wheel"
shell: cmd
- - uses: actions/upload-artifact@v1
- if: "github.event_name == 'push' && !contains(matrix.python-version, 'pypy')"
+ - uses: actions/upload-artifact@v2
+ if: "github.event_name == 'push'"
with:
name: ${{ steps.wheel.outputs.dist }}
- path: dist
+ path: dist\*.whl
diff --git a/Tests/test_imageshow.py b/Tests/test_imageshow.py
index 0d513a47dc4..64f15326b40 100644
--- a/Tests/test_imageshow.py
+++ b/Tests/test_imageshow.py
@@ -1,7 +1,7 @@
import pytest
from PIL import Image, ImageShow
-from .helper import hopper, is_win32, on_ci, on_github_actions
+from .helper import hopper, is_win32, on_ci
def test_sanity():
@@ -38,8 +38,7 @@ def show_image(self, image, **options):
@pytest.mark.skipif(
- not on_ci() or (is_win32() and on_github_actions()),
- reason="Only run on CIs; hangs on Windows on GitHub Actions",
+ not on_ci() or is_win32(), reason="Only run on CIs; hangs on Windows CIs",
)
def test_show():
for mode in ("1", "I;16", "LA", "RGB", "RGBA"):
diff --git a/docs/installation.rst b/docs/installation.rst
index 58784ee1250..1b5f2e056e4 100644
--- a/docs/installation.rst
+++ b/docs/installation.rst
@@ -292,9 +292,10 @@ or from within the uncompressed source directory::
Building on Windows
^^^^^^^^^^^^^^^^^^^
-We don't recommend trying to build on Windows. It is a maze of twisty
-passages, mostly dead ends. There are build scripts and notes for the
-Windows build in the ``winbuild`` directory.
+We recommend you use prebuilt wheels from PyPI.
+If you wish to compile Pillow manually, you can use the build scripts
+in the ``winbuild`` directory used for CI testing and development.
+These scripts require Visual Studio 2017 or newer and NASM.
Building on FreeBSD
^^^^^^^^^^^^^^^^^^^
@@ -408,9 +409,11 @@ These platforms are built and tested for every change.
+----------------------------------+--------------------------+-----------------------+
| Ubuntu Linux 20.04 LTS | 3.8 |x86-64 |
+----------------------------------+--------------------------+-----------------------+
-| Windows Server 2012 R2 | 3.5, 3.8 |x86, x86-64 |
+| Windows Server 2016 | 3.8 |x86 |
| +--------------------------+-----------------------+
-| | PyPy3, 3.7/MinGW |x86 |
+| | 3.5 |x86-64 |
+| +--------------------------+-----------------------+
+| | 3.7/MinGW |x86 |
+----------------------------------+--------------------------+-----------------------+
| Windows Server 2019 | 3.5, 3.6, 3.7, 3.8 |x86, x86-64 |
| +--------------------------+-----------------------+
@@ -478,11 +481,13 @@ These platforms have been reported to work at the versions mentioned.
+----------------------------------+------------------------------+--------------------------------+-----------------------+
| FreeBSD 10.2 | 2.7, 3.4 | 3.1.0 |x86-64 |
+----------------------------------+------------------------------+--------------------------------+-----------------------+
+| Windows 10 | 3.7 | 7.1.0 |x86-64 |
++----------------------------------+------------------------------+--------------------------------+-----------------------+
| Windows 8.1 Pro | 2.6, 2.7, 3.2, 3.3, 3.4 | 2.4.0 |x86,x86-64 |
+----------------------------------+------------------------------+--------------------------------+-----------------------+
| Windows 8 Pro | 2.6, 2.7, 3.2, 3.3, 3.4a3 | 2.2.0 |x86,x86-64 |
+----------------------------------+------------------------------+--------------------------------+-----------------------+
-| Windows 7 Pro | 2.7, 3.2, 3.3 | 3.4.1 |x86-64 |
+| Windows 7 Professional | 3.7 | 7.0.0 |x86,x86-64 |
+----------------------------------+------------------------------+--------------------------------+-----------------------+
| Windows Server 2008 R2 Enterprise| 3.3 | |x86-64 |
+----------------------------------+------------------------------+--------------------------------+-----------------------+
diff --git a/winbuild/README.md b/winbuild/README.md
index 471b61a574f..d46361c9e8e 100644
--- a/winbuild/README.md
+++ b/winbuild/README.md
@@ -1,18 +1,30 @@
-Quick README
-------------
-
-For more extensive info, see the [Windows build instructions](build.rst).
-
-* See https://github.com/python-pillow/Pillow/issues/553#issuecomment-37877416 and https://github.com/matplotlib/matplotlib/issues/1717#issuecomment-13343859
-
-* Works best with Python 3.4, due to virtualenv and pip batteries included. Python3+ required for fetch command.
-* Check config.py for virtual env paths, suffix for 64-bit releases. Defaults to `x64`, set `X64_EXT` to change.
-* When running in CI with one Python per invocation, set the `PYTHON` env variable to the Python folder. (e.g. `PYTHON`=`c:\Python27\`) This overrides the matrix in config.py and will just build and test for the specific Python.
-* `python get_pythons.py` downloads all the Python releases, and their signatures. (Manually) Install in `c:\PythonXX[x64]\`.
-* `python build_dep.py` downloads and creates a build script for all the dependencies, in 32 and 64-bit versions, and with both compiler versions.
-* (in powershell) `build_deps.cmd` invokes the dependency build.
-* `python build.py --clean` makes Pillow for the matrix of Pythons.
-* `python test.py` runs the tests on Pillow in all the virtual envs.
-* Currently working with zlib, libjpeg, freetype, and libtiff on Python 2.7, and 3.4, both 32 and 64-bit, on a local win7 pro machine and appveyor.com
-* WebP is built, not detected.
-* LCMS, OpenJPEG and libimagequant are not building.
+Quick README
+------------
+
+For more extensive info, see the [Windows build instructions](build.rst).
+
+* See [Current Windows Build/Testing process (Pillow#553)](https://github.com/python-pillow/Pillow/issues/553#issuecomment-37877416),
+ [Definitive docs for how to compile on Windows (matplotlib#1717)](https://github.com/matplotlib/matplotlib/issues/1717#issuecomment-13343859),
+ [Test Windows with GitHub Actions (Pillow#4084)](https://github.com/python-pillow/Pillow/pull/4084).
+
+
+* Requires Microsoft Visual Studio 2017 or newer with C++ component.
+* Requires NASM for libjpeg-turbo, a required dependency when using this script.
+* Requires CMake 3.12 or newer (available as Visual Studio component).
+* Python 3.6+ is required to generate valid scripts, but builds targeting Python 3.5+ are supported.
+* Tested on Windows Server 2016 with Visual Studio 2017 Community (AppVeyor).
+* Tested on Windows Server 2019 with Visual Studio 2019 Enterprise (GitHub Actions).
+
+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 -v --depends=C:\pillow-depends
+build\build_dep_all.cmd
+build\build_pillow.cmd install
+cd ..
+path C:\Pillow\winbuild\build\bin;%PATH%
+%PYTHON%\python.exe selftest.py
+%PYTHON%\python.exe -m pytest -vx --cov PIL --cov Tests --cov-report term --cov-report xml Tests
+build\build_pillow.cmd bdist_wheel
+```
diff --git a/winbuild/appveyor_install_pypy3.cmd b/winbuild/appveyor_install_pypy3.cmd
deleted file mode 100644
index 4ec5384be4d..00000000000
--- a/winbuild/appveyor_install_pypy3.cmd
+++ /dev/null
@@ -1,3 +0,0 @@
-curl -fsSL -o pypy3.zip https://bitbucket.org/pypy/pypy/downloads/pypy3.6-v7.3.1-win32.zip
-7z x pypy3.zip -oc:\
-c:\Python37\Scripts\virtualenv.exe -p c:\pypy3.6-v7.3.1-win32\pypy3.exe c:\vp\pypy3
diff --git a/winbuild/build.py b/winbuild/build.py
deleted file mode 100755
index e565226bd92..00000000000
--- a/winbuild/build.py
+++ /dev/null
@@ -1,205 +0,0 @@
-#!/usr/bin/env python3
-
-import getopt
-import os
-import shutil
-import subprocess
-import sys
-
-from config import (
- VIRT_BASE,
- X64_EXT,
- bit_from_env,
- compiler_from_env,
- compilers,
- pythons,
- pyversion_from_env,
-)
-
-
-def setup_vms():
- ret = []
- for py in pythons:
- for arch in ("", X64_EXT):
- ret.append(
- "virtualenv -p c:/Python%s%s/python.exe --clear %s%s%s"
- % (py, arch, VIRT_BASE, py, arch)
- )
- ret.append(
- r"%s%s%s\Scripts\pip.exe install pytest pytest-cov"
- % (VIRT_BASE, py, arch)
- )
- return "\n".join(ret)
-
-
-def run_script(params):
- (version, script) = params
- try:
- print("Running %s" % version)
- filename = "build_pillow_%s.cmd" % version
- with open(filename, "w") as f:
- f.write(script)
-
- command = ["powershell", "./%s" % filename]
- proc = subprocess.Popen(
- command,
- stdin=subprocess.PIPE,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- )
- (trace, stderr) = proc.communicate()
- status = proc.returncode
- print("-- stderr --")
- print(stderr.decode())
- print("-- stdout --")
- print(trace.decode())
- print("Done with {}: {}".format(version, status))
- return (version, status, trace, stderr)
- except Exception as msg:
- print("Error with {}: {}".format(version, str(msg)))
- return (version, -1, "", str(msg))
-
-
-def header(op):
- return r"""
-setlocal
-set MPLSRC=%%~dp0\..
-set INCLIB=%%~dp0\depends
-set BLDOPT=%s
-cd /D %%MPLSRC%%
-""" % (
- op
- )
-
-
-def footer():
- return """endlocal
-exit
-"""
-
-
-def vc_setup(compiler, bit):
- script = ""
- if compiler["vc_version"] == "2015":
- arch = "x86" if bit == 32 else "x86_amd64"
- script = (
- r"""
-call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" %s
-echo on"""
- % arch
- )
- return script
-
-
-def build_one(py_ver, compiler, bit):
- # UNDONE virtual envs if we're not running on AppVeyor
- args = {}
- args.update(compiler)
- if "PYTHON" in os.environ:
- args["python_path"] = "%PYTHON%"
- else:
- args["python_path"] = "{}{}\\Scripts".format(VIRT_BASE, py_ver)
-
- args["executable"] = "python.exe"
- if "EXECUTABLE" in os.environ:
- args["executable"] = "%EXECUTABLE%"
-
- args["py_ver"] = py_ver
- args["tcl_ver"] = "86"
-
- if compiler["vc_version"] == "2015":
- args["imaging_libs"] = " build_ext --add-imaging-libs=msvcrt"
- else:
- args["imaging_libs"] = ""
-
- args["vc_setup"] = vc_setup(compiler, bit)
-
- script = r"""
-setlocal EnableDelayedExpansion
-call "%%ProgramFiles%%\Microsoft SDKs\Windows\%(env_version)s\Bin\SetEnv.Cmd" /Release %(env_flags)s
-set DISTUTILS_USE_SDK=1
-set LIB=%%LIB%%;%%INCLIB%%\%(inc_dir)s
-set INCLUDE=%%INCLUDE%%;%%INCLIB%%\%(inc_dir)s;%%INCLIB%%\tcl%(tcl_ver)s\include
-
-setlocal
-set LIB=%%LIB%%;C:\Python%(py_ver)s\tcl%(vc_setup)s
-call %(python_path)s\%(executable)s setup.py %(imaging_libs)s %%BLDOPT%%
-call %(python_path)s\%(executable)s -c "from PIL import _webp;import os, shutil;shutil.copy(r'%%INCLIB%%\freetype.dll', os.path.dirname(_webp.__file__));"
-endlocal
-
-endlocal
-""" # noqa: E501
- return script % args
-
-
-def clean():
- try:
- shutil.rmtree("../build")
- except Exception:
- # could already be removed
- pass
- run_script(("virtualenvs", setup_vms()))
-
-
-def main(op):
- scripts = []
-
- for py_version, py_info in pythons.items():
- py_compilers = compilers[py_info["compiler"]][py_info["vc"]]
- scripts.append(
- (
- py_version,
- "\n".join(
- [header(op), build_one(py_version, py_compilers[32], 32), footer()]
- ),
- )
- )
-
- scripts.append(
- (
- "{}{}".format(py_version, X64_EXT),
- "\n".join(
- [
- header(op),
- build_one("%sx64" % py_version, py_compilers[64], 64),
- footer(),
- ]
- ),
- )
- )
-
- results = map(run_script, scripts)
-
- for (version, status, trace, err) in results:
- print("Compiled {}: {}".format(version, status and "ERR" or "OK"))
-
-
-def run_one(op):
-
- compiler = compiler_from_env()
- py_version = pyversion_from_env()
- bit = bit_from_env()
-
- run_script(
- (
- py_version,
- "\n".join([header(op), build_one(py_version, compiler, bit), footer()]),
- )
- )
-
-
-if __name__ == "__main__":
- opts, args = getopt.getopt(sys.argv[1:], "", ["clean", "wheel"])
- opts = dict(opts)
-
- if "--clean" in opts:
- clean()
-
- op = "install"
- if "--wheel" in opts:
- op = "bdist_wheel"
-
- if "PYTHON" in os.environ:
- run_one(op)
- else:
- main(op)
diff --git a/winbuild/build.rst b/winbuild/build.rst
index 1d20840447a..517843a66b2 100644
--- a/winbuild/build.rst
+++ b/winbuild/build.rst
@@ -5,89 +5,112 @@ Building Pillow on Windows
<../docs/installation.rst#windows-installation>`_ should
be sufficient.
-This page will describe a build setup to build Pillow against the
-supported Python versions in 32 and 64-bit modes, using freely
-available Microsoft compilers. This has been developed and tested
-against 64-bit Windows 7 Professional and Windows Server 2012
-64-bit version on Amazon EC2.
+This page describes the steps necessary to build Pillow using the same
+scripts used on GitHub Actions and AppVeyor CIs.
Prerequisites
-------------
-Extra Build Helpers
-^^^^^^^^^^^^^^^^^^^
-* Powershell (available by default on Windows Server)
-* GitHub client (provides git+bash shell)
+Python
+^^^^^^
-Optional:
-* GPG (for checking signatures) (UNDONE -- Python signature checking)
+While the scripts can target any version of Python supported by Pillow,
+Python 3.6+ is required to generate valid build scripts.
+Compilers
+^^^^^^^^^
-Pythons
-^^^^^^^
+Download and install:
-The build routines expect Python to be installed at C:\PythonXX for
-32-bit versions or C:\PythonXXx64 for the 64-bit versions.
+* `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)
-Download Python 3.4, install it, and add it to the path. This is the
-Python that we will use to bootstrap the build process. (The download
-routines are using 3 features, and installing 3.4 gives us pip and
-virtualenv as well, reducing the number of packages that we need to
-install.)
+* `CMake 3.12 or newer `_
+ (also available as Visual Studio component C++ CMake tools for Windows)
-Download the rest of the Pythons by opening a command window, changing
-to the ``winbuild`` directory, and running ``python
-get_pythons.py``.
+* `NASM `_
-UNDONE -- gpg verify the signatures (note that we can download from
-https)
+Any version of Visual Studio 2017 or newer should be supported,
+including Visual Studio 2017 Community, or Build Tools for Visual Studio 2019.
-Run each installer and set the proper path to the installation. Don't
-set any of them as the default Python, or add them to the path.
+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
+-------------------
-Compilers
-^^^^^^^^^
-
-Download and install:
+The following environment variables, if set, will override the default
+behaviour of ``build_prepare.py``:
-* `Microsoft Windows SDK for Windows 7 and .NET Framework
- 4 `_
+* ``PYTHON`` + ``EXECUTABLE`` point to the target version of Python.
+ If ``PYTHON`` is unset, the version of Python used to run
+ ``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,
+ 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.
+ **Warning:** This directory is wiped when ``build_prepare.py`` is run.
+* ``PILLOW_DEPS`` points to the directory used to store downloaded
+ dependencies. By default ``winbuild\depends`` is used.
-* `CMake-2.8.10.2-win32-x86.exe
- `_
+``build_prepare.py`` also supports the following command line parameters:
-The samples and the .NET SDK portions aren't required, just the
-compilers and other tools. UNDONE -- check exact wording.
+* ``-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
------------
-The script 'build_dep.py' downloads and builds the dependencies. Open
-a command window, change directory into ``winbuild`` and run ``python
-build_dep.py``.
+Dependencies will be automatically downloaded by ``build_prepare.py``.
+By default, downloaded dependencies are stored in ``winbuild\depends``;
+set the ``PILLOW_DEPS`` environment variable to override this location.
-This will download libjpeg, libtiff, libz, and freetype. It will then
-compile 32 and 64-bit versions of the libraries, with both versions of
-the compilers.
-
-UNDONE -- lcms fails.
-UNDONE -- webp, jpeg2k not recognized
+To build all dependencies, run ``winbuild\build\build_dep_all.cmd``,
+or run the individual scripts to build each dependency separately.
Building Pillow
---------------
-Once the dependencies are built, run ``python build.py --clean`` to
-build and install Pillow in virtualenvs for each Python
-build. ``build.py --wheel`` will build wheels instead of
-installing into virtualenvs.
-
-UNDONE -- suppressed output, what about failures.
+Once the dependencies are built, run
+``winbuild\build\build_pillow.cmd install`` to build and install
+Pillow for the selected version of Python.
+``winbuild\build\build_pillow.cmd bdist_wheel`` will build wheels
+instead of installing Pillow.
Testing Pillow
--------------
-Build and install Pillow, then run ``python test.py`` from the
-``winbuild`` directory.
+Some binary dependencies (e.g. ``libraqm.dll``) will be stored in the
+``winbuild\build\bin`` directory; this directory should be added to ``PATH``
+before running tests.
+
+Build and install Pillow, then run ``python -m pytest Tests``
+from the root Pillow directory.
+
+Example
+-------
+
+The following is a simplified version of the script used on AppVeyor:
+
+.. code-block::
+ set PYTHON=C:\Python35\bin
+ cd /D C:\Pillow\winbuild
+ C:\Python37\bin\python.exe build_prepare.py -v --depends=C:\pillow-depends
+ build\build_dep_all.cmd
+ build\build_pillow.cmd install
+ cd ..
+ path C:\Pillow\winbuild\build\bin;%PATH%
+ %PYTHON%\python.exe selftest.py
+ %PYTHON%\python.exe -m pytest -vx --cov PIL --cov Tests --cov-report term --cov-report xml Tests
+ build\build_pillow.cmd bdist_wheel
diff --git a/winbuild/build_dep.py b/winbuild/build_dep.py
deleted file mode 100644
index 77857013938..00000000000
--- a/winbuild/build_dep.py
+++ /dev/null
@@ -1,328 +0,0 @@
-import os
-
-from build import vc_setup
-from config import all_compilers, bit_from_env, compiler_from_env, compilers, libs
-from fetch import fetch
-from untar import untar
-from unzip import unzip
-
-
-def _relpath(*args):
- return os.path.join(os.getcwd(), *args)
-
-
-build_dir = _relpath("build")
-inc_dir = _relpath("depends")
-
-
-def check_sig(filename, signame):
- # UNDONE -- need gpg
- return filename
-
-
-def mkdirs():
- try:
- os.mkdir(build_dir)
- except OSError:
- pass
- try:
- os.mkdir(inc_dir)
- except OSError:
- pass
- for compiler in all_compilers():
- try:
- os.mkdir(os.path.join(inc_dir, compiler["inc_dir"]))
- except OSError:
- pass
-
-
-def extract(src, dest):
- if ".zip" in src:
- return unzip(src, dest)
- if ".tar.gz" in src or ".tgz" in src:
- return untar(src, dest)
-
-
-def extract_libs():
- for name, lib in libs.items():
- filename = fetch(lib["url"])
- if name == "openjpeg":
- for compiler in all_compilers():
- if not os.path.exists(
- os.path.join(build_dir, lib["dir"] + compiler["inc_dir"])
- ):
- extract(filename, build_dir)
- os.rename(
- os.path.join(build_dir, lib["dir"]),
- os.path.join(build_dir, lib["dir"] + compiler["inc_dir"]),
- )
- else:
- extract(filename, build_dir)
-
-
-def extract_openjpeg(compiler):
- return (
- r"""
-rem build openjpeg
-setlocal
-cd %%BUILD%%
-mkdir %%INCLIB%%\openjpeg-2.0
-copy /Y /B openjpeg-2.0.0-win32-x86\include\openjpeg-2.0 %%INCLIB%%\openjpeg-2.0
-copy /Y /B openjpeg-2.0.0-win32-x86\bin\ %%INCLIB%%
-copy /Y /B openjpeg-2.0.0-win32-x86\lib\ %%INCLIB%%
-endlocal
-"""
- % compiler
- )
-
-
-def cp_tk(ver_85, ver_86):
- versions = {"ver_85": ver_85, "ver_86": ver_86}
- return (
- r"""
-mkdir %%INCLIB%%\tcl85\include\X11
-copy /Y /B %%BUILD%%\tcl%(ver_85)s\generic\*.h %%INCLIB%%\tcl85\include\
-copy /Y /B %%BUILD%%\tk%(ver_85)s\generic\*.h %%INCLIB%%\tcl85\include\
-copy /Y /B %%BUILD%%\tk%(ver_85)s\xlib\X11\* %%INCLIB%%\tcl85\include\X11\
-
-mkdir %%INCLIB%%\tcl86\include\X11
-copy /Y /B %%BUILD%%\tcl%(ver_86)s\generic\*.h %%INCLIB%%\tcl86\include\
-copy /Y /B %%BUILD%%\tk%(ver_86)s\generic\*.h %%INCLIB%%\tcl86\include\
-copy /Y /B %%BUILD%%\tk%(ver_86)s\xlib\X11\* %%INCLIB%%\tcl86\include\X11\
-"""
- % versions
- )
-
-
-def header():
- return r"""setlocal
-set MSBUILD=C:\Windows\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe
-set CMAKE="cmake.exe"
-set INCLIB=%~dp0\depends
-set BUILD=%~dp0\build
-""" + "\n".join(
- r"set {}=%BUILD%\{}".format(k.upper(), v["dir"])
- for (k, v) in libs.items()
- if v["dir"]
- )
-
-
-def setup_compiler(compiler):
- return (
- r"""setlocal EnableDelayedExpansion
-call "%%ProgramFiles%%\Microsoft SDKs\Windows\%(env_version)s\Bin\SetEnv.Cmd" /Release %(env_flags)s
-echo on
-set INCLIB=%%INCLIB%%\%(inc_dir)s
-""" # noqa: E501
- % compiler
- )
-
-
-def end_compiler():
- return """
-endlocal
-"""
-
-
-def nmake_openjpeg(compiler, bit):
- if compiler["env_version"] == "v7.0":
- return ""
-
- atts = {"op_ver": "2.3.1"}
- atts.update(compiler)
- return (
- r"""
-rem build openjpeg
-setlocal
-"""
- + vc_setup(compiler, bit)
- + r"""
-cd /D %%OPENJPEG%%%(inc_dir)s
-
-%%CMAKE%% -DBUILD_THIRDPARTY:BOOL=OFF -DBUILD_SHARED_LIBS:BOOL=OFF -DCMAKE_BUILD_TYPE=Release -G "NMake Makefiles" .
-nmake -nologo -f Makefile clean
-nmake -nologo -f Makefile
-copy /Y /B bin\* %%INCLIB%%
-mkdir %%INCLIB%%\openjpeg-%(op_ver)s
-copy /Y /B src\lib\openjp2\*.h %%INCLIB%%\openjpeg-%(op_ver)s
-endlocal
-""" # noqa: E501
- % atts
- )
-
-
-def nmake_libs(compiler, bit):
- # undone -- pre, makes, headers, libs
- script = (
- r"""
-rem Build libjpeg
-setlocal
-"""
- + vc_setup(compiler, bit)
- + r"""
-cd /D %%JPEG%%
-nmake -nologo -f makefile.vc setup-vc6
-nmake -nologo -f makefile.vc clean
-nmake -nologo -f makefile.vc nodebug=1 libjpeg.lib
-copy /Y /B *.dll %%INCLIB%%
-copy /Y /B *.lib %%INCLIB%%
-copy /Y /B j*.h %%INCLIB%%
-endlocal
-
-rem Build zlib
-setlocal
-cd /D %%ZLIB%%
-nmake -nologo -f win32\Makefile.msc clean
-nmake -nologo -f win32\Makefile.msc zlib.lib
-copy /Y /B *.dll %%INCLIB%%
-copy /Y /B *.lib %%INCLIB%%
-copy /Y /B zlib.lib %%INCLIB%%\z.lib
-copy /Y /B zlib.h %%INCLIB%%
-copy /Y /B zconf.h %%INCLIB%%
-endlocal
-
-rem Build webp
-setlocal
-"""
- + vc_setup(compiler, bit)
- + r"""
-cd /D %%WEBP%%
-rd /S /Q %%WEBP%%\output\release-static
-nmake -nologo -f Makefile.vc CFG=release-static RTLIBCFG=static OBJDIR=output all
-copy /Y /B output\release-static\%(webp_platform)s\lib\* %%INCLIB%%
-mkdir %%INCLIB%%\webp
-copy /Y /B src\webp\*.h %%INCLIB%%\\webp
-endlocal
-
-rem Build libtiff
-setlocal
-"""
- + vc_setup(compiler, bit)
- + r"""
-rem do after building jpeg and zlib
-copy %%~dp0\tiff.opt %%TIFF%%\nmake.opt
-
-cd /D %%TIFF%%
-nmake -nologo -f makefile.vc clean
-nmake -nologo -f makefile.vc lib
-copy /Y /B libtiff\*.dll %%INCLIB%%
-copy /Y /B libtiff\*.lib %%INCLIB%%
-copy /Y /B libtiff\tiff*.h %%INCLIB%%
-endlocal
-"""
- )
- return script % compiler
-
-
-def msbuild_freetype(compiler, bit):
- script = r"""
-rem Build freetype
-setlocal
-rd /S /Q %%FREETYPE%%\objs
-set DefaultPlatformToolset=v100
-"""
- properties = r"""/p:Configuration="Release" /p:Platform=%(platform)s"""
- if bit == 64:
- script += (
- r"copy /Y /B "
- r'"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Lib\x64\*.Lib" '
- r"%%FREETYPE%%\builds\windows\vc2010"
- )
- properties += r" /p:_IsNativeEnvironment=false"
- script += (
- r"""
-%%MSBUILD%% %%FREETYPE%%\builds\windows\vc2010\freetype.sln /t:Clean;Build """
- + properties
- + r""" /m
-xcopy /Y /E /Q %%FREETYPE%%\include %%INCLIB%%
-"""
- )
- freetypeReleaseDir = r"%%FREETYPE%%\objs\%(platform)s\Release"
- script += (
- r"""
-copy /Y /B """
- + freetypeReleaseDir
- + r"""\freetype.lib %%INCLIB%%\freetype.lib
-copy /Y /B """
- + freetypeReleaseDir
- + r"""\freetype.dll %%INCLIB%%\..\freetype.dll
-endlocal
-"""
- )
- return script % compiler
-
-
-def build_lcms2(compiler):
- if compiler["env_version"] == "v7.1":
- return build_lcms_71(compiler)
- return build_lcms_70(compiler)
-
-
-def build_lcms_70(compiler):
- """Link error here on x64"""
- if compiler["platform"] == "x64":
- return ""
-
- """Build LCMS on VC2008. This version is only 32bit/Win32"""
- return (
- r"""
-rem Build lcms2
-setlocal
-set LCMS=%%LCMS-2.7%%
-rd /S /Q %%LCMS%%\Lib
-rd /S /Q %%LCMS%%\Projects\VC%(vc_version)s\Release
-%%MSBUILD%% %%LCMS%%\Projects\VC%(vc_version)s\lcms2.sln /t:Clean /p:Configuration="Release" /p:Platform=Win32 /m
-%%MSBUILD%% %%LCMS%%\Projects\VC%(vc_version)s\lcms2.sln /t:lcms2_static /p:Configuration="Release" /p:Platform=Win32 /p:PlatformToolset=v90 /m
-xcopy /Y /E /Q %%LCMS%%\include %%INCLIB%%
-copy /Y /B %%LCMS%%\Lib\MS\*.lib %%INCLIB%%
-endlocal
-""" # noqa: E501
- % compiler
- )
-
-
-def build_lcms_71(compiler):
- return (
- r"""
-rem Build lcms2
-setlocal
-set LCMS=%%LCMS-2.8%%
-rd /S /Q %%LCMS%%\Lib
-rd /S /Q %%LCMS%%\Projects\VC%(vc_version)s\Release
-powershell -Command "(gc Projects\VC2015\lcms2_static\lcms2_static.vcxproj) -replace 'MultiThreadedDLL', 'MultiThreaded' | Out-File -encoding ASCII Projects\VC2015\lcms2_static\lcms2_static.vcxproj"
-%%MSBUILD%% %%LCMS%%\Projects\VC%(vc_version)s\lcms2.sln /t:Clean /p:Configuration="Release" /p:Platform=%(platform)s /m
-%%MSBUILD%% %%LCMS%%\Projects\VC%(vc_version)s\lcms2.sln /t:lcms2_static /p:Configuration="Release" /p:Platform=%(platform)s /m
-xcopy /Y /E /Q %%LCMS%%\include %%INCLIB%%
-copy /Y /B %%LCMS%%\Lib\MS\*.lib %%INCLIB%%
-endlocal
-""" # noqa: E501
- % compiler
- )
-
-
-def add_compiler(compiler, bit):
- script.append(setup_compiler(compiler))
- script.append(nmake_libs(compiler, bit))
-
- # script.append(extract_openjpeg(compiler))
-
- script.append(msbuild_freetype(compiler, bit))
- script.append(build_lcms2(compiler))
- script.append(nmake_openjpeg(compiler, bit))
- script.append(end_compiler())
-
-
-mkdirs()
-extract_libs()
-script = [header(), cp_tk(libs["tk-8.5"]["version"], libs["tk-8.6"]["version"])]
-
-
-if "PYTHON" in os.environ:
- add_compiler(compiler_from_env(), bit_from_env())
-else:
- # for compiler in all_compilers():
- # add_compiler(compiler)
- add_compiler(compilers[7.0][2010][32], 32)
-
-with open("build_deps.cmd", "w") as f:
- f.write("\n".join(script))
diff --git a/winbuild/build_prepare.py b/winbuild/build_prepare.py
new file mode 100644
index 00000000000..e42f471908d
--- /dev/null
+++ b/winbuild/build_prepare.py
@@ -0,0 +1,557 @@
+import os
+import shutil
+import struct
+import subprocess
+import sys
+
+
+def cmd_cd(path):
+ return "cd /D {path}".format(**locals())
+
+
+def cmd_set(name, value):
+ return "set {name}={value}".format(**locals())
+
+
+def cmd_append(name, value):
+ op = "path " if name == "PATH" else "set {name}="
+ return (op + "%{name}%;{value}").format(**locals())
+
+
+def cmd_copy(src, tgt):
+ return 'copy /Y /B "{src}" "{tgt}"'.format(**locals())
+
+
+def cmd_xcopy(src, tgt):
+ return 'xcopy /Y /E "{src}" "{tgt}"'.format(**locals())
+
+
+def cmd_mkdir(path):
+ return 'mkdir "{path}"'.format(**locals())
+
+
+def cmd_rmdir(path):
+ return 'rmdir /S /Q "{path}"'.format(**locals())
+
+
+def cmd_nmake(makefile=None, target="", params=None):
+ if params is None:
+ params = ""
+ elif isinstance(params, list) or isinstance(params, tuple):
+ params = " ".join(params)
+ else:
+ params = str(params)
+
+ return " ".join(
+ [
+ "{{nmake}}",
+ "-nologo",
+ '-f "{makefile}"' if makefile is not None else "",
+ "{params}",
+ '"{target}"',
+ ]
+ ).format(**locals())
+
+
+def cmd_cmake(params=None, file="."):
+ if params is None:
+ params = ""
+ elif isinstance(params, list) or isinstance(params, tuple):
+ params = " ".join(params)
+ else:
+ params = str(params)
+ return " ".join(
+ [
+ "{{cmake}}",
+ "-DCMAKE_VERBOSE_MAKEFILE=ON",
+ "-DCMAKE_RULE_MESSAGES:BOOL=OFF",
+ "-DCMAKE_BUILD_TYPE=Release",
+ "{params}",
+ '-G "NMake Makefiles"',
+ '"{file}"',
+ ]
+ ).format(**locals())
+
+
+def cmd_msbuild(
+ file, configuration="Release", target="Build", platform="{msbuild_arch}"
+):
+ return " ".join(
+ [
+ "{{msbuild}}",
+ "{file}",
+ '/t:"{target}"',
+ '/p:Configuration="{configuration}"',
+ "/p:Platform={platform}",
+ "/m",
+ ]
+ ).format(**locals())
+
+
+SF_MIRROR = "http://iweb.dl.sourceforge.net"
+
+architectures = {
+ "x86": {"vcvars_arch": "x86", "msbuild_arch": "Win32"},
+ "x64": {"vcvars_arch": "x86_amd64", "msbuild_arch": "x64"},
+}
+
+header = [
+ cmd_set("INCLUDE", "{inc_dir}"),
+ cmd_set("INCLIB", "{lib_dir}"),
+ cmd_set("LIB", "{lib_dir}"),
+ cmd_append("PATH", "{bin_dir}"),
+]
+
+# dependencies, listed in order of compilation
+deps = {
+ "libjpeg": {
+ "url": SF_MIRROR + "/project/libjpeg-turbo/2.0.3/libjpeg-turbo-2.0.3.tar.gz",
+ "filename": "libjpeg-turbo-2.0.3.tar.gz",
+ "dir": "libjpeg-turbo-2.0.3",
+ "build": [
+ cmd_cmake(
+ [
+ "-DENABLE_SHARED:BOOL=FALSE",
+ "-DWITH_JPEG8:BOOL=TRUE",
+ "-DWITH_CRT_DLL:BOOL=TRUE",
+ ]
+ ),
+ cmd_nmake(target="clean"),
+ cmd_nmake(target="jpeg-static"),
+ cmd_copy("jpeg-static.lib", "libjpeg.lib"),
+ cmd_nmake(target="cjpeg-static"),
+ cmd_copy("cjpeg-static.exe", "cjpeg.exe"),
+ cmd_nmake(target="djpeg-static"),
+ cmd_copy("djpeg-static.exe", "djpeg.exe"),
+ ],
+ "headers": ["j*.h"],
+ "libs": ["libjpeg.lib"],
+ "bins": ["cjpeg.exe", "djpeg.exe"],
+ },
+ "zlib": {
+ "url": "http://zlib.net/zlib1211.zip",
+ "filename": "zlib1211.zip",
+ "dir": "zlib-1.2.11",
+ "build": [
+ cmd_nmake(r"win32\Makefile.msc", "clean"),
+ cmd_nmake(r"win32\Makefile.msc", "zlib.lib"),
+ cmd_copy("zlib.lib", "z.lib"),
+ ],
+ "headers": [r"z*.h"],
+ "libs": [r"*.lib"],
+ },
+ "libtiff": {
+ "url": "https://download.osgeo.org/libtiff/tiff-4.1.0.tar.gz",
+ "filename": "tiff-4.1.0.tar.gz",
+ "dir": "tiff-4.1.0",
+ "build": [
+ cmd_copy(r"{winbuild_dir}\tiff.opt", "nmake.opt"),
+ cmd_nmake("makefile.vc", "clean"),
+ cmd_nmake("makefile.vc", "lib"),
+ ],
+ "headers": [r"libtiff\tiff*.h"],
+ "libs": [r"libtiff\*.lib"],
+ # "bins": [r"libtiff\*.dll"],
+ },
+ "libwebp": {
+ "url": "http://downloads.webmproject.org/releases/webp/libwebp-1.1.0.tar.gz", # noqa: E501
+ "filename": "libwebp-1.1.0.tar.gz",
+ "dir": "libwebp-1.1.0",
+ "build": [
+ cmd_rmdir(r"output\release-static"), # clean
+ cmd_nmake(
+ "Makefile.vc",
+ "all",
+ ["CFG=release-static", "OBJDIR=output", "ARCH={architecture}"],
+ ),
+ cmd_mkdir(r"{inc_dir}\webp"),
+ cmd_copy(r"src\webp\*.h", r"{inc_dir}\webp"),
+ ],
+ "libs": [r"output\release-static\{architecture}\lib\*.lib"],
+ },
+ "freetype": {
+ "url": "https://download.savannah.gnu.org/releases/freetype/freetype-2.10.2.tar.gz", # noqa: E501
+ "filename": "freetype-2.10.2.tar.gz",
+ "dir": "freetype-2.10.2",
+ "patch": {
+ 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": [
+ cmd_rmdir("objs"),
+ cmd_msbuild(
+ r"builds\windows\vc2010\freetype.sln", "Release Static", "Clean"
+ ),
+ cmd_msbuild(
+ r"builds\windows\vc2010\freetype.sln", "Release Static", "Build"
+ ),
+ cmd_xcopy("include", "{inc_dir}"),
+ ],
+ "libs": [r"objs\{msbuild_arch}\Release Static\freetype.lib"],
+ # "bins": [r"objs\{msbuild_arch}\Release\freetype.dll"],
+ },
+ "lcms2": {
+ "url": SF_MIRROR + "/project/lcms/lcms/2.9/lcms2-2.9.tar.gz",
+ "filename": "lcms2-2.9.tar.gz",
+ "dir": "lcms2-2.9",
+ "patch": {
+ r"Projects\VC2017\lcms2_static\lcms2_static.vcxproj": {
+ # default is /MD for x86 and /MT for x64, we need /MD always
+ "MultiThreaded": "MultiThreadedDLL", # noqa: E501
+ # retarget to default toolset (selected by vcvarsall.bat)
+ "v141": "$(DefaultPlatformToolset)", # noqa: E501
+ # retarget to latest (selected by vcvarsall.bat)
+ "8.1": "$(WindowsSDKVersion)", # noqa: E501
+ }
+ },
+ "build": [
+ cmd_rmdir("Lib"),
+ cmd_rmdir(r"Projects\VC2017\Release"),
+ cmd_msbuild(r"Projects\VC2017\lcms2.sln", "Release", "Clean"),
+ cmd_msbuild(r"Projects\VC2017\lcms2.sln", "Release", "lcms2_static"),
+ cmd_xcopy("include", "{inc_dir}"),
+ ],
+ "libs": [r"Lib\MS\*.lib"],
+ },
+ "openjpeg": {
+ "url": "https://github.com/uclouvain/openjpeg/archive/v2.3.1.tar.gz",
+ "filename": "openjpeg-2.3.1.tar.gz",
+ "dir": "openjpeg-2.3.1",
+ "build": [
+ cmd_cmake(("-DBUILD_THIRDPARTY:BOOL=OFF", "-DBUILD_SHARED_LIBS:BOOL=OFF")),
+ cmd_nmake(target="clean"),
+ cmd_nmake(target="openjp2"),
+ cmd_mkdir(r"{inc_dir}\openjpeg-2.3.1"),
+ cmd_copy(r"src\lib\openjp2\*.h", r"{inc_dir}\openjpeg-2.3.1"),
+ ],
+ "libs": [r"bin\*.lib"],
+ },
+ "libimagequant": {
+ # e5d454b: Merge tag '2.12.6' into msvc
+ "url": "https://github.com/ImageOptim/libimagequant/archive/e5d454bc7f5eb63ee50c84a83a7fa5ac94f68ec4.zip", # noqa: E501
+ "filename": "libimagequant-e5d454bc7f5eb63ee50c84a83a7fa5ac94f68ec4.zip",
+ "dir": "libimagequant-e5d454bc7f5eb63ee50c84a83a7fa5ac94f68ec4",
+ "patch": {
+ "CMakeLists.txt": {
+ "add_library": "add_compile_options(-openmp-)\r\nadd_library",
+ " SHARED": " STATIC",
+ }
+ },
+ "build": [
+ # lint: do not inline
+ cmd_cmake(),
+ cmd_nmake(target="clean"),
+ cmd_nmake(),
+ ],
+ "headers": [r"*.h"],
+ "libs": [r"*.lib"],
+ },
+ "harfbuzz": {
+ "url": "https://github.com/harfbuzz/harfbuzz/archive/2.6.4.zip",
+ "filename": "harfbuzz-2.6.4.zip",
+ "dir": "harfbuzz-2.6.4",
+ "build": [
+ cmd_cmake("-DHB_HAVE_FREETYPE:BOOL=TRUE"),
+ cmd_nmake(target="clean"),
+ cmd_nmake(target="harfbuzz"),
+ ],
+ "headers": [r"src\*.h"],
+ "libs": [r"*.lib"],
+ },
+ "fribidi": {
+ "url": "https://github.com/fribidi/fribidi/archive/v1.0.9.zip",
+ "filename": "fribidi-1.0.9.zip",
+ "dir": "fribidi-1.0.9",
+ "build": [
+ cmd_copy(r"{winbuild_dir}\fribidi.cmake", r"CMakeLists.txt"),
+ cmd_cmake(),
+ cmd_nmake(target="clean"),
+ cmd_nmake(target="fribidi"),
+ ],
+ "headers": [r"lib\*.h"],
+ "libs": [r"*.lib"],
+ },
+ "libraqm": {
+ "url": "https://github.com/HOST-Oman/libraqm/archive/v0.7.0.zip",
+ "filename": "libraqm-0.7.0.zip",
+ "dir": "libraqm-0.7.0",
+ "build": [
+ cmd_copy(r"{winbuild_dir}\raqm.cmake", r"CMakeLists.txt"),
+ cmd_cmake(),
+ cmd_nmake(target="clean"),
+ cmd_nmake(target="libraqm"),
+ ],
+ "headers": [r"src\*.h"],
+ "bins": [r"libraqm.dll"],
+ },
+}
+
+
+# based on distutils._msvccompiler from CPython 3.7.4
+def find_msvs():
+ root = os.environ.get("ProgramFiles(x86)") or os.environ.get("ProgramFiles")
+ if not root:
+ print("Program Files not found")
+ return None
+
+ try:
+ vspath = (
+ subprocess.check_output(
+ [
+ os.path.join(
+ root, "Microsoft Visual Studio", "Installer", "vswhere.exe"
+ ),
+ "-latest",
+ "-prerelease",
+ "-requires",
+ "Microsoft.VisualStudio.Component.VC.Tools.x86.x64",
+ "-property",
+ "installationPath",
+ "-products",
+ "*",
+ ]
+ )
+ .decode(encoding="mbcs")
+ .strip()
+ )
+ except (subprocess.CalledProcessError, OSError, UnicodeDecodeError):
+ print("vswhere not found")
+ return None
+
+ if not os.path.isdir(os.path.join(vspath, "VC", "Auxiliary", "Build")):
+ print("Visual Studio seems to be missing C compiler")
+ return None
+
+ vs = {
+ "header": [],
+ # nmake selected by vcvarsall
+ "nmake": "nmake.exe",
+ "vs_dir": vspath,
+ }
+
+ # vs2017
+ msbuild = os.path.join(vspath, "MSBuild", "15.0", "Bin", "MSBuild.exe")
+ if os.path.isfile(msbuild):
+ vs["msbuild"] = '"{}"'.format(msbuild)
+ else:
+ # vs2019
+ msbuild = os.path.join(vspath, "MSBuild", "Current", "Bin", "MSBuild.exe")
+ if os.path.isfile(msbuild):
+ vs["msbuild"] = '"{}"'.format(msbuild)
+ else:
+ print("Visual Studio MSBuild not found")
+ return None
+
+ vcvarsall = os.path.join(vspath, "VC", "Auxiliary", "Build", "vcvarsall.bat")
+ if not os.path.isfile(vcvarsall):
+ print("Visual Studio vcvarsall not found")
+ return None
+ vs["header"].append('call "{}" {{vcvars_arch}}'.format(vcvarsall))
+
+ return vs
+
+
+def extract_dep(url, filename):
+ import urllib.request
+ import tarfile
+ import zipfile
+
+ file = os.path.join(depends_dir, filename)
+ if not os.path.exists(file):
+ ex = None
+ for i in range(3):
+ try:
+ print("Fetching %s (attempt %d)..." % (url, i + 1))
+ content = urllib.request.urlopen(url).read()
+ with open(file, "wb") as f:
+ f.write(content)
+ break
+ except urllib.error.URLError as e:
+ ex = e
+ else:
+ raise RuntimeError(ex)
+
+ print("Extracting " + filename)
+ if filename.endswith(".zip"):
+ with zipfile.ZipFile(file) as zf:
+ zf.extractall(build_dir)
+ elif filename.endswith(".tar.gz") or filename.endswith(".tgz"):
+ with tarfile.open(file, "r:gz") as tgz:
+ tgz.extractall(build_dir)
+ else:
+ raise RuntimeError("Unknown archive type: " + filename)
+
+
+def write_script(name, lines):
+ name = os.path.join(build_dir, name)
+ lines = [line.format(**prefs) for line in lines]
+ print("Writing " + name)
+ with open(name, "w") as f:
+ f.write("\n\r".join(lines))
+ if verbose:
+ for line in lines:
+ print(" " + line)
+
+
+def get_footer(dep):
+ lines = []
+ for out in dep.get("headers", []):
+ lines.append(cmd_copy(out, "{inc_dir}"))
+ for out in dep.get("libs", []):
+ lines.append(cmd_copy(out, "{lib_dir}"))
+ for out in dep.get("bins", []):
+ lines.append(cmd_copy(out, "{bin_dir}"))
+ return lines
+
+
+def build_dep(name):
+ dep = deps[name]
+ dir = dep["dir"]
+ file = "build_dep_{name}.cmd".format(**locals())
+
+ extract_dep(dep["url"], dep["filename"])
+
+ for patch_file, patch_list in dep.get("patch", {}).items():
+ patch_file = os.path.join(build_dir, dir, patch_file.format(**prefs))
+ with open(patch_file, "r") as f:
+ text = f.read()
+ for patch_from, patch_to in patch_list.items():
+ text = text.replace(patch_from.format(**prefs), patch_to.format(**prefs))
+ with open(patch_file, "w") as f:
+ f.write(text)
+
+ banner = "Building {name} ({dir})".format(**locals())
+ lines = [
+ "@echo " + ("=" * 70),
+ "@echo ==== {:<60} ====".format(banner),
+ "@echo " + ("=" * 70),
+ "cd /D %s" % os.path.join(build_dir, dir),
+ *prefs["header"],
+ *dep.get("build", []),
+ *get_footer(dep),
+ ]
+
+ write_script(file, lines)
+ return file
+
+
+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!")
+ write_script("build_dep_all.cmd", lines)
+
+
+def build_pillow():
+ lines = [
+ "@echo ---- Building Pillow (build_ext %*) ----",
+ cmd_cd("{pillow_dir}"),
+ *prefs["header"],
+ cmd_set("DISTUTILS_USE_SDK", "1"), # use same compiler to build Pillow
+ cmd_set("MSSdk", "1"), # for Python 3.5 and PyPy3.6
+ cmd_set("py_vcruntime_redist", "true"), # use /MD, not /MT
+ r'"{python_dir}\{python_exe}" setup.py build_ext %*',
+ ]
+
+ write_script("build_pillow.cmd", lines)
+
+
+if __name__ == "__main__":
+ # winbuild directory
+ winbuild_dir = os.path.dirname(os.path.realpath(__file__))
+
+ verbose = False
+ disabled = []
+ depends_dir = os.environ.get("PILLOW_DEPS", os.path.join(winbuild_dir, "depends"))
+ python_dir = os.environ.get("PYTHON")
+ python_exe = os.environ.get("EXECUTABLE", "python.exe")
+ architecture = os.environ.get(
+ "ARCHITECTURE", "x86" if struct.calcsize("P") == 4 else "x64"
+ )
+ build_dir = os.environ.get("PILLOW_BUILD", os.path.join(winbuild_dir, "build"))
+ 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="):
+ depends_dir = arg[10:]
+ elif arg.startswith("--python="):
+ python_dir = arg[9:]
+ elif arg.startswith("--executable="):
+ python_exe = arg[13:]
+ elif arg.startswith("--architecture="):
+ architecture = arg[15:]
+ elif arg.startswith("--dir="):
+ build_dir = arg[6:]
+ else:
+ raise ValueError("Unknown parameter: " + arg)
+
+ # dependency cache directory
+ os.makedirs(depends_dir, exist_ok=True)
+ print("Caching dependencies in:", depends_dir)
+
+ if python_dir is None:
+ python_dir = os.path.dirname(os.path.realpath(sys.executable))
+ python_exe = os.path.basename(sys.executable)
+ print("Target Python:", os.path.join(python_dir, python_exe))
+
+ arch_prefs = architectures[architecture]
+ print("Target Architecture:", architecture)
+
+ msvs = find_msvs()
+ if msvs is None:
+ raise RuntimeError(
+ "Visual Studio not found. Please install Visual Studio 2017 or newer."
+ )
+ print("Found Visual Studio at:", msvs["vs_dir"])
+
+ print("Using output directory:", build_dir)
+
+ # build directory for *.h files
+ inc_dir = os.path.join(build_dir, "inc")
+ # build directory for *.lib files
+ lib_dir = os.path.join(build_dir, "lib")
+ # build directory for *.bin files
+ bin_dir = os.path.join(build_dir, "bin")
+
+ shutil.rmtree(build_dir, ignore_errors=True)
+ for path in [build_dir, inc_dir, lib_dir, bin_dir]:
+ os.makedirs(path)
+
+ prefs = {
+ # Python paths / preferences
+ "python_dir": python_dir,
+ "python_exe": python_exe,
+ "architecture": architecture,
+ **arch_prefs,
+ # Pillow paths
+ "pillow_dir": os.path.realpath(os.path.join(winbuild_dir, "..")),
+ "winbuild_dir": winbuild_dir,
+ # Build paths
+ "build_dir": build_dir,
+ "inc_dir": inc_dir,
+ "lib_dir": lib_dir,
+ "bin_dir": bin_dir,
+ # Compilers / Tools
+ **msvs,
+ "cmake": "cmake.exe", # TODO find CMAKE automatically
+ # TODO find NASM automatically
+ # script header
+ "header": sum([header, msvs["header"], ["@echo on"]], []),
+ }
+
+ print()
+
+ build_dep_all()
+ build_pillow()
diff --git a/winbuild/config.py b/winbuild/config.py
deleted file mode 100644
index 6d512945cd8..00000000000
--- a/winbuild/config.py
+++ /dev/null
@@ -1,199 +0,0 @@
-import os
-
-SF_MIRROR = "https://iweb.dl.sourceforge.net"
-
-pythons = {
- "pypy3": {"compiler": 7.1, "vc": 2015},
- # for AppVeyor
- "35": {"compiler": 7.1, "vc": 2015},
- "36": {"compiler": 7.1, "vc": 2015},
- "37": {"compiler": 7.1, "vc": 2015},
- "38": {"compiler": 7.1, "vc": 2015},
- # for GitHub Actions
- "3.5": {"compiler": 7.1, "vc": 2015},
- "3.6": {"compiler": 7.1, "vc": 2015},
- "3.7": {"compiler": 7.1, "vc": 2015},
- "3.8": {"compiler": 7.1, "vc": 2015},
-}
-
-VIRT_BASE = "c:/vp/"
-X64_EXT = os.environ.get("X64_EXT", "x64")
-
-libs = {
- # 'openjpeg': {
- # 'filename': 'openjpeg-2.0.0-win32-x86.zip',
- # 'version': '2.0'
- # },
- "zlib": {
- "url": "http://zlib.net/zlib1211.zip",
- "filename": "zlib1211.zip",
- "dir": "zlib-1.2.11",
- },
- "jpeg": {
- "url": "http://www.ijg.org/files/jpegsr9d.zip",
- "filename": "jpegsr9d.zip",
- "dir": "jpeg-9d",
- },
- "tiff": {
- "url": "ftp://download.osgeo.org/libtiff/tiff-4.1.0.tar.gz",
- "filename": "tiff-4.1.0.tar.gz",
- "dir": "tiff-4.1.0",
- },
- "freetype": {
- "url": "https://download.savannah.gnu.org/releases/freetype/freetype-2.10.2.tar.gz", # noqa: E501
- "filename": "freetype-2.10.2.tar.gz",
- "dir": "freetype-2.10.2",
- },
- "lcms-2.7": {
- "url": SF_MIRROR + "/project/lcms/lcms/2.7/lcms2-2.7.zip",
- "filename": "lcms2-2.7.zip",
- "dir": "lcms2-2.7",
- },
- "lcms-2.8": {
- "url": SF_MIRROR + "/project/lcms/lcms/2.8/lcms2-2.8.zip",
- "filename": "lcms2-2.8.zip",
- "dir": "lcms2-2.8",
- },
- "tcl-8.5": {
- "url": SF_MIRROR + "/project/tcl/Tcl/8.5.19/tcl8519-src.zip",
- "filename": "tcl8519-src.zip",
- "dir": "",
- },
- "tk-8.5": {
- "url": SF_MIRROR + "/project/tcl/Tcl/8.5.19/tk8519-src.zip",
- "filename": "tk8519-src.zip",
- "dir": "",
- "version": "8.5.19",
- },
- "tcl-8.6": {
- "url": SF_MIRROR + "/project/tcl/Tcl/8.6.10/tcl8610-src.zip",
- "filename": "tcl8610-src.zip",
- "dir": "",
- },
- "tk-8.6": {
- "url": SF_MIRROR + "/project/tcl/Tcl/8.6.10/tk8610-src.zip",
- "filename": "tk8610-src.zip",
- "dir": "",
- "version": "8.6.10",
- },
- "webp": {
- "url": "http://downloads.webmproject.org/releases/webp/libwebp-1.1.0.tar.gz",
- "filename": "libwebp-1.1.0.tar.gz",
- "dir": "libwebp-1.1.0",
- },
- "openjpeg": {
- "url": "https://github.com/uclouvain/openjpeg/archive/v2.3.1.tar.gz",
- "filename": "openjpeg-2.3.1.tar.gz",
- "dir": "openjpeg-2.3.1",
- },
- "jpeg-turbo": {
- "url": SF_MIRROR + "/project/libjpeg-turbo/2.0.3/libjpeg-turbo-2.0.3.tar.gz",
- "filename": "libjpeg-turbo-2.0.3.tar.gz",
- "dir": "libjpeg-turbo-2.0.3",
- },
- # e5d454b: Merge tag '2.12.6' into msvc
- "imagequant": {
- "url": "https://github.com/ImageOptim/libimagequant/archive/e5d454bc7f5eb63ee50c84a83a7fa5ac94f68ec4.zip", # noqa: E501
- "filename": "libimagequant-e5d454bc7f5eb63ee50c84a83a7fa5ac94f68ec4.zip",
- "dir": "libimagequant-e5d454bc7f5eb63ee50c84a83a7fa5ac94f68ec4",
- },
- "harfbuzz": {
- "url": "https://github.com/harfbuzz/harfbuzz/archive/2.6.4.zip",
- "filename": "harfbuzz-2.6.4.zip",
- "dir": "harfbuzz-2.6.4",
- },
- "fribidi": {
- "url": "https://github.com/fribidi/fribidi/archive/v1.0.9.zip",
- "filename": "fribidi-1.0.9.zip",
- "dir": "fribidi-1.0.9",
- },
- "libraqm": {
- "url": "https://github.com/HOST-Oman/libraqm/archive/v0.7.0.zip",
- "filename": "libraqm-0.7.0.zip",
- "dir": "libraqm-0.7.0",
- },
-}
-
-compilers = {
- 7: {
- 2010: {
- 64: {
- "env_version": "v7.0",
- "vc_version": "2010",
- "env_flags": "/x64 /xp",
- "inc_dir": "msvcr90-x64",
- "platform": "x64",
- "webp_platform": "x64",
- },
- 32: {
- "env_version": "v7.0",
- "vc_version": "2010",
- "env_flags": "/x86 /xp",
- "inc_dir": "msvcr90-x32",
- "platform": "Win32",
- "webp_platform": "x86",
- },
- }
- },
- 7.1: {
- 2015: {
- 64: {
- "env_version": "v7.1",
- "vc_version": "2015",
- "env_flags": "/x64 /vista",
- "inc_dir": "msvcr10-x64",
- "platform": "x64",
- "webp_platform": "x64",
- },
- 32: {
- "env_version": "v7.1",
- "vc_version": "2015",
- "env_flags": "/x86 /vista",
- "inc_dir": "msvcr10-x32",
- "platform": "Win32",
- "webp_platform": "x86",
- },
- }
- },
-}
-
-
-def pyversion_from_env():
- py = os.environ["PYTHON"]
-
- py_version = "35"
- for k in pythons:
- if k in py:
- py_version = k
- break
-
- if "64" in py:
- py_version = "{}{}".format(py_version, X64_EXT)
-
- return py_version
-
-
-def compiler_from_env():
- py = os.environ["PYTHON"]
-
- for k, v in pythons.items():
- if k in py:
- py_info = v
- break
-
- bit = bit_from_env()
- return compilers[py_info["compiler"]][py_info["vc"]][bit]
-
-
-def bit_from_env():
- py = os.environ["PYTHON"]
-
- return 64 if "64" in py else 32
-
-
-def all_compilers():
- all = []
- for vc_compilers in compilers.values():
- for bit_compilers in vc_compilers.values():
- all += bit_compilers.values()
- return all
diff --git a/winbuild/fetch.py b/winbuild/fetch.py
deleted file mode 100644
index adc45429a44..00000000000
--- a/winbuild/fetch.py
+++ /dev/null
@@ -1,44 +0,0 @@
-import os
-import sys
-import urllib.parse
-import urllib.request
-
-from config import libs
-
-
-def fetch(url):
- depends_filename = None
- for lib in libs.values():
- if lib["url"] == url:
- depends_filename = lib["filename"]
- break
- if depends_filename and os.path.exists(depends_filename):
- return depends_filename
- name = urllib.parse.urlsplit(url)[2].split("/")[-1]
-
- if not os.path.exists(name):
-
- def retrieve(request_url):
- print("Fetching", request_url)
- try:
- return urllib.request.urlopen(request_url)
- except urllib.error.URLError:
- return urllib.request.urlopen(request_url)
-
- try:
- r = retrieve(url)
- except urllib.error.HTTPError:
- if depends_filename:
- r = retrieve(
- "https://github.com/python-pillow/pillow-depends/raw/master/"
- + depends_filename
- )
- name = depends_filename
- content = r.read()
- with open(name, "wb") as fd:
- fd.write(content)
- return name
-
-
-if __name__ == "__main__":
- fetch(sys.argv[1])
diff --git a/winbuild/fribidi.cmake b/winbuild/fribidi.cmake
index 247e79e4cdd..11217473139 100644
--- a/winbuild/fribidi.cmake
+++ b/winbuild/fribidi.cmake
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.13)
+cmake_minimum_required(VERSION 3.12)
project(fribidi)
diff --git a/winbuild/get_pythons.py b/winbuild/get_pythons.py
deleted file mode 100644
index a853fc6f7ea..00000000000
--- a/winbuild/get_pythons.py
+++ /dev/null
@@ -1,15 +0,0 @@
-import os
-
-from fetch import fetch
-
-if __name__ == "__main__":
- for version in ["3.4.4"]:
- for platform in ["", ".amd64"]:
- for extension in ["", ".asc"]:
- fetch(
- "https://www.python.org/ftp/python/%s/python-%s%s.msi%s"
- % (version, version, platform, extension)
- )
-
- # find pip, if it's not in the path!
- os.system("pip install virtualenv")
diff --git a/winbuild/lcms2_patch.ps1 b/winbuild/lcms2_patch.ps1
deleted file mode 100644
index 7fc48c034e5..00000000000
--- a/winbuild/lcms2_patch.ps1
+++ /dev/null
@@ -1,9 +0,0 @@
-
-Get-ChildItem .\Projects\VC2015\ *.vcxproj -recurse |
- Foreach-Object {
- $c = ($_ | Get-Content)
- $c = $c -replace 'MultiThreaded<','MultiThreadedDLL<'
- $c = $c -replace '8.1','10'
- $c = $c -replace 'v140','v142'
- [IO.File]::WriteAllText($_.FullName, ($c -join "`r`n"))
- }
diff --git a/winbuild/raqm.cmake b/winbuild/raqm.cmake
index 88eb7f28479..e8e71800e00 100644
--- a/winbuild/raqm.cmake
+++ b/winbuild/raqm.cmake
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.13)
+cmake_minimum_required(VERSION 3.12)
project(libraqm)
diff --git a/winbuild/test.py b/winbuild/test.py
deleted file mode 100755
index a05a20b1892..00000000000
--- a/winbuild/test.py
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/usr/bin/env python3
-
-import glob
-import os
-import subprocess
-import sys
-
-from config import VIRT_BASE, X64_EXT, pythons
-
-
-def test_one(params):
- python, architecture = params
- try:
- print("Running: %s, %s" % params)
- command = [
- r"{}\{}{}\Scripts\python.exe".format(VIRT_BASE, python, architecture),
- "test-installed.py",
- "--processes=-0",
- "--process-timeout=30",
- ]
- command.extend(glob.glob("Tests/test*.py"))
- proc = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
- (trace, stderr) = proc.communicate()
- status = proc.returncode
- print("Done with {}, {} -- {}".format(python, architecture, status))
- return (python, architecture, status, trace)
- except Exception as msg:
- print("Error with {}, {}: {}".format(python, architecture, msg))
- return (python, architecture, -1, str(msg))
-
-
-if __name__ == "__main__":
-
- os.chdir("..")
- matrix = [
- (python, architecture) for python in pythons for architecture in ("", X64_EXT)
- ]
-
- results = map(test_one, matrix)
-
- for (python, architecture, status, trace) in results:
- print("{}{}: {}".format(python, architecture, status and "ERR" or "PASS"))
-
- res = all(status for (python, architecture, status, trace) in results)
- sys.exit(res)
diff --git a/winbuild/untar.py b/winbuild/untar.py
deleted file mode 100644
index f2713b2f27d..00000000000
--- a/winbuild/untar.py
+++ /dev/null
@@ -1,11 +0,0 @@
-import sys
-import tarfile
-
-
-def untar(src, dest):
- with tarfile.open(src, "r:gz") as tgz:
- tgz.extractall(dest)
-
-
-if __name__ == "__main__":
- untar(sys.argv[1], sys.argv[2])
diff --git a/winbuild/unzip.py b/winbuild/unzip.py
deleted file mode 100644
index eb17a2e6330..00000000000
--- a/winbuild/unzip.py
+++ /dev/null
@@ -1,11 +0,0 @@
-import sys
-import zipfile
-
-
-def unzip(src, dest):
- with zipfile.ZipFile(src) as zf:
- zf.extractall(dest)
-
-
-if __name__ == "__main__":
- unzip(sys.argv[1], sys.argv[2])