summarylogtreecommitdiffstats
path: root/include_dirs_from_externs.patch
blob: 7f115e76b460109ad20b86600c7e3d71089815e5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
https://github.com/cython/cython/pull/1654

commit 8f71406d1713f97979a602dbf4af92f0da8926ca
Author: Jeroen Demeyer <jdemeyer@cage.ugent.be>
Date:   Fri Mar 31 16:08:40 2017 +0200

    Automatically add include_dirs for externs

diff --git a/Cython/Build/Dependencies.py b/Cython/Build/Dependencies.py
index 9817c30..658d850 100644
--- a/Cython/Build/Dependencies.py
+++ b/Cython/Build/Dependencies.py
@@ -375,14 +375,30 @@ def normalize_existing(base_path, rel_paths):
 
 @cached_function
 def normalize_existing0(base_dir, rel_paths):
+    """
+    Given some base directory ``base_dir`` and a list of path names
+    ``rel_paths``, normalize each relative path name ``rel`` by
+    replacing it by ``os.path.join(base, rel)`` if that file exists.
+
+    Return a couple ``(normalized, needed_base)`` where ``normalized``
+    if the list of normalized file names and ``needed_base`` is
+    ``base_dir`` if we actually needed ``base_dir``. If no paths were
+    changed (for example, if all paths were already absolute), then
+    ``needed_base`` is ``None``.
+    """
     normalized = []
+    needed_base = None
     for rel in rel_paths:
+        if os.path.isabs(rel):
+            normalized.append(rel)
+            continue
         path = join_path(base_dir, rel)
         if path_exists(path):
             normalized.append(os.path.normpath(path))
+            needed_base = base_dir
         else:
             normalized.append(rel)
-    return normalized
+    return (normalized, needed_base)
 
 
 def resolve_depends(depends, include_dirs):
@@ -483,20 +499,25 @@ class DependencyTree(object):
         return all
 
     @cached_method
-    def cimports_and_externs(self, filename):
+    def cimports_externs_incdirs(self, filename):
         # This is really ugly. Nested cimports are resolved with respect to the
         # includer, but includes are resolved with respect to the includee.
         cimports, includes, externs = self.parse_dependencies(filename)[:3]
         cimports = set(cimports)
         externs = set(externs)
+        incdirs = set()
         for include in self.included_files(filename):
-            included_cimports, included_externs = self.cimports_and_externs(include)
+            included_cimports, included_externs, included_incdirs = self.cimports_externs_incdirs(include)
             cimports.update(included_cimports)
             externs.update(included_externs)
-        return tuple(cimports), normalize_existing(filename, externs)
+            incdirs.update(included_incdirs)
+        externs, incdir = normalize_existing(filename, externs)
+        if incdir:
+            incdirs.add(incdir)
+        return tuple(cimports), externs, incdirs
 
     def cimports(self, filename):
-        return self.cimports_and_externs(filename)[0]
+        return self.cimports_externs_incdirs(filename)[0]
 
     def package(self, filename):
         return package(filename)
@@ -579,12 +600,22 @@ class DependencyTree(object):
 
     def distutils_info0(self, filename):
         info = self.parse_dependencies(filename)[3]
-        externs = self.cimports_and_externs(filename)[1]
+        kwds = info.values
+        cimports, externs, incdirs = self.cimports_externs_incdirs(filename)
+        # Add dependencies on "cdef extern from ..." files
         if externs:
-            if 'depends' in info.values:
-                info.values['depends'] = list(set(info.values['depends']).union(externs))
+            if 'depends' in kwds:
+                kwds['depends'] = list(set(kwds['depends']).union(externs))
             else:
-                info.values['depends'] = list(externs)
+                kwds['depends'] = list(externs)
+        # Add include_dirs to ensure that the C compiler will find the
+        # "cdef extern from ..." files
+        if incdirs:
+            include_dirs = kwds.get('include_dirs', [])
+            for inc in incdirs:
+                if inc not in include_dirs:
+                    include_dirs = include_dirs + [inc]
+            kwds['include_dirs'] = include_dirs
         return info
 
     def distutils_info(self, filename, aliases=None, base=None):