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