Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 29b088c

Browse files
committed
Simplify version checks for freetype and libpng.
Currently, setupext.py replicates a lot of work done by the compiler to check whether header files are present, and whether freetype and libpng have sufficiently recent versions. Instead, we can just add a small stub source file at the top of the extension sources which just tries to include the header and checks the version macros. If the header is not found, compilation will immediately abort with `foo.h: No such file or directory`; if the version is too old, we can emit an appropriate error message (`#pragma message` is supported by all major compilers and allows expanding of macros in the error message).
1 parent bfd25e7 commit 29b088c

File tree

3 files changed

+28
-73
lines changed

3 files changed

+28
-73
lines changed

setupext.py

Lines changed: 10 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -887,6 +887,13 @@ def add_flags(self, ext, add_sources=True):
887887
os.path.join('extern', 'agg24-svn', 'src', x) for x in agg_sources)
888888

889889

890+
# For FreeType2 and libpng, we add a separate checkdep_foo.c source to at the
891+
# top of the extension sources. This file is compiled first and immediately
892+
# aborts the compilation either with "foo.h: No such file or directory" if the
893+
# header is not found, or an appropriate error message if the header indicates
894+
# a too-old version.
895+
896+
890897
class FreeType(SetupPackage):
891898
name = "freetype"
892899
pkg_names = {
@@ -898,59 +905,8 @@ class FreeType(SetupPackage):
898905
"windows_url": "http://gnuwin32.sourceforge.net/packages/freetype.htm"
899906
}
900907

901-
def check(self):
902-
if options.get('local_freetype'):
903-
return "Using local version for testing"
904-
905-
if sys.platform == 'win32':
906-
try:
907-
check_include_file(get_include_dirs(), 'ft2build.h', 'freetype')
908-
except CheckFailed:
909-
check_include_file(get_include_dirs(), os.path.join('freetype2', 'ft2build.h'), 'freetype')
910-
return 'Using unknown version found on system.'
911-
912-
status, output = subprocess.getstatusoutput(
913-
"freetype-config --ftversion")
914-
if status == 0:
915-
version = output
916-
else:
917-
version = None
918-
919-
# Early versions of freetype grep badly inside freetype-config,
920-
# so catch those cases. (tested with 2.5.3).
921-
if version is None or 'No such file or directory\ngrep:' in version:
922-
version = self.version_from_header()
923-
924-
# pkg_config returns the libtool version rather than the
925-
# freetype version so we need to explicitly pass the version
926-
# to _check_for_pkg_config
927-
return self._check_for_pkg_config(
928-
'freetype2', 'ft2build.h',
929-
min_version='2.3', version=version)
930-
931-
def version_from_header(self):
932-
version = 'unknown'
933-
ext = self.get_extension()
934-
if ext is None:
935-
return version
936-
# Return the first version found in the include dirs.
937-
for include_dir in ext.include_dirs:
938-
header_fname = os.path.join(include_dir, 'freetype.h')
939-
if os.path.exists(header_fname):
940-
major, minor, patch = 0, 0, 0
941-
with open(header_fname, 'r') as fh:
942-
for line in fh:
943-
if line.startswith('#define FREETYPE_'):
944-
value = line.rsplit(' ', 1)[1].strip()
945-
if 'MAJOR' in line:
946-
major = value
947-
elif 'MINOR' in line:
948-
minor = value
949-
else:
950-
patch = value
951-
return '.'.join([major, minor, patch])
952-
953908
def add_flags(self, ext):
909+
ext.sources.insert(0, 'src/checkdep_freetype2.c')
954910
if options.get('local_freetype'):
955911
src_path = os.path.join(
956912
'build', 'freetype-{0}'.format(LOCAL_FREETYPE_VERSION))
@@ -1131,30 +1087,11 @@ class Png(SetupPackage):
11311087
"windows_url": "http://gnuwin32.sourceforge.net/packages/libpng.htm"
11321088
}
11331089

1134-
def check(self):
1135-
if sys.platform == 'win32':
1136-
check_include_file(get_include_dirs(), 'png.h', 'png')
1137-
return 'Using unknown version found on system.'
1138-
1139-
status, output = subprocess.getstatusoutput("libpng-config --version")
1140-
if status == 0:
1141-
version = output
1142-
else:
1143-
version = None
1144-
1145-
try:
1146-
return self._check_for_pkg_config(
1147-
'libpng', 'png.h',
1148-
min_version='1.2', version=version)
1149-
except CheckFailed as e:
1150-
if has_include_file(get_include_dirs(), 'png.h'):
1151-
return str(e) + ' Using unknown version found on system.'
1152-
raise
1153-
11541090
def get_extension(self):
11551091
sources = [
1092+
'src/checkdep_libpng.c',
11561093
'src/_png.cpp',
1157-
'src/mplutils.cpp'
1094+
'src/mplutils.cpp',
11581095
]
11591096
ext = make_extension('matplotlib._png', sources)
11601097
pkg_config.setup_extension(

src/checkdep_freetype2.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#include <ft2build.h>
2+
#include FT_FREETYPE_H
3+
4+
#define XSTR(x) STR(x)
5+
#define STR(x) #x
6+
7+
#pragma message "Compiling with FreeType version " \
8+
XSTR(FREETYPE_MAJOR) "." XSTR(FREETYPE_MINOR) "." XSTR(FREETYPE_PATCH) "."
9+
#if FREETYPE_MAJOR << 16 + FREETYPE_MINOR << 8 + FREETYPE_PATCH < 0x020300
10+
#error "FreeType version 2.3 or higher is required." \
11+
"Consider setting the MPLLOCALFREETYPE environment variable to 1."
12+
#error
13+
#endif

src/checkdep_libpng.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#include <png.h>
2+
#pragma message "Compiling with libpng version " PNG_LIBPNG_VER_STRING "."
3+
#if PNG_LIBPNG_VER < 10200
4+
#error "libpng version 1.2 or higher is required."
5+
#endif

0 commit comments

Comments
 (0)