diff --git a/tests/apis/custom_toolchain/toolchains/modules/core/tools/ar6x.lua b/tests/apis/custom_toolchain/toolchains/modules/core/tools/ar6x.lua new file mode 100644 index 00000000000..821b955e3b5 --- /dev/null +++ b/tests/apis/custom_toolchain/toolchains/modules/core/tools/ar6x.lua @@ -0,0 +1,27 @@ +--!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, TBOOX Open Source Group. +-- +-- @author ruki +-- @file ar6x.lua +-- + +inherit("core.tools.ar") + +-- init it +function init(self) + self:set("arflags", "-r") +end + diff --git a/tests/apis/custom_toolchain/toolchains/modules/core/tools/cl6x.lua b/tests/apis/custom_toolchain/toolchains/modules/core/tools/cl6x.lua new file mode 100644 index 00000000000..f350808da8f --- /dev/null +++ b/tests/apis/custom_toolchain/toolchains/modules/core/tools/cl6x.lua @@ -0,0 +1,207 @@ +--!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, TBOOX Open Source Group. +-- +-- @author ruki +-- @file cl6x.lua +-- + +-- imports +import("core.base.option") +import("core.base.global") +import("core.project.policy") +import("core.language.language") +import("utils.progress") + +-- init it +function init(self) +end + +-- make the symbol flag +function nf_symbol(self, level) + -- only for source kind + local kind = self:kind() + if language.sourcekinds()[kind] then + local maps = _g.symbol_maps + if not maps then + maps = + { + debug = "-g" + } + _g.symbol_maps = maps + end + return maps[level .. '_' .. kind] or maps[level] + end +end + +-- make the optimize flag +function nf_optimize(self, level) + local maps = + { + none = "-O0" + , fast = "-O1" + , faster = "-O2" + , fastest = "-O3" + , smallest = "-m3" + , aggressive = "-O3" + } + return maps[level] +end + +-- make the define flag +function nf_define(self, macro) + return "-D" .. macro +end + +-- make the undefine flag +function nf_undefine(self, macro) + return "-U" .. macro +end + +-- make the includedir flag +function nf_includedir(self, dir) + return {"-I" .. dir} +end + +-- make the sysincludedir flag +function nf_sysincludedir(self, dir) + return nf_includedir(self, dir) +end + +-- make the link flag +function nf_link(self, lib) + if not lib:endswith(".a") and not lib:endswith(".so") then + lib = "lib" .. lib .. ".a" + end + return "-l" .. lib +end + +-- make the syslink flag +function nf_syslink(self, lib) + return nf_link(self, lib) +end + +-- make the linkdir flag +function nf_linkdir(self, dir) + return {"-i" .. path.translate(dir)} +end + +-- make the rpathdir flag +function nf_rpathdir(self, dir, opt) + opt = opt or {} + local extra = opt.extra + if extra and extra.installonly then + return + end + dir = path.translate(dir) + return {"-rpath=" .. dir} +end + +-- make the link arguments list +function linkargv(self, objectfiles, targetkind, targetfile, flags, opt) + local argv = table.join("-z", "--output_file=" .. targetfile, objectfiles, flags) + return self:program(), argv +end + +-- link the target file +-- +-- maybe we need to use os.vrunv() to show link output when enable verbose information +-- @see https://github.com/xmake-io/xmake/discussions/2916 +-- +function link(self, objectfiles, targetkind, targetfile, flags, opt) + opt = opt or {} + os.mkdir(path.directory(targetfile)) + local program, argv = linkargv(self, objectfiles, targetkind, targetfile, flags) + if option.get("verbose") then + os.execv(program, argv, {envs = self:runenvs(), shell = opt.shell}) + else + os.vrunv(program, argv, {envs = self:runenvs(), shell = opt.shell}) + end +end + +-- make the compile arguments list +function compargv(self, sourcefile, objectfile, flags) + return self:program(), table.join("-c", "--preproc_with_compile", flags, "--output_file=" .. objectfile, sourcefile) +end + +-- compile the source file +function compile(self, sourcefile, objectfile, dependinfo, flags, opt) + os.mkdir(path.directory(objectfile)) + local depfile = dependinfo and os.tmpfile() or nil + try + { + function () + local compflags = flags + if depfile then + compflags = table.join(compflags, "-ppd=" .. depfile) + end + local outdata, errdata = os.iorunv(compargv(self, sourcefile, objectfile, compflags)) + return (outdata or "") .. (errdata or "") + end, + catch + { + function (errors) + + -- try removing the old object file for forcing to rebuild this source file + os.tryrm(objectfile) + + -- find the start line of error + local lines = tostring(errors):split("\n") + local start = 0 + for index, line in ipairs(lines) do + if line:find("error:", 1, true) or line:find("错误:", 1, true) then + start = index + break + end + end + + -- get 16 lines of errors + if start > 0 or not option.get("verbose") then + if start == 0 then start = 1 end + errors = table.concat(table.slice(lines, start, start + ((#lines - start > 16) and 16 or (#lines - start))), "\n") + end + + -- raise compiling errors + raise(errors) + end + }, + finally + { + function (ok, warnings) + + -- print some warnings + if warnings and #warnings > 0 and policy.build_warnings(opt) then + if progress.showing_without_scroll() then + print("") + end + cprint("${color.warning}%s", table.concat(table.slice(warnings:split('\n'), 1, 8), '\n')) + end + + -- generate the dependent includes + if depfile and os.isfile(depfile) then + if dependinfo then + dependinfo.depfiles_format = "cl6x" + dependinfo.depfiles = io.readfile(depfile, {continuation = "\\"}) + end + + -- remove the temporary dependent file + os.tryrm(depfile) + end + end + } + } +end + + diff --git a/tests/apis/custom_toolchain/toolchains/modules/detect/tools/cl6x/has_flags.lua b/tests/apis/custom_toolchain/toolchains/modules/detect/tools/cl6x/has_flags.lua new file mode 100644 index 00000000000..d18d9b23375 --- /dev/null +++ b/tests/apis/custom_toolchain/toolchains/modules/detect/tools/cl6x/has_flags.lua @@ -0,0 +1,121 @@ +--!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, TBOOX Open Source Group. +-- +-- @author ruki +-- @file has_flags.lua +-- + +-- imports +import("core.cache.detectcache") +import("core.language.language") + +-- is linker? +function _islinker(flags, opt) + local toolkind = opt.toolkind or "" + return toolkind == "ld" or toolkind == "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 + +-- attempt to check it from known flags +function _check_from_knownargs(flags, opt, islinker) + local flag = flags[1] + if not islinker then + if flag:startswith("-D") or + flag:startswith("-U") or + flag:startswith("-I") then + return true + end + end +end + +-- attempt to check it from the argument list +function _check_from_arglist(flags, opt, islinker) + local key = "detect.tools.cl6x." .. (islinker and "has_ldflags" or "has_cflags") + 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) + detectcache:save() + end + local flag = flags[1] + return allflags[flag] +end + +-- get extension +function _get_extension(opt) + -- @note we need to detect extension for ndk/clang++.exe: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated [-Wdeprecated] + return (opt.program:endswith("++") or opt.flagkind == "cxxflags") and ".cpp" or (table.wrap(language.sourcekinds()[opt.toolkind or "cc"])[1] or ".c") +end + +-- try running to check flags +function _check_try_running(flags, opt, islinker) + + -- make an stub source file + local snippet = opt.snippet or "int main(int argc, char** argv)\n{return 0;}\n" + local sourcefile = os.tmpfile("cl6x_has_flags:" .. snippet) .. _get_extension(opt) + if not os.isfile(sourcefile) then + io.writefile(sourcefile, snippet) + end + + -- check flags for linker + local tmpfile = os.tmpfile() + if islinker then + return _try_running(opt.program, table.join(flags, "-z", "--output_file=" .. tmpfile, sourcefile), opt) + end + + -- check flags for compiler + -- @note we cannot use os.nuldev() as the output file, maybe run failed for some flags, e.g. --coverage + return _try_running(opt.program, table.join(flags, "-c", "--output_file=" .. tmpfile, sourcefile), opt) +end + +-- has_flags(flags)? +-- +-- @param opt the argument options, e.g. {toolname = "", program = "", programver = "", toolkind = "[cc|cxx|ld|ar|sh|gc|mm|mxx]"} +-- +-- @return true or false +-- +function main(flags, opt) + + -- is linker? + opt = opt or {} + local islinker = _islinker(flags, opt) + + -- attempt to check it from the argument list + if not opt.tryrun then + if _check_from_arglist(flags, opt, islinker) then + return true + end + if _check_from_knownargs(flags, opt, islinker) then + return true + end + end + + -- try running to check it + return _check_try_running(flags, opt, islinker) +end + diff --git a/tests/apis/custom_toolchain/toolchains/modules/detect/tools/find_ar6x.lua b/tests/apis/custom_toolchain/toolchains/modules/detect/tools/find_ar6x.lua new file mode 100644 index 00000000000..823a1f2200a --- /dev/null +++ b/tests/apis/custom_toolchain/toolchains/modules/detect/tools/find_ar6x.lua @@ -0,0 +1,58 @@ +--!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, TBOOX Open Source Group. +-- +-- @author ruki +-- @file find_ar6x.lua +-- + +-- imports +import("lib.detect.find_program") + +-- check +function _check(program) + + -- make a stub object file + local libraryfile = os.tmpfile() .. ".a" + local objectfile = os.tmpfile() .. ".o" + io.writefile(objectfile, "") + + -- archive it + os.execv(program, {"-r", libraryfile, objectfile}) + + -- remove files + os.rm(objectfile) + os.rm(libraryfile) +end + +-- find ar +-- +-- @param opt the argument options, e.g. {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local ar = find_ar6x() +-- local ar, version = find_ar6x({program = "xcrun -sdk macosx g++", version = true}) +-- +-- @endcode +-- +function main(opt) + opt = opt or {} + opt.check = opt.check or _check + return find_program(opt.program or "ar6x", opt) +end + diff --git a/tests/apis/custom_toolchain/toolchains/modules/detect/tools/find_cl6x.lua b/tests/apis/custom_toolchain/toolchains/modules/detect/tools/find_cl6x.lua new file mode 100644 index 00000000000..c961326ad33 --- /dev/null +++ b/tests/apis/custom_toolchain/toolchains/modules/detect/tools/find_cl6x.lua @@ -0,0 +1,48 @@ +--!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, TBOOX Open Source Group. +-- +-- @author ruki +-- @file find_cl6x.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find cl6x +-- +-- @param opt the argument options, e.g. {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local cl6x = find_cl6x() +-- local cl6x, version = find_cl6x({program = "cl6x", version = true}) +-- +-- @endcode +-- +function main(opt) + opt = opt or {} + opt.check = "--help" + opt.command = "--help" + local program = find_program(opt.program or "cl6x", opt) + local version = nil + if program and opt.version then + version = find_programver(program, opt) + end + return program, version +end diff --git a/tests/apis/custom_toolchain/xmake.lua b/tests/apis/custom_toolchain/xmake.lua index dc15f1a055c..dc772417b05 100644 --- a/tests/apis/custom_toolchain/xmake.lua +++ b/tests/apis/custom_toolchain/xmake.lua @@ -1,7 +1,9 @@ add_rules("mode.debug", "mode.release") +add_moduledirs("toolchains/modules") +includes("toolchains/my-c6000") + set_toolchains("my-c6000") -add_toolchaindirs("toolchains") target("test") set_kind("static") diff --git a/xmake/core/project/project.lua b/xmake/core/project/project.lua index 7b42d47eafb..20b0a171b3d 100644 --- a/xmake/core/project/project.lua +++ b/xmake/core/project/project.lua @@ -202,17 +202,6 @@ function project._api_add_platformdirs(interp, ...) end end --- add toolchain directories -function project._api_add_toolchaindirs(interp, ...) - local scriptdir = project.interpreter():scriptdir() - for _, dir in ipairs({...}) do - if not path.is_absolute(dir) then - dir = path.absolute(dir, scriptdir) - end - toolchain.add_directories(dir) - end -end - -- load the project file function project._load(force, disable_filter) @@ -669,7 +658,6 @@ function project.apis() , {"add_moduledirs", project._api_add_moduledirs } , {"add_plugindirs", project._api_add_plugindirs } , {"add_platformdirs", project._api_add_platformdirs } - , {"add_toolchaindirs", project._api_add_toolchaindirs } } } end diff --git a/xmake/core/sandbox/modules/import/core/tool/toolchain.lua b/xmake/core/sandbox/modules/import/core/tool/toolchain.lua index 48867300ec1..46bd9fb1d4b 100644 --- a/xmake/core/sandbox/modules/import/core/tool/toolchain.lua +++ b/xmake/core/sandbox/modules/import/core/tool/toolchain.lua @@ -28,8 +28,7 @@ local project = require("project/project") local raise = require("sandbox/modules/raise") -- inherit some builtin interfaces -sandbox_core_tool_toolchain.apis = toolchain.apis -sandbox_core_tool_toolchain.directories = toolchain.directories +sandbox_core_tool_toolchain.apis = toolchain.apis -- get all toolchains list function sandbox_core_tool_toolchain.list() diff --git a/xmake/core/tool/toolchain.lua b/xmake/core/tool/toolchain.lua index 1085df1984f..a19413d345e 100644 --- a/xmake/core/tool/toolchain.lua +++ b/xmake/core/tool/toolchain.lua @@ -640,15 +640,6 @@ function toolchain.directories() return dirs end --- add toolchain directories -function toolchain.add_directories(...) - local dirs = toolchain.directories() - for _, dir in ipairs({...}) do - table.insert(dirs, 1, dir) - end - toolchain._DIRS = table.unique(dirs) -end - -- load toolchain function toolchain.load(name, opt) diff --git a/xmake/modules/lib/detect/find_tool.lua b/xmake/modules/lib/detect/find_tool.lua index 8b5892483f4..fa2b7b3bbef 100644 --- a/xmake/modules/lib/detect/find_tool.lua +++ b/xmake/modules/lib/detect/find_tool.lua @@ -27,9 +27,6 @@ import("core.tool.toolchain") -- find tool from modules function _find_from_modules(name, opt) - -- TODO - print(toolchain.directories()) - local find_tool = import("detect.tools.find_" .. name, {try = true}) if find_tool then local program, version, toolname = find_tool(opt)