Merge pull request #4084 from nulano/gha-win

Test Windows with GitHub Actions
This commit is contained in:
Hugo van Kemenade 2019-10-11 22:16:45 +03:00 committed by GitHub
commit 23c3891b81
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 615 additions and 63 deletions

360
.github/workflows/test-windows.yml vendored Normal file
View File

@ -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

View File

@ -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

View File

@ -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 @@ codecs = dir(Image.core)
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:

View File

@ -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 @@ valgrind --tool=massif python test-installed.py -s -v Tests/check_jpeg_leaks.py
"""
@unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS")
@unittest.skipIf(is_win32(), "requires Unix or macOS")
class TestJpegLeaks(PillowTestCase):
"""

View File

@ -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":

View File

@ -4,9 +4,7 @@ import sys
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 @@ class TestCoreMemory(PillowTestCase):
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 @@ class TestCoreMemory(PillowTestCase):
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 @@ class TestCoreMemory(PillowTestCase):
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 @@ class TestCoreMemory(PillowTestCase):
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)

View File

@ -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 @@ class TestFileJpeg(PillowTestCase):
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:

View File

@ -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 @@ class TestFilePng(PillowTestCase):
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

View File

@ -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 @@ class TestFileTiff(PillowTestCase):
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")

View File

@ -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

View File

@ -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 @@ class TestImage(PillowTestCase):
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)

View File

@ -6,7 +6,7 @@ from distutils import ccompiler, sysconfig
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 @@ class TestCffi(AccessTest):
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:

View File

@ -9,7 +9,7 @@ from io import BytesIO
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 @@ class TestImageFont(PillowTestCase):
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 @@ class TestImageFont(PillowTestCase):
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 @@ class TestImageFont(PillowTestCase):
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.

View File

@ -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 @@ class TestImageShow(PillowTestCase):
# 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)

View File

@ -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 @@ class TestImageWin(PillowTestCase):
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

View File

@ -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):

View File

@ -5,8 +5,14 @@ import subprocess
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()

View File

@ -2,7 +2,7 @@ import sys
from PIL import Image
from .helper import PillowTestCase, unittest
from .helper import PillowTestCase, is_win32, unittest
try:
import numpy
@ -10,7 +10,7 @@ except ImportError:
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

View File

@ -1,5 +1,4 @@
import shutil
import sys
from PIL import GifImagePlugin, Image, JpegImagePlugin
@ -7,6 +6,7 @@ from .helper import (
PillowTestCase,
cjpeg_available,
djpeg_available,
is_win32,
netpbm_available,
unittest,
)
@ -17,7 +17,7 @@ TEST_GIF = "Tests/images/hopper.gif"
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:

View File

@ -127,7 +127,7 @@ 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('%%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

View File

@ -202,7 +202,7 @@ setlocal
+ 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%%

View File

@ -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 @@ pythons = {
"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 @@ libs = {
"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 @@ libs = {
"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 = {

102
winbuild/fribidi.cmake Normal file
View File

@ -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)

39
winbuild/raqm.cmake Normal file
View File

@ -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})