@@ -191,14 +191,7 @@ def get_executable_name(name: str) -> str:
191
191
class _BaseExtension (Extension ):
192
192
"""A base class that maps an abstract source to an abstract destination."""
193
193
194
- def __init__ (
195
- self ,
196
- src : str ,
197
- dst : str ,
198
- name : str ,
199
- is_cmake_built : bool = True ,
200
- dst_is_dir : bool = False ,
201
- ):
194
+ def __init__ (self , src : str , dst : str , name : str ):
202
195
# Source path; semantics defined by the subclass.
203
196
self .src : str = src
204
197
@@ -213,14 +206,6 @@ def __init__(
213
206
# that doesn't look like a module path.
214
207
self .name : str = name
215
208
216
- # If True, the file is built by cmake. If False, the file is copied from
217
- # the source tree.
218
- self .is_cmake_built : bool = is_cmake_built
219
-
220
- # If True, the destination is a directory. If False, the destination is a
221
- # file.
222
- self .dst_is_dir : bool = dst_is_dir
223
-
224
209
super ().__init__ (name = self .name , sources = [])
225
210
226
211
def src_path (self , installer : "InstallerBuildExt" ) -> Path :
@@ -230,25 +215,26 @@ def src_path(self, installer: "InstallerBuildExt") -> Path:
230
215
installer: The InstallerBuildExt instance that is installing the
231
216
file.
232
217
"""
233
- if self .is_cmake_built :
234
- # Share the cmake-out location with CustomBuild.
235
- cmake_cache_dir = Path (
236
- installer .get_finalized_command ("build" ).cmake_cache_dir
237
- )
238
-
239
- cfg = get_build_type (installer .debug )
218
+ # Share the cmake-out location with CustomBuild.
219
+ cmake_cache_dir = Path (installer .get_finalized_command ("build" ).cmake_cache_dir )
240
220
241
- if os .name == "nt" :
242
- # Replace %BUILD_TYPE% with the current build type.
243
- self .src = self .src .replace ("%BUILD_TYPE%" , cfg )
244
- else :
245
- # Remove %BUILD_TYPE% from the path.
246
- self .src = self .src .replace ("/%BUILD_TYPE%" , "" )
221
+ cfg = get_build_type (installer .debug )
247
222
248
- # Construct the full source path, do not resolve globs.
249
- return cmake_cache_dir / Path (self .src )
223
+ if os .name == "nt" :
224
+ # Replace %BUILD_TYPE% with the current build type.
225
+ self .src = self .src .replace ("%BUILD_TYPE%" , cfg )
250
226
else :
251
- return Path (self .src )
227
+ # Remove %BUILD_TYPE% from the path.
228
+ self .src = self .src .replace ("/%BUILD_TYPE%" , "" )
229
+
230
+ # Construct the full source path, resolving globs. If there are no glob
231
+ # pattern characters, this will just ensure that the source file exists.
232
+ srcs = tuple (cmake_cache_dir .glob (self .src ))
233
+ if len (srcs ) != 1 :
234
+ raise ValueError (
235
+ f"Expected exactly one file matching '{ self .src } '; found { repr (srcs )} "
236
+ )
237
+ return srcs [0 ]
252
238
253
239
254
240
class BuiltFile (_BaseExtension ):
@@ -316,49 +302,6 @@ def dst_path(self, installer: "InstallerBuildExt") -> Path:
316
302
return dst_root / Path (self .dst )
317
303
318
304
319
- class HeaderFile (_BaseExtension ):
320
- """An extension that installs headers in a directory.
321
-
322
- This isn't technically a `build_ext` style python extension, but there's no
323
- dedicated command for installing arbitrary data. It's convenient to use
324
- this, though, because it lets us manage the files to install as entries in
325
- `ext_modules`.
326
- """
327
-
328
- def __init__ (
329
- self ,
330
- src_dir : str ,
331
- src_name : str = "*.h" ,
332
- dst_dir : str = "executorch/include/executorch/" ,
333
- ):
334
- """Initializes a BuiltFile.
335
-
336
- Args:
337
- src_dir: The directory of the headers to install, relative to the root
338
- ExecuTorch source directory. Under the hood, we recursively glob all
339
- the headers using `*.h` patterns.
340
- src_name: The name of the header to install. If not specified, all the
341
- headers in the src_dir will be installed.
342
- dst_dir: The directory to install to, relative to the root of the pip
343
- package. If not specified, defaults to `executorch/include/executorch/`.
344
- """
345
- src = os .path .join (src_dir , src_name )
346
- assert dst_dir .endswith ("/" ), f"dst_dir must end with '/', got { dst_dir } "
347
- super ().__init__ (
348
- src = src , dst = dst_dir , name = src_name , is_cmake_built = False , dst_is_dir = True
349
- )
350
-
351
- def dst_path (self , installer : "InstallerBuildExt" ) -> Path :
352
- """Returns the path to the destination file.
353
-
354
- Args:
355
- installer: The InstallerBuildExt instance that is installing the
356
- file.
357
- """
358
- dst_root = Path (installer .build_lib ).resolve ()
359
- return dst_root / Path (self .dst )
360
-
361
-
362
305
class BuiltExtension (_BaseExtension ):
363
306
"""An extension that installs a python extension that was built by cmake."""
364
307
@@ -421,29 +364,19 @@ def build_extension(self, ext: _BaseExtension) -> None:
421
364
src_file : Path = ext .src_path (self )
422
365
dst_file : Path = ext .dst_path (self )
423
366
424
- # Copy the file.
425
- src_list = src_file .parent .rglob (src_file .name )
426
- for src in src_list :
427
- if ext .dst_is_dir :
428
- # Destination is a prefix directory. Copy the file to the
429
- # destination directory.
430
- dst = dst_file / src
431
- else :
432
- # Destination is a file. Copy the file to the destination file.
433
- dst = dst_file
434
-
435
- # Ensure that the destination directory exists.
436
- self .mkpath (os .fspath (dst .parent ))
367
+ # Ensure that the destination directory exists.
368
+ self .mkpath (os .fspath (dst_file .parent ))
437
369
438
- self .copy_file (os .fspath (src ), os .fspath (dst ))
370
+ # Copy the file.
371
+ self .copy_file (os .fspath (src_file ), os .fspath (dst_file ))
439
372
440
- # Ensure that the destination file is writable, even if the source was
441
- # not. build_py does this by passing preserve_mode=False to copy_file,
442
- # but that would clobber the X bit on any executables. TODO(dbort): This
443
- # probably won't work on Windows.
444
- if not os .access (src , os .W_OK ):
445
- # Make the file writable. This should respect the umask.
446
- os .chmod (src , os .stat (src ).st_mode | 0o222 )
373
+ # Ensure that the destination file is writable, even if the source was
374
+ # not. build_py does this by passing preserve_mode=False to copy_file,
375
+ # but that would clobber the X bit on any executables. TODO(dbort): This
376
+ # probably won't work on Windows.
377
+ if not os .access (src_file , os .W_OK ):
378
+ # Make the file writable. This should respect the umask.
379
+ os .chmod (src_file , os .stat (src_file ).st_mode | 0o222 )
447
380
448
381
449
382
class CustomBuildPy (build_py ):
@@ -491,6 +424,25 @@ def run(self):
491
424
"devtools/bundled_program/serialize/scalar_type.fbs" ,
492
425
),
493
426
]
427
+ # Copy all the necessary headers into include/executorch/ so that they can
428
+ # be found in the pip package. This is the subset of headers that are
429
+ # essential for building custom ops extensions.
430
+ # TODO: Use cmake to gather the headers instead of hard-coding them here.
431
+ # For example: https://discourse.cmake.org/t/installing-headers-the-modern-
432
+ # way-regurgitated-and-revisited/3238/3
433
+ for include_dir in [
434
+ "runtime/core/" ,
435
+ "runtime/kernel/" ,
436
+ "runtime/platform/" ,
437
+ "extension/kernel_util/" ,
438
+ "extension/tensor/" ,
439
+ "extension/threadpool/" ,
440
+ ]:
441
+ src_list = Path (include_dir ).rglob ("*.h" )
442
+ for src in src_list :
443
+ src_to_dst .append (
444
+ (str (src ), os .path .join ("include/executorch" , str (src )))
445
+ )
494
446
for src , dst in src_to_dst :
495
447
dst = os .path .join (dst_root , dst )
496
448
@@ -685,26 +637,6 @@ def run(self):
685
637
def get_ext_modules () -> List [Extension ]:
686
638
"""Returns the set of extension modules to build."""
687
639
ext_modules = []
688
-
689
- # Copy all the necessary headers into include/executorch/ so that they can
690
- # be found in the pip package. This is the subset of headers that are
691
- # essential for building custom ops extensions.
692
- # TODO: Use cmake to gather the headers instead of hard-coding them here.
693
- # For example: https://discourse.cmake.org/t/installing-headers-the-modern-
694
- # way-regurgitated-and-revisited/3238/3
695
- for include_dir in [
696
- "runtime/core/" ,
697
- "runtime/kernel/" ,
698
- "runtime/platform/" ,
699
- "extension/kernel_util/" ,
700
- "extension/tensor/" ,
701
- "extension/threadpool/" ,
702
- ]:
703
- ext_modules .append (
704
- HeaderFile (
705
- src_dir = include_dir ,
706
- )
707
- )
708
640
if ShouldBuild .flatc ():
709
641
ext_modules .append (
710
642
BuiltFile (
0 commit comments