@@ -241,8 +241,70 @@ if(WITH_ASCEND)
241241 list (APPEND DEVICE_LIST "ascend" )
242242
243243 # Custom `AscendC` kernels (PyTorch extension, requires `torch_npu`).
244- if (BUILD_CUSTOM_KERNEL)
245- add_subdirectory (native/ascend/custom )
244+ if (BUILD_ASCEND_CUSTOM)
245+ # In-tree `ascendc_library()` trips the `CANN` `extract_host_stub.py`
246+ # path-handling bug under `scikit-build-core`'s temp-dir builds
247+ # (`KeyError` on `/./workspace/...` paths in `$<TARGET_OBJECTS>`).
248+ # Work around it by driving the standalone `src/native/ascend/custom/build.sh`;
249+ # that script invokes a separate `cmake` with
250+ # `src/native/ascend/custom/` as its `SOURCE_DIR`, avoiding the buggy
251+ # path shape. The produced `.a` is imported and linked into
252+ # `ops` with `--whole-archive`.
253+ set (_custom_build_dir "${CMAKE_SOURCE_DIR} /build/build_ascend_custom" )
254+ set (_custom_lib "${_custom_build_dir} /lib/libno_workspace_kernel.a" )
255+ set (_custom_source_dir "${CMAKE_CURRENT_BINARY_DIR} /ascend_custom_source" )
256+
257+ if (NOT DEFINED SOC_VERSION OR "${SOC_VERSION} " STREQUAL "" )
258+ include (${CMAKE_CURRENT_SOURCE_DIR} /native/ascend/custom/cmake/detect_soc.cmake )
259+ infiniops_detect_soc (SOC_VERSION )
260+ endif ()
261+
262+ # Drive `build.sh` as a build-phase target with explicit source
263+ # dependencies so that editing any `op_host/` or `op_kernel/`
264+ # source re-triggers the build (plain `execute_process` at
265+ # configure time would only gate on file existence and leave
266+ # stale `.a` files in place).
267+ file (GLOB_RECURSE _custom_srcs CONFIGURE_DEPENDS
268+ "${CMAKE_CURRENT_SOURCE_DIR} /native/ascend/custom/*.cpp"
269+ "${CMAKE_CURRENT_SOURCE_DIR} /native/ascend/custom/*.h"
270+ "${CMAKE_CURRENT_SOURCE_DIR} /native/ascend/custom/build.sh" )
271+
272+ # Scrub env inherited from the outer `scikit-build-core` invocation
273+ # before handing control to `build.sh`: `CMAKE_GENERATOR` /
274+ # `CMAKE_EXPORT_COMPILE_COMMANDS` leaking into the inner `cmake`
275+ # change the path format passed to `ninja`'s `_host_cpp` rule and
276+ # re-trigger the `CANN` `extract_host_stub.py` `KeyError`
277+ # (`/./workspace/...`) that standalone `build.sh` avoids.
278+ #
279+ # `pip install` MUST be invoked with `--no-build-isolation` on
280+ # Ascend; otherwise pip's build-isolation overlay shadows system
281+ # `torch` (via `PYTHONPATH`) and the inner `cmake`'s
282+ # `import torch` in `config_envs.cmake` fails with
283+ # `ModuleNotFoundError`.
284+ add_custom_command (
285+ OUTPUT ${_custom_lib}
286+ COMMAND ${CMAKE_COMMAND} -E rm -f "${_custom_source_dir} "
287+ COMMAND ${CMAKE_COMMAND} -E create_symlink
288+ "${CMAKE_CURRENT_SOURCE_DIR} /native/ascend/custom"
289+ "${_custom_source_dir} "
290+ COMMAND ${CMAKE_COMMAND} -E env
291+ --unset=CMAKE_GENERATOR
292+ --unset=CMAKE_EXPORT_COMPILE_COMMANDS
293+ --unset=CMAKE_BUILD_PARALLEL_LEVEL
294+ "BUILD_DIR=${_custom_build_dir} "
295+ "MAIN_SRC_DIR=${CMAKE_CURRENT_SOURCE_DIR} "
296+ bash ${_custom_source_dir} /build.sh ${SOC_VERSION}
297+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} /native/ascend/custom
298+ DEPENDS ${_custom_srcs}
299+ COMMENT "Building custom AscendC kernels (SOC_VERSION=${SOC_VERSION} )"
300+ VERBATIM )
301+
302+ add_custom_target (no_workspace_kernel_build ALL DEPENDS ${_custom_lib} )
303+
304+ add_library (no_workspace_kernel STATIC IMPORTED GLOBAL )
305+ set_target_properties (no_workspace_kernel PROPERTIES
306+ IMPORTED_LOCATION "${_custom_lib} " )
307+ add_dependencies (no_workspace_kernel no_workspace_kernel_build )
246308
247309 # Link the compiled `AscendC` kernel objects into `infiniops` so that
248310 # custom kernel implementations (e.g. `RmsNorm` index 1) can call
@@ -380,9 +442,17 @@ if(GENERATE_PYTHON_BINDINGS)
380442 # The `Operator<..., 1>` template instantiations that call
381443 # `aclrtlaunch_*` live in `ops.cc`, so link here with
382444 # `--whole-archive` to ensure all launch functions are available.
383- if (BUILD_CUSTOM_KERNEL)
445+ # `$<TARGET_FILE>` works for both real `ascendc_library()` targets and
446+ # `IMPORTED` targets pointing at a pre-built `.a`. The
447+ # `no_workspace_kernel` target is only created inside the
448+ # `WITH_ASCEND` block above, so this branch must mirror that gate;
449+ # otherwise non-Ascend builds error out with "No target
450+ # no_workspace_kernel".
451+ if (WITH_ASCEND AND BUILD_ASCEND_CUSTOM)
384452 target_link_libraries (ops PRIVATE
385- -Wl,--whole-archive no_workspace_kernel -Wl,--no-whole-archive )
453+ -Wl,--whole-archive $<TARGET_FILE :no_workspace_kernel > -Wl,--no-whole-archive )
454+ # `ops` link step must wait for `build.sh` to produce the `.a`.
455+ add_dependencies (ops no_workspace_kernel_build )
386456 endif ()
387457
388458 set_target_properties (infiniops PROPERTIES INSTALL_RPATH "$ORIGIN" )
0 commit comments