mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-01-13 10:46:16 +03:00
Merge remote-tracking branch 'upstream/master' into gha-msys
# Conflicts: # .appveyor.yml # .github/workflows/test-windows.yml
This commit is contained in:
commit
21325b8ce3
|
@ -1,4 +1,5 @@
|
||||||
version: '{build}'
|
version: '{build}'
|
||||||
|
image: Visual Studio 2017
|
||||||
clone_folder: c:\pillow
|
clone_folder: c:\pillow
|
||||||
init:
|
init:
|
||||||
- ECHO %PYTHON%
|
- ECHO %PYTHON%
|
||||||
|
@ -6,46 +7,36 @@ init:
|
||||||
# Uncomment previous line to get RDP access during the build.
|
# Uncomment previous line to get RDP access during the build.
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
X64_EXT: -x64
|
|
||||||
EXECUTABLE: python.exe
|
EXECUTABLE: python.exe
|
||||||
PIP_DIR: Scripts
|
PIP_DIR: Scripts
|
||||||
VENV: NO
|
|
||||||
TEST_OPTIONS:
|
TEST_OPTIONS:
|
||||||
DEPLOY: YES
|
DEPLOY: YES
|
||||||
matrix:
|
matrix:
|
||||||
- PYTHON: C:/Python38
|
- PYTHON: C:/Python38
|
||||||
- PYTHON: C:/Python38-x64
|
ARCHITECTURE: x86
|
||||||
- PYTHON: C:/Python35
|
|
||||||
- PYTHON: C:/Python35-x64
|
- PYTHON: C:/Python35-x64
|
||||||
- PYTHON: C:/vp/pypy3
|
ARCHITECTURE: x64
|
||||||
EXECUTABLE: bin/pypy.exe
|
|
||||||
VENV: YES
|
|
||||||
|
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- curl -fsSL -o pillow-depends.zip https://github.com/python-pillow/pillow-depends/archive/master.zip
|
- curl -fsSL -o pillow-depends.zip https://github.com/python-pillow/pillow-depends/archive/master.zip
|
||||||
- 7z x pillow-depends.zip -oc:\
|
- 7z x pillow-depends.zip -oc:\
|
||||||
- mv c:\pillow-depends-master c:\pillow-depends
|
- 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
|
- xcopy /s c:\pillow-depends\test_images\* c:\pillow\tests\images
|
||||||
- cd c:\pillow\winbuild\
|
- 7z x ..\pillow-depends\nasm-2.14.02-win64.zip -oc:\
|
||||||
- ps: |
|
|
||||||
if ($env:PYTHON -eq "c:/vp/pypy3")
|
|
||||||
{
|
|
||||||
c:\pillow\winbuild\appveyor_install_pypy3.cmd
|
|
||||||
}
|
|
||||||
- ps: |
|
|
||||||
c:\python37\python.exe c:\pillow\winbuild\build_dep.py
|
|
||||||
c:\pillow\winbuild\build_deps.cmd
|
|
||||||
$host.SetShouldExit(0)
|
|
||||||
- curl -fsSL -o gs952.exe https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs952/gs952w32.exe
|
- curl -fsSL -o gs952.exe https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs952/gs952w32.exe
|
||||||
- gs952.exe /S
|
- gs952.exe /S
|
||||||
- path %path%;C:\Program Files (x86)\gs\gs9.52\bin
|
- path c:\nasm-2.14.02;C:\Program Files (x86)\gs\gs9.52\bin;%PATH%
|
||||||
|
- cd c:\pillow\winbuild\
|
||||||
|
- ps: |
|
||||||
|
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)
|
||||||
|
- path C:\pillow\winbuild\build\bin;%PATH%
|
||||||
|
|
||||||
build_script:
|
build_script:
|
||||||
- ps: |
|
- ps: |
|
||||||
& $env:PYTHON/$env:EXECUTABLE c:\pillow\winbuild\build.py
|
c:\pillow\winbuild\build\build_pillow.cmd install
|
||||||
$host.SetShouldExit(0)
|
$host.SetShouldExit(0)
|
||||||
- cd c:\pillow
|
- cd c:\pillow
|
||||||
- '%PYTHON%\%EXECUTABLE% selftest.py --installed'
|
- '%PYTHON%\%EXECUTABLE% selftest.py --installed'
|
||||||
|
@ -77,7 +68,7 @@ before_deploy:
|
||||||
- cd c:\pillow
|
- cd c:\pillow
|
||||||
- '%PYTHON%\%PIP_DIR%\pip.exe install wheel'
|
- '%PYTHON%\%PIP_DIR%\pip.exe install wheel'
|
||||||
- cd c:\pillow\winbuild\
|
- cd c:\pillow\winbuild\
|
||||||
- '%PYTHON%\%EXECUTABLE% c:\pillow\winbuild\build.py --wheel'
|
- c:\pillow\winbuild\build\build_pillow.cmd bdist_wheel
|
||||||
- cd c:\pillow
|
- cd c:\pillow
|
||||||
- ps: Get-ChildItem .\dist\*.* | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name }
|
- ps: Get-ChildItem .\dist\*.* | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name }
|
||||||
|
|
||||||
|
|
2
.github/workflows/lint.yml
vendored
2
.github/workflows/lint.yml
vendored
|
@ -13,7 +13,7 @@ jobs:
|
||||||
name: Python ${{ matrix.python-version }}
|
name: Python ${{ matrix.python-version }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: pip cache
|
- name: pip cache
|
||||||
uses: actions/cache@v1
|
uses: actions/cache@v1
|
||||||
|
|
2
.github/workflows/test-docker.yml
vendored
2
.github/workflows/test-docker.yml
vendored
|
@ -30,7 +30,7 @@ jobs:
|
||||||
name: ${{ matrix.docker }}
|
name: ${{ matrix.docker }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Build system information
|
- name: Build system information
|
||||||
run: python .github/workflows/system-info.py
|
run: python .github/workflows/system-info.py
|
||||||
|
|
315
.github/workflows/test-windows.yml
vendored
315
.github/workflows/test-windows.yml
vendored
|
@ -4,7 +4,6 @@ on: [push, pull_request]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
|
||||||
runs-on: windows-2019
|
runs-on: windows-2019
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
|
@ -27,14 +26,16 @@ jobs:
|
||||||
name: Python ${{ matrix.python-version }} ${{ matrix.architecture }}
|
name: Python ${{ matrix.python-version }} ${{ matrix.architecture }}
|
||||||
|
|
||||||
steps:
|
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:
|
with:
|
||||||
repository: python-pillow/pillow-depends
|
repository: python-pillow/pillow-depends
|
||||||
ref: master
|
path: winbuild\depends
|
||||||
|
|
||||||
- name: Cache
|
- name: Cache pip
|
||||||
uses: actions/cache@v1
|
uses: actions/cache@v1
|
||||||
with:
|
with:
|
||||||
path: ~\AppData\Local\pip\Cache
|
path: ~\AppData\Local\pip\Cache
|
||||||
|
@ -51,291 +52,68 @@ jobs:
|
||||||
python-version: ${{ matrix.python-version }}
|
python-version: ${{ matrix.python-version }}
|
||||||
architecture: ${{ matrix.architecture }}
|
architecture: ${{ matrix.architecture }}
|
||||||
|
|
||||||
- name: Build system information
|
- name: Print build system information
|
||||||
run: python .github/workflows/system-info.py
|
run: python .github/workflows/system-info.py
|
||||||
|
|
||||||
- name: pip install wheel pytest pytest-cov
|
- name: pip install wheel pytest pytest-cov
|
||||||
run: |
|
run: python -m pip install wheel pytest pytest-cov
|
||||||
"%pythonLocation%\python.exe" -m pip install wheel pytest pytest-cov
|
|
||||||
shell: cmd
|
|
||||||
|
|
||||||
- name: Fetch dependencies
|
- name: Prepare dependencies
|
||||||
run: |
|
run: |
|
||||||
7z x ..\pillow-depends\nasm-2.14.02-win64.zip "-o$env:RUNNER_WORKSPACE\"
|
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"
|
|
||||||
Write-Host "::add-path::$env:RUNNER_WORKSPACE\nasm-2.14.02"
|
Write-Host "::add-path::$env:RUNNER_WORKSPACE\nasm-2.14.02"
|
||||||
|
|
||||||
..\pillow-depends\gs950w32.exe /S
|
winbuild\depends\gs950w32.exe /S
|
||||||
Write-Host "`#`#[add-path]C:\Program Files (x86)\gs\gs9.50\bin"
|
|
||||||
Write-Host "::add-path::C:\Program Files (x86)\gs\gs9.50\bin"
|
Write-Host "::add-path::C:\Program Files (x86)\gs\gs9.50\bin"
|
||||||
|
|
||||||
$env:PYTHON=$env:pythonLocation
|
xcopy /s winbuild\depends\test_images\* Tests\images\
|
||||||
xcopy ..\pillow-depends\*.zip $env:GITHUB_WORKSPACE\winbuild\
|
|
||||||
xcopy ..\pillow-depends\*.tar.gz $env:GITHUB_WORKSPACE\winbuild\
|
& python.exe winbuild\build_prepare.py -v --python=$env:pythonLocation
|
||||||
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
|
shell: pwsh
|
||||||
|
|
||||||
- name: Build dependencies / libjpeg
|
|
||||||
if: false
|
|
||||||
run: |
|
|
||||||
REM FIXME uses /MT not /MD, see makefile.vc and win32.mak for more info
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
- name: Build dependencies / libjpeg-turbo
|
- name: Build dependencies / libjpeg-turbo
|
||||||
run: |
|
run: "& winbuild\\build\\build_dep_libjpeg.cmd"
|
||||||
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
|
|
||||||
|
|
||||||
- name: Build dependencies / zlib
|
- name: Build dependencies / zlib
|
||||||
run: |
|
run: "& winbuild\\build\\build_dep_zlib.cmd"
|
||||||
set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include
|
- name: Build dependencies / LibTiff
|
||||||
set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32
|
run: "& winbuild\\build\\build_dep_libtiff.cmd"
|
||||||
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
|
|
||||||
|
|
||||||
- name: Build dependencies / WebP
|
- name: Build dependencies / WebP
|
||||||
run: |
|
run: "& winbuild\\build\\build_dep_libwebp.cmd"
|
||||||
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
|
|
||||||
|
|
||||||
- name: Build dependencies / FreeType
|
- name: Build dependencies / FreeType
|
||||||
run: |
|
run: "& winbuild\\build\\build_dep_freetype.cmd"
|
||||||
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
|
|
||||||
|
|
||||||
- name: Build dependencies / LCMS2
|
- name: Build dependencies / LCMS2
|
||||||
run: |
|
run: "& winbuild\\build\\build_dep_lcms2.cmd"
|
||||||
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
|
|
||||||
|
|
||||||
- name: Build dependencies / OpenJPEG
|
- name: Build dependencies / OpenJPEG
|
||||||
run: |
|
run: "& winbuild\\build\\build_dep_openjpeg.cmd"
|
||||||
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
|
|
||||||
|
|
||||||
# GPL licensed; skip if building wheels
|
# GPL licensed; skip if building wheels
|
||||||
- name: Build dependencies / libimagequant
|
- name: Build dependencies / libimagequant
|
||||||
if: "github.event_name != 'push' || contains(matrix.python-version, 'pypy')"
|
if: "github.event_name != 'push'"
|
||||||
run: |
|
run: "& winbuild\\build\\build_dep_libimagequant.cmd"
|
||||||
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
|
|
||||||
|
|
||||||
# for Raqm
|
# Raqm dependencies
|
||||||
- name: Build dependencies / HarfBuzz
|
- name: Build dependencies / HarfBuzz
|
||||||
run: |
|
run: "& winbuild\\build\\build_dep_harfbuzz.cmd"
|
||||||
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
|
|
||||||
- name: Build dependencies / FriBidi
|
- name: Build dependencies / FriBidi
|
||||||
run: |
|
run: "& winbuild\\build\\build_dep_fribidi.cmd"
|
||||||
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
|
|
||||||
|
|
||||||
- name: Build dependencies / Raqm
|
- name: Build dependencies / Raqm
|
||||||
run: |
|
run: "& winbuild\\build\\build_dep_libraqm.cmd"
|
||||||
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
|
|
||||||
|
|
||||||
- name: Build Pillow
|
- name: Build Pillow
|
||||||
run: |
|
run: |
|
||||||
set PYTHON=%pythonLocation%
|
& winbuild\build\build_pillow.cmd install
|
||||||
set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include
|
& $env:pythonLocation\python.exe selftest.py --installed
|
||||||
set MPLSRC=%GITHUB_WORKSPACE%
|
shell: pwsh
|
||||||
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
|
|
||||||
|
|
||||||
# failing with PyPy3
|
# failing with PyPy3
|
||||||
- name: Enable heap verification
|
- name: Enable heap verification
|
||||||
if: "!contains(matrix.python-version, 'pypy')"
|
if: "!contains(matrix.python-version, 'pypy')"
|
||||||
run: |
|
run: "& 'C:\\Program Files (x86)\\Windows Kits\\10\\Debuggers\\x86\\gflags.exe' /p /enable $env:pythonLocation\\python.exe"
|
||||||
c:\"Program Files (x86)"\"Windows Kits"\10\Debuggers\x86\gflags.exe /p /enable %PYTHON%\python.exe
|
|
||||||
shell: cmd
|
|
||||||
|
|
||||||
- name: Test Pillow
|
- name: Test Pillow
|
||||||
run: |
|
run: |
|
||||||
set PYTHON=%pythonLocation%
|
path %GITHUB_WORKSPACE%\\winbuild\\build\\bin;%PATH%
|
||||||
set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32
|
python.exe -m pytest -vx -W always --cov PIL --cov Tests --cov-report term --cov-report xml Tests
|
||||||
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
|
|
||||||
shell: cmd
|
shell: cmd
|
||||||
|
|
||||||
- name: Prepare to upload errors
|
- name: Prepare to upload errors
|
||||||
|
@ -359,32 +137,23 @@ jobs:
|
||||||
- name: Upload coverage
|
- name: Upload coverage
|
||||||
uses: codecov/codecov-action@v1
|
uses: codecov/codecov-action@v1
|
||||||
with:
|
with:
|
||||||
file: ./coverage.xml
|
file: ./coverage.xml
|
||||||
flags: GHA_Windows
|
flags: GHA_Windows
|
||||||
name: ${{ runner.os }} Python ${{ matrix.python-version }}
|
name: ${{ runner.os }} Python ${{ matrix.python-version }} ${{ matrix.architecture }}
|
||||||
|
|
||||||
- name: Build wheel
|
- name: Build wheel
|
||||||
id: wheel
|
id: wheel
|
||||||
if: "github.event_name == 'push' && !contains(matrix.python-version, 'pypy')"
|
if: "github.event_name == 'push'"
|
||||||
run: |
|
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
|
for /f "tokens=3 delims=/" %%a in ("${{ github.ref }}") do echo ::set-output name=dist::dist-%%a
|
||||||
set PYTHON=%pythonLocation%
|
winbuild\\build\\build_pillow.cmd bdist_wheel"
|
||||||
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
|
|
||||||
shell: cmd
|
shell: cmd
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v1
|
- uses: actions/upload-artifact@v2
|
||||||
if: "github.event_name == 'push' && !contains(matrix.python-version, 'pypy')"
|
if: "github.event_name == 'push'"
|
||||||
with:
|
with:
|
||||||
name: ${{ steps.wheel.outputs.dist }}
|
name: ${{ steps.wheel.outputs.dist }}
|
||||||
path: dist
|
path: dist\*.whl
|
||||||
|
|
||||||
msys:
|
msys:
|
||||||
runs-on: windows-2019
|
runs-on: windows-2019
|
||||||
|
|
|
@ -63,6 +63,12 @@ def test_aspect():
|
||||||
assert im.size == (75, 23) # ratio is 3.260869565217
|
assert im.size == (75, 23) # ratio is 3.260869565217
|
||||||
|
|
||||||
|
|
||||||
|
def test_division_by_zero():
|
||||||
|
im = Image.new("L", (200, 2))
|
||||||
|
im.thumbnail((75, 75))
|
||||||
|
assert im.size == (75, 1)
|
||||||
|
|
||||||
|
|
||||||
def test_float():
|
def test_float():
|
||||||
im = Image.new("L", (128, 128))
|
im = Image.new("L", (128, 128))
|
||||||
im.thumbnail((99.9, 99.9))
|
im.thumbnail((99.9, 99.9))
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import pytest
|
import pytest
|
||||||
from PIL import Image, ImageShow
|
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():
|
def test_sanity():
|
||||||
|
@ -38,8 +38,7 @@ def test_viewer_show():
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skipif(
|
@pytest.mark.skipif(
|
||||||
not on_ci() or (is_win32() and on_github_actions()),
|
not on_ci() or is_win32(), reason="Only run on CIs; hangs on Windows CIs",
|
||||||
reason="Only run on CIs; hangs on Windows on GitHub Actions",
|
|
||||||
)
|
)
|
||||||
def test_show():
|
def test_show():
|
||||||
for mode in ("1", "I;16", "LA", "RGB", "RGBA"):
|
for mode in ("1", "I;16", "LA", "RGB", "RGBA"):
|
||||||
|
|
|
@ -292,9 +292,10 @@ or from within the uncompressed source directory::
|
||||||
Building on Windows
|
Building on Windows
|
||||||
^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
We don't recommend trying to build on Windows. It is a maze of twisty
|
We recommend you use prebuilt wheels from PyPI.
|
||||||
passages, mostly dead ends. There are build scripts and notes for the
|
If you wish to compile Pillow manually, you can use the build scripts
|
||||||
Windows build in the ``winbuild`` directory.
|
in the ``winbuild`` directory used for CI testing and development.
|
||||||
|
These scripts require Visual Studio 2017 or newer and NASM.
|
||||||
|
|
||||||
Building on FreeBSD
|
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 |
|
| 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 |
|
| 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 |
|
| 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.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 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 |
|
| Windows Server 2008 R2 Enterprise| 3.3 | |x86-64 |
|
||||||
+----------------------------------+------------------------------+--------------------------------+-----------------------+
|
+----------------------------------+------------------------------+--------------------------------+-----------------------+
|
||||||
|
|
|
@ -2277,7 +2277,9 @@ class Image:
|
||||||
if x / y >= aspect:
|
if x / y >= aspect:
|
||||||
x = round_aspect(y * aspect, key=lambda n: abs(aspect - n / y))
|
x = round_aspect(y * aspect, key=lambda n: abs(aspect - n / y))
|
||||||
else:
|
else:
|
||||||
y = round_aspect(x / aspect, key=lambda n: abs(aspect - x / n))
|
y = round_aspect(
|
||||||
|
x / aspect, key=lambda n: 0 if n == 0 else abs(aspect - x / n)
|
||||||
|
)
|
||||||
size = (x, y)
|
size = (x, y)
|
||||||
|
|
||||||
box = None
|
box = None
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
#
|
#
|
||||||
import io
|
import io
|
||||||
import itertools
|
import itertools
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
import struct
|
import struct
|
||||||
import warnings
|
import warnings
|
||||||
|
@ -51,7 +52,7 @@ from . import Image, ImageFile, ImagePalette, TiffTags
|
||||||
from ._binary import i8, o8
|
from ._binary import i8, o8
|
||||||
from .TiffTags import TYPES
|
from .TiffTags import TYPES
|
||||||
|
|
||||||
DEBUG = False # Needs to be merged with the new logging approach.
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
# Set these to true to force use of libtiff for reading or writing.
|
# Set these to true to force use of libtiff for reading or writing.
|
||||||
READ_LIBTIFF = False
|
READ_LIBTIFF = False
|
||||||
|
@ -734,29 +735,21 @@ class ImageFileDirectory_v2(MutableMapping):
|
||||||
try:
|
try:
|
||||||
for i in range(self._unpack("H", self._ensure_read(fp, 2))[0]):
|
for i in range(self._unpack("H", self._ensure_read(fp, 2))[0]):
|
||||||
tag, typ, count, data = self._unpack("HHL4s", self._ensure_read(fp, 12))
|
tag, typ, count, data = self._unpack("HHL4s", self._ensure_read(fp, 12))
|
||||||
if DEBUG:
|
|
||||||
tagname = TiffTags.lookup(tag).name
|
tagname = TiffTags.lookup(tag).name
|
||||||
typname = TYPES.get(typ, "unknown")
|
typname = TYPES.get(typ, "unknown")
|
||||||
print(
|
msg = "tag: %s (%d) - type: %s (%d)" % (tagname, tag, typname, typ)
|
||||||
"tag: %s (%d) - type: %s (%d)" % (tagname, tag, typname, typ),
|
|
||||||
end=" ",
|
|
||||||
)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
unit_size, handler = self._load_dispatch[typ]
|
unit_size, handler = self._load_dispatch[typ]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
if DEBUG:
|
logger.debug(msg + " - unsupported type {}".format(typ))
|
||||||
print("- unsupported type", typ)
|
|
||||||
continue # ignore unsupported type
|
continue # ignore unsupported type
|
||||||
size = count * unit_size
|
size = count * unit_size
|
||||||
if size > 4:
|
if size > 4:
|
||||||
here = fp.tell()
|
here = fp.tell()
|
||||||
(offset,) = self._unpack("L", data)
|
(offset,) = self._unpack("L", data)
|
||||||
if DEBUG:
|
msg += " Tag Location: {} - Data Location: {}".format(here, offset)
|
||||||
print(
|
|
||||||
"Tag Location: {} - Data Location: {}".format(here, offset),
|
|
||||||
end=" ",
|
|
||||||
)
|
|
||||||
fp.seek(offset)
|
fp.seek(offset)
|
||||||
data = ImageFile._safe_read(fp, size)
|
data = ImageFile._safe_read(fp, size)
|
||||||
fp.seek(here)
|
fp.seek(here)
|
||||||
|
@ -769,19 +762,20 @@ class ImageFileDirectory_v2(MutableMapping):
|
||||||
"Expecting to read %d bytes but only got %d."
|
"Expecting to read %d bytes but only got %d."
|
||||||
" Skipping tag %s" % (size, len(data), tag)
|
" Skipping tag %s" % (size, len(data), tag)
|
||||||
)
|
)
|
||||||
|
logger.debug(msg)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if not data:
|
if not data:
|
||||||
|
logger.debug(msg)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
self._tagdata[tag] = data
|
self._tagdata[tag] = data
|
||||||
self.tagtype[tag] = typ
|
self.tagtype[tag] = typ
|
||||||
|
|
||||||
if DEBUG:
|
msg += " - value: " + (
|
||||||
if size > 32:
|
"<table: %d bytes>" % size if size > 32 else str(data)
|
||||||
print("- value: <table: %d bytes>" % size)
|
)
|
||||||
else:
|
logger.debug(msg)
|
||||||
print("- value:", self[tag])
|
|
||||||
|
|
||||||
(self.next,) = self._unpack("L", self._ensure_read(fp, 4))
|
(self.next,) = self._unpack("L", self._ensure_read(fp, 4))
|
||||||
except OSError as msg:
|
except OSError as msg:
|
||||||
|
@ -802,21 +796,17 @@ class ImageFileDirectory_v2(MutableMapping):
|
||||||
if tag == STRIPOFFSETS:
|
if tag == STRIPOFFSETS:
|
||||||
stripoffsets = len(entries)
|
stripoffsets = len(entries)
|
||||||
typ = self.tagtype.get(tag)
|
typ = self.tagtype.get(tag)
|
||||||
if DEBUG:
|
logger.debug("Tag {}, Type: {}, Value: {}".format(tag, typ, value))
|
||||||
print("Tag {}, Type: {}, Value: {}".format(tag, typ, value))
|
|
||||||
values = value if isinstance(value, tuple) else (value,)
|
values = value if isinstance(value, tuple) else (value,)
|
||||||
data = self._write_dispatch[typ](self, *values)
|
data = self._write_dispatch[typ](self, *values)
|
||||||
if DEBUG:
|
|
||||||
tagname = TiffTags.lookup(tag).name
|
tagname = TiffTags.lookup(tag).name
|
||||||
typname = TYPES.get(typ, "unknown")
|
typname = TYPES.get(typ, "unknown")
|
||||||
print(
|
msg = "save: %s (%d) - type: %s (%d)" % (tagname, tag, typname, typ)
|
||||||
"save: %s (%d) - type: %s (%d)" % (tagname, tag, typname, typ),
|
msg += " - value: " + (
|
||||||
end=" ",
|
"<table: %d bytes>" % len(data) if len(data) >= 16 else str(values)
|
||||||
)
|
)
|
||||||
if len(data) >= 16:
|
logger.debug(msg)
|
||||||
print("- value: <table: %d bytes>" % len(data))
|
|
||||||
else:
|
|
||||||
print("- value:", values)
|
|
||||||
|
|
||||||
# count is sum of lengths for string and arbitrary data
|
# count is sum of lengths for string and arbitrary data
|
||||||
if typ in [TiffTags.BYTE, TiffTags.ASCII, TiffTags.UNDEFINED]:
|
if typ in [TiffTags.BYTE, TiffTags.ASCII, TiffTags.UNDEFINED]:
|
||||||
|
@ -840,8 +830,9 @@ class ImageFileDirectory_v2(MutableMapping):
|
||||||
|
|
||||||
# pass 2: write entries to file
|
# pass 2: write entries to file
|
||||||
for tag, typ, count, value, data in entries:
|
for tag, typ, count, value, data in entries:
|
||||||
if DEBUG:
|
logger.debug(
|
||||||
print(tag, typ, count, repr(value), repr(data))
|
"{} {} {} {} {}".format(tag, typ, count, repr(value), repr(data))
|
||||||
|
)
|
||||||
result += self._pack("HHL4s", tag, typ, count, value)
|
result += self._pack("HHL4s", tag, typ, count, value)
|
||||||
|
|
||||||
# -- overwrite here for multi-page --
|
# -- overwrite here for multi-page --
|
||||||
|
@ -997,10 +988,9 @@ class TiffImageFile(ImageFile.ImageFile):
|
||||||
self._frame_pos = []
|
self._frame_pos = []
|
||||||
self._n_frames = None
|
self._n_frames = None
|
||||||
|
|
||||||
if DEBUG:
|
logger.debug("*** TiffImageFile._open ***")
|
||||||
print("*** TiffImageFile._open ***")
|
logger.debug("- __first: {}".format(self.__first))
|
||||||
print("- __first:", self.__first)
|
logger.debug("- ifh: {}".format(ifh))
|
||||||
print("- ifh: ", ifh)
|
|
||||||
|
|
||||||
# and load the first frame
|
# and load the first frame
|
||||||
self._seek(0)
|
self._seek(0)
|
||||||
|
@ -1031,18 +1021,16 @@ class TiffImageFile(ImageFile.ImageFile):
|
||||||
while len(self._frame_pos) <= frame:
|
while len(self._frame_pos) <= frame:
|
||||||
if not self.__next:
|
if not self.__next:
|
||||||
raise EOFError("no more images in TIFF file")
|
raise EOFError("no more images in TIFF file")
|
||||||
if DEBUG:
|
logger.debug(
|
||||||
print(
|
"Seeking to frame %s, on frame %s, __next %s, location: %s"
|
||||||
"Seeking to frame %s, on frame %s, __next %s, location: %s"
|
% (frame, self.__frame, self.__next, self.fp.tell())
|
||||||
% (frame, self.__frame, self.__next, self.fp.tell())
|
)
|
||||||
)
|
|
||||||
# reset buffered io handle in case fp
|
# reset buffered io handle in case fp
|
||||||
# was passed to libtiff, invalidating the buffer
|
# was passed to libtiff, invalidating the buffer
|
||||||
self.fp.tell()
|
self.fp.tell()
|
||||||
self.fp.seek(self.__next)
|
self.fp.seek(self.__next)
|
||||||
self._frame_pos.append(self.__next)
|
self._frame_pos.append(self.__next)
|
||||||
if DEBUG:
|
logger.debug("Loading tags, location: %s" % self.fp.tell())
|
||||||
print("Loading tags, location: %s" % self.fp.tell())
|
|
||||||
self.tag_v2.load(self.fp)
|
self.tag_v2.load(self.fp)
|
||||||
self.__next = self.tag_v2.next
|
self.__next = self.tag_v2.next
|
||||||
if self.__next == 0:
|
if self.__next == 0:
|
||||||
|
@ -1140,21 +1128,18 @@ class TiffImageFile(ImageFile.ImageFile):
|
||||||
# Rearranging for supporting byteio items, since they have a fileno
|
# Rearranging for supporting byteio items, since they have a fileno
|
||||||
# that returns an OSError if there's no underlying fp. Easier to
|
# that returns an OSError if there's no underlying fp. Easier to
|
||||||
# deal with here by reordering.
|
# deal with here by reordering.
|
||||||
if DEBUG:
|
logger.debug("have getvalue. just sending in a string from getvalue")
|
||||||
print("have getvalue. just sending in a string from getvalue")
|
|
||||||
n, err = decoder.decode(self.fp.getvalue())
|
n, err = decoder.decode(self.fp.getvalue())
|
||||||
elif fp:
|
elif fp:
|
||||||
# we've got a actual file on disk, pass in the fp.
|
# we've got a actual file on disk, pass in the fp.
|
||||||
if DEBUG:
|
logger.debug("have fileno, calling fileno version of the decoder.")
|
||||||
print("have fileno, calling fileno version of the decoder.")
|
|
||||||
if not close_self_fp:
|
if not close_self_fp:
|
||||||
self.fp.seek(0)
|
self.fp.seek(0)
|
||||||
# 4 bytes, otherwise the trace might error out
|
# 4 bytes, otherwise the trace might error out
|
||||||
n, err = decoder.decode(b"fpfp")
|
n, err = decoder.decode(b"fpfp")
|
||||||
else:
|
else:
|
||||||
# we have something else.
|
# we have something else.
|
||||||
if DEBUG:
|
logger.debug("don't have fileno or getvalue. just reading")
|
||||||
print("don't have fileno or getvalue. just reading")
|
|
||||||
self.fp.seek(0)
|
self.fp.seek(0)
|
||||||
# UNDONE -- so much for that buffer size thing.
|
# UNDONE -- so much for that buffer size thing.
|
||||||
n, err = decoder.decode(self.fp.read())
|
n, err = decoder.decode(self.fp.read())
|
||||||
|
@ -1194,21 +1179,19 @@ class TiffImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
fillorder = self.tag_v2.get(FILLORDER, 1)
|
fillorder = self.tag_v2.get(FILLORDER, 1)
|
||||||
|
|
||||||
if DEBUG:
|
logger.debug("*** Summary ***")
|
||||||
print("*** Summary ***")
|
logger.debug("- compression: {}".format(self._compression))
|
||||||
print("- compression:", self._compression)
|
logger.debug("- photometric_interpretation: {}".format(photo))
|
||||||
print("- photometric_interpretation:", photo)
|
logger.debug("- planar_configuration: {}".format(self._planar_configuration))
|
||||||
print("- planar_configuration:", self._planar_configuration)
|
logger.debug("- fill_order: {}".format(fillorder))
|
||||||
print("- fill_order:", fillorder)
|
logger.debug("- YCbCr subsampling: {}".format(self.tag.get(530)))
|
||||||
print("- YCbCr subsampling:", self.tag.get(530))
|
|
||||||
|
|
||||||
# size
|
# size
|
||||||
xsize = int(self.tag_v2.get(IMAGEWIDTH))
|
xsize = int(self.tag_v2.get(IMAGEWIDTH))
|
||||||
ysize = int(self.tag_v2.get(IMAGELENGTH))
|
ysize = int(self.tag_v2.get(IMAGELENGTH))
|
||||||
self._size = xsize, ysize
|
self._size = xsize, ysize
|
||||||
|
|
||||||
if DEBUG:
|
logger.debug("- size: {}".format(self.size))
|
||||||
print("- size:", self.size)
|
|
||||||
|
|
||||||
sampleFormat = self.tag_v2.get(SAMPLEFORMAT, (1,))
|
sampleFormat = self.tag_v2.get(SAMPLEFORMAT, (1,))
|
||||||
if len(sampleFormat) > 1 and max(sampleFormat) == min(sampleFormat) == 1:
|
if len(sampleFormat) > 1 and max(sampleFormat) == min(sampleFormat) == 1:
|
||||||
|
@ -1242,18 +1225,15 @@ class TiffImageFile(ImageFile.ImageFile):
|
||||||
bps_tuple,
|
bps_tuple,
|
||||||
extra_tuple,
|
extra_tuple,
|
||||||
)
|
)
|
||||||
if DEBUG:
|
logger.debug("format key: {}".format(key))
|
||||||
print("format key:", key)
|
|
||||||
try:
|
try:
|
||||||
self.mode, rawmode = OPEN_INFO[key]
|
self.mode, rawmode = OPEN_INFO[key]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
if DEBUG:
|
logger.debug("- unsupported format")
|
||||||
print("- unsupported format")
|
|
||||||
raise SyntaxError("unknown pixel mode")
|
raise SyntaxError("unknown pixel mode")
|
||||||
|
|
||||||
if DEBUG:
|
logger.debug("- raw mode: {}".format(rawmode))
|
||||||
print("- raw mode:", rawmode)
|
logger.debug("- pil mode: {}".format(self.mode))
|
||||||
print("- pil mode:", self.mode)
|
|
||||||
|
|
||||||
self.info["compression"] = self._compression
|
self.info["compression"] = self._compression
|
||||||
|
|
||||||
|
@ -1294,8 +1274,7 @@ class TiffImageFile(ImageFile.ImageFile):
|
||||||
if fillorder == 2:
|
if fillorder == 2:
|
||||||
# Replace fillorder with fillorder=1
|
# Replace fillorder with fillorder=1
|
||||||
key = key[:3] + (1,) + key[4:]
|
key = key[:3] + (1,) + key[4:]
|
||||||
if DEBUG:
|
logger.debug("format key: {}".format(key))
|
||||||
print("format key:", key)
|
|
||||||
# this should always work, since all the
|
# this should always work, since all the
|
||||||
# fillorder==2 modes have a corresponding
|
# fillorder==2 modes have a corresponding
|
||||||
# fillorder=1 mode
|
# fillorder=1 mode
|
||||||
|
@ -1357,8 +1336,7 @@ class TiffImageFile(ImageFile.ImageFile):
|
||||||
x = y = 0
|
x = y = 0
|
||||||
layer += 1
|
layer += 1
|
||||||
else:
|
else:
|
||||||
if DEBUG:
|
logger.debug("- unsupported data organization")
|
||||||
print("- unsupported data organization")
|
|
||||||
raise SyntaxError("unknown data organization")
|
raise SyntaxError("unknown data organization")
|
||||||
|
|
||||||
# Fix up info.
|
# Fix up info.
|
||||||
|
@ -1438,8 +1416,7 @@ def _save(im, fp, filename):
|
||||||
|
|
||||||
# write any arbitrary tags passed in as an ImageFileDirectory
|
# write any arbitrary tags passed in as an ImageFileDirectory
|
||||||
info = im.encoderinfo.get("tiffinfo", {})
|
info = im.encoderinfo.get("tiffinfo", {})
|
||||||
if DEBUG:
|
logger.debug("Tiffinfo Keys: %s" % list(info))
|
||||||
print("Tiffinfo Keys: %s" % list(info))
|
|
||||||
if isinstance(info, ImageFileDirectory_v1):
|
if isinstance(info, ImageFileDirectory_v1):
|
||||||
info = info.to_v2()
|
info = info.to_v2()
|
||||||
for key in info:
|
for key in info:
|
||||||
|
@ -1524,9 +1501,8 @@ def _save(im, fp, filename):
|
||||||
)
|
)
|
||||||
ifd[JPEGQUALITY] = quality
|
ifd[JPEGQUALITY] = quality
|
||||||
|
|
||||||
if DEBUG:
|
logger.debug("Saving using libtiff encoder")
|
||||||
print("Saving using libtiff encoder")
|
logger.debug("Items: %s" % sorted(ifd.items()))
|
||||||
print("Items: %s" % sorted(ifd.items()))
|
|
||||||
_fp = 0
|
_fp = 0
|
||||||
if hasattr(fp, "fileno"):
|
if hasattr(fp, "fileno"):
|
||||||
try:
|
try:
|
||||||
|
@ -1588,8 +1564,7 @@ def _save(im, fp, filename):
|
||||||
else:
|
else:
|
||||||
atts[tag] = value
|
atts[tag] = value
|
||||||
|
|
||||||
if DEBUG:
|
logger.debug("Converted items: %s" % sorted(atts.items()))
|
||||||
print("Converted items: %s" % sorted(atts.items()))
|
|
||||||
|
|
||||||
# libtiff always expects the bytes in native order.
|
# libtiff always expects the bytes in native order.
|
||||||
# we're storing image byte order. So, if the rawmode
|
# we're storing image byte order. So, if the rawmode
|
||||||
|
|
|
@ -43,14 +43,12 @@ void *
|
||||||
ImagingError_ModeError(void)
|
ImagingError_ModeError(void)
|
||||||
{
|
{
|
||||||
return ImagingError_ValueError("bad image mode");
|
return ImagingError_ValueError("bad image mode");
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
ImagingError_Mismatch(void)
|
ImagingError_Mismatch(void)
|
||||||
{
|
{
|
||||||
return ImagingError_ValueError("images don't match");
|
return ImagingError_ValueError("images don't match");
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
|
|
|
@ -3,16 +3,28 @@ Quick README
|
||||||
|
|
||||||
For more extensive info, see the [Windows build instructions](build.rst).
|
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
|
* 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).
|
||||||
|
|
||||||
* 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.
|
* Requires Microsoft Visual Studio 2017 or newer with C++ component.
|
||||||
* 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.
|
* Requires NASM for libjpeg-turbo, a required dependency when using this script.
|
||||||
* `python get_pythons.py` downloads all the Python releases, and their signatures. (Manually) Install in `c:\PythonXX[x64]\`.
|
* Requires CMake 3.12 or newer (available as Visual Studio component).
|
||||||
* `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.
|
* Python 3.6+ is required to generate valid scripts, but builds targeting Python 3.5+ are supported.
|
||||||
* (in powershell) `build_deps.cmd` invokes the dependency build.
|
* Tested on Windows Server 2016 with Visual Studio 2017 Community (AppVeyor).
|
||||||
* `python build.py --clean` makes Pillow for the matrix of Pythons.
|
* Tested on Windows Server 2019 with Visual Studio 2019 Enterprise (GitHub Actions).
|
||||||
* `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
|
The following is a simplified version of the script used on AppVeyor:
|
||||||
* WebP is built, not detected.
|
```
|
||||||
* LCMS, OpenJPEG and libimagequant are not building.
|
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
|
||||||
|
```
|
||||||
|
|
|
@ -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
|
|
|
@ -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)
|
|
|
@ -5,89 +5,112 @@ Building Pillow on Windows
|
||||||
<../docs/installation.rst#windows-installation>`_ should
|
<../docs/installation.rst#windows-installation>`_ should
|
||||||
be sufficient.
|
be sufficient.
|
||||||
|
|
||||||
This page will describe a build setup to build Pillow against the
|
This page describes the steps necessary to build Pillow using the same
|
||||||
supported Python versions in 32 and 64-bit modes, using freely
|
scripts used on GitHub Actions and AppVeyor CIs.
|
||||||
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.
|
|
||||||
|
|
||||||
Prerequisites
|
Prerequisites
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
Extra Build Helpers
|
|
||||||
^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
* Powershell (available by default on Windows Server)
|
Python
|
||||||
* GitHub client (provides git+bash shell)
|
^^^^^^
|
||||||
|
|
||||||
Optional:
|
|
||||||
* GPG (for checking signatures) (UNDONE -- Python signature checking)
|
|
||||||
|
|
||||||
|
|
||||||
Pythons
|
|
||||||
^^^^^^^
|
|
||||||
|
|
||||||
The build routines expect Python to be installed at C:\PythonXX for
|
|
||||||
32-bit versions or C:\PythonXXx64 for the 64-bit versions.
|
|
||||||
|
|
||||||
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.)
|
|
||||||
|
|
||||||
Download the rest of the Pythons by opening a command window, changing
|
|
||||||
to the ``winbuild`` directory, and running ``python
|
|
||||||
get_pythons.py``.
|
|
||||||
|
|
||||||
UNDONE -- gpg verify the signatures (note that we can download from
|
|
||||||
https)
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
|
While the scripts can target any version of Python supported by Pillow,
|
||||||
|
Python 3.6+ is required to generate valid build scripts.
|
||||||
|
|
||||||
Compilers
|
Compilers
|
||||||
^^^^^^^^^
|
^^^^^^^^^
|
||||||
|
|
||||||
Download and install:
|
Download and install:
|
||||||
|
|
||||||
* `Microsoft Windows SDK for Windows 7 and .NET Framework
|
* `Microsoft Visual Studio 2017 or newer or Build Tools for Visual Studio 2017 or newer
|
||||||
4 <https://www.microsoft.com/en-us/download/details.aspx?id=8279>`_
|
<https://visualstudio.microsoft.com/downloads/>`_
|
||||||
|
(MSVC C++ build tools, and any Windows SDK version required)
|
||||||
|
|
||||||
* `CMake-2.8.10.2-win32-x86.exe
|
* `CMake 3.12 or newer <https://cmake.org/download/>`_
|
||||||
<https://cmake.org/files/v2.8/cmake-2.8.10.2-win32-x86.exe>`_
|
(also available as Visual Studio component C++ CMake tools for Windows)
|
||||||
|
|
||||||
The samples and the .NET SDK portions aren't required, just the
|
* `NASM <https://www.nasm.us/pub/nasm/releasebuilds/?C=M;O=D>`_
|
||||||
compilers and other tools. UNDONE -- check exact wording.
|
|
||||||
|
Any version of Visual Studio 2017 or newer should be supported,
|
||||||
|
including Visual Studio 2017 Community, or Build Tools for Visual Studio 2019.
|
||||||
|
|
||||||
|
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
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
The following environment variables, if set, will override the default
|
||||||
|
behaviour of ``build_prepare.py``:
|
||||||
|
|
||||||
|
* ``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.
|
||||||
|
|
||||||
|
``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=<path>`` and ``--executable=<exe>`` override ``PYTHON`` and ``EXECUTABLE``.
|
||||||
|
* ``--architecture=<arch>`` overrides ``ARCHITECTURE``.
|
||||||
|
* ``--dir=<path>`` and ``--depends=<path>`` override ``PILLOW_BUILD``
|
||||||
|
and ``PILLOW_DEPS``.
|
||||||
|
|
||||||
Dependencies
|
Dependencies
|
||||||
------------
|
------------
|
||||||
|
|
||||||
The script 'build_dep.py' downloads and builds the dependencies. Open
|
Dependencies will be automatically downloaded by ``build_prepare.py``.
|
||||||
a command window, change directory into ``winbuild`` and run ``python
|
By default, downloaded dependencies are stored in ``winbuild\depends``;
|
||||||
build_dep.py``.
|
set the ``PILLOW_DEPS`` environment variable to override this location.
|
||||||
|
|
||||||
This will download libjpeg, libtiff, libz, and freetype. It will then
|
To build all dependencies, run ``winbuild\build\build_dep_all.cmd``,
|
||||||
compile 32 and 64-bit versions of the libraries, with both versions of
|
or run the individual scripts to build each dependency separately.
|
||||||
the compilers.
|
|
||||||
|
|
||||||
UNDONE -- lcms fails.
|
|
||||||
UNDONE -- webp, jpeg2k not recognized
|
|
||||||
|
|
||||||
Building Pillow
|
Building Pillow
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
Once the dependencies are built, run ``python build.py --clean`` to
|
Once the dependencies are built, run
|
||||||
build and install Pillow in virtualenvs for each Python
|
``winbuild\build\build_pillow.cmd install`` to build and install
|
||||||
build. ``build.py --wheel`` will build wheels instead of
|
Pillow for the selected version of Python.
|
||||||
installing into virtualenvs.
|
``winbuild\build\build_pillow.cmd bdist_wheel`` will build wheels
|
||||||
|
instead of installing Pillow.
|
||||||
UNDONE -- suppressed output, what about failures.
|
|
||||||
|
|
||||||
Testing Pillow
|
Testing Pillow
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
Build and install Pillow, then run ``python test.py`` from the
|
Some binary dependencies (e.g. ``libraqm.dll``) will be stored in the
|
||||||
``winbuild`` directory.
|
``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
|
||||||
|
|
|
@ -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))
|
|
557
winbuild/build_prepare.py
Normal file
557
winbuild/build_prepare.py
Normal file
|
@ -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
|
||||||
|
"<RuntimeLibrary>MultiThreaded</RuntimeLibrary>": "<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>", # noqa: E501
|
||||||
|
# freetype doesn't specify SDK version, MSBuild may guess incorrectly
|
||||||
|
'<PropertyGroup Label="Globals">': '<PropertyGroup Label="Globals">\n <WindowsTargetPlatformVersion>$(WindowsSDKVersion)</WindowsTargetPlatformVersion>', # 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
|
||||||
|
"<RuntimeLibrary>MultiThreaded</RuntimeLibrary>": "<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>", # noqa: E501
|
||||||
|
# retarget to default toolset (selected by vcvarsall.bat)
|
||||||
|
"<PlatformToolset>v141</PlatformToolset>": "<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>", # noqa: E501
|
||||||
|
# retarget to latest (selected by vcvarsall.bat)
|
||||||
|
"<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>": "<WindowsTargetPlatformVersion>$(WindowsSDKVersion)</WindowsTargetPlatformVersion>", # 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()
|
|
@ -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
|
|
|
@ -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])
|
|
|
@ -1,4 +1,4 @@
|
||||||
cmake_minimum_required(VERSION 3.13)
|
cmake_minimum_required(VERSION 3.12)
|
||||||
|
|
||||||
project(fribidi)
|
project(fribidi)
|
||||||
|
|
||||||
|
|
|
@ -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")
|
|
|
@ -1,9 +0,0 @@
|
||||||
|
|
||||||
Get-ChildItem .\Projects\VC2015\ *.vcxproj -recurse |
|
|
||||||
Foreach-Object {
|
|
||||||
$c = ($_ | Get-Content)
|
|
||||||
$c = $c -replace 'MultiThreaded<','MultiThreadedDLL<'
|
|
||||||
$c = $c -replace '<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>','<WindowsTargetPlatformVersion>10</WindowsTargetPlatformVersion>'
|
|
||||||
$c = $c -replace '<PlatformToolset>v140</PlatformToolset>','<PlatformToolset>v142</PlatformToolset>'
|
|
||||||
[IO.File]::WriteAllText($_.FullName, ($c -join "`r`n"))
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
cmake_minimum_required(VERSION 3.13)
|
cmake_minimum_required(VERSION 3.12)
|
||||||
|
|
||||||
project(libraqm)
|
project(libraqm)
|
||||||
|
|
||||||
|
|
|
@ -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)
|
|
|
@ -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])
|
|
|
@ -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])
|
|
Loading…
Reference in New Issue
Block a user