From 411e455ba256d4f67289a267f62a74930212c8f9 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 27 Sep 2022 00:42:29 +0800 Subject: add set_base to rules --- tests/apis/rules_override_cxx/src/main.xx | 6 ++++++ tests/apis/rules_override_cxx/xmake.lua | 26 ++++++++++++++++++++++++++ tests/apis/rules_override_order/src/main.cc | 6 ++++++ tests/apis/rules_override_order/xmake.lua | 15 +++++++++++++++ tests/projects/c++/unity_build/src/test.cpp | 8 ++++++++ xmake/core/project/project.lua | 4 ++++ xmake/core/project/rule.lua | 22 ++++++++++++++++++++-- 7 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 tests/apis/rules_override_cxx/src/main.xx create mode 100644 tests/apis/rules_override_cxx/xmake.lua create mode 100644 tests/apis/rules_override_order/src/main.cc create mode 100644 tests/apis/rules_override_order/xmake.lua create mode 100644 tests/projects/c++/unity_build/src/test.cpp diff --git a/tests/apis/rules_override_cxx/src/main.xx b/tests/apis/rules_override_cxx/src/main.xx new file mode 100644 index 000000000..d612d8782 --- /dev/null +++ b/tests/apis/rules_override_cxx/src/main.xx @@ -0,0 +1,6 @@ +#include + +int main(int argc, char** argv) +{ + return 0; +} diff --git a/tests/apis/rules_override_cxx/xmake.lua b/tests/apis/rules_override_cxx/xmake.lua new file mode 100644 index 000000000..0dc2261ca --- /dev/null +++ b/tests/apis/rules_override_cxx/xmake.lua @@ -0,0 +1,26 @@ +rule("xx.build") + set_base("c++.build") + set_extensions(".xx") + on_load(function (target) + local sourcebatch = target:sourcebatches()["xx.build"] + sourcebatch.sourcekind = "cxx" + sourcebatch.objectfiles = {} + sourcebatch.dependfiles = {} + for _, sourcefile in ipairs(sourcebatch.sourcefiles) do + local objectfile = target:objectfile(sourcefile) + local dependfile = target:dependfile(objectfile) + table.insert(sourcebatch.objectfiles, objectfile) + table.insert(sourcebatch.dependfiles, dependfile) + end + target:add("cxxflags", "-x c++") + end) + +rule("xx") + set_base("c++") + add_deps("xx.build") + +target("test") + set_kind("binary") + add_rules("xx") + add_files("src/*.xx") + diff --git a/tests/apis/rules_override_order/src/main.cc b/tests/apis/rules_override_order/src/main.cc new file mode 100644 index 000000000..d612d8782 --- /dev/null +++ b/tests/apis/rules_override_order/src/main.cc @@ -0,0 +1,6 @@ +#include + +int main(int argc, char** argv) +{ + return 0; +} diff --git a/tests/apis/rules_override_order/xmake.lua b/tests/apis/rules_override_order/xmake.lua new file mode 100644 index 000000000..61b42a943 --- /dev/null +++ b/tests/apis/rules_override_order/xmake.lua @@ -0,0 +1,15 @@ +rule("cppfront") + set_extensions(".cpp2") + on_build_files(function (target, batchjobs, sourcebatch, opt) + print("on_build_files") + end, {batch = true, distcc = true}) + +rule("xx") + set_base("c++") + add_deps("cppfront", {order = true}) + +target("test") + set_kind("binary") + add_rules("xx") + add_files("src/*.cc") + diff --git a/tests/projects/c++/unity_build/src/test.cpp b/tests/projects/c++/unity_build/src/test.cpp new file mode 100644 index 000000000..27d41ee50 --- /dev/null +++ b/tests/projects/c++/unity_build/src/test.cpp @@ -0,0 +1,8 @@ +#include "header.h" + +int main(int argc, char** argv) +{ + std::string s("xmake"); + printf("hello %s!\n", s.c_str()); + return 0; +} diff --git a/xmake/core/project/project.lua b/xmake/core/project/project.lua index f48a45205..3c4c39232 100644 --- a/xmake/core/project/project.lua +++ b/xmake/core/project/project.lua @@ -326,6 +326,10 @@ function project._load_rules() for _, instance in pairs(instances) do instance._DEPS = instance._DEPS or {} instance._ORDERDEPS = instance._ORDERDEPS or {} + local base = instance:get("base") + if base then + instance._BASE = instances[base] + end project._load_deps(instance, instances, instance._DEPS, instance._ORDERDEPS, {instance:name()}) end return rules diff --git a/xmake/core/project/rule.lua b/xmake/core/project/rule.lua index 599294a45..841203c9d 100644 --- a/xmake/core/project/rule.lua +++ b/xmake/core/project/rule.lua @@ -150,6 +150,7 @@ function rule.apis() "rule.set_extensions" , "rule.set_sourcekinds" , "rule.set_kind" + , "rule.set_base" -- rule.add_xxx , "rule.add_deps" , "rule.add_imports" @@ -214,14 +215,31 @@ function rule.new(name, info) return instance end +-- get the base rule +function rule:base() + return self._BASE +end + -- get the rule info function rule:get(name) - return self._INFO:get(name) + local value = self._INFO:get(name) + if value == nil and self:base() then + value = self:base():get(name) + end + if value ~= nil then + return value + end end -- get the extra configuration function rule:extraconf(name, item, key) - return self._INFO:extraconf(name, item, key) + local value = self._INFO:extraconf(name, item, key) + if value == nil and self:base() then + value = self:base():extraconf(name) + end + if value ~= nil then + return value + end end -- get the rule name -- cgit v1.3.1 From 9952e0cc62da89cdb899fe1dd02b86e156073e3e Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 27 Sep 2022 00:54:06 +0800 Subject: inject rule deps --- tests/apis/rules_inject_deps/src/hello.mpp | 10 ++++++++++ tests/apis/rules_inject_deps/src/main.cpp | 6 ++++++ tests/apis/rules_inject_deps/src/main.cpp2 | 0 tests/apis/rules_inject_deps/xmake.lua | 19 +++++++++++++++++++ tests/apis/rules_override_order/src/main.cc | 6 ------ tests/apis/rules_override_order/xmake.lua | 15 --------------- 6 files changed, 35 insertions(+), 21 deletions(-) create mode 100644 tests/apis/rules_inject_deps/src/hello.mpp create mode 100644 tests/apis/rules_inject_deps/src/main.cpp create mode 100644 tests/apis/rules_inject_deps/src/main.cpp2 create mode 100644 tests/apis/rules_inject_deps/xmake.lua delete mode 100644 tests/apis/rules_override_order/src/main.cc delete mode 100644 tests/apis/rules_override_order/xmake.lua diff --git a/tests/apis/rules_inject_deps/src/hello.mpp b/tests/apis/rules_inject_deps/src/hello.mpp new file mode 100644 index 000000000..124bd72bc --- /dev/null +++ b/tests/apis/rules_inject_deps/src/hello.mpp @@ -0,0 +1,10 @@ +module; +#include + +export module hello; + +export namespace hello { + void say(const char* str) { + printf("%s\n", str); + } +} diff --git a/tests/apis/rules_inject_deps/src/main.cpp b/tests/apis/rules_inject_deps/src/main.cpp new file mode 100644 index 000000000..1e5cc698f --- /dev/null +++ b/tests/apis/rules_inject_deps/src/main.cpp @@ -0,0 +1,6 @@ +import hello; + +int main() { + hello::say("hello module!"); + return 0; +} diff --git a/tests/apis/rules_inject_deps/src/main.cpp2 b/tests/apis/rules_inject_deps/src/main.cpp2 new file mode 100644 index 000000000..e69de29bb diff --git a/tests/apis/rules_inject_deps/xmake.lua b/tests/apis/rules_inject_deps/xmake.lua new file mode 100644 index 000000000..d7cfcf61f --- /dev/null +++ b/tests/apis/rules_inject_deps/xmake.lua @@ -0,0 +1,19 @@ +rule("cppfront") + set_extensions(".cpp2") + on_load(function (target) + local rule = target:rule("c++.build.modules.builder"):clone() + rule:add_deps("cppfront", {order = true}) + target:rule_set("c++.build.modules.builder", rule) + end) + before_build_files(function (target, batchjobs, sourcebatch, opt) + print("build cppfront files") + end, {batch = true}) + +target("test") + set_kind("binary") + add_rules("cppfront") + set_languages("c++20") + add_files("src/*.cpp") + add_files("src/*.mpp") + add_files("src/*.cpp2") + diff --git a/tests/apis/rules_override_order/src/main.cc b/tests/apis/rules_override_order/src/main.cc deleted file mode 100644 index d612d8782..000000000 --- a/tests/apis/rules_override_order/src/main.cc +++ /dev/null @@ -1,6 +0,0 @@ -#include - -int main(int argc, char** argv) -{ - return 0; -} diff --git a/tests/apis/rules_override_order/xmake.lua b/tests/apis/rules_override_order/xmake.lua deleted file mode 100644 index 61b42a943..000000000 --- a/tests/apis/rules_override_order/xmake.lua +++ /dev/null @@ -1,15 +0,0 @@ -rule("cppfront") - set_extensions(".cpp2") - on_build_files(function (target, batchjobs, sourcebatch, opt) - print("on_build_files") - end, {batch = true, distcc = true}) - -rule("xx") - set_base("c++") - add_deps("cppfront", {order = true}) - -target("test") - set_kind("binary") - add_rules("xx") - add_files("src/*.cc") - -- cgit v1.3.1 From 701f42aec0dd4acb291a7c69582823687a5edf85 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 27 Sep 2022 00:55:51 +0800 Subject: improve rule, rename to instance --- tests/apis/rules_inject_deps/xmake.lua | 2 +- xmake/core/project/rule.lua | 253 +++++++++++++++++---------------- 2 files changed, 133 insertions(+), 122 deletions(-) diff --git a/tests/apis/rules_inject_deps/xmake.lua b/tests/apis/rules_inject_deps/xmake.lua index d7cfcf61f..383789e0a 100644 --- a/tests/apis/rules_inject_deps/xmake.lua +++ b/tests/apis/rules_inject_deps/xmake.lua @@ -2,7 +2,7 @@ rule("cppfront") set_extensions(".cpp2") on_load(function (target) local rule = target:rule("c++.build.modules.builder"):clone() - rule:add_deps("cppfront", {order = true}) + rule:add("deps", "cppfront", {order = true}) target:rule_set("c++.build.modules.builder", rule) end) before_build_files(function (target, batchjobs, sourcebatch, opt) diff --git a/xmake/core/project/rule.lua b/xmake/core/project/rule.lua index 841203c9d..1ac551ffd 100644 --- a/xmake/core/project/rule.lua +++ b/xmake/core/project/rule.lua @@ -20,6 +20,7 @@ -- define module local rule = rule or {} +local _instance = _instance or {} -- load modules local os = require("base/os") @@ -33,6 +34,136 @@ local sandbox = require("sandbox/sandbox") local sandbox_os = require("sandbox/modules/os") local sandbox_module = require("sandbox/modules/import/core/sandbox/module") +-- get the base rule +function _instance:base() + return self._BASE +end + +-- get the rule info +function _instance:get(name) + local value = self._INFO:get(name) + if value == nil and self:base() then + value = self:base():get(name) + end + if value ~= nil then + return value + end +end + +-- set the value to the package info +function _instance:set(name, ...) + self._INFO:apival_set(name, ...) +end + +-- add the value to the package info +function _instance:add(name, ...) + self._INFO:apival_add(name, ...) +end + +-- get the extra configuration +function _instance:extraconf(name, item, key) + local value = self._INFO:extraconf(name, item, key) + if value == nil and self:base() then + value = self:base():extraconf(name) + end + if value ~= nil then + return value + end +end + +-- get the rule name +function _instance:name() + return self._NAME +end + +-- get the rule kind +-- +-- current supported kind: +-- - target: default, only for each target +-- - project: global rule, for whole project +-- +function _instance:kind() + return self:get("kind") or "target" +end + +-- get the given dependent rule +function _instance:dep(name) + local deps = self:deps() + if deps then + return deps[name] + end +end + +-- get rule deps +function _instance:deps() + return self._DEPS +end + +-- get rule order deps +function _instance:orderdeps() + return self._ORDERDEPS +end + +-- get xxx_script +function _instance:script(name, generic) + + -- get script + local script = self:get(name) + local result = nil + if type(script) == "function" then + result = script + elseif type(script) == "table" then + + -- get plat and arch + local plat = config.get("plat") or "" + local arch = config.get("arch") or "" + + -- match pattern + -- + -- `@linux` + -- `@linux|x86_64` + -- `@macosx,linux` + -- `android@macosx,linux` + -- `android|armeabi-v7a@macosx,linux` + -- `android|armeabi-v7a@macosx,linux|x86_64` + -- `android|armeabi-v7a@linux|x86_64` + -- + for _pattern, _script in pairs(script) do + local hosts = {} + local hosts_spec = false + _pattern = _pattern:gsub("@(.+)", function (v) + for _, host in ipairs(v:split(',')) do + hosts[host] = true + hosts_spec = true + end + return "" + end) + if not _pattern:startswith("__") and (not hosts_spec or hosts[os.subhost() .. '|' .. os.subarch()] or hosts[os.subhost()]) + and (_pattern:trim() == "" or (plat .. '|' .. arch):find('^' .. _pattern .. '$') or plat:find('^' .. _pattern .. '$')) then + result = _script + break + end + end + + -- get generic script + result = result or script["__generic__"] or generic + end + + -- only generic script + result = result or generic + + -- imports some modules first + if result and result ~= generic then + local scope = getfenv(result) + if scope then + for _, modulename in ipairs(table.wrap(self:get("imports"))) do + scope[sandbox_module.name(modulename)] = sandbox_module.import(modulename, {anonymous = true}) + end + end + end + return result +end + -- the directories of rule function rule._directories() return { path.join(global.directory(), "rules") @@ -209,132 +340,12 @@ end -- new a rule instance function rule.new(name, info) - local instance = table.inherit(rule) + local instance = table.inherit(_instance) instance._NAME = name instance._INFO = info return instance end --- get the base rule -function rule:base() - return self._BASE -end - --- get the rule info -function rule:get(name) - local value = self._INFO:get(name) - if value == nil and self:base() then - value = self:base():get(name) - end - if value ~= nil then - return value - end -end - --- get the extra configuration -function rule:extraconf(name, item, key) - local value = self._INFO:extraconf(name, item, key) - if value == nil and self:base() then - value = self:base():extraconf(name) - end - if value ~= nil then - return value - end -end - --- get the rule name -function rule:name() - return self._NAME -end - --- get the rule kind --- --- current supported kind: --- - target: default, only for each target --- - project: global rule, for whole project --- -function rule:kind() - return self:get("kind") or "target" -end - --- get the given dependent rule -function rule:dep(name) - local deps = self:deps() - if deps then - return deps[name] - end -end - --- get rule deps -function rule:deps() - return self._DEPS -end - --- get rule order deps -function rule:orderdeps() - return self._ORDERDEPS -end - --- get xxx_script -function rule:script(name, generic) - - -- get script - local script = self:get(name) - local result = nil - if type(script) == "function" then - result = script - elseif type(script) == "table" then - - -- get plat and arch - local plat = config.get("plat") or "" - local arch = config.get("arch") or "" - - -- match pattern - -- - -- `@linux` - -- `@linux|x86_64` - -- `@macosx,linux` - -- `android@macosx,linux` - -- `android|armeabi-v7a@macosx,linux` - -- `android|armeabi-v7a@macosx,linux|x86_64` - -- `android|armeabi-v7a@linux|x86_64` - -- - for _pattern, _script in pairs(script) do - local hosts = {} - local hosts_spec = false - _pattern = _pattern:gsub("@(.+)", function (v) - for _, host in ipairs(v:split(',')) do - hosts[host] = true - hosts_spec = true - end - return "" - end) - if not _pattern:startswith("__") and (not hosts_spec or hosts[os.subhost() .. '|' .. os.subarch()] or hosts[os.subhost()]) - and (_pattern:trim() == "" or (plat .. '|' .. arch):find('^' .. _pattern .. '$') or plat:find('^' .. _pattern .. '$')) then - result = _script - break - end - end - - -- get generic script - result = result or script["__generic__"] or generic - end - - -- only generic script - result = result or generic - - -- imports some modules first - if result and result ~= generic then - local scope = getfenv(result) - if scope then - for _, modulename in ipairs(table.wrap(self:get("imports"))) do - scope[sandbox_module.name(modulename)] = sandbox_module.import(modulename, {anonymous = true}) - end - end - end - return result -end - -- get the given global rule function rule.rule(name) return rule.rules()[name] -- cgit v1.3.1 From 466896dac3710e145baa671c95af27a97dbb5ebe Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 27 Sep 2022 22:37:12 +0800 Subject: impl target:rule_set --- xmake/core/base/private/instance_deps.lua | 62 +++++++++++++++++++++++++++++++ xmake/core/project/project.lua | 40 ++------------------ xmake/core/project/rule.lua | 9 +++++ xmake/core/project/target.lua | 26 ++++++++++++- 4 files changed, 100 insertions(+), 37 deletions(-) create mode 100644 xmake/core/base/private/instance_deps.lua diff --git a/xmake/core/base/private/instance_deps.lua b/xmake/core/base/private/instance_deps.lua new file mode 100644 index 000000000..7a5d9aada --- /dev/null +++ b/xmake/core/base/private/instance_deps.lua @@ -0,0 +1,62 @@ +--!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 instance_deps.lua +-- + +-- define module +local instance_deps = instance_deps or {} + +-- load modules +local option = require("base/option") +local string = require("base/string") + +-- load deps for instance: e.g. option, target and rule +-- +-- e.g. +-- +-- a.deps = b +-- b.deps = c +-- +-- orderdeps: c -> b -> a +-- +function instance_deps.load_deps(instance, instances, deps, orderdeps, depspath) + for _, dep in ipairs(table.wrap(instance:get("deps"))) do + local depinst = instances[dep] + if depinst then + local depspath_sub + if depspath then + for idx, name in ipairs(depspath) do + if name == dep then + local circular_deps = table.slice(depspath, idx) + table.insert(circular_deps, dep) + os.raise("circular dependency(%s) detected!", table.concat(circular_deps, ", ")) + end + end + depspath_sub = table.join(depspath, dep) + end + instance_deps.load_deps(depinst, instances, deps, orderdeps, depspath_sub) + if not deps[dep] then + deps[dep] = depinst + table.insert(orderdeps, depinst) + end + end + end +end + +-- return module +return instance_deps diff --git a/xmake/core/project/project.lua b/xmake/core/project/project.lua index 3c4c39232..62e180a87 100644 --- a/xmake/core/project/project.lua +++ b/xmake/core/project/project.lua @@ -34,6 +34,7 @@ local hashset = require("base/hashset") local baseoption = require("base/option") local deprecated = require("base/deprecated") local interpreter = require("base/interpreter") +local instance_deps = require("base/private/instance_deps") local memcache = require("cache/memcache") local rule = require("project/rule") local target = require("project/target") @@ -207,39 +208,6 @@ function project._load(force, disable_filter) return true end --- load deps for instance: e.g. option, target and rule --- --- e.g. --- --- a.deps = b --- b.deps = c --- --- orderdeps: c -> b -> a --- -function project._load_deps(instance, instances, deps, orderdeps, depspath) - for _, dep in ipairs(table.wrap(instance:get("deps"))) do - local depinst = instances[dep] - if depinst then - local depspath_sub - if depspath then - for idx, name in ipairs(depspath) do - if name == dep then - local circular_deps = table.slice(depspath, idx) - table.insert(circular_deps, dep) - os.raise("circular dependency(%s) detected!", table.concat(circular_deps, ", ")) - end - end - depspath_sub = table.join(depspath, dep) - end - project._load_deps(depinst, instances, deps, orderdeps, depspath_sub) - if not deps[dep] then - deps[dep] = depinst - table.insert(orderdeps, depinst) - end - end - end -end - -- load scope from the project file function project._load_scope(scope_kind, deduplicate, enable_filter) @@ -330,7 +298,7 @@ function project._load_rules() if base then instance._BASE = instances[base] end - project._load_deps(instance, instances, instance._DEPS, instance._ORDERDEPS, {instance:name()}) + instance_deps.load_deps(instance, instances, instance._DEPS, instance._ORDERDEPS, {instance:name()}) end return rules end @@ -452,7 +420,7 @@ function project._load_targets() -- load deps t._DEPS = t._DEPS or {} t._ORDERDEPS = t._ORDERDEPS or {} - project._load_deps(t, targets, t._DEPS, t._ORDERDEPS, {t:name()}) + instance_deps.load_deps(t, targets, t._DEPS, t._ORDERDEPS, {t:name()}) end -- sort targets for all deps @@ -545,7 +513,7 @@ function project._load_options(disable_filter) for _, opt in pairs(options) do opt._DEPS = opt._DEPS or {} opt._ORDERDEPS = opt._ORDERDEPS or {} - project._load_deps(opt, options, opt._DEPS, opt._ORDERDEPS, {opt:name()}) + instance_deps.load_deps(opt, options, opt._DEPS, opt._ORDERDEPS, {opt:name()}) end return options end diff --git a/xmake/core/project/rule.lua b/xmake/core/project/rule.lua index 1ac551ffd..39a7c49e3 100644 --- a/xmake/core/project/rule.lua +++ b/xmake/core/project/rule.lua @@ -39,6 +39,15 @@ function _instance:base() return self._BASE end +-- clone rule +function _instance:clone() + local instance = rule.new(self:name(), self._INFO:clone()) + -- TODO + instance._RULES = self._RULES + instance._ORDERDEPS = self._ORDERDEPS + return instance +end + -- get the rule info function _instance:get(name) local value = self._INFO:get(name) diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index 329eb53e3..a568fb15b 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -685,7 +685,24 @@ end -- get target ordered rules function _instance:orderules() - return self._ORDERULES + local rules = self._RULES + local orderules = self._ORDERULES + if orderules == nil and rules then + orderules = {} + local rules_unique = {} + for _, r in pairs(rules) do + for _, deprule in ipairs(r:orderdeps()) do + local name = deprule:name() + if not rules_unique[name] then + rules_unique[name] = deprule + table.insert(orderules, deprule) + end + end + table.insert(orderules, r) + end + self._ORDERULES = orderules + end + return orderules end -- get target rule from the given rule name @@ -695,6 +712,13 @@ function _instance:rule(name) end end +-- set rule +function _instance:rule_set(name, ruleinst) + self._RULES = self._RULES or {} + self._RULES[name] = ruleinst + self._ORDERULES = nil +end + -- is phony target? function _instance:is_phony() local targetkind = self:kind() -- cgit v1.3.1 From 239a254ca980adb927e086cf2cf1e4392e9c61c6 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 27 Sep 2022 22:40:43 +0800 Subject: build rule deps --- xmake/core/project/rule.lua | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/xmake/core/project/rule.lua b/xmake/core/project/rule.lua index 39a7c49e3..f9449ad58 100644 --- a/xmake/core/project/rule.lua +++ b/xmake/core/project/rule.lua @@ -34,6 +34,18 @@ local sandbox = require("sandbox/sandbox") local sandbox_os = require("sandbox/modules/os") local sandbox_module = require("sandbox/modules/import/core/sandbox/module") +-- invalidate the previous cache +function _instance:_invalidate(name) + if name == "deps" then + self._DEPS = nil + self._ORDERDEPS = nil + end +end + +-- build deps +function _instance:_build_deps() +end + -- get the base rule function _instance:base() return self._BASE @@ -42,8 +54,7 @@ end -- clone rule function _instance:clone() local instance = rule.new(self:name(), self._INFO:clone()) - -- TODO - instance._RULES = self._RULES + instance._DEPS = self._DEPS instance._ORDERDEPS = self._ORDERDEPS return instance end @@ -62,11 +73,13 @@ end -- set the value to the package info function _instance:set(name, ...) self._INFO:apival_set(name, ...) + self:_invalidate(name) end -- add the value to the package info function _instance:add(name, ...) self._INFO:apival_add(name, ...) + self:_invalidate(name) end -- get the extra configuration @@ -105,11 +118,17 @@ end -- get rule deps function _instance:deps() + if self._DEPS == nil then + self:_build_deps() + end return self._DEPS end -- get rule order deps function _instance:orderdeps() + if self._DEPS == nil then + self:_build_deps() + end return self._ORDERDEPS end -- cgit v1.3.1 From ac1ae70b7226b32ff62d19b54465c42ecd70e99c Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 27 Sep 2022 22:41:48 +0800 Subject: remove load rule deps --- xmake/core/project/project.lua | 12 ------------ xmake/core/project/rule.lua | 34 ++++------------------------------ 2 files changed, 4 insertions(+), 42 deletions(-) diff --git a/xmake/core/project/project.lua b/xmake/core/project/project.lua index 62e180a87..62f1f2398 100644 --- a/xmake/core/project/project.lua +++ b/xmake/core/project/project.lua @@ -288,18 +288,6 @@ function project._load_rules() for rulename, ruleinfo in pairs(results) do rules[rulename] = rule.new(rulename, ruleinfo) end - - -- load rule deps - local instances = table.join(rule.rules(), rules) - for _, instance in pairs(instances) do - instance._DEPS = instance._DEPS or {} - instance._ORDERDEPS = instance._ORDERDEPS or {} - local base = instance:get("base") - if base then - instance._BASE = instances[base] - end - instance_deps.load_deps(instance, instances, instance._DEPS, instance._ORDERDEPS, {instance:name()}) - end return rules end diff --git a/xmake/core/project/rule.lua b/xmake/core/project/rule.lua index f9449ad58..d0fbfb93d 100644 --- a/xmake/core/project/rule.lua +++ b/xmake/core/project/rule.lua @@ -46,11 +46,6 @@ end function _instance:_build_deps() end --- get the base rule -function _instance:base() - return self._BASE -end - -- clone rule function _instance:clone() local instance = rule.new(self:name(), self._INFO:clone()) @@ -61,13 +56,7 @@ end -- get the rule info function _instance:get(name) - local value = self._INFO:get(name) - if value == nil and self:base() then - value = self:base():get(name) - end - if value ~= nil then - return value - end + return self._INFO:get(name) end -- set the value to the package info @@ -84,13 +73,7 @@ end -- get the extra configuration function _instance:extraconf(name, item, key) - local value = self._INFO:extraconf(name, item, key) - if value == nil and self:base() then - value = self:base():extraconf(name) - end - if value ~= nil then - return value - end + return self._INFO:extraconf(name, item, key) end -- get the rule name @@ -309,7 +292,6 @@ function rule.apis() "rule.set_extensions" , "rule.set_sourcekinds" , "rule.set_kind" - , "rule.set_base" -- rule.add_xxx , "rule.add_deps" , "rule.add_imports" @@ -400,19 +382,11 @@ function rule.rules() end -- make rule instances - local instances = {} + rules = {} for rulename, ruleinfo in pairs(ruleinfos) do local instance = rule.new(rulename, ruleinfo) - instances[rulename] = instance - end - - -- load rule deps - for _, instance in pairs(instances) do - instance._DEPS = instance._DEPS or {} - instance._ORDERDEPS = instance._ORDERDEPS or {} - rule._load_deps(instance, instances, instance._DEPS, instance._ORDERDEPS) + rules[rulename] = instance end - rules = instances rule._RULES = rules end return rules -- cgit v1.3.1 From 25e9a13d183e4639e258d31b73e4281b1242081f Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 27 Sep 2022 22:43:20 +0800 Subject: rewrite build rule deps --- xmake/core/project/project.lua | 4 +++- xmake/core/project/rule.lua | 13 +++++++++++++ xmake/core/project/target.lua | 13 +++++++++---- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/xmake/core/project/project.lua b/xmake/core/project/project.lua index 62f1f2398..989dc0302 100644 --- a/xmake/core/project/project.lua +++ b/xmake/core/project/project.lua @@ -50,8 +50,10 @@ local language = require("language/language") local sandbox_os = require("sandbox/modules/os") local sandbox_module = require("sandbox/modules/import/core/sandbox/module") --- register project to platform +-- register project to platform, rule and target platform._PROJECT = project +target._PROJECT = project +rule._PROJECT = project -- the current os is belong to the given os? function project._api_is_os(interp, ...) diff --git a/xmake/core/project/rule.lua b/xmake/core/project/rule.lua index d0fbfb93d..c3403a197 100644 --- a/xmake/core/project/rule.lua +++ b/xmake/core/project/rule.lua @@ -29,6 +29,7 @@ local utils = require("base/utils") local table = require("base/table") local global = require("base/global") local interpreter = require("base/interpreter") +local instance_deps = require("base/private/instance_deps") local config = require("project/config") local sandbox = require("sandbox/sandbox") local sandbox_os = require("sandbox/modules/os") @@ -44,6 +45,13 @@ end -- build deps function _instance:_build_deps() + local instances = rule.rules() + if rule._project() then + instances = table.join(rule.rules(), rule._project().rules()) + end + self._DEPS = self._DEPS or {} + self._ORDERDEPS = self._ORDERDEPS or {} + instance_deps.load_deps(self, instances, self._DEPS, self._ORDERDEPS, {self:name()}) end -- clone rule @@ -236,6 +244,11 @@ function rule._interpreter() return interp end +-- get project +function rule._project() + return rule._PROJECT +end + -- load rule function rule._load(filepath) diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index a568fb15b..4e5f150be 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -859,7 +859,7 @@ function _instance:orderpkgs(opt) local packages = self:_memcache():get(cachekey) if not packages then packages = {} - local requires = self._PROJECT.required_packages() + local requires = target._project().required_packages() if requires then for _, packagename in ipairs(table.wrap(self:get("packages", opt))) do local pkg = requires[packagename] @@ -1220,7 +1220,7 @@ function _instance:filerules(sourcefile) if filerules then override = filerules.override for _, rulename in ipairs(table.wrap(filerules)) do - local r = self._PROJECT.rule(rulename) or rule.rule(rulename) + local r = target._project().rule(rulename) or rule.rule(rulename) if r then table.insert(rules, r) end @@ -2062,8 +2062,8 @@ function _instance:toolchains() toolchain_opt.plat = self:plat() local toolchain_inst, errors = toolchain.load(name, toolchain_opt) -- attempt to load toolchain from project - if not toolchain_inst and self._PROJECT then - toolchain_inst = self._PROJECT.toolchain(name, toolchain_opt) + if not toolchain_inst and target._project() then + toolchain_inst = target._project().toolchain(name, toolchain_opt) end if not toolchain_inst then os.raise(errors) @@ -2160,6 +2160,11 @@ function _instance:has_tool(toolkind, ...) end end +-- get project +function target._project() + return target._PROJECT +end + -- get target apis function target.apis() -- cgit v1.3.1 From 7d45ffda6d19cd057a445b1a20ad37e8b9094cb5 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 27 Sep 2022 22:44:26 +0800 Subject: improve load rules for target --- xmake/core/project/project.lua | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/xmake/core/project/project.lua b/xmake/core/project/project.lua index 989dc0302..d0f0145df 100644 --- a/xmake/core/project/project.lua +++ b/xmake/core/project/project.lua @@ -350,16 +350,7 @@ function project._load_targets() for _, t in pairs(targets) do -- load rules from target and language - -- - -- e.g. - -- - -- a.deps = b - -- b.deps = c - -- - -- orderules: c -> b -> a - -- - t._RULES = t._RULES or {} - t._ORDERULES = t._ORDERULES or {} + t._RULES = t._RULES or {} local rulenames = {} local extensions = {} table.join2(rulenames, t:get("rules")) @@ -381,13 +372,8 @@ function project._load_targets() if r:kind() == "target" then t._RULES[rulename] = r for _, deprule in ipairs(r:orderdeps()) do - local name = deprule:name() - if not t._RULES[name] then - t._RULES[name] = deprule - table.insert(t._ORDERULES, deprule) - end + t._RULES[deprule:name()] = deprule end - table.insert(t._ORDERULES, r) end else return nil, nil, string.format("unknown rule(%s) in target(%s)!", rulename, t:name()) -- cgit v1.3.1 From dae9a4fd5c1e75eb64d24c49261d2b4f42d0fbbe Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 27 Sep 2022 22:56:02 +0800 Subject: improve tests --- tests/apis/rules_inject_deps/xmake.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/apis/rules_inject_deps/xmake.lua b/tests/apis/rules_inject_deps/xmake.lua index 383789e0a..18a8fdeaa 100644 --- a/tests/apis/rules_inject_deps/xmake.lua +++ b/tests/apis/rules_inject_deps/xmake.lua @@ -5,9 +5,9 @@ rule("cppfront") rule:add("deps", "cppfront", {order = true}) target:rule_set("c++.build.modules.builder", rule) end) - before_build_files(function (target, batchjobs, sourcebatch, opt) + before_build_files(function (target, sourcebatch, opt) print("build cppfront files") - end, {batch = true}) + end) target("test") set_kind("binary") -- cgit v1.3.1 From fa198c5925c5faf00db7946a31db4e9fc611dc91 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 27 Sep 2022 23:03:28 +0800 Subject: improve rule test --- tests/apis/rules_inject_deps/src/hello.mpp | 10 ---------- tests/apis/rules_inject_deps/src/main.cpp | 9 ++++++--- tests/apis/rules_inject_deps/test.lua | 3 +++ tests/apis/rules_inject_deps/xmake.lua | 16 ++++++++++------ 4 files changed, 19 insertions(+), 19 deletions(-) delete mode 100644 tests/apis/rules_inject_deps/src/hello.mpp create mode 100644 tests/apis/rules_inject_deps/test.lua diff --git a/tests/apis/rules_inject_deps/src/hello.mpp b/tests/apis/rules_inject_deps/src/hello.mpp deleted file mode 100644 index 124bd72bc..000000000 --- a/tests/apis/rules_inject_deps/src/hello.mpp +++ /dev/null @@ -1,10 +0,0 @@ -module; -#include - -export module hello; - -export namespace hello { - void say(const char* str) { - printf("%s\n", str); - } -} diff --git a/tests/apis/rules_inject_deps/src/main.cpp b/tests/apis/rules_inject_deps/src/main.cpp index 1e5cc698f..db2361659 100644 --- a/tests/apis/rules_inject_deps/src/main.cpp +++ b/tests/apis/rules_inject_deps/src/main.cpp @@ -1,6 +1,9 @@ -import hello; +#include -int main() { - hello::say("hello module!"); +using namespace std; + +int main(int argc, char** argv) +{ + cout << "hello world!" << endl; return 0; } diff --git a/tests/apis/rules_inject_deps/test.lua b/tests/apis/rules_inject_deps/test.lua new file mode 100644 index 000000000..a750f2cf4 --- /dev/null +++ b/tests/apis/rules_inject_deps/test.lua @@ -0,0 +1,3 @@ +function main() + os.exec("xmake -j1") +end diff --git a/tests/apis/rules_inject_deps/xmake.lua b/tests/apis/rules_inject_deps/xmake.lua index 18a8fdeaa..6a11192cd 100644 --- a/tests/apis/rules_inject_deps/xmake.lua +++ b/tests/apis/rules_inject_deps/xmake.lua @@ -1,19 +1,23 @@ rule("cppfront") set_extensions(".cpp2") on_load(function (target) - local rule = target:rule("c++.build.modules.builder"):clone() + local rule = target:rule("c++.build"):clone() rule:add("deps", "cppfront", {order = true}) - target:rule_set("c++.build.modules.builder", rule) + target:rule_set("c++.build", rule) end) - before_build_files(function (target, sourcebatch, opt) - print("build cppfront files") + on_build_file(function (target, sourcefile, opt) + print("build cppfront file") + local objectfile = target:objectfile(sourcefile:gsub("cpp2", "cpp")) + assert(not os.isfile(objectfile), "invalid rule order!") end) target("test") set_kind("binary") add_rules("cppfront") - set_languages("c++20") add_files("src/*.cpp") - add_files("src/*.mpp") add_files("src/*.cpp2") + before_build_file(function (target, sourcefile, opt) + local objectfile = target:objectfile(sourcefile) + os.tryrm(objectfile) + end) -- cgit v1.3.1 From 96792611562600d3060d2f76b30b1c6dfda972e7 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 27 Sep 2022 23:05:58 +0800 Subject: improve rules_override --- tests/apis/rules_override_cxx/src/test.cc | 0 tests/apis/rules_override_cxx/test.lua | 3 +++ tests/apis/rules_override_cxx/xmake.lua | 21 +++++++++++---------- 3 files changed, 14 insertions(+), 10 deletions(-) create mode 100644 tests/apis/rules_override_cxx/src/test.cc create mode 100644 tests/apis/rules_override_cxx/test.lua diff --git a/tests/apis/rules_override_cxx/src/test.cc b/tests/apis/rules_override_cxx/src/test.cc new file mode 100644 index 000000000..e69de29bb diff --git a/tests/apis/rules_override_cxx/test.lua b/tests/apis/rules_override_cxx/test.lua new file mode 100644 index 000000000..a4a38b0ce --- /dev/null +++ b/tests/apis/rules_override_cxx/test.lua @@ -0,0 +1,3 @@ +function main() + os.exec("xmake") +end diff --git a/tests/apis/rules_override_cxx/xmake.lua b/tests/apis/rules_override_cxx/xmake.lua index 0dc2261ca..4b44d2111 100644 --- a/tests/apis/rules_override_cxx/xmake.lua +++ b/tests/apis/rules_override_cxx/xmake.lua @@ -1,8 +1,14 @@ -rule("xx.build") - set_base("c++.build") - set_extensions(".xx") +rule("xx") + add_deps("c++") on_load(function (target) - local sourcebatch = target:sourcebatches()["xx.build"] + + -- add .xx + local rule = target:rule("c++.build"):clone() + rule:set("extensions", ".xx") + target:rule_set("c++.build", rule) + + -- patch sourcebatch for .xx + local sourcebatch = target:sourcebatches()["c++.build"] sourcebatch.sourcekind = "cxx" sourcebatch.objectfiles = {} sourcebatch.dependfiles = {} @@ -12,15 +18,10 @@ rule("xx.build") table.insert(sourcebatch.objectfiles, objectfile) table.insert(sourcebatch.dependfiles, dependfile) end - target:add("cxxflags", "-x c++") end) -rule("xx") - set_base("c++") - add_deps("xx.build") - target("test") set_kind("binary") add_rules("xx") - add_files("src/*.xx") + add_files("src/*.xx", "src/*.cc") -- cgit v1.3.1 From b1dd0bd59f5d35717b2493a45bf5a0274fed2a9a Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 27 Sep 2022 23:27:12 +0800 Subject: remove unity test.cpp --- tests/projects/c++/unity_build/src/test.cpp | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 tests/projects/c++/unity_build/src/test.cpp diff --git a/tests/projects/c++/unity_build/src/test.cpp b/tests/projects/c++/unity_build/src/test.cpp deleted file mode 100644 index 27d41ee50..000000000 --- a/tests/projects/c++/unity_build/src/test.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include "header.h" - -int main(int argc, char** argv) -{ - std::string s("xmake"); - printf("hello %s!\n", s.c_str()); - return 0; -} -- cgit v1.3.1 From 89a12a21daf519d0f9d9cb5846dfe7c4835c97b5 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 27 Sep 2022 23:32:17 +0800 Subject: fix tests --- tests/apis/rules_override_cxx/xmake.lua | 7 +++++++ xmake/core/project/rule.lua | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/tests/apis/rules_override_cxx/xmake.lua b/tests/apis/rules_override_cxx/xmake.lua index 4b44d2111..812680ef0 100644 --- a/tests/apis/rules_override_cxx/xmake.lua +++ b/tests/apis/rules_override_cxx/xmake.lua @@ -18,6 +18,13 @@ rule("xx") table.insert(sourcebatch.objectfiles, objectfile) table.insert(sourcebatch.dependfiles, dependfile) end + + -- force as c++ source file + if target:is_plat("windows") then + target:add("cxxflags", "/TP") + else + target:add("cxxflags", "-x c++") + end end) target("test") diff --git a/xmake/core/project/rule.lua b/xmake/core/project/rule.lua index c3403a197..52b8e9ff9 100644 --- a/xmake/core/project/rule.lua +++ b/xmake/core/project/rule.lua @@ -67,13 +67,13 @@ function _instance:get(name) return self._INFO:get(name) end --- set the value to the package info +-- set the value to the rule info function _instance:set(name, ...) self._INFO:apival_set(name, ...) self:_invalidate(name) end --- add the value to the package info +-- add the value to the rule info function _instance:add(name, ...) self._INFO:apival_add(name, ...) self:_invalidate(name) -- cgit v1.3.1 From a1d3d4633fcbe0d112952f5d0ea111570ce3876f Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 27 Sep 2022 23:53:57 +0800 Subject: improve rule api --- tests/apis/clone_target/src/main.cpp | 9 +++++++++ tests/apis/clone_target/test.lua | 3 +++ tests/apis/clone_target/xmake.lua | 7 +++++++ tests/apis/rules_inject_deps/xmake.lua | 2 +- xmake/core/project/rule.lua | 5 +++++ xmake/core/project/target.lua | 4 ++-- 6 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 tests/apis/clone_target/src/main.cpp create mode 100644 tests/apis/clone_target/test.lua create mode 100644 tests/apis/clone_target/xmake.lua diff --git a/tests/apis/clone_target/src/main.cpp b/tests/apis/clone_target/src/main.cpp new file mode 100644 index 000000000..db2361659 --- /dev/null +++ b/tests/apis/clone_target/src/main.cpp @@ -0,0 +1,9 @@ +#include + +using namespace std; + +int main(int argc, char** argv) +{ + cout << "hello world!" << endl; + return 0; +} diff --git a/tests/apis/clone_target/test.lua b/tests/apis/clone_target/test.lua new file mode 100644 index 000000000..a4a38b0ce --- /dev/null +++ b/tests/apis/clone_target/test.lua @@ -0,0 +1,3 @@ +function main() + os.exec("xmake") +end diff --git a/tests/apis/clone_target/xmake.lua b/tests/apis/clone_target/xmake.lua new file mode 100644 index 000000000..4aa01b034 --- /dev/null +++ b/tests/apis/clone_target/xmake.lua @@ -0,0 +1,7 @@ +target("test") + set_kind("binary") + add_files("src/*.cpp") + after_load(function (target) + --target:clone() + end) + diff --git a/tests/apis/rules_inject_deps/xmake.lua b/tests/apis/rules_inject_deps/xmake.lua index 6a11192cd..cf73449bb 100644 --- a/tests/apis/rules_inject_deps/xmake.lua +++ b/tests/apis/rules_inject_deps/xmake.lua @@ -3,7 +3,7 @@ rule("cppfront") on_load(function (target) local rule = target:rule("c++.build"):clone() rule:add("deps", "cppfront", {order = true}) - target:rule_set("c++.build", rule) + target:rule_add(rule) end) on_build_file(function (target, sourcefile, opt) print("build cppfront file") diff --git a/xmake/core/project/rule.lua b/xmake/core/project/rule.lua index 52b8e9ff9..155f96754 100644 --- a/xmake/core/project/rule.lua +++ b/xmake/core/project/rule.lua @@ -89,6 +89,11 @@ function _instance:name() return self._NAME end +-- set the rule name +function _instance:name_set(name) + self._NAME = name +end + -- get the rule kind -- -- current supported kind: diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index 4e5f150be..f0e519384 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -713,9 +713,9 @@ function _instance:rule(name) end -- set rule -function _instance:rule_set(name, ruleinst) +function _instance:rule_add(r) self._RULES = self._RULES or {} - self._RULES[name] = ruleinst + self._RULES[r:name()] = r self._ORDERULES = nil end -- cgit v1.3.1 From 309a51cb9692851e30ed9cf44f8e33b34976332c Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 27 Sep 2022 23:57:20 +0800 Subject: clone target --- tests/apis/clone_target/xmake.lua | 6 +++- xmake/core/base/table.lua | 14 +++++++++- xmake/core/project/project.lua | 6 +++- xmake/core/project/target.lua | 32 ++++++++++++++++++++-- .../modules/import/core/project/project.lua | 1 + 5 files changed, 54 insertions(+), 5 deletions(-) diff --git a/tests/apis/clone_target/xmake.lua b/tests/apis/clone_target/xmake.lua index 4aa01b034..4def46283 100644 --- a/tests/apis/clone_target/xmake.lua +++ b/tests/apis/clone_target/xmake.lua @@ -2,6 +2,10 @@ target("test") set_kind("binary") add_files("src/*.cpp") after_load(function (target) - --target:clone() + import("core.project.project") + local t = target:clone() + t:name_set("test2") + t:add("defines", "TEST2") + project.target_add(t) end) diff --git a/xmake/core/base/table.lua b/xmake/core/base/table.lua index b3e8840e3..5e04b0256 100644 --- a/xmake/core/base/table.lua +++ b/xmake/core/base/table.lua @@ -153,7 +153,19 @@ function table.append(array, ...) return array end --- copy the table to self +-- clone table +function table.clone(self) + local result + if type(self) == "table" then + result = {} + for k, v in pairs(self) do + result[k] = v + end + end + return result +end + +-- copy the table (deprecated, please use table.clone) function table.copy(copied) local result = {} copied = copied or {} diff --git a/xmake/core/project/project.lua b/xmake/core/project/project.lua index d0f0145df..73ff45332 100644 --- a/xmake/core/project/project.lua +++ b/xmake/core/project/project.lua @@ -340,7 +340,7 @@ function project._load_targets() -- make targets local targets = {} for targetname, targetinfo in pairs(results) do - local t = target.new(targetname, targetinfo, project) + local t = target.new(targetname, targetinfo) if t and (t:get("enabled") == nil or t:get("enabled") == true) then targets[targetname] = t end @@ -898,6 +898,10 @@ function project.target(name) return targets and targets[name] end +-- add the given target +function project.target_add(t) +end + -- get targets function project.targets() local targets = project._memcache():get("targets") diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index f0e519384..8365c50ff 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -48,11 +48,10 @@ local sandbox = require("sandbox/sandbox") local sandbox_module = require("sandbox/modules/import/core/sandbox/module") -- new a target instance -function _instance.new(name, info, project) +function _instance.new(name, info) local instance = table.inherit(_instance) instance._NAME = name instance._INFO = info - instance._PROJECT = project instance._CACHEID = 1 return instance end @@ -283,6 +282,30 @@ function _instance:_is_loaded() return self._LOADED end +-- clone target +function _instance:clone() + local instance = target.new(self:name(), self._INFO:clone()) + if self._DEPS then + instance._DEPS = table.clone(self._DEPS) + end + if self._ORDERDEPS then + instance._ORDERDEPS = table.clone(self._ORDERDEPS) + end + if self._RULES then + instance._RULES = table.clone(self._RULES) + end + if self._ORDERULES then + instance._ORDERULES = table.clone(self._ORDERULES) + end + if self._DATA then + instance._DATA = table.clone(self._DATA) + end + if self._SOURCEFILES then + instance._SOURCEFILES = table.clone(self._SOURCEFILES) + end + return instance +end + -- get the target info -- -- e.g. @@ -491,6 +514,11 @@ function _instance:name() return self._NAME end +-- set the target name +function _instance:name_set(name) + self._NAME = name +end + -- get the target kind function _instance:kind() return self:get("kind") or "binary" diff --git a/xmake/core/sandbox/modules/import/core/project/project.lua b/xmake/core/sandbox/modules/import/core/project/project.lua index 46c9b973d..a5778bc9e 100644 --- a/xmake/core/sandbox/modules/import/core/project/project.lua +++ b/xmake/core/sandbox/modules/import/core/project/project.lua @@ -43,6 +43,7 @@ sandbox_core_project.rules = project.rules sandbox_core_project.toolchain = project.toolchain sandbox_core_project.toolchains = project.toolchains sandbox_core_project.target = project.target +sandbox_core_project.target_add = project.target_add sandbox_core_project.targets = project.targets sandbox_core_project.ordertargets = project.ordertargets sandbox_core_project.option = project.option -- cgit v1.3.1 From 387559affcc0239182e51101c67278e989a655e5 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 28 Sep 2022 00:38:51 +0800 Subject: fix tests --- tests/apis/rules_override_cxx/xmake.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/apis/rules_override_cxx/xmake.lua b/tests/apis/rules_override_cxx/xmake.lua index 812680ef0..564a55989 100644 --- a/tests/apis/rules_override_cxx/xmake.lua +++ b/tests/apis/rules_override_cxx/xmake.lua @@ -5,7 +5,7 @@ rule("xx") -- add .xx local rule = target:rule("c++.build"):clone() rule:set("extensions", ".xx") - target:rule_set("c++.build", rule) + target:rule_add(rule) -- patch sourcebatch for .xx local sourcebatch = target:sourcebatches()["c++.build"] -- cgit v1.3.1 From 4a67a67c0535f465dec6d1054579d3960ed057bf Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 28 Sep 2022 00:55:57 +0800 Subject: clone and add targets --- tests/apis/clone_target/xmake.lua | 10 +++ xmake/core/base/scopeinfo.lua | 2 +- xmake/core/project/project.lua | 73 ++++++++-------------- xmake/core/project/target.lua | 27 +++++++- .../modules/import/core/project/project.lua | 45 +++++++++++++ 5 files changed, 109 insertions(+), 48 deletions(-) diff --git a/tests/apis/clone_target/xmake.lua b/tests/apis/clone_target/xmake.lua index 4def46283..13d460eeb 100644 --- a/tests/apis/clone_target/xmake.lua +++ b/tests/apis/clone_target/xmake.lua @@ -1,11 +1,21 @@ target("test") set_kind("binary") add_files("src/*.cpp") + add_defines("TEST") after_load(function (target) import("core.project.project") local t = target:clone() t:name_set("test2") + t:add("deps", "test") t:add("defines", "TEST2") + t:set("link_before", function (target) + print("link1", target:name()) + assert(target:dep("test"):data("linked")) + end) project.target_add(t) end) + before_link(function (target) + print("link2", target:name()) + target:data_set("linked", true) + end) diff --git a/xmake/core/base/scopeinfo.lua b/xmake/core/base/scopeinfo.lua index ef15fc2e1..f6dd7d475 100644 --- a/xmake/core/base/scopeinfo.lua +++ b/xmake/core/base/scopeinfo.lua @@ -666,7 +666,7 @@ end -- clone a new instance from the current function _instance:clone() - return _instance.new(self:kind(), self:info(), {interpreter = self:interpreter(), deduplicate = self._DEDUPLICATE, enable_filter = self._ENABLE_FILTER}) + return _instance.new(self:kind(), table.clone(self:info()), {interpreter = self:interpreter(), deduplicate = self._DEDUPLICATE, enable_filter = self._ENABLE_FILTER}) end -- new a scope instance diff --git a/xmake/core/project/project.lua b/xmake/core/project/project.lua index 73ff45332..2c18a6c95 100644 --- a/xmake/core/project/project.lua +++ b/xmake/core/project/project.lua @@ -328,13 +328,13 @@ function project._load_targets() local requires = project.required_packages() local ok, errors = project._load(true) if not ok then - return nil, nil, errors + return nil, errors end -- load targets local results, errors = project._load_scope("target", true, true) if not results then - return nil, nil, errors + return nil, errors end -- make targets @@ -376,44 +376,24 @@ function project._load_targets() end end else - return nil, nil, string.format("unknown rule(%s) in target(%s)!", rulename, t:name()) + return nil, string.format("unknown rule(%s) in target(%s)!", rulename, t:name()) end end -- @note it's deprecated, please use on_load instead of before_load ok, errors = t:_load_before() if not ok then - return nil, nil, errors + return nil, errors end -- we need call on_load() before building deps/rules, -- so we can use `target:add("deps", "xxx")` to add deps in on_load ok, errors = t:_load() if not ok then - return nil, nil, errors - end - - -- load deps - t._DEPS = t._DEPS or {} - t._ORDERDEPS = t._ORDERDEPS or {} - instance_deps.load_deps(t, targets, t._DEPS, t._ORDERDEPS, {t:name()}) - end - - -- sort targets for all deps - local targetrefs = {} - local ordertargets = {} - for _, t in pairs(targets) do - project._sort_targets(targets, ordertargets, targetrefs, t) - end - - -- do after_load() for targets - for _, t in ipairs(ordertargets) do - ok, errors = t:_load_after() - if not ok then - return nil, nil, errors + return nil, errors end end - return targets, ordertargets + return targets end -- load options @@ -549,20 +529,6 @@ function project._load_packages() return project._load_scope("package", true, false) end --- sort targets for all deps -function project._sort_targets(targets, ordertargets, targetrefs, target) - for _, depname in ipairs(table.wrap(target:get("deps"))) do - local targetinst = targets[depname] - if targetinst then - project._sort_targets(targets, ordertargets, targetrefs, targetinst) - end - end - if not targetrefs[target:name()] then - targetrefs[target:name()] = true - table.insert(ordertargets, target) - end -end - -- get project memcache function project._memcache() return memcache.cache("core.project.project") @@ -900,19 +866,23 @@ end -- add the given target function project.target_add(t) + local targets = project.targets() + if targets then + targets[t:name()] = t + project._memcache():set("ordertargets", nil) + end end -- get targets function project.targets() local targets = project._memcache():get("targets") if not targets then - local ordertargets, errors - targets, ordertargets, errors = project._load_targets() + local errors + targets, errors = project._load_targets() if errors then os.raise(errors) end project._memcache():set("targets", targets) - project._memcache():set("ordertargets", ordertargets) end return targets end @@ -921,9 +891,20 @@ end function project.ordertargets() local ordertargets = project._memcache():get("ordertargets") if not ordertargets then - -- ensure ordertargets to be cached - project.targets() - ordertargets = project._memcache():get("ordertargets") + local targets = project.targets() + ordertargets = {} + local targets_unique = {} + for _, t in pairs(targets) do + for _, dep in ipairs(t:orderdeps()) do + local name = dep:name() + if not targets_unique[name] then + targets_unique[name] = dep + table.insert(ordertargets, dep) + end + end + table.insert(ordertargets, t) + end + project._memcache():set("ordertargets", ordertargets) end return ordertargets end diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index 8365c50ff..f1b04a0e4 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -31,6 +31,7 @@ local table = require("base/table") local baseoption = require("base/option") local hashset = require("base/hashset") local deprecated = require("base/deprecated") +local instance_deps = require("base/private/instance_deps") local memcache = require("cache/memcache") local rule = require("project/rule") local option = require("project/option") @@ -274,6 +275,19 @@ function _instance:_invalidate(name) -- we need flush the source files cache if target/files are modified, e.g. `target:add("files", "xxx.c")` if name == "files" then self._SOURCEFILES = nil + elseif name == "deps" then + self._DEPS = nil + self._ORDERDEPS = nil + end +end + +-- build deps +function _instance:_build_deps() + if target._project() then + local instances = target._project().targets() + self._DEPS = self._DEPS or {} + self._ORDERDEPS = self._ORDERDEPS or {} + instance_deps.load_deps(self, instances, self._DEPS, self._ORDERDEPS, {self:name()}) end end @@ -282,8 +296,11 @@ function _instance:_is_loaded() return self._LOADED end --- clone target +-- clone target, @note we can just call it in after_load() function _instance:clone() + if not self:_is_loaded() or self._LOADED_AFTER then + os.raise("please call target:clone() in after_load().", self:name()) + end local instance = target.new(self:name(), self._INFO:clone()) if self._DEPS then instance._DEPS = table.clone(self._DEPS) @@ -303,6 +320,8 @@ function _instance:clone() if self._SOURCEFILES then instance._SOURCEFILES = table.clone(self._SOURCEFILES) end + instance._LOADED = self._LOADED + instance._LOADED_AFTER = true return instance end @@ -695,6 +714,9 @@ function _instance:deps() if not self:_is_loaded() then os.raise("please call target:deps() or target:dep() in after_load()!") end + if self._DEPS == nil then + self:_build_deps() + end return self._DEPS end @@ -703,6 +725,9 @@ function _instance:orderdeps() if not self:_is_loaded() then os.raise("please call target:orderdeps() in after_load()!") end + if self._DEPS == nil then + self:_build_deps() + end return self._ORDERDEPS end diff --git a/xmake/core/sandbox/modules/import/core/project/project.lua b/xmake/core/sandbox/modules/import/core/project/project.lua index a5778bc9e..b1d1101ba 100644 --- a/xmake/core/sandbox/modules/import/core/project/project.lua +++ b/xmake/core/sandbox/modules/import/core/project/project.lua @@ -71,6 +71,24 @@ sandbox_core_project.tmpdir = project.tmpdir sandbox_core_project.tmpfile = project.tmpfile sandbox_core_project.is_loaded = project.is_loaded +-- load project targets +function sandbox_core_project._load_targets() + local loaded = sandbox_core_project._TARGETS_LOADED + if not loaded then + -- do after_load() for targets + -- @note we cannot call it in project.targets(), + -- because we maybe will call project.targets() in after_load + for _, t in ipairs(project.ordertargets()) do + local ok, errors = t:_load_after() + if not ok then + return false, errors + end + end + sandbox_core_project._TARGETS_LOADED = true + end + return true +end + -- check project options function sandbox_core_project.check() @@ -171,5 +189,32 @@ function sandbox_core_project.chdir(projectdir, projectfile) config._DIRECTORY = nil end +-- get project target +function sandbox_core_project.target(name) + local ok, errors = sandbox_core_project._load_targets() + if not ok then + raise(errors) + end + return project.target(name) +end + +-- get project targets +function sandbox_core_project.targets() + local ok, errors = sandbox_core_project._load_targets() + if not ok then + raise(errors) + end + return project.targets() +end + +-- get project order targets +function sandbox_core_project.ordertargets() + local ok, errors = sandbox_core_project._load_targets() + if not ok then + raise(errors) + end + return project.ordertargets() +end + -- return module return sandbox_core_project -- cgit v1.3.1 From 39237af067f83918549427b27e95b0f479984e47 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 28 Sep 2022 22:38:12 +0800 Subject: fix rule --- xmake/actions/build/kinds/object.lua | 17 +++++++++-------- xmake/core/base/private/instance_deps.lua | 17 ++++++++++++++++- xmake/core/project/project.lua | 13 +++---------- xmake/core/project/target.lua | 16 ++++++---------- 4 files changed, 34 insertions(+), 29 deletions(-) diff --git a/xmake/actions/build/kinds/object.lua b/xmake/actions/build/kinds/object.lua index 0498cf0d7..01fbb5a05 100644 --- a/xmake/actions/build/kinds/object.lua +++ b/xmake/actions/build/kinds/object.lua @@ -27,21 +27,22 @@ import("private.async.runjobs") import("private.utils.batchcmds") -- get rule -function _get_rule(rulename) - local ruleinst = assert(project.rule(rulename) or rule.rule(rulename), "unknown rule: %s", rulename) +-- @note we need get rule from target first, because we maybe will inject and replace builtin rule in target +function _get_rule(target, rulename) + local ruleinst = assert(target:rule(rulename) or project.rule(rulename) or rule.rule(rulename), "unknown rule: %s", rulename) return ruleinst end -- get max depth of rule -function _get_rule_max_depth(ruleinst, depth) +function _get_rule_max_depth(target, ruleinst, depth) local max_depth = depth for _, depname in ipairs(ruleinst:get("deps")) do - local dep = _get_rule(depname) + local dep = _get_rule(target, depname) local dep_depth = depth if ruleinst:extraconf("deps", depname, "order") then dep_depth = dep_depth + 1 end - local cur_depth = _get_rule_max_depth(dep, dep_depth) + local cur_depth = _get_rule_max_depth(target, dep, dep_depth) if cur_depth > max_depth then max_depth = cur_depth end @@ -113,7 +114,7 @@ function _add_batchjobs_for_rule(batchjobs, rootjob, target, sourcebatch, suffix -- get rule local rulename = assert(sourcebatch.rulename, "unknown rule for sourcebatch!") - local ruleinst = _get_rule(rulename) + local ruleinst = _get_rule(target, rulename) -- add batch jobs for xx_build_files local scriptname = "build_files" .. (suffix and ("_" .. suffix) or "") @@ -233,8 +234,8 @@ end function _build_sourcebatch_groups_for_rules(groups, target, sourcebatches) for _, sourcebatch in pairs(sourcebatches) do local rulename = assert(sourcebatch.rulename, "unknown rule for sourcebatch!") - local ruleinst = _get_rule(rulename) - local depth = _get_rule_max_depth(ruleinst, 1) + local ruleinst = _get_rule(target, rulename) + local depth = _get_rule_max_depth(target, ruleinst, 1) local group = groups[depth] if group == nil then group = {} diff --git a/xmake/core/base/private/instance_deps.lua b/xmake/core/base/private/instance_deps.lua index 7a5d9aada..535b2d2bb 100644 --- a/xmake/core/base/private/instance_deps.lua +++ b/xmake/core/base/private/instance_deps.lua @@ -24,8 +24,9 @@ local instance_deps = instance_deps or {} -- load modules local option = require("base/option") local string = require("base/string") +local table = require("base/table") --- load deps for instance: e.g. option, target and rule +-- load deps for instance: e.g. option, instance and rule -- -- e.g. -- @@ -58,5 +59,19 @@ function instance_deps.load_deps(instance, instances, deps, orderdeps, depspath) end end +-- sort instances for all deps +function instance_deps.sort_deps(instances, orderinstances, instancerefs, instance) + for _, depname in ipairs(table.wrap(instance:get("deps"))) do + local instanceinst = instances[depname] + if instanceinst then + instance_deps.sort_deps(instances, orderinstances, instancerefs, instanceinst) + end + end + if not instancerefs[instance:name()] then + instancerefs[instance:name()] = true + table.insert(orderinstances, instance) + end +end + -- return module return instance_deps diff --git a/xmake/core/project/project.lua b/xmake/core/project/project.lua index 2c18a6c95..40ae3a74f 100644 --- a/xmake/core/project/project.lua +++ b/xmake/core/project/project.lua @@ -864,7 +864,7 @@ function project.target(name) return targets and targets[name] end --- add the given target +-- add the given target, @note if the target name is the same, it will be replaced function project.target_add(t) local targets = project.targets() if targets then @@ -893,16 +893,9 @@ function project.ordertargets() if not ordertargets then local targets = project.targets() ordertargets = {} - local targets_unique = {} + local targetrefs = {} for _, t in pairs(targets) do - for _, dep in ipairs(t:orderdeps()) do - local name = dep:name() - if not targets_unique[name] then - targets_unique[name] = dep - table.insert(ordertargets, dep) - end - end - table.insert(ordertargets, t) + instance_deps.sort_deps(targets, ordertargets, targetrefs, t) end project._memcache():set("ordertargets", ordertargets) end diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index f1b04a0e4..1c6914743 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -742,16 +742,9 @@ function _instance:orderules() local orderules = self._ORDERULES if orderules == nil and rules then orderules = {} - local rules_unique = {} + local rulerefs = {} for _, r in pairs(rules) do - for _, deprule in ipairs(r:orderdeps()) do - local name = deprule:name() - if not rules_unique[name] then - rules_unique[name] = deprule - table.insert(orderules, deprule) - end - end - table.insert(orderules, r) + instance_deps.sort_deps(rules, orderules, rulerefs, r) end self._ORDERULES = orderules end @@ -765,7 +758,10 @@ function _instance:rule(name) end end --- set rule +-- add rule +-- +-- @note If a rule has the same name as a built-in rule, +-- it will be replaced in the target:rules() and target:orderules(), but will be not replaced globally in the project.rules() function _instance:rule_add(r) self._RULES = self._RULES or {} self._RULES[r:name()] = r -- cgit v1.3.1 From 82bfc71e7810157e8f71d43d4a2d82b609c17bf9 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 28 Sep 2022 23:32:11 +0800 Subject: improve to load targets --- xmake/core/project/project.lua | 13 +++++++ .../modules/import/core/project/project.lua | 45 ---------------------- 2 files changed, 13 insertions(+), 45 deletions(-) diff --git a/xmake/core/project/project.lua b/xmake/core/project/project.lua index 40ae3a74f..e47463a89 100644 --- a/xmake/core/project/project.lua +++ b/xmake/core/project/project.lua @@ -875,6 +875,7 @@ end -- get targets function project.targets() + local loading = false local targets = project._memcache():get("targets") if not targets then local errors @@ -883,6 +884,18 @@ function project.targets() os.raise(errors) end project._memcache():set("targets", targets) + loading = true + end + if loading then + -- do after_load() for targets + -- @note we must call it after finishing to cache targets + -- because we maybe will call project.targets() in after_load, we need avoid dead recursion loop + for _, t in ipairs(project.ordertargets()) do + local ok, errors = t:_load_after() + if not ok then + os.raise(errors or string.format("load target %s failed", t:name())) + end + end end return targets end diff --git a/xmake/core/sandbox/modules/import/core/project/project.lua b/xmake/core/sandbox/modules/import/core/project/project.lua index b1d1101ba..a5778bc9e 100644 --- a/xmake/core/sandbox/modules/import/core/project/project.lua +++ b/xmake/core/sandbox/modules/import/core/project/project.lua @@ -71,24 +71,6 @@ sandbox_core_project.tmpdir = project.tmpdir sandbox_core_project.tmpfile = project.tmpfile sandbox_core_project.is_loaded = project.is_loaded --- load project targets -function sandbox_core_project._load_targets() - local loaded = sandbox_core_project._TARGETS_LOADED - if not loaded then - -- do after_load() for targets - -- @note we cannot call it in project.targets(), - -- because we maybe will call project.targets() in after_load - for _, t in ipairs(project.ordertargets()) do - local ok, errors = t:_load_after() - if not ok then - return false, errors - end - end - sandbox_core_project._TARGETS_LOADED = true - end - return true -end - -- check project options function sandbox_core_project.check() @@ -189,32 +171,5 @@ function sandbox_core_project.chdir(projectdir, projectfile) config._DIRECTORY = nil end --- get project target -function sandbox_core_project.target(name) - local ok, errors = sandbox_core_project._load_targets() - if not ok then - raise(errors) - end - return project.target(name) -end - --- get project targets -function sandbox_core_project.targets() - local ok, errors = sandbox_core_project._load_targets() - if not ok then - raise(errors) - end - return project.targets() -end - --- get project order targets -function sandbox_core_project.ordertargets() - local ok, errors = sandbox_core_project._load_targets() - if not ok then - raise(errors) - end - return project.ordertargets() -end - -- return module return sandbox_core_project -- cgit v1.3.1