diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml new file mode 100644 index 00000000000..541fe021c22 --- /dev/null +++ b/.github/workflows/test-windows.yml @@ -0,0 +1,360 @@ +name: Test Windows + +on: [push, pull_request] + +jobs: + build: + + runs-on: windows-2016 + strategy: + fail-fast: false + matrix: + python-version: ["3.5", "3.6", "3.7", "pypy3.6"] + architecture: ["x86", "x64"] + include: + - architecture: "x86" + platform-vcvars: "x86" + platform-msbuild: "Win32" + - architecture: "x64" + platform-vcvars: "x86_amd64" + platform-msbuild: "x64" + - python-version: "pypy3.6" + pypy-version: "pypy-c-jit-97588-7392d01b93d0-win32" + pypy-url: "http://buildbot.pypy.org/nightly/py3.6/pypy-c-jit-97588-7392d01b93d0-win32.zip" + # pypy-url: "https://bitbucket.org/pypy/pypy/downloads/${{ matrix.pypy-version }}.zip" + exclude: + - python-version: "pypy3.6" + architecture: "x64" + timeout-minutes: 30 + + name: Python ${{ matrix.python-version }} ${{ matrix.architecture }} + + steps: + - uses: actions/checkout@v1 + + - name: Install PyPy + if: "contains(matrix.python-version, 'pypy')" + run: | + curl -fsSL -o pypy3.zip "${{ matrix.pypy-url }}" + 7z x pypy3.zip "-o$env:RUNNER_WORKSPACE\" + mv "$env:RUNNER_WORKSPACE\${{ matrix.pypy-version }}" "$env:RUNNER_WORKSPACE\${{ matrix.python-version }}" + $env:PYTHON="$env:RUNNER_WORKSPACE\${{ matrix.python-version }}" + # set env: pythonLocation + Write-Host "`#`#[set-env name=pythonLocation;]$env:PYTHON" # old syntax https://github.com/actions/toolkit/issues/61 + Write-Host "::set-env name=pythonLocation::$env:PYTHON" # new syntax https://github.com/actions/toolkit/blob/5bb77ec03fea98332e41f9347c8fbb1ce1e48f4a/docs/commands.md + New-Item -ItemType SymbolicLink -Path "$env:PYTHON\python.exe" -Target "$env:PYTHON\pypy3.exe" + curl -fsSL -o get-pip.py https://bootstrap.pypa.io/get-pip.py + & $env:PYTHON\python.exe get-pip.py + shell: pwsh + + # sets env: pythonLocation + - name: Set up Python + if: "!contains(matrix.python-version, 'pypy')" + uses: actions/setup-python@v1 + with: + python-version: ${{ matrix.python-version }} + architecture: ${{ matrix.architecture }} + + - name: pip install wheel pytest pytest-cov codecov + run: | + "%pythonLocation%\python.exe" -m pip install wheel pytest pytest-cov + pip install codecov + + - name: Fetch dependencies + run: | + curl -fsSL -o nasm.zip https://www.nasm.us/pub/nasm/releasebuilds/2.14.02/win64/nasm-2.14.02-win64.zip + 7z x nasm.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" + + $env:PYTHON=$env:pythonLocation + curl -fsSL -o pillow-depends.zip https://github.com/python-pillow/pillow-depends/archive/master.zip + 7z x pillow-depends.zip -oc:\ + mv c:\pillow-depends-master c:\pillow-depends + xcopy c:\pillow-depends\*.zip $env:GITHUB_WORKSPACE\winbuild\ + xcopy c:\pillow-depends\*.tar.gz $env:GITHUB_WORKSPACE\winbuild\ + xcopy /s c:\pillow-depends\test_images\* $env:GITHUB_WORKSPACE\tests\images\ + cd $env:GITHUB_WORKSPACE/winbuild/ + python.exe $env:GITHUB_WORKSPACE\winbuild\build_dep.py + env: + EXECUTABLE: bin\python.exe + shell: pwsh + + - name: Build dependencies / libjpeg + if: false + run: | + REM FIXME uses /MT not /MD, see makefile.vc and win32.mak for more info + + 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-9c + call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" ${{ matrix.platform-vcvars }} 8.1 + 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% + + - name: Build dependencies / libjpeg-turbo + run: | + set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include + set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32 + set BUILD=%GITHUB_WORKSPACE%\winbuild\build + cd /D %BUILD%\libjpeg-turbo-2.0.3 + call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" ${{ matrix.platform-vcvars }} 8.1 + 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 + + - name: Build dependencies / zlib + run: | + set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include + set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32 + set BUILD=%GITHUB_WORKSPACE%\winbuild\build + cd /D %BUILD%\zlib-1.2.11 + call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" ${{ matrix.platform-vcvars }} 8.1 + 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 + + - 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.0.10 + call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" ${{ matrix.platform-vcvars }} 8.1 + 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% + + - name: Build dependencies / WebP + run: | + set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include + set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32 + set BUILD=%GITHUB_WORKSPACE%\winbuild\build + cd /D %BUILD%\libwebp-1.0.3 + call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" ${{ matrix.platform-vcvars }} 8.1 + 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% + + - name: Build dependencies / FreeType + run: | + REM Toolkit v100 not available; missing VCTargetsPath; Clean fails + + set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include + set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32 + set BUILD=%GITHUB_WORKSPACE%\winbuild\build + cd /D %BUILD%\freetype-2.10.1 + call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" ${{ matrix.platform-vcvars }} 8.1 + echo on + rmdir /S /Q objs + set DefaultPlatformToolset=v140 + set VCTargetsPath=C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\VC\VCTargets + set MSBUILD="C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\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% + + - name: Build dependencies / LCMS2 + run: | + set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include + set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32 + set BUILD=%GITHUB_WORKSPACE%\winbuild\build + cd /D %BUILD%\lcms2-2.8 + call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" ${{ matrix.platform-vcvars }} 8.1 + echo on + rmdir /S /Q Lib + rmdir /S /Q Projects\VC2015\Release + set VCTargetsPath=C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\VC\VCTargets + set MSBUILD="C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\MSBuild.exe" + powershell -Command "(gc Projects\VC2015\lcms2_static\lcms2_static.vcxproj) -replace 'MultiThreaded<', 'MultiThreadedDLL<' | Out-File -encoding ASCII Projects\VC2015\lcms2_static\lcms2_static.vcxproj" + %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% + + - name: Build dependencies / OpenJPEG + run: | + set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include + set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32 + set BUILD=%GITHUB_WORKSPACE%\winbuild\build + cd /D %BUILD%\openjpeg-2.3.1msvcr10-x32 + call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" ${{ matrix.platform-vcvars }} 8.1 + 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% + + # GPL licensed; skip if building wheels + - name: Build dependencies / libimagequant + if: "github.event_name != 'push' || contains(matrix.python-version, 'pypy')" + run: | + set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include + set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32 + set BUILD=%GITHUB_WORKSPACE%\winbuild\build + rem ba653c8: Merge tag '2.12.5' into msvc + cd /D %BUILD%\libimagequant-ba653c8ccb34dde4e21c6076d85a72d21ed9d971 + call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" ${{ matrix.platform-vcvars }} 8.1 + 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% + + # for Raqm + - name: Build dependencies / HarfBuzz + if: "!contains(matrix.python-version, 'pypy')" + run: | + set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include + set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32 + set BUILD=%GITHUB_WORKSPACE%\winbuild\build + set INCLUDE=%INCLUDE%;%INCLIB% + set LIB=%LIB%;%INCLIB% + cd /D %BUILD%\harfbuzz-2.6.1 + call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" ${{ matrix.platform-vcvars }} 8.1 + 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% + + # for Raqm + - name: Build dependencies / FriBidi + if: "!contains(matrix.python-version, 'pypy')" + run: | + set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include + set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32 + set BUILD=%GITHUB_WORKSPACE%\winbuild\build + cd /D %BUILD%\fribidi-1.0.7 + call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" ${{ matrix.platform-vcvars }} 8.1 + 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% + + # failing with PyPy3 + - name: Build dependencies / Raqm + if: "!contains(matrix.python-version, 'pypy')" + run: | + set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include + set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32 + set BUILD=%GITHUB_WORKSPACE%\winbuild\build + set INCLUDE=%INCLUDE%;%INCLIB% + set LIB=%LIB%;%INCLIB% + cd /D %BUILD%\libraqm-0.7.0 + call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" ${{ matrix.platform-vcvars }} 8.1 + 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% + + - name: Build dependencies / ghostscript + 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%\ghostscript-9.27 + call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" ${{ matrix.platform-vcvars }} 8.1 + echo on + set MSVC_VERSION=14 + set RCOMP="C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Bin\RC.Exe" + if "${{ matrix.architecture }}"=="x64" set WIN64="" + nmake -nologo -f psi\msvc.mak + rem Add bin to PATH variable: Copy to INCLIB, then add INCLIB to PATH in Test step. + copy /Y /B bin\* %INCLIB% + + - name: Build Pillow + run: | + set PYTHON=%pythonLocation% + set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include + set MPLSRC=%GITHUB_WORKSPACE% + set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32 + cd /D %GITHUB_WORKSPACE% + set LIB=%INCLIB%;%PYTHON%\tcl + set INCLUDE=%INCLIB%;%GITHUB_WORKSPACE%\depends\tcl86\include;%INCLUDE% + call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" ${{ matrix.platform-vcvars }} 8.1 + %PYTHON%\python.exe setup.py build_ext install + rem Add GhostScript and Raqm binaries (copied to INCLIB) to PATH. + path %INCLIB%;%PATH% + %PYTHON%\python.exe selftest.py --installed + + - name: Test Pillow + run: | + set PYTHON=%pythonLocation% + set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32 + rem Add GhostScript and Raqm binaries (copied to INCLIB) to PATH. + path %INCLIB%;%PATH% + cd /D %GITHUB_WORKSPACE% + %PYTHON%\python.exe -m pytest -vx --cov PIL --cov-report term --cov-report xml Tests + + - name: Upload coverage + run: 'codecov --file "%GITHUB_WORKSPACE%\coverage.xml" --name "%pythonLocation%"' + + - name: Build wheel + id: wheel + if: "github.event_name == 'push' && !contains(matrix.python-version, 'pypy')" + run: | + for /f "tokens=3 delims=/" %%a in ("${{ github.ref }}") do echo ##[set-output name=dist;]dist-%%a + for /f "tokens=3 delims=/" %%a in ("${{ github.ref }}") do echo ::set-output name=dist::dist-%%a + set PYTHON=%pythonLocation% + set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\V7.1A\Include + set MPLSRC=%GITHUB_WORKSPACE% + set INCLIB=%GITHUB_WORKSPACE%\winbuild\depends\msvcr10-x32 + cd /D %GITHUB_WORKSPACE% + set LIB=%INCLIB%;%PYTHON%\tcl + set INCLUDE=%INCLIB%;%GITHUB_WORKSPACE%\depends\tcl86\include;%INCLUDE% + call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" ${{ matrix.platform-vcvars }} 8.1 + %PYTHON%\python.exe setup.py bdist_wheel + + - uses: actions/upload-artifact@v1 + if: "github.event_name == 'push' && !contains(matrix.python-version, 'pypy')" + with: + name: ${{ steps.wheel.outputs.dist }} + path: dist diff --git a/Tests/check_imaging_leaks.py b/Tests/check_imaging_leaks.py index 2b9a9605be4..a109b5cd59b 100755 --- a/Tests/check_imaging_leaks.py +++ b/Tests/check_imaging_leaks.py @@ -2,17 +2,15 @@ from __future__ import division -import sys - from PIL import Image -from .helper import PillowTestCase, unittest +from .helper import PillowTestCase, is_win32, unittest min_iterations = 100 max_iterations = 10000 -@unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS") +@unittest.skipIf(is_win32(), "requires Unix or macOS") class TestImagingLeaks(PillowTestCase): def _get_mem_usage(self): from resource import getpagesize, getrusage, RUSAGE_SELF diff --git a/Tests/check_j2k_leaks.py b/Tests/check_j2k_leaks.py index 4614529ed11..d9c6c68b7a9 100755 --- a/Tests/check_j2k_leaks.py +++ b/Tests/check_j2k_leaks.py @@ -1,9 +1,8 @@ -import sys from io import BytesIO from PIL import Image -from .helper import PillowTestCase, unittest +from .helper import PillowTestCase, is_win32, unittest # Limits for testing the leak mem_limit = 1024 * 1048576 @@ -13,7 +12,7 @@ test_file = "Tests/images/rgb_trns_ycbc.jp2" -@unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS") +@unittest.skipIf(is_win32(), "requires Unix or macOS") class TestJpegLeaks(PillowTestCase): def setUp(self): if "jpeg2k_encoder" not in codecs or "jpeg2k_decoder" not in codecs: diff --git a/Tests/check_jpeg_leaks.py b/Tests/check_jpeg_leaks.py index 2f758ba10c1..8cb93f2dd0a 100644 --- a/Tests/check_jpeg_leaks.py +++ b/Tests/check_jpeg_leaks.py @@ -1,7 +1,6 @@ -import sys from io import BytesIO -from .helper import PillowTestCase, hopper, unittest +from .helper import PillowTestCase, hopper, is_win32, unittest iterations = 5000 @@ -15,7 +14,7 @@ """ -@unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS") +@unittest.skipIf(is_win32(), "requires Unix or macOS") class TestJpegLeaks(PillowTestCase): """ diff --git a/Tests/helper.py b/Tests/helper.py index c39b11c8303..466d04bda45 100644 --- a/Tests/helper.py +++ b/Tests/helper.py @@ -351,10 +351,25 @@ def on_appveyor(): return "APPVEYOR" in os.environ +def on_github_actions(): + return "GITHUB_ACTIONS" in os.environ + + def on_ci(): # Travis and AppVeyor have "CI" # Azure Pipelines has "TF_BUILD" - return "CI" in os.environ or "TF_BUILD" in os.environ + # GitHub Actions has "GITHUB_ACTIONS" + return ( + "CI" in os.environ or "TF_BUILD" in os.environ or "GITHUB_ACTIONS" in os.environ + ) + + +def is_win32(): + return sys.platform.startswith("win32") + + +def is_pypy(): + return hasattr(sys, "pypy_translation_info") if sys.platform == "win32": diff --git a/Tests/test_core_resources.py b/Tests/test_core_resources.py index eefb1a0efab..0aedb91c926 100644 --- a/Tests/test_core_resources.py +++ b/Tests/test_core_resources.py @@ -4,9 +4,7 @@ from PIL import Image -from .helper import PillowTestCase, unittest - -is_pypy = hasattr(sys, "pypy_version_info") +from .helper import PillowTestCase, is_pypy, unittest class TestCoreStats(PillowTestCase): @@ -87,7 +85,7 @@ def test_set_block_size_stats(self): stats = Image.core.get_stats() self.assertGreaterEqual(stats["new_count"], 1) self.assertGreaterEqual(stats["allocated_blocks"], 64) - if not is_pypy: + if not is_pypy(): self.assertGreaterEqual(stats["freed_blocks"], 64) def test_get_blocks_max(self): @@ -108,7 +106,7 @@ def test_set_blocks_max(self): if sys.maxsize < 2 ** 32: self.assertRaises(ValueError, Image.core.set_blocks_max, 2 ** 29) - @unittest.skipIf(is_pypy, "images are not collected") + @unittest.skipIf(is_pypy(), "images are not collected") def test_set_blocks_max_stats(self): Image.core.reset_stats() Image.core.set_blocks_max(128) @@ -123,7 +121,7 @@ def test_set_blocks_max_stats(self): self.assertEqual(stats["freed_blocks"], 0) self.assertEqual(stats["blocks_cached"], 64) - @unittest.skipIf(is_pypy, "images are not collected") + @unittest.skipIf(is_pypy(), "images are not collected") def test_clear_cache_stats(self): Image.core.reset_stats() Image.core.clear_cache() @@ -153,7 +151,7 @@ def test_large_images(self): self.assertGreaterEqual(stats["allocated_blocks"], 16) self.assertGreaterEqual(stats["reused_blocks"], 0) self.assertEqual(stats["blocks_cached"], 0) - if not is_pypy: + if not is_pypy(): self.assertGreaterEqual(stats["freed_blocks"], 16) diff --git a/Tests/test_file_jpeg.py b/Tests/test_file_jpeg.py index 7f9bf7c1d6d..5a34a3faa74 100644 --- a/Tests/test_file_jpeg.py +++ b/Tests/test_file_jpeg.py @@ -1,10 +1,16 @@ import os -import sys from io import BytesIO from PIL import Image, ImageFile, JpegImagePlugin -from .helper import PillowTestCase, cjpeg_available, djpeg_available, hopper, unittest +from .helper import ( + PillowTestCase, + cjpeg_available, + djpeg_available, + hopper, + is_win32, + unittest, +) codecs = dir(Image.core) @@ -654,7 +660,7 @@ def test_photoshop(self): self.assertNotIn("photoshop", im.info) -@unittest.skipUnless(sys.platform.startswith("win32"), "Windows only") +@unittest.skipUnless(is_win32(), "Windows only") class TestFileCloseW32(PillowTestCase): def setUp(self): if "jpeg_encoder" not in codecs or "jpeg_decoder" not in codecs: diff --git a/Tests/test_file_png.py b/Tests/test_file_png.py index 6d76a6caa7c..07e84ef722b 100644 --- a/Tests/test_file_png.py +++ b/Tests/test_file_png.py @@ -1,11 +1,10 @@ -import sys import zlib from io import BytesIO from PIL import Image, ImageFile, PngImagePlugin from PIL._util import py3 -from .helper import PillowLeakTestCase, PillowTestCase, hopper, unittest +from .helper import PillowLeakTestCase, PillowTestCase, hopper, is_win32, unittest try: from PIL import _webp @@ -650,7 +649,7 @@ def test_apng(self): self.assert_image_similar(im, expected, 0.23) -@unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS") +@unittest.skipIf(is_win32(), "requires Unix or macOS") class TestTruncatedPngPLeaks(PillowLeakTestCase): mem_limit = 2 * 1024 # max increase in K iterations = 100 # Leak is 56k/iteration, this will leak 5.6megs diff --git a/Tests/test_file_tiff.py b/Tests/test_file_tiff.py index 076f5b8cd0e..a335e5e7a61 100644 --- a/Tests/test_file_tiff.py +++ b/Tests/test_file_tiff.py @@ -1,13 +1,12 @@ import logging import os -import sys from io import BytesIO from PIL import Image, TiffImagePlugin from PIL._util import py3 from PIL.TiffImagePlugin import RESOLUTION_UNIT, X_RESOLUTION, Y_RESOLUTION -from .helper import PillowTestCase, hopper, unittest +from .helper import PillowTestCase, hopper, is_win32, unittest logger = logging.getLogger(__name__) @@ -582,7 +581,7 @@ def test_string_dimension(self): Image.open("Tests/images/string_dimension.tiff") -@unittest.skipUnless(sys.platform.startswith("win32"), "Windows only") +@unittest.skipUnless(is_win32(), "Windows only") class TestFileTiffW32(PillowTestCase): def test_fd_leak(self): tmpfile = self.tempfile("temp.tif") diff --git a/Tests/test_font_leaks.py b/Tests/test_font_leaks.py index 14b36858523..9b5fe2055d4 100644 --- a/Tests/test_font_leaks.py +++ b/Tests/test_font_leaks.py @@ -1,13 +1,11 @@ from __future__ import division -import sys - from PIL import Image, ImageDraw, ImageFont, features -from .helper import PillowLeakTestCase, unittest +from .helper import PillowLeakTestCase, is_win32, unittest -@unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS") +@unittest.skipIf(is_win32(), "requires Unix or macOS") class TestTTypeFontLeak(PillowLeakTestCase): # fails at iteration 3 in master iterations = 10 diff --git a/Tests/test_image.py b/Tests/test_image.py index d48b70ffb50..54a7680c629 100644 --- a/Tests/test_image.py +++ b/Tests/test_image.py @@ -1,12 +1,11 @@ import os import shutil -import sys import tempfile from PIL import Image from PIL._util import py3 -from .helper import PillowTestCase, hopper, unittest +from .helper import PillowTestCase, hopper, is_win32, unittest class TestImage(PillowTestCase): @@ -149,9 +148,7 @@ def test_internals(self): im.paste(0, (0, 0, 100, 100)) self.assertFalse(im.readonly) - @unittest.skipIf( - sys.platform.startswith("win32"), "Test requires opening tempfile twice" - ) + @unittest.skipIf(is_win32(), "Test requires opening tempfile twice") def test_readonly_save(self): temp_file = self.tempfile("temp.bmp") shutil.copy("Tests/images/rgb32bf-rgba.bmp", temp_file) diff --git a/Tests/test_image_access.py b/Tests/test_image_access.py index 4b28a2eda30..d7bd828e929 100644 --- a/Tests/test_image_access.py +++ b/Tests/test_image_access.py @@ -6,7 +6,7 @@ from PIL import Image -from .helper import PillowTestCase, hopper, on_appveyor, unittest +from .helper import PillowTestCase, hopper, is_win32, on_ci, unittest # CFFI imports pycparser which doesn't support PYTHONOPTIMIZE=2 # https://github.com/eliben/pycparser/pull/198#issuecomment-317001670 @@ -336,8 +336,8 @@ def test_p_putpixel_rgb_rgba(self): class TestEmbeddable(unittest.TestCase): @unittest.skipIf( - not sys.platform.startswith("win32") or on_appveyor(), - "Failing on AppVeyor when run from subprocess, not from shell", + not is_win32() or on_ci(), + "Failing on AppVeyor / GitHub Actions when run from subprocess, not from shell", ) def test_embeddable(self): with open("embed_pil.c", "w") as fh: diff --git a/Tests/test_imagefont.py b/Tests/test_imagefont.py index 6a2d572a954..6944404c163 100644 --- a/Tests/test_imagefont.py +++ b/Tests/test_imagefont.py @@ -9,7 +9,7 @@ from PIL import Image, ImageDraw, ImageFont, features -from .helper import PillowTestCase, unittest +from .helper import PillowTestCase, is_pypy, is_win32, unittest FONT_PATH = "Tests/fonts/FreeMono.ttf" FONT_SIZE = 20 @@ -464,10 +464,7 @@ def test_unicode_pilfont(self): with self.assertRaises(UnicodeEncodeError): font.getsize(u"’") - @unittest.skipIf( - sys.version.startswith("2") or hasattr(sys, "pypy_translation_info"), - "requires CPython 3.3+", - ) + @unittest.skipIf(sys.version.startswith("2") or is_pypy(), "requires CPython 3.3+") def test_unicode_extended(self): # issue #3777 text = u"A\u278A\U0001F12B" @@ -504,7 +501,7 @@ def loadable_font(filepath, size, index, encoding, *args, **kwargs): name = font.getname() self.assertEqual(("FreeMono", "Regular"), name) - @unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS") + @unittest.skipIf(is_win32(), "requires Unix or macOS") def test_find_linux_font(self): # A lot of mocking here - this is more for hitting code and # catching syntax like errors @@ -550,7 +547,7 @@ def fake_walker(path): font_directory + "/Duplicate.ttf", "Duplicate" ) - @unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS") + @unittest.skipIf(is_win32(), "requires Unix or macOS") def test_find_macos_font(self): # Like the linux test, more cover hitting code rather than testing # correctness. diff --git a/Tests/test_imageshow.py b/Tests/test_imageshow.py index 2f2620b7408..aac48d6c082 100644 --- a/Tests/test_imageshow.py +++ b/Tests/test_imageshow.py @@ -1,6 +1,6 @@ from PIL import Image, ImageShow -from .helper import PillowTestCase, hopper, on_ci, unittest +from .helper import PillowTestCase, hopper, is_win32, on_ci, on_github_actions, unittest class TestImageShow(PillowTestCase): @@ -34,7 +34,10 @@ def show_image(self, image, **options): # Restore original state ImageShow._viewers.pop(0) - @unittest.skipUnless(on_ci(), "Only run on CIs") + @unittest.skipUnless( + on_ci() and not (is_win32() and on_github_actions()), + "Only run on CIs; hangs on Windows on GitHub Actions", + ) def test_show(self): for mode in ("1", "I;16", "LA", "RGB", "RGBA"): im = hopper(mode) diff --git a/Tests/test_imagewin.py b/Tests/test_imagewin.py index 92fcdc28d60..2b203418752 100644 --- a/Tests/test_imagewin.py +++ b/Tests/test_imagewin.py @@ -1,8 +1,6 @@ -import sys - from PIL import ImageWin -from .helper import PillowTestCase, hopper, unittest +from .helper import PillowTestCase, hopper, is_win32, unittest class TestImageWin(PillowTestCase): @@ -32,7 +30,7 @@ def test_hwnd(self): self.assertEqual(wnd2, 50) -@unittest.skipUnless(sys.platform.startswith("win32"), "Windows only") +@unittest.skipUnless(is_win32(), "Windows only") class TestImageWinDib(PillowTestCase): def test_dib_image(self): # Arrange diff --git a/Tests/test_imagewin_pointers.py b/Tests/test_imagewin_pointers.py index efa3753b951..d7c22a209e6 100644 --- a/Tests/test_imagewin_pointers.py +++ b/Tests/test_imagewin_pointers.py @@ -1,14 +1,13 @@ import ctypes -import sys from io import BytesIO from PIL import Image, ImageWin -from .helper import PillowTestCase, hopper +from .helper import PillowTestCase, hopper, is_win32 # see https://github.com/python-pillow/Pillow/pull/1431#issuecomment-144692652 -if sys.platform.startswith("win32"): +if is_win32(): import ctypes.wintypes class BITMAPFILEHEADER(ctypes.Structure): diff --git a/Tests/test_main.py b/Tests/test_main.py index 847def83423..c6f9a694e68 100644 --- a/Tests/test_main.py +++ b/Tests/test_main.py @@ -5,8 +5,14 @@ import sys from unittest import TestCase +from .helper import is_pypy, is_win32, on_github_actions, unittest + class TestMain(TestCase): + @unittest.skipIf( + is_win32() and is_pypy() and on_github_actions(), + "Failing on Windows on GitHub Actions running PyPy", + ) def test_main(self): out = subprocess.check_output([sys.executable, "-m", "PIL"]).decode("utf-8") lines = out.splitlines() diff --git a/Tests/test_map.py b/Tests/test_map.py index 3fc42651b30..8d4e32219d8 100644 --- a/Tests/test_map.py +++ b/Tests/test_map.py @@ -2,7 +2,7 @@ from PIL import Image -from .helper import PillowTestCase, unittest +from .helper import PillowTestCase, is_win32, unittest try: import numpy @@ -10,7 +10,7 @@ numpy = None -@unittest.skipIf(sys.platform.startswith("win32"), "Win32 does not call map_buffer") +@unittest.skipIf(is_win32(), "Win32 does not call map_buffer") class TestMap(PillowTestCase): def test_overflow(self): # There is the potential to overflow comparisons in map.c diff --git a/Tests/test_shell_injection.py b/Tests/test_shell_injection.py index 35a3dcfcd86..97774a0a43b 100644 --- a/Tests/test_shell_injection.py +++ b/Tests/test_shell_injection.py @@ -1,5 +1,4 @@ import shutil -import sys from PIL import GifImagePlugin, Image, JpegImagePlugin @@ -7,6 +6,7 @@ PillowTestCase, cjpeg_available, djpeg_available, + is_win32, netpbm_available, unittest, ) @@ -17,7 +17,7 @@ test_filenames = ("temp_';", 'temp_";', "temp_'\"|", "temp_'\"||", "temp_'\"&&") -@unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS") +@unittest.skipIf(is_win32(), "requires Unix or macOS") class TestShellInjection(PillowTestCase): def assert_save_filename_check(self, src_img, save_func): for filename in test_filenames: diff --git a/winbuild/build.py b/winbuild/build.py index 0617022dcf9..e66df2f030c 100755 --- a/winbuild/build.py +++ b/winbuild/build.py @@ -127,7 +127,7 @@ def build_one(py_ver, compiler, bit): 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('%%INCLIB%%\\freetype.dll', os.path.dirname(_webp.__file__));" +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 diff --git a/winbuild/build_dep.py b/winbuild/build_dep.py index 487329db8b5..d7df22584ad 100644 --- a/winbuild/build_dep.py +++ b/winbuild/build_dep.py @@ -202,7 +202,7 @@ def nmake_libs(compiler, bit): + vc_setup(compiler, bit) + r""" rem do after building jpeg and zlib -copy %%~dp0\nmake.opt %%TIFF%% +copy %%~dp0\tiff.opt %%TIFF%%\nmake.opt cd /D %%TIFF%% nmake -nologo -f makefile.vc clean @@ -270,6 +270,7 @@ def build_lcms_70(compiler): 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 @@ -287,8 +288,10 @@ def build_lcms_71(compiler): 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%% diff --git a/winbuild/config.py b/winbuild/config.py index fb45f4527c4..37e45e8cb21 100644 --- a/winbuild/config.py +++ b/winbuild/config.py @@ -1,9 +1,10 @@ import os -SF_MIRROR = "http://iweb.dl.sourceforge.net" +SF_MIRROR = "https://iweb.dl.sourceforge.net" PILLOW_DEPENDS_DIR = "C:\\pillow-depends\\" pythons = { + # for AppVeyor "27": {"compiler": 7, "vc": 2010}, "pypy2": {"compiler": 7, "vc": 2010}, "35": {"compiler": 7.1, "vc": 2015}, @@ -11,6 +12,10 @@ "pypy3": {"compiler": 7.1, "vc": 2015}, "37": {"compiler": 7.1, "vc": 2015}, "38rc1-x64": {"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}, } VIRT_BASE = "c:/vp/" @@ -41,11 +46,16 @@ "filename": PILLOW_DEPENDS_DIR + "freetype-2.10.1.tar.gz", "dir": "freetype-2.10.1", }, - "lcms": { + "lcms-2.7": { "url": SF_MIRROR + "/project/lcms/lcms/2.7/lcms2-2.7.zip", "filename": PILLOW_DEPENDS_DIR + "lcms2-2.7.zip", "dir": "lcms2-2.7", }, + "lcms-2.8": { + "url": SF_MIRROR + "/project/lcms/lcms/2.8/lcms2-2.8.zip", + "filename": PILLOW_DEPENDS_DIR + "lcms2-2.8.zip", + "dir": "lcms2-2.8", + }, "ghostscript": { "url": "https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs927/ghostscript-9.27.tar.gz", # noqa: E501 "filename": PILLOW_DEPENDS_DIR + "ghostscript-9.27.tar.gz", @@ -83,6 +93,33 @@ "filename": PILLOW_DEPENDS_DIR + "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": PILLOW_DEPENDS_DIR + "libjpeg-turbo-2.0.3.tar.gz", + "dir": "libjpeg-turbo-2.0.3", + }, + # ba653c8: Merge tag '2.12.5' into msvc + "imagequant": { + "url": "https://github.com/ImageOptim/libimagequant/archive/ba653c8ccb34dde4e21c6076d85a72d21ed9d971.zip", # noqa: E501 + "filename": PILLOW_DEPENDS_DIR + + "libimagequant-ba653c8ccb34dde4e21c6076d85a72d21ed9d971.zip", + "dir": "libimagequant-ba653c8ccb34dde4e21c6076d85a72d21ed9d971", + }, + "harfbuzz": { + "url": "https://github.com/harfbuzz/harfbuzz/archive/2.6.1.zip", + "filename": PILLOW_DEPENDS_DIR + "harfbuzz-2.6.1.zip", + "dir": "harfbuzz-2.6.1", + }, + "fribidi": { + "url": "https://github.com/fribidi/fribidi/archive/v1.0.7.zip", + "filename": PILLOW_DEPENDS_DIR + "fribidi-1.0.7.zip", + "dir": "fribidi-1.0.7", + }, + "libraqm": { + "url": "https://github.com/HOST-Oman/libraqm/archive/v0.7.0.zip", + "filename": PILLOW_DEPENDS_DIR + "libraqm-0.7.0.zip", + "dir": "libraqm-0.7.0", + }, } compilers = { diff --git a/winbuild/fribidi.cmake b/winbuild/fribidi.cmake new file mode 100644 index 00000000000..247e79e4cdd --- /dev/null +++ b/winbuild/fribidi.cmake @@ -0,0 +1,102 @@ +cmake_minimum_required(VERSION 3.13) + +project(fribidi) + +add_definitions(-D_CRT_SECURE_NO_WARNINGS) + +include_directories(${CMAKE_CURRENT_BINARY_DIR}) +include_directories(lib) + +function(extract_regex_1 var text regex) + string(REGEX MATCH ${regex} _ ${text}) + set(${var} "${CMAKE_MATCH_1}" PARENT_SCOPE) +endfunction() + + +function(fribidi_conf) + file(READ configure.ac FRIBIDI_CONF) + extract_regex_1(FRIBIDI_MAJOR_VERSION "${FRIBIDI_CONF}" "\\(fribidi_major_version, ([0-9]+)\\)") + extract_regex_1(FRIBIDI_MINOR_VERSION "${FRIBIDI_CONF}" "\\(fribidi_minor_version, ([0-9]+)\\)") + extract_regex_1(FRIBIDI_MICRO_VERSION "${FRIBIDI_CONF}" "\\(fribidi_micro_version, ([0-9]+)\\)") + extract_regex_1(FRIBIDI_INTERFACE_VERSION "${FRIBIDI_CONF}" "\\(fribidi_interface_version, ([0-9]+)\\)") + extract_regex_1(FRIBIDI_INTERFACE_AGE "${FRIBIDI_CONF}" "\\(fribidi_interface_age, ([0-9]+)\\)") + extract_regex_1(FRIBIDI_BINARY_AGE "${FRIBIDI_CONF}" "\\(fribidi_binary_age, ([0-9]+)\\)") + set(FRIBIDI_VERSION "${FRIBIDI_MAJOR_VERSION}.${FRIBIDI_MINOR_VERSION}.${FRIBIDI_MICRO_VERSION}") + set(PACKAGE "fribidi") + set(PACKAGE_NAME "GNU FriBidi") + set(PACKAGE_BUGREPORT "https://github.com/fribidi/fribidi/issues/new") + set(SIZEOF_INT 4) + set(FRIBIDI_MSVC_BUILD_PLACEHOLDER "#define FRIBIDI_BUILT_WITH_MSVC") + message("detected ${PACKAGE_NAME} version ${FRIBIDI_VERSION}") + configure_file(lib/fribidi-config.h.in lib/fribidi-config.h @ONLY) +endfunction() +fribidi_conf() + + +function(prepend var prefix) + set(out "") + foreach(f ${ARGN}) + list(APPEND out "${prefix}${f}") + endforeach() + set(${var} "${out}" PARENT_SCOPE) +endfunction() + +macro(fribidi_definitions _TGT) + target_compile_definitions(${_TGT} PUBLIC + HAVE_MEMSET + HAVE_MEMMOVE + HAVE_STRDUP + HAVE_STDLIB_H=1 + HAVE_STRING_H=1 + HAVE_MEMORY_H=1 + #HAVE_STRINGS_H + #HAVE_SYS_TIMES_H + STDC_HEADERS=1 + HAVE_STRINGIZE=1) +endmacro() + +function(fribidi_gen _NAME _OUTNAME _PARAM) + set(_OUT lib/${_OUTNAME}) + prepend(_DEP "${CMAKE_CURRENT_SOURCE_DIR}/gen.tab/" ${ARGN}) + add_executable(gen-${_NAME} + gen.tab/gen-${_NAME}.c + gen.tab/packtab.c) + fribidi_definitions(gen-${_NAME}) + target_compile_definitions(gen-${_NAME} + PUBLIC DONT_HAVE_FRIBIDI_CONFIG_H) + add_custom_command( + COMMAND gen-${_NAME} ${_PARAM} ${_DEP} > ${_OUT} + DEPENDS ${_DEP} + OUTPUT ${_OUT}) + list(APPEND FRIBIDI_SOURCES_GENERATED "${_OUT}") + set(FRIBIDI_SOURCES_GENERATED ${FRIBIDI_SOURCES_GENERATED} PARENT_SCOPE) +endfunction() + +fribidi_gen(unicode-version fribidi-unicode-version.h "" + unidata/ReadMe.txt unidata/BidiMirroring.txt) + + +macro(fribidi_tab _NAME) + fribidi_gen(${_NAME}-tab ${_NAME}.tab.i 2 ${ARGN}) + target_sources(gen-${_NAME}-tab + PRIVATE lib/fribidi-unicode-version.h) +endmacro() + +fribidi_tab(bidi-type unidata/UnicodeData.txt) +fribidi_tab(joining-type unidata/UnicodeData.txt unidata/ArabicShaping.txt) +fribidi_tab(arabic-shaping unidata/UnicodeData.txt) +fribidi_tab(mirroring unidata/BidiMirroring.txt) +fribidi_tab(brackets unidata/BidiBrackets.txt unidata/UnicodeData.txt) +fribidi_tab(brackets-type unidata/BidiBrackets.txt) + + +file(GLOB FRIBIDI_SOURCES lib/*.c) +file(GLOB FRIBIDI_HEADERS lib/*.h) + +add_library(fribidi STATIC + ${FRIBIDI_SOURCES} + ${FRIBIDI_HEADERS} + ${FRIBIDI_SOURCES_GENERATED}) +fribidi_definitions(fribidi) +target_compile_definitions(fribidi + PUBLIC -DFRIBIDI_ENTRY=extern) diff --git a/winbuild/raqm.cmake b/winbuild/raqm.cmake new file mode 100644 index 00000000000..88eb7f28479 --- /dev/null +++ b/winbuild/raqm.cmake @@ -0,0 +1,39 @@ +cmake_minimum_required(VERSION 3.13) + +project(libraqm) + + +find_library(fribidi NAMES fribidi) +find_library(harfbuzz NAMES harfbuzz) +find_library(freetype NAMES freetype) + +add_definitions(-DFRIBIDI_ENTRY=extern) + + +function(raqm_conf) + file(READ configure.ac RAQM_CONF) + string(REGEX MATCH "\\[([0-9]+)\\.([0-9]+)\\.([0-9]+)\\]," _ "${RAQM_CONF}") + set(RAQM_VERSION_MAJOR "${CMAKE_MATCH_1}") + set(RAQM_VERSION_MINOR "${CMAKE_MATCH_2}") + set(RAQM_VERSION_MICRO "${CMAKE_MATCH_3}") + set(RAQM_VERSION "${RAQM_VERSION_MAJOR}.${RAQM_VERSION_MINOR}.${RAQM_VERSION_MICRO}") + message("detected libraqm version ${RAQM_VERSION}") + configure_file(src/raqm-version.h.in src/raqm-version.h @ONLY) +endfunction() +raqm_conf() + + +set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) +set(RAQM_SOURCES + src/raqm.c) +set(RAQM_HEADERS + src/raqm.h + src/raqm-version.h) + +add_library(libraqm SHARED + ${RAQM_SOURCES} + ${RAQM_HEADERS}) +target_link_libraries(libraqm + ${fribidi} + ${harfbuzz} + ${freetype}) diff --git a/winbuild/nmake.opt b/winbuild/tiff.opt similarity index 100% rename from winbuild/nmake.opt rename to winbuild/tiff.opt