From ecb1e9948ed95fbe8c5b43dce118718449cff93d Mon Sep 17 00:00:00 2001 From: "Wu, Zhenyu" Date: Fri, 13 Dec 2024 00:37:51 +0800 Subject: rename luarocks.module to lua.module, platform.linux.driver to platform.linux.module --- tests/projects/linux/driver/hello/xmake.lua | 2 +- tests/projects/linux/driver/hello_custom/xmake.lua | 2 +- xmake/rules/lua/module/xmake.lua | 83 ++++++ xmake/rules/luarocks/module/xmake.lua | 64 +--- .../rules/platform/linux/driver/driver_modules.lua | 326 --------------------- xmake/rules/platform/linux/driver/xmake.lua | 19 +- .../rules/platform/linux/module/driver_modules.lua | 326 +++++++++++++++++++++ xmake/rules/platform/linux/module/xmake.lua | 40 +++ 8 files changed, 456 insertions(+), 406 deletions(-) create mode 100644 xmake/rules/lua/module/xmake.lua delete mode 100644 xmake/rules/platform/linux/driver/driver_modules.lua create mode 100644 xmake/rules/platform/linux/module/driver_modules.lua create mode 100644 xmake/rules/platform/linux/module/xmake.lua diff --git a/tests/projects/linux/driver/hello/xmake.lua b/tests/projects/linux/driver/hello/xmake.lua index bac728434..810ed8fa8 100644 --- a/tests/projects/linux/driver/hello/xmake.lua +++ b/tests/projects/linux/driver/hello/xmake.lua @@ -1,7 +1,7 @@ add_requires("linux-headers", {configs = {driver_modules = true}}) target("hello") - add_rules("platform.linux.driver") + add_rules("platform.linux.module") add_files("src/*.c") add_packages("linux-headers") set_license("GPL-2.0") diff --git a/tests/projects/linux/driver/hello_custom/xmake.lua b/tests/projects/linux/driver/hello_custom/xmake.lua index 846bddc55..a51f76c82 100644 --- a/tests/projects/linux/driver/hello_custom/xmake.lua +++ b/tests/projects/linux/driver/hello_custom/xmake.lua @@ -1,6 +1,6 @@ option("linux-headers", {showmenu = true, description = "Set linux-headers path."}) target("hello") - add_rules("platform.linux.driver") + add_rules("platform.linux.module") add_files("src/*.c") set_values("linux.driver.linux-headers", "$(linux-headers)") diff --git a/xmake/rules/lua/module/xmake.lua b/xmake/rules/lua/module/xmake.lua new file mode 100644 index 000000000..078f6bd6b --- /dev/null +++ b/xmake/rules/lua/module/xmake.lua @@ -0,0 +1,83 @@ +--!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 xmake.lua +-- + +rule("lua.module") + on_load(function (target) + + -- imports + import("core.cache.detectcache") + import("core.project.target", {alias = "project_target"}) + + -- set kind + if target:is_plat("macosx") then + target:set("kind", "binary") + target:add("ldflags", "-bundle", "-undefined dynamic_lookup", {force = true}) + else + target:set("kind", "shared") + end + + -- set library name + local modulename = target:name():split('.', {plain = true}) + modulename = modulename[#modulename] + if target:is_plat("windows", "mingw") then + target:set("basename", modulename) + else + target:set("filename", modulename .. ".so") + end + + -- export symbols + if target:is_plat("windows") then + local exported_name = target:name():gsub("%.", "_") + exported_name = exported_name:match('^[^%-]+%-(.+)$') or exported_name + target:add("shflags", "/export:luaopen_" .. exported_name, {force = true}) + else + target:set("symbols", "none") + end + + -- add lua library + local has_lua = false + local includedirs = get_config("includedirs") -- pass lua library from luarocks-build-xmake/xmake.lua + if includedirs and includedirs:find("lua", 1, true) then + has_lua = true + end + if not has_lua then + -- user use `add_requires/add_packages` to add lua/luajit package + for _, pkg in ipairs(target:get("packages")) do + if pkg == "lua" or pkg == "luajit" then + has_lua = true + break + end + end + end + if not has_lua then + target:add(find_package("lua")) + end + end) + on_install(function (target) + if target:is_plat("macosx") then + target:set("kind", "shared") + end + local moduledir = path.directory((target:name():gsub('%.', '/'))) + import("target.action.install")(target, { + installdir = target:installdir(), + libdir = path.join("lib", moduledir), + bindir = path.join("lib", moduledir), + includedir = path.join("include", moduledir)}) + end) diff --git a/xmake/rules/luarocks/module/xmake.lua b/xmake/rules/luarocks/module/xmake.lua index cf39c969b..d33fc810c 100644 --- a/xmake/rules/luarocks/module/xmake.lua +++ b/xmake/rules/luarocks/module/xmake.lua @@ -19,65 +19,7 @@ -- rule("luarocks.module") - on_load(function (target) - - -- imports - import("core.cache.detectcache") - import("core.project.target", {alias = "project_target"}) - - -- set kind - if target:is_plat("macosx") then - target:set("kind", "binary") - target:add("ldflags", "-bundle", "-undefined dynamic_lookup", {force = true}) - else - target:set("kind", "shared") - end - - -- set library name - local modulename = target:name():split('.', {plain = true}) - modulename = modulename[#modulename] - if target:is_plat("windows", "mingw") then - target:set("basename", modulename) - else - target:set("filename", modulename .. ".so") - end - - -- export symbols - if target:is_plat("windows") then - local exported_name = target:name():gsub("%.", "_") - exported_name = exported_name:match('^[^%-]+%-(.+)$') or exported_name - target:add("shflags", "/export:luaopen_" .. exported_name, {force = true}) - else - target:set("symbols", "none") - end - - -- add lua library - local has_lua = false - local includedirs = get_config("includedirs") -- pass lua library from luarocks-build-xmake/xmake.lua - if includedirs and includedirs:find("lua", 1, true) then - has_lua = true - end - if not has_lua then - -- user use `add_requires/add_packages` to add lua/luajit package - for _, pkg in ipairs(target:get("packages")) do - if pkg == "lua" or pkg == "luajit" then - has_lua = true - break - end - end - end - if not has_lua then - target:add(find_package("lua")) - end - end) - on_install(function (target) - if target:is_plat("macosx") then - target:set("kind", "shared") - end - local moduledir = path.directory((target:name():gsub('%.', '/'))) - import("target.action.install")(target, { - installdir = target:installdir(), - libdir = path.join("lib", moduledir), - bindir = path.join("lib", moduledir), - includedir = path.join("include", moduledir)}) + on_config(function (target) + wprint('deprecated: please use rule("lua.module") instead of rule("luarocks.module")') end) + add_deps("lua.module") diff --git a/xmake/rules/platform/linux/driver/driver_modules.lua b/xmake/rules/platform/linux/driver/driver_modules.lua deleted file mode 100644 index 8218a972c..000000000 --- a/xmake/rules/platform/linux/driver/driver_modules.lua +++ /dev/null @@ -1,326 +0,0 @@ ---!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 driver_modules.lua --- - --- imports -import("core.base.option") -import("core.project.depend") -import("core.cache.memcache") -import("lib.detect.find_tool") -import("utils.progress") - --- get linux-headers sdk -function _get_linux_headers_sdk(target) - local linux_headersdir = target:values("linux.driver.linux-headers") - local linux_builddir = target:values("linux.driver.linux-builddir") - if linux_headersdir then - return { - sdkdir = linux_headersdir, - builddir = linux_builddir, - includedir = path.join(linux_headersdir, "include") - } - end - local linux_headers = assert(target:pkg("linux-headers"), "please add `add_requires(\"linux-headers\", {configs = {driver_modules = true}})` and `add_packages(\"linux-headers\")` to the given target!") - local includedirs = linux_headers:get("includedirs") or linux_headers:get("sysincludedirs") - local version = linux_headers:version() - local includedir - for _, dir in ipairs(includedirs) do - if dir:find("linux-headers", 1, true) then - includedir = dir - linux_headersdir = path.directory(dir) - break - end - end - assert(linux_headersdir, "linux-headers not found!") - if not os.isfile(path.join(includedir, "generated/autoconf.h")) and - not os.isfile(path.join(includedir, "config/auto.conf")) then - raise("kernel configuration is invalid. include/generated/autoconf.h or include/config/auto.conf are missing.") - end - return {version = version, sdkdir = linux_headersdir, includedir = includedir} -end - --- get cflags from make -function _get_cflags_from_make(target, sdkdir, builddir) - local key = sdkdir .. target:arch() - local cflags = memcache.get2("linux.driver", key, "cflags") - local ldflags_o = memcache.get2("linux.driver", key, "ldflags_o") - local ldflags_ko = memcache.get2("linux.driver", key, "ldflags_ko") - if cflags == nil then - local make = assert(find_tool("make"), "make not found!") - local tmpdir = os.tmpfile() .. ".dir" - local makefile = path.join(tmpdir, "Makefile") - local stubfile = path.join(tmpdir, "src/stub.c") - local foofile = path.join(tmpdir, "src/foo.c") - io.writefile(makefile, [[obj-m := stub.o -stub-objs := src/stub.o src/foo.o]]) - io.writefile(foofile, "") - io.writefile(stubfile, [[ -#include -#include - -MODULE_LICENSE("Dual BSD/GPL"); -MODULE_AUTHOR("Ruki"); -MODULE_DESCRIPTION("A simple Hello World Module"); -MODULE_ALIAS("a simplest module"); - -static int hello_init(void) { - printk(KERN_INFO "Hello World\n"); - return 0; -} - -static void hello_exit(void) { - printk(KERN_INFO "Goodbye World\n"); -} - -module_init(hello_init); -module_exit(hello_exit); - ]]) - local argv = {"-C", sdkdir, "V=1", "M=" .. tmpdir, "modules"} - if builddir then - table.insert(argv, "O=" .. builddir) - end - if not target:is_plat(os.subhost()) then - -- e.g. $(MAKE) -C $(KERN_DIR) V=1 ARCH=arm64 CROSS_COMPILE=/mnt/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- M=$(PWD) modules - local arch - if target:is_arch("arm", "armv7") then - arch = "arm" - elseif target:is_arch("arm64", "arm64-v8a") then - arch = "arm64" - elseif target:is_arch("mips") then - arch = "mips" - elseif target:is_arch("ppc", "ppc64", "powerpc", "powerpc64") then - arch = "powerpc" - end - assert(arch, "unknown arch(%s)!", target:arch()) - local cc = target:tool("cc") - local cross = cc:gsub("%-gcc$", "-") - table.insert(argv, "ARCH=" .. arch) - table.insert(argv, "CROSS_COMPILE=" .. cross) - end - local result, errors = try {function () return os.iorunv(make.program, argv, {curdir = tmpdir}) end} - if result then - -- we can also split ';' for the muliple commands - for _, line in ipairs(result:split("[\n;]")) do - line = line:trim() - if line:endswith("stub.c") then - local include_cflag = false - for _, cflag in ipairs(line:split("%s+")) do - local has_cflag = false - if cflag:startswith("-fplugin=") then - -- @see https://github.com/xmake-io/xmake/issues/3279 - local plugindir = cflag:sub(10) - if not path.is_absolute(plugindir) then - plugindir = path.absolute(plugindir, sdkdir) - end - cflag = "-fplugin=" .. plugindir - has_cflag = true - elseif cflag:startswith("-f") or cflag:startswith("-m") - or (cflag:startswith("-W") and not cflag:startswith("-Wp,-MMD,") and not cflag:startswith("-Wp,-MD,")) - or (cflag:startswith("-D") and not cflag:find("KBUILD_MODNAME=") and not cflag:find("KBUILD_BASENAME=")) then - has_cflag = true - local macro = cflag:match("%-D\"(.+)\"") -- -D"KBUILD_XXX=xxx" - if macro then - cflag = "-D" .. macro - end - elseif cflag == "-I" or cflag == "-isystem" or cflag == "-include" then - include_cflag = cflag - elseif cflag:startswith("-I") or include_cflag then - local includedir = cflag - if cflag:startswith("-I") then - includedir = cflag:sub(3) - end - if not path.is_absolute(includedir) then - includedir = path.absolute(includedir, builddir or sdkdir) - end - if cflag:startswith("-I") then - cflag = "-I" .. includedir - else - cflag = include_cflag .. " " .. includedir - end - has_cflag = true - include_cflag = nil - end - if has_cflag then - cflags = cflags or {} - table.insert(cflags, cflag) - end - end - end - local ldflags = line:match("%-ld (.+) %-o ") or line:match("ld (.+) %-o ") - if ldflags then - local ko = ldflags:find("-T ", 1, true) - for _, ldflag in ipairs(os.argv(ldflags)) do - if ldflag:endswith(".lds") then - if not path.is_absolute(ldflag) then - ldflag = path.absolute(ldflag, builddir or sdkdir) - end - end - if ko then - -- e.g. aarch64-linux-gnu-ld -r -EL -maarch64elf --build-id=sha1 -T scripts/module.lds -o hello.ko hello.o hello.mod.o - ldflags_ko = ldflags_ko or {} - table.insert(ldflags_ko, ldflag) - else - -- e.g. aarch64-linux-gnu-ld -EL -maarch64elf -r -o hello.o xxx.o - ldflags_o = ldflags_o or {} - table.insert(ldflags_o, ldflag) - end - end - end - if cflags and ldflags_o and ldflags_ko then - break - end - end - else - if option.get("diagnosis") then - print("rule(platform.linux.driver): cannot get cflags from make!") - print(errors) - end - end - os.tryrm(tmpdir) - memcache.set2("linux.driver", key, "cflags", cflags or false) - memcache.set2("linux.driver", key, "ldflags_o", ldflags_o or false) - memcache.set2("linux.driver", key, "ldflags_ko", ldflags_ko or false) - end - return cflags or nil, ldflags_o or nil, ldflags_ko or nil -end - -function load(target) - -- we only need binary kind, because we will rewrite on_link - target:set("kind", "binary") - target:set("extension", ".ko") -end - -function config(target) - - -- get and save linux-headers sdk - local linux_headers = _get_linux_headers_sdk(target) - target:data_set("linux.driver.linux_headers", linux_headers) - - -- check compiler, we must use gcc - assert(target:has_tool("cc", "gcc"), "we must use gcc compiler!") - - -- check rules - for _, rulename in ipairs({"mode.release", "mode.debug", "mode.releasedbg", "mode.minsizerel", "mode.asan", "mode.tsan"}) do - assert(not target:rule(rulename), "target(%s) is linux driver module, it need not rule(%s)!", target:name(), rulename) - end - - -- we need to disable includedirs from add_packages("linux-headers") - if target:pkg("linux-headers") then - target:pkg("linux-headers"):set("includedirs", nil) - target:pkg("linux-headers"):set("sysincludedirs", nil) - end - - -- add compilation flags - target:add("defines", "KBUILD_MODNAME=\"" .. target:name() .. "\"") - for _, sourcefile in ipairs(target:sourcefiles()) do - target:fileconfig_set(sourcefile, {defines = "KBUILD_BASENAME=\"" .. path.basename(sourcefile) .. "\""}) - end - local cflags, ldflags_o, ldflags_ko = _get_cflags_from_make(target, linux_headers.sdkdir, linux_headers.builddir) - if cflags then - target:add("cflags", cflags, {force = true}) - target:data_set("linux.driver.ldflags_o", ldflags_o) - target:data_set("linux.driver.ldflags_ko", ldflags_ko) - end -end - -function link(target, opt) - local targetfile = target:targetfile() - local dependfile = target:dependfile(targetfile) - local objectfiles = target:objectfiles() - depend.on_changed(function () - - -- trace - progress.show(opt.progress, "${color.build.object}linking.$(mode) %s", targetfile) - - -- get module scripts - local modpost - local linux_headers = target:data("linux.driver.linux_headers") - if linux_headers then - modpost = path.join(linux_headers.builddir or linux_headers.sdkdir, "scripts", "mod", "modpost") - end - assert(modpost and os.isfile(modpost), "scripts/mod/modpost not found!") - - -- get ld - local ld = target:tool("ld") - assert(ld, "ld not found!") - ld = ld:gsub("gcc$", "ld") - ld = ld:gsub("g%+%+$", "ld") - - -- link target.o - local argv = {} - local ldflags_o = target:data("linux.driver.ldflags_o") - if ldflags_o then - table.join2(argv, ldflags_o) - end - local targetfile_o = target:objectfile(targetfile) - table.join2(argv, "-o", targetfile_o) - table.join2(argv, objectfiles) - os.mkdir(path.directory(targetfile_o)) - os.vrunv(ld, argv) - - -- generate target.mod - local targetfile_mod = targetfile_o:gsub("%.o$", ".mod") - io.writefile(targetfile_mod, table.concat(objectfiles, "\n") .. "\n\n") - - -- generate .sourcename.o.cmd - -- we only need to touch an empty file, otherwise modpost command will raise error. - for _, objectfile in ipairs(objectfiles) do - local objectdir = path.directory(objectfile) - local objectname = path.filename(objectfile) - local cmdfile = path.join(objectdir, "." .. objectname .. ".cmd") - io.writefile(cmdfile, "") - end - - -- generate target.mod.c - local orderfile = path.join(path.directory(targetfile_o), "modules.order") - local symversfile = path.join(path.directory(targetfile_o), "Module.symvers") - argv = {"-m", "-a", "-o", symversfile, "-e", "-N", "-w", "-T", orderfile} - io.writefile(orderfile, targetfile_o .. "\n") - os.vrunv(modpost, argv) - - -- compile target.mod.c - local targetfile_mod_c = targetfile_o:gsub("%.o$", ".mod.c") - local targetfile_mod_o = targetfile_o:gsub("%.o$", ".mod.o") - local compinst = target:compiler("cc") - if option.get("verbose") then - print(compinst:compcmd(targetfile_mod_c, targetfile_mod_o, {target = target, rawargs = true})) - end - assert(compinst:compile(targetfile_mod_c, targetfile_mod_o, {target = target})) - - -- link target.ko - argv = {} - local ldflags_ko = target:data("linux.driver.ldflags_ko") - if ldflags_ko then - table.join2(argv, ldflags_ko) - end - local targetfile_o = target:objectfile(targetfile) - table.join2(argv, "-o", targetfile, targetfile_o, targetfile_mod_o) - os.mkdir(path.directory(targetfile)) - os.vrunv(ld, argv) - - end, {dependfile = dependfile, lastmtime = os.mtime(target:targetfile()), files = objectfiles, changed = target:is_rebuilt()}) -end - -function install(target) - os.vrunv("insmod", {target:targetfile()}) -end - -function uninstall(target) - os.vrunv("rmmod", {target:targetfile()}) -end diff --git a/xmake/rules/platform/linux/driver/xmake.lua b/xmake/rules/platform/linux/driver/xmake.lua index 297dcc83e..661850a6d 100644 --- a/xmake/rules/platform/linux/driver/xmake.lua +++ b/xmake/rules/platform/linux/driver/xmake.lua @@ -18,23 +18,8 @@ -- @file xmake.lua -- --- build linux driver module rule("platform.linux.driver") - set_sourcekinds("cc") - on_load(function (target) - import("driver_modules").load(target) - end) on_config(function (target) - import("driver_modules").config(target) - end) - on_link(function (target, opt) - import("driver_modules").link(target, opt) - end) - on_install(function (target) - import("driver_modules").install(target) + wprint('deprecated: please use rule("platform.linux.module") instead of rule("platform.linux.driver")') end) - on_uninstall(function (target) - import("driver_modules").uninstall(target) - end) - - + add_deps("platform.linux.module") diff --git a/xmake/rules/platform/linux/module/driver_modules.lua b/xmake/rules/platform/linux/module/driver_modules.lua new file mode 100644 index 000000000..8218a972c --- /dev/null +++ b/xmake/rules/platform/linux/module/driver_modules.lua @@ -0,0 +1,326 @@ +--!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 driver_modules.lua +-- + +-- imports +import("core.base.option") +import("core.project.depend") +import("core.cache.memcache") +import("lib.detect.find_tool") +import("utils.progress") + +-- get linux-headers sdk +function _get_linux_headers_sdk(target) + local linux_headersdir = target:values("linux.driver.linux-headers") + local linux_builddir = target:values("linux.driver.linux-builddir") + if linux_headersdir then + return { + sdkdir = linux_headersdir, + builddir = linux_builddir, + includedir = path.join(linux_headersdir, "include") + } + end + local linux_headers = assert(target:pkg("linux-headers"), "please add `add_requires(\"linux-headers\", {configs = {driver_modules = true}})` and `add_packages(\"linux-headers\")` to the given target!") + local includedirs = linux_headers:get("includedirs") or linux_headers:get("sysincludedirs") + local version = linux_headers:version() + local includedir + for _, dir in ipairs(includedirs) do + if dir:find("linux-headers", 1, true) then + includedir = dir + linux_headersdir = path.directory(dir) + break + end + end + assert(linux_headersdir, "linux-headers not found!") + if not os.isfile(path.join(includedir, "generated/autoconf.h")) and + not os.isfile(path.join(includedir, "config/auto.conf")) then + raise("kernel configuration is invalid. include/generated/autoconf.h or include/config/auto.conf are missing.") + end + return {version = version, sdkdir = linux_headersdir, includedir = includedir} +end + +-- get cflags from make +function _get_cflags_from_make(target, sdkdir, builddir) + local key = sdkdir .. target:arch() + local cflags = memcache.get2("linux.driver", key, "cflags") + local ldflags_o = memcache.get2("linux.driver", key, "ldflags_o") + local ldflags_ko = memcache.get2("linux.driver", key, "ldflags_ko") + if cflags == nil then + local make = assert(find_tool("make"), "make not found!") + local tmpdir = os.tmpfile() .. ".dir" + local makefile = path.join(tmpdir, "Makefile") + local stubfile = path.join(tmpdir, "src/stub.c") + local foofile = path.join(tmpdir, "src/foo.c") + io.writefile(makefile, [[obj-m := stub.o +stub-objs := src/stub.o src/foo.o]]) + io.writefile(foofile, "") + io.writefile(stubfile, [[ +#include +#include + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("Ruki"); +MODULE_DESCRIPTION("A simple Hello World Module"); +MODULE_ALIAS("a simplest module"); + +static int hello_init(void) { + printk(KERN_INFO "Hello World\n"); + return 0; +} + +static void hello_exit(void) { + printk(KERN_INFO "Goodbye World\n"); +} + +module_init(hello_init); +module_exit(hello_exit); + ]]) + local argv = {"-C", sdkdir, "V=1", "M=" .. tmpdir, "modules"} + if builddir then + table.insert(argv, "O=" .. builddir) + end + if not target:is_plat(os.subhost()) then + -- e.g. $(MAKE) -C $(KERN_DIR) V=1 ARCH=arm64 CROSS_COMPILE=/mnt/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- M=$(PWD) modules + local arch + if target:is_arch("arm", "armv7") then + arch = "arm" + elseif target:is_arch("arm64", "arm64-v8a") then + arch = "arm64" + elseif target:is_arch("mips") then + arch = "mips" + elseif target:is_arch("ppc", "ppc64", "powerpc", "powerpc64") then + arch = "powerpc" + end + assert(arch, "unknown arch(%s)!", target:arch()) + local cc = target:tool("cc") + local cross = cc:gsub("%-gcc$", "-") + table.insert(argv, "ARCH=" .. arch) + table.insert(argv, "CROSS_COMPILE=" .. cross) + end + local result, errors = try {function () return os.iorunv(make.program, argv, {curdir = tmpdir}) end} + if result then + -- we can also split ';' for the muliple commands + for _, line in ipairs(result:split("[\n;]")) do + line = line:trim() + if line:endswith("stub.c") then + local include_cflag = false + for _, cflag in ipairs(line:split("%s+")) do + local has_cflag = false + if cflag:startswith("-fplugin=") then + -- @see https://github.com/xmake-io/xmake/issues/3279 + local plugindir = cflag:sub(10) + if not path.is_absolute(plugindir) then + plugindir = path.absolute(plugindir, sdkdir) + end + cflag = "-fplugin=" .. plugindir + has_cflag = true + elseif cflag:startswith("-f") or cflag:startswith("-m") + or (cflag:startswith("-W") and not cflag:startswith("-Wp,-MMD,") and not cflag:startswith("-Wp,-MD,")) + or (cflag:startswith("-D") and not cflag:find("KBUILD_MODNAME=") and not cflag:find("KBUILD_BASENAME=")) then + has_cflag = true + local macro = cflag:match("%-D\"(.+)\"") -- -D"KBUILD_XXX=xxx" + if macro then + cflag = "-D" .. macro + end + elseif cflag == "-I" or cflag == "-isystem" or cflag == "-include" then + include_cflag = cflag + elseif cflag:startswith("-I") or include_cflag then + local includedir = cflag + if cflag:startswith("-I") then + includedir = cflag:sub(3) + end + if not path.is_absolute(includedir) then + includedir = path.absolute(includedir, builddir or sdkdir) + end + if cflag:startswith("-I") then + cflag = "-I" .. includedir + else + cflag = include_cflag .. " " .. includedir + end + has_cflag = true + include_cflag = nil + end + if has_cflag then + cflags = cflags or {} + table.insert(cflags, cflag) + end + end + end + local ldflags = line:match("%-ld (.+) %-o ") or line:match("ld (.+) %-o ") + if ldflags then + local ko = ldflags:find("-T ", 1, true) + for _, ldflag in ipairs(os.argv(ldflags)) do + if ldflag:endswith(".lds") then + if not path.is_absolute(ldflag) then + ldflag = path.absolute(ldflag, builddir or sdkdir) + end + end + if ko then + -- e.g. aarch64-linux-gnu-ld -r -EL -maarch64elf --build-id=sha1 -T scripts/module.lds -o hello.ko hello.o hello.mod.o + ldflags_ko = ldflags_ko or {} + table.insert(ldflags_ko, ldflag) + else + -- e.g. aarch64-linux-gnu-ld -EL -maarch64elf -r -o hello.o xxx.o + ldflags_o = ldflags_o or {} + table.insert(ldflags_o, ldflag) + end + end + end + if cflags and ldflags_o and ldflags_ko then + break + end + end + else + if option.get("diagnosis") then + print("rule(platform.linux.driver): cannot get cflags from make!") + print(errors) + end + end + os.tryrm(tmpdir) + memcache.set2("linux.driver", key, "cflags", cflags or false) + memcache.set2("linux.driver", key, "ldflags_o", ldflags_o or false) + memcache.set2("linux.driver", key, "ldflags_ko", ldflags_ko or false) + end + return cflags or nil, ldflags_o or nil, ldflags_ko or nil +end + +function load(target) + -- we only need binary kind, because we will rewrite on_link + target:set("kind", "binary") + target:set("extension", ".ko") +end + +function config(target) + + -- get and save linux-headers sdk + local linux_headers = _get_linux_headers_sdk(target) + target:data_set("linux.driver.linux_headers", linux_headers) + + -- check compiler, we must use gcc + assert(target:has_tool("cc", "gcc"), "we must use gcc compiler!") + + -- check rules + for _, rulename in ipairs({"mode.release", "mode.debug", "mode.releasedbg", "mode.minsizerel", "mode.asan", "mode.tsan"}) do + assert(not target:rule(rulename), "target(%s) is linux driver module, it need not rule(%s)!", target:name(), rulename) + end + + -- we need to disable includedirs from add_packages("linux-headers") + if target:pkg("linux-headers") then + target:pkg("linux-headers"):set("includedirs", nil) + target:pkg("linux-headers"):set("sysincludedirs", nil) + end + + -- add compilation flags + target:add("defines", "KBUILD_MODNAME=\"" .. target:name() .. "\"") + for _, sourcefile in ipairs(target:sourcefiles()) do + target:fileconfig_set(sourcefile, {defines = "KBUILD_BASENAME=\"" .. path.basename(sourcefile) .. "\""}) + end + local cflags, ldflags_o, ldflags_ko = _get_cflags_from_make(target, linux_headers.sdkdir, linux_headers.builddir) + if cflags then + target:add("cflags", cflags, {force = true}) + target:data_set("linux.driver.ldflags_o", ldflags_o) + target:data_set("linux.driver.ldflags_ko", ldflags_ko) + end +end + +function link(target, opt) + local targetfile = target:targetfile() + local dependfile = target:dependfile(targetfile) + local objectfiles = target:objectfiles() + depend.on_changed(function () + + -- trace + progress.show(opt.progress, "${color.build.object}linking.$(mode) %s", targetfile) + + -- get module scripts + local modpost + local linux_headers = target:data("linux.driver.linux_headers") + if linux_headers then + modpost = path.join(linux_headers.builddir or linux_headers.sdkdir, "scripts", "mod", "modpost") + end + assert(modpost and os.isfile(modpost), "scripts/mod/modpost not found!") + + -- get ld + local ld = target:tool("ld") + assert(ld, "ld not found!") + ld = ld:gsub("gcc$", "ld") + ld = ld:gsub("g%+%+$", "ld") + + -- link target.o + local argv = {} + local ldflags_o = target:data("linux.driver.ldflags_o") + if ldflags_o then + table.join2(argv, ldflags_o) + end + local targetfile_o = target:objectfile(targetfile) + table.join2(argv, "-o", targetfile_o) + table.join2(argv, objectfiles) + os.mkdir(path.directory(targetfile_o)) + os.vrunv(ld, argv) + + -- generate target.mod + local targetfile_mod = targetfile_o:gsub("%.o$", ".mod") + io.writefile(targetfile_mod, table.concat(objectfiles, "\n") .. "\n\n") + + -- generate .sourcename.o.cmd + -- we only need to touch an empty file, otherwise modpost command will raise error. + for _, objectfile in ipairs(objectfiles) do + local objectdir = path.directory(objectfile) + local objectname = path.filename(objectfile) + local cmdfile = path.join(objectdir, "." .. objectname .. ".cmd") + io.writefile(cmdfile, "") + end + + -- generate target.mod.c + local orderfile = path.join(path.directory(targetfile_o), "modules.order") + local symversfile = path.join(path.directory(targetfile_o), "Module.symvers") + argv = {"-m", "-a", "-o", symversfile, "-e", "-N", "-w", "-T", orderfile} + io.writefile(orderfile, targetfile_o .. "\n") + os.vrunv(modpost, argv) + + -- compile target.mod.c + local targetfile_mod_c = targetfile_o:gsub("%.o$", ".mod.c") + local targetfile_mod_o = targetfile_o:gsub("%.o$", ".mod.o") + local compinst = target:compiler("cc") + if option.get("verbose") then + print(compinst:compcmd(targetfile_mod_c, targetfile_mod_o, {target = target, rawargs = true})) + end + assert(compinst:compile(targetfile_mod_c, targetfile_mod_o, {target = target})) + + -- link target.ko + argv = {} + local ldflags_ko = target:data("linux.driver.ldflags_ko") + if ldflags_ko then + table.join2(argv, ldflags_ko) + end + local targetfile_o = target:objectfile(targetfile) + table.join2(argv, "-o", targetfile, targetfile_o, targetfile_mod_o) + os.mkdir(path.directory(targetfile)) + os.vrunv(ld, argv) + + end, {dependfile = dependfile, lastmtime = os.mtime(target:targetfile()), files = objectfiles, changed = target:is_rebuilt()}) +end + +function install(target) + os.vrunv("insmod", {target:targetfile()}) +end + +function uninstall(target) + os.vrunv("rmmod", {target:targetfile()}) +end diff --git a/xmake/rules/platform/linux/module/xmake.lua b/xmake/rules/platform/linux/module/xmake.lua new file mode 100644 index 000000000..297dcc83e --- /dev/null +++ b/xmake/rules/platform/linux/module/xmake.lua @@ -0,0 +1,40 @@ +--!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 xmake.lua +-- + +-- build linux driver module +rule("platform.linux.driver") + set_sourcekinds("cc") + on_load(function (target) + import("driver_modules").load(target) + end) + on_config(function (target) + import("driver_modules").config(target) + end) + on_link(function (target, opt) + import("driver_modules").link(target, opt) + end) + on_install(function (target) + import("driver_modules").install(target) + end) + on_uninstall(function (target) + import("driver_modules").uninstall(target) + end) + + -- cgit v1.3.1 From ab173b6f1162919076175d91ffbc240de07edbde Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 13 Dec 2024 10:13:54 +0800 Subject: Update xmake.lua --- xmake/rules/luarocks/module/xmake.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/rules/luarocks/module/xmake.lua b/xmake/rules/luarocks/module/xmake.lua index d33fc810c..3439e1ed5 100644 --- a/xmake/rules/luarocks/module/xmake.lua +++ b/xmake/rules/luarocks/module/xmake.lua @@ -20,6 +20,6 @@ rule("luarocks.module") on_config(function (target) - wprint('deprecated: please use rule("lua.module") instead of rule("luarocks.module")') + wprint('deprecated: please use add_rules("lua.module") instead of add_rules("luarocks.module")') end) add_deps("lua.module") -- cgit v1.3.1 From d53f304899857e247c6491acae97ef2c6f8cad6f Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 13 Dec 2024 10:14:14 +0800 Subject: Update xmake.lua --- xmake/rules/platform/linux/driver/xmake.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/rules/platform/linux/driver/xmake.lua b/xmake/rules/platform/linux/driver/xmake.lua index 661850a6d..a050185b3 100644 --- a/xmake/rules/platform/linux/driver/xmake.lua +++ b/xmake/rules/platform/linux/driver/xmake.lua @@ -20,6 +20,6 @@ rule("platform.linux.driver") on_config(function (target) - wprint('deprecated: please use rule("platform.linux.module") instead of rule("platform.linux.driver")') + wprint('deprecated: please use add_rules("platform.linux.module") instead of add_rules("platform.linux.driver")') end) add_deps("platform.linux.module") -- cgit v1.3.1