From fa807b737b4b6b3004cccafc0dfdfdd66fcdce2d Mon Sep 17 00:00:00 2001 From: wuzhenqing Date: Mon, 4 May 2026 11:15:50 +0000 Subject: feat(ascendc): add Huawei Ascend C toolchain support Add toolchain, language, rules, and compiler modules for the bisheng compiler driver from CANN (Compute Architecture for Neural Networks) toolkit. Supports .asc (Ascend C kernel) and .aicpu (AI-CPU operator) source kinds with binary/static/shared target types. - Toolchain: SDK auto-detection via ASCEND_HOME_PATH env or --sdk - Compiler: bisheng module inherits from clang, adds add_sourceflags for explicit sourcekind overrides - Rules: ascendc.env (default C++17), npuarchs (--npu-arch), build - Language: check_main detection, add_ascnpuarchs API - Tests: unit tests for check_main, project tests for libs/mixed Fixes #7506 --- xmake/modules/core/tools/bisheng.lua | 71 +++++++++++ xmake/modules/core/tools/bisheng/has_flags.lua | 166 +++++++++++++++++++++++++ xmake/modules/detect/tools/find_bisheng.lua | 47 +++++++ 3 files changed, 284 insertions(+) create mode 100644 xmake/modules/core/tools/bisheng.lua create mode 100644 xmake/modules/core/tools/bisheng/has_flags.lua create mode 100644 xmake/modules/detect/tools/find_bisheng.lua (limited to 'xmake/modules') diff --git a/xmake/modules/core/tools/bisheng.lua b/xmake/modules/core/tools/bisheng.lua new file mode 100644 index 000000000..5d3726e66 --- /dev/null +++ b/xmake/modules/core/tools/bisheng.lua @@ -0,0 +1,71 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-present, Xmake Open Source Community. +-- +-- @author wuzhenqing +-- @file bisheng.lua +-- + +inherit("clang") + +function init(self) + _super.init(self) + self:add("shared.ascflags", "-fPIC") + self:add("shared.aicpuflags", "-fPIC") + self:add("ascflags", "-Qunused-arguments") + self:add("aicpuflags", "-Qunused-arguments") + self:set("ascshflags", "-shared") +end + +-- make the language flag +function nf_language(self, stdname) + if _g.cxxmaps == nil then + _g.cxxmaps = + { + cxx03 = "-std=c++03" + , cxx11 = "-std=c++11" + , cxx14 = "-std=c++14" + , cxx17 = "-std=c++17" + , cxx20 = "-std=c++20" + , cxxlatest = {"-std=c++20", "-std=c++17", "-std=c++14", "-std=c++11", "-std=c++03"} + } + local cxxmaps2 = {} + for k, v in pairs(_g.cxxmaps) do + cxxmaps2[k:gsub("xx", "++")] = v + end + table.join2(_g.cxxmaps, cxxmaps2) + end + local result = _g.cxxmaps[stdname] + if type(result) == "table" then + local flagkind = self:kind() == "aicpu" and "aicpuflags" or "ascflags" + for _, flag in ipairs(result) do + if self:has_flags(flag, flagkind) then + result = flag + _g.cxxmaps[stdname] = result + break + end + end + end + return result +end + +-- add source kind override flags (e.g. for .cce files compiled as asc) +function add_sourceflags(self, sourcefile, fileconfig, target, targetkind) + local sourcekind = fileconfig.sourcekind + if sourcekind then + local maps = {asc = "-x asc", aicpu = "-x aicpu"} + return maps[sourcekind] + end +end diff --git a/xmake/modules/core/tools/bisheng/has_flags.lua b/xmake/modules/core/tools/bisheng/has_flags.lua new file mode 100644 index 000000000..626c58c51 --- /dev/null +++ b/xmake/modules/core/tools/bisheng/has_flags.lua @@ -0,0 +1,166 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-present, Xmake Open Source Community. +-- +-- @author wuzhenqing +-- @file has_flags.lua +-- + +-- Note: This module is derived from gcc/has_flags.lua with modifications +-- for Ascend C specific source kinds (.asc, .aicpu) and --npu-arch handling. +-- Inherit cannot be used here because xmake's tool module inheritance does +-- not support overriding individual local functions. + +-- imports +import("core.cache.detectcache") +import("core.language.language") + +-- is linker? +function _islinker(flags, opt) + + -- the flags is "-Wl," or "-Xlinker "? + local flags_str = table.concat(flags, " ") + if flags_str:startswith("-Wl,") or + flags_str:startswith("-Xlinker ") then + return true + end + + -- the tool kind is ld or sh? + local toolkind = opt.toolkind or "" + return toolkind == "ld" or + toolkind == "sh" or + toolkind == "ascld" or + toolkind == "ascsh" or + toolkind:endswith("-ld") or + toolkind:endswith("-sh") or + toolkind:endswith("ld") or + toolkind:endswith("sh") +end + +-- try running +function _try_running(program, argv, opt) + local errors = nil + return try { + function () + os.runv(program, argv, opt) + return true + end, + catch { + function (errs) + errors = (errs or ""):trim() + end + } + }, errors +end + +-- get source kind +function _get_sourcekind(opt, islinker) + if not islinker then + local toolkind = opt.toolkind or "asc" + if language.sourcekinds()[toolkind] then + return toolkind + end + end + return "asc" +end + +function _map_sourcekind(sourcekind) + local map = {cxx = "c++"} + return map[sourcekind] or sourcekind +end + +-- get extension +function _get_extension(sourcekind) + return table.wrap(language.sourcekinds()[sourcekind])[1] or ".asc" +end + +-- has npu arch? +function _has_npu_arch(flags) + for _, flag in ipairs(flags) do + if flag:startswith("--npu-arch=") then + return true + end + end +end + +-- attempt to check it from the argument list +function _check_from_arglist(flags, opt, islinker) + local flag = flags[1] + if not flag then + return false + end + + -- check for the builtin flag=value + if flag:startswith("--npu-arch=") then + return true + end + + -- check from the `--help` menu, only for compile flags + if islinker or #flags > 1 then + return + end + + local key = "core.tools.bisheng.has_flags" + local flagskey = opt.program .. "_" .. (opt.programver or "") + local allflags = detectcache:get2(key, flagskey) + if not allflags then + allflags = {} + local arglist = try {function () return os.iorunv(opt.program, {"--help"}, {envs = opt.envs}) end} + if arglist then + for arg in arglist:gmatch("%s+(%-[%-%a%d]+)%s+") do + allflags[arg] = true + end + end + detectcache:set2(key, flagskey, allflags) + end + return allflags[flag] +end + +-- try running to check flags +function _check_try_running(flags, opt, islinker) + local snippet = opt.snippet or + "int main(int argc, char** argv)\n{return 0;}\n" + local sourcekind = _get_sourcekind(opt, islinker) + local sourcefile = os.tmpfile("bisheng_has_flags") .. + _get_extension(sourcekind) + if not os.isfile(sourcefile) then + io.writefile(sourcefile, snippet) + end + + local args = table.join("-o", os.tmpfile(), sourcefile) + if not islinker then + table.insert(args, 1, "-c") + end + if sourcekind == "asc" and not _has_npu_arch(flags) then + sourcekind = "c++" + end + sourcekind = _map_sourcekind(sourcekind) + table.insert(args, 1, sourcekind) + table.insert(args, 1, "-x") + return _try_running(opt.program, table.join(flags, args), opt) +end + +function _has_flags(flags, opt) + opt = opt or {} + local islinker = _islinker(flags, opt) + if not opt.tryrun and _check_from_arglist(flags, opt, islinker) then + return true + end + return _check_try_running(flags, opt, islinker) +end + +function main(...) + return _has_flags(...) +end diff --git a/xmake/modules/detect/tools/find_bisheng.lua b/xmake/modules/detect/tools/find_bisheng.lua new file mode 100644 index 000000000..f5832b09e --- /dev/null +++ b/xmake/modules/detect/tools/find_bisheng.lua @@ -0,0 +1,47 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-present, Xmake Open Source Community. +-- +-- @author wuzhenqing +-- @file find_bisheng.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find bisheng +-- +-- @param opt the argument options, e.g. {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local bisheng = find_bisheng() +-- local bisheng, version = find_bisheng({version = true}) +-- +-- @endcode +-- +function main(opt) + opt = opt or {} + opt.norunfile = true + local program = find_program(opt.program or "bisheng", opt) + local version = nil + if program and opt and opt.version then + version = find_programver(program, opt) + end + return program, version +end -- cgit v1.3.1