4
4
# Setup script for PyPI; use CMakeFile.txt to build extension modules
5
5
6
6
import contextlib
7
- import glob
8
7
import os
9
- import re
10
8
import shutil
11
9
import subprocess
12
10
import sys
13
11
import tempfile
14
- from distutils .command .install_headers import install_headers
15
12
16
- from setuptools import setup
13
+ # PYBIND11_ALT_SDIST will build a different sdist, with the python-headers
14
+ # files, and the sys.prefix files (CMake and headers).
17
15
18
- # For now, there are three parts to this package. Besides the "normal" module:
19
- # PYBIND11_USE_HEADERS will include the python-headers files.
20
- # PYBIND11_USE_SYSTEM will include the sys.prefix files (CMake and headers).
21
- # The final version will likely only include the normal module or come in
22
- # different versions.
23
-
24
- use_headers = os .environ .get ("PYBIND11_USE_HEADERS" , False )
25
- use_system = os .environ .get ("PYBIND11_USE_SYSTEM" , False )
26
-
27
- setup_opts = dict ()
16
+ alt_sdist = os .environ .get ("PYBIND11_ALT_SDIST" , False )
17
+ setup_py = "tools/setup_alt.py" if alt_sdist else "tools/setup_main.py"
18
+ pyproject_toml = "tools/pyproject.toml"
28
19
29
20
# In a PEP 518 build, this will be in its own environment, so it will not
30
21
# create extra files in the source
31
22
32
23
DIR = os .path .abspath (os .path .dirname (__file__ ))
33
24
34
- prexist_include = os .path .exists ("pybind11/include" )
35
- prexist_share = os .path .exists ("pybind11/share" )
36
-
37
25
38
26
@contextlib .contextmanager
39
- def monkey_patch_file (input_file ):
40
- "Allow a file to be temporarily modified"
27
+ def monkey_patch_file (input_file , replacement_file ):
28
+ "Allow a file to be temporarily replaced"
29
+ inp_file = os .path .abspath (os .path .join (DIR , input_file ))
30
+ rep_file = os .path .abspath (os .path .join (DIR , replacement_file ))
41
31
42
- with open (os . path . join ( DIR , input_file ), "r " ) as f :
32
+ with open (inp_file , "rb " ) as f :
43
33
contents = f .read ()
34
+ with open (rep_file , "rb" ) as f :
35
+ replacement = f .read ()
44
36
try :
45
- yield contents
37
+ with open (inp_file , "wb" ) as f :
38
+ f .write (replacement )
39
+ yield
46
40
finally :
47
- with open (os . path . join ( DIR , input_file ), "w " ) as f :
41
+ with open (inp_file , "wb " ) as f :
48
42
f .write (contents )
49
43
50
44
@@ -67,118 +61,20 @@ def remove_output(*sources):
67
61
shutil .rmtree (src )
68
62
69
63
70
- def check_compare (input_set , * patterns ):
71
- "Just a quick way to make sure all files are present"
72
- disk_files = set ()
73
- for pattern in patterns :
74
- disk_files |= set (glob .glob (pattern , recursive = True ))
75
-
76
- assert input_set == disk_files , "{} setup.py only, {} on disk only" .format (
77
- input_set - disk_files , disk_files - input_set
78
- )
79
-
80
-
81
- class InstallHeadersNested (install_headers ):
82
- def run (self ):
83
- headers = self .distribution .headers or []
84
- for header in headers :
85
- # Remove include/*/
86
- short_header = header .split ("/" , 2 )[- 1 ]
87
-
88
- dst = os .path .join (self .install_dir , os .path .dirname (short_header ))
89
- self .mkpath (dst )
90
- (out , _ ) = self .copy_file (header , dst )
91
- self .outfiles .append (out )
92
-
93
-
94
- main_headers = {
95
- "include/pybind11/attr.h" ,
96
- "include/pybind11/buffer_info.h" ,
97
- "include/pybind11/cast.h" ,
98
- "include/pybind11/chrono.h" ,
99
- "include/pybind11/common.h" ,
100
- "include/pybind11/complex.h" ,
101
- "include/pybind11/eigen.h" ,
102
- "include/pybind11/embed.h" ,
103
- "include/pybind11/eval.h" ,
104
- "include/pybind11/functional.h" ,
105
- "include/pybind11/iostream.h" ,
106
- "include/pybind11/numpy.h" ,
107
- "include/pybind11/operators.h" ,
108
- "include/pybind11/options.h" ,
109
- "include/pybind11/pybind11.h" ,
110
- "include/pybind11/pytypes.h" ,
111
- "include/pybind11/stl.h" ,
112
- "include/pybind11/stl_bind.h" ,
113
- }
114
-
115
- detail_headers = {
116
- "include/pybind11/detail/class.h" ,
117
- "include/pybind11/detail/common.h" ,
118
- "include/pybind11/detail/descr.h" ,
119
- "include/pybind11/detail/init.h" ,
120
- "include/pybind11/detail/internals.h" ,
121
- "include/pybind11/detail/typeid.h" ,
122
- }
123
-
124
- headers = main_headers | detail_headers
125
- check_compare (headers , "include/**/*.h" )
126
-
127
- if use_headers :
128
- setup_opts ["headers" ] = headers
129
- setup_opts ["cmdclass" ] = {"install_headers" : InstallHeadersNested }
130
-
131
- cmake_files = {
132
- "pybind11/share/cmake/pybind11/FindPythonLibsNew.cmake" ,
133
- "pybind11/share/cmake/pybind11/pybind11Common.cmake" ,
134
- "pybind11/share/cmake/pybind11/pybind11Config.cmake" ,
135
- "pybind11/share/cmake/pybind11/pybind11ConfigVersion.cmake" ,
136
- "pybind11/share/cmake/pybind11/pybind11NewTools.cmake" ,
137
- "pybind11/share/cmake/pybind11/pybind11Targets.cmake" ,
138
- "pybind11/share/cmake/pybind11/pybind11Tools.cmake" ,
139
- }
140
-
141
-
142
- package_headers = set ("pybind11/{}" .format (h ) for h in headers )
143
- package_files = package_headers | cmake_files
144
-
145
- # Generate the files if they are not generated (will be present in tarball)
146
- GENERATED = (
147
- []
148
- if all (os .path .exists (h ) for h in package_files )
149
- else ["pybind11/include" , "pybind11/share" ]
150
- )
151
- with remove_output (* GENERATED ):
64
+ with remove_output ("pybind11/include" , "pybind11/share" ):
152
65
# Generate the files if they are not present.
153
- if GENERATED :
154
- with TemporaryDirectory () as tmpdir :
155
- cmd = ["cmake" , "-S" , "." , "-B" , tmpdir ] + [
156
- "-DCMAKE_INSTALL_PREFIX=pybind11" ,
157
- "-DBUILD_TESTING=OFF" ,
158
- "-DPYBIND11_NOPYTHON=ON" ,
159
- ]
160
- cmake_opts = dict (cwd = DIR , stdout = sys .stdout , stderr = sys .stderr )
161
- subprocess .check_call (cmd , ** cmake_opts )
162
- subprocess .check_call (["cmake" , "--install" , tmpdir ], ** cmake_opts )
163
-
164
- # Make sure all files are present
165
- check_compare (package_files , "pybind11/include/**/*.h" , "pybind11/share/**/*.cmake" )
166
-
167
- if use_system :
168
- setup_opts ["data_files" ] = [
169
- ("share/cmake" , cmake_files ),
170
- ("include/pybind11" , main_headers ),
171
- ("include/pybind11/detail" , detail_headers ),
66
+ with TemporaryDirectory () as tmpdir :
67
+ cmd = ["cmake" , "-S" , "." , "-B" , tmpdir ] + [
68
+ "-DCMAKE_INSTALL_PREFIX=pybind11" ,
69
+ "-DBUILD_TESTING=OFF" ,
70
+ "-DPYBIND11_NOPYTHON=ON" ,
172
71
]
173
-
174
- # Remove the cmake / ninja requirements as now all files are guaranteed to exist
175
- if GENERATED :
176
- REQUIRES = re .compile (r"requires\s*=.+?\]" , re .DOTALL | re .MULTILINE )
177
- with monkey_patch_file ("pyproject.toml" ) as txt :
178
- with open ("pyproject.toml" , "w" ) as f :
179
- new_txt = REQUIRES .sub ('requires = ["setuptools", "wheel"]' , txt )
180
- f .write (new_txt )
181
-
182
- setup (** setup_opts )
183
- else :
184
- setup (** setup_opts )
72
+ cmake_opts = dict (cwd = DIR , stdout = sys .stdout , stderr = sys .stderr )
73
+ subprocess .check_call (cmd , ** cmake_opts )
74
+ subprocess .check_call (["cmake" , "--install" , tmpdir ], ** cmake_opts )
75
+
76
+ with monkey_patch_file ("pyproject.toml" , pyproject_toml ):
77
+ with monkey_patch_file ("setup.py" , setup_py ):
78
+ with open (setup_py ) as f :
79
+ code = compile (f .read (), setup_py , "exec" )
80
+ exec (code , globals (), {})
0 commit comments