@@ -305,8 +305,70 @@ if(WITH_ASCEND)
305305 list (APPEND DEVICE_LIST "ascend" )
306306
307307 # Custom `AscendC` kernels (PyTorch extension, requires `torch_npu`).
308- if (BUILD_CUSTOM_KERNEL)
309- add_subdirectory (native/ascend/custom )
308+ if (BUILD_ASCEND_CUSTOM)
309+ # In-tree `ascendc_library()` trips the `CANN` `extract_host_stub.py`
310+ # path-handling bug under `scikit-build-core`'s temp-dir builds
311+ # (`KeyError` on `/./workspace/...` paths in `$<TARGET_OBJECTS>`).
312+ # Work around it by driving the standalone `src/native/ascend/custom/build.sh`;
313+ # that script invokes a separate `cmake` with
314+ # `src/native/ascend/custom/` as its `SOURCE_DIR`, avoiding the buggy
315+ # path shape. The produced `.a` is imported and linked into
316+ # `ops` with `--whole-archive`.
317+ set (_custom_build_dir "${CMAKE_SOURCE_DIR } /build/build_ascend_custom" )
318+ set (_custom_lib "${_custom_build_dir} /lib/libno_workspace_kernel.a" )
319+ set (_custom_source_dir "${CMAKE_CURRENT_BINARY_DIR } /ascend_custom_source" )
320+
321+ if (NOT DEFINED SOC_VERSION OR "${SOC_VERSION} " STREQUAL "" )
322+ include (${CMAKE_CURRENT_SOURCE_DIR } /native/ascend/custom/cmake/detect_soc.cmake )
323+ infiniops_detect_soc (SOC_VERSION )
324+ endif ()
325+
326+ # Drive `build.sh` as a build-phase target with explicit source
327+ # dependencies so that editing any `op_host/` or `op_kernel/`
328+ # source re-triggers the build (plain `execute_process` at
329+ # configure time would only gate on file existence and leave
330+ # stale `.a` files in place).
331+ file (GLOB_RECURSE _custom_srcs CONFIGURE_DEPENDS
332+ "${CMAKE_CURRENT_SOURCE_DIR } /native/ascend/custom/*.cpp"
333+ "${CMAKE_CURRENT_SOURCE_DIR } /native/ascend/custom/*.h"
334+ "${CMAKE_CURRENT_SOURCE_DIR } /native/ascend/custom/build.sh" )
335+
336+ # Scrub env inherited from the outer `scikit-build-core` invocation
337+ # before handing control to `build.sh`: `CMAKE_GENERATOR` /
338+ # `CMAKE_EXPORT_COMPILE_COMMANDS` leaking into the inner `cmake`
339+ # change the path format passed to `ninja`'s `_host_cpp` rule and
340+ # re-trigger the `CANN` `extract_host_stub.py` `KeyError`
341+ # (`/./workspace/...`) that standalone `build.sh` avoids.
342+ #
343+ # `pip install` MUST be invoked with `--no-build-isolation` on
344+ # Ascend; otherwise pip's build-isolation overlay shadows system
345+ # `torch` (via `PYTHONPATH`) and the inner `cmake`'s
346+ # `import torch` in `config_envs.cmake` fails with
347+ # `ModuleNotFoundError`.
348+ add_custom_command (
349+ OUTPUT ${_custom_lib}
350+ COMMAND ${CMAKE_COMMAND } -E rm -f "${_custom_source_dir } "
351+ COMMAND ${CMAKE_COMMAND } -E create_symlink
352+ "${CMAKE_CURRENT_SOURCE_DIR } /native/ascend/custom"
353+ "${_custom_source_dir } "
354+ COMMAND ${CMAKE_COMMAND } -E env
355+ --unset=CMAKE_GENERATOR
356+ --unset=CMAKE_EXPORT_COMPILE_COMMANDS
357+ --unset=CMAKE_BUILD_PARALLEL_LEVEL
358+ "BUILD_DIR=${_custom_build_dir} "
359+ "MAIN_SRC_DIR=${CMAKE_CURRENT_SOURCE_DIR } "
360+ bash ${_custom_source_dir } /build.sh ${SOC_VERSION}
361+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR } /native/ascend/custom
362+ DEPENDS ${_custom_srcs}
363+ COMMENT "Building custom AscendC kernels (SOC_VERSION=${SOC_VERSION} )"
364+ VERBATIM )
365+
366+ add_custom_target (no_workspace_kernel_build ALL DEPENDS ${_custom_lib} )
367+
368+ add_library (no_workspace_kernel STATIC IMPORTED GLOBAL )
369+ set_target_properties (no_workspace_kernel PROPERTIES
370+ IMPORTED_LOCATION "${_custom_lib} " )
371+ add_dependencies (no_workspace_kernel no_workspace_kernel_build )
310372
311373 # Link the compiled `AscendC` kernel objects into `infiniops` so that
312374 # custom kernel implementations (e.g. `RmsNorm` index 1) can call
@@ -786,9 +848,17 @@ if(GENERATE_PYTHON_BINDINGS)
786848 # The `Operator<..., 1>` template instantiations that call
787849 # `aclrtlaunch_*` live in `ops.cc`, so link here with
788850 # `--whole-archive` to ensure all launch functions are available.
789- if (BUILD_CUSTOM_KERNEL)
851+ # `$<TARGET_FILE>` works for both real `ascendc_library()` targets and
852+ # `IMPORTED` targets pointing at a pre-built `.a`. The
853+ # `no_workspace_kernel` target is only created inside the
854+ # `WITH_ASCEND` block above, so this branch must mirror that gate;
855+ # otherwise non-Ascend builds error out with "No target
856+ # no_workspace_kernel".
857+ if (WITH_ASCEND AND BUILD_ASCEND_CUSTOM)
790858 target_link_libraries (ops PRIVATE
791- -Wl,--whole-archive no_workspace_kernel -Wl,--no-whole-archive )
859+ -Wl,--whole-archive $<TARGET_FILE :no_workspace_kernel > -Wl,--no-whole-archive )
860+ # `ops` link step must wait for `build.sh` to produce the `.a`.
861+ add_dependencies (ops no_workspace_kernel_build )
792862 endif ()
793863 set (_INFINIOPS_INSTALL_RPATH "$ORIGIN" )
794864 if (WITH_TORCH)
0 commit comments