diff options
| author | ruki <[email protected]> | 2016-04-11 14:08:47 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2016-04-11 14:08:47 +0800 |
| commit | 833bfb207b3f924eaa81feb496cf74e6223d0041 (patch) | |
| tree | 0b1774ba14cbe63ecb6eb347deea19975f2c8554 | |
| parent | 71296f55db2d5b0a9249592c3428797708cd0683 (diff) | |
add new tool module
| -rw-r--r-- | xmake/core/base/deprecated/interpreter.lua | 2 | ||||
| -rw-r--r-- | xmake/core/base/filter.lua | 14 | ||||
| -rw-r--r-- | xmake/core/base/interpreter.lua | 2 | ||||
| -rw-r--r-- | xmake/core/project/project.lua | 2 | ||||
| -rw-r--r-- | xmake/core/project/task.lua | 7 | ||||
| -rw-r--r-- | xmake/core/project/template.lua | 2 | ||||
| -rw-r--r--[-rwxr-xr-x] | xmake/core/sandbox/modules/_g.lua (renamed from xmake/tools/gcc.lua) | 4 | ||||
| -rw-r--r-- | xmake/core/sandbox/modules/import.lua | 23 | ||||
| -rw-r--r-- | xmake/core/sandbox/sandbox.lua | 43 | ||||
| -rw-r--r-- | xmake/core/tool/tool.lua | 237 | ||||
| -rwxr-xr-x | xmake/tools/compiler/gcc.lua | 119 |
11 files changed, 413 insertions, 42 deletions
diff --git a/xmake/core/base/deprecated/interpreter.lua b/xmake/core/base/deprecated/interpreter.lua index 22e0cde00..ec06d8866 100644 --- a/xmake/core/base/deprecated/interpreter.lua +++ b/xmake/core/base/deprecated/interpreter.lua @@ -122,7 +122,7 @@ function deprecated_interpreter:api_register_set_script(scope_kind, prefix, ...) utils.warning("please uses on_%s(), \"set_%s()\" has been deprecated!", name, name, scope) -- make sandbox instance with the given script - local instance, errors = sandbox.new(script, self) + local instance, errors = sandbox.new(script, self:filter(), self:rootdir()) if not instance then os.raise("set_%s(): %s", name, errors) end diff --git a/xmake/core/base/filter.lua b/xmake/core/base/filter.lua index a23bc25a4..7a77a98a1 100644 --- a/xmake/core/base/filter.lua +++ b/xmake/core/base/filter.lua @@ -29,18 +29,14 @@ local table = require("base/table") local utils = require("base/utils") local string = require("base/string") --- init filter -function filter.init(handler) +-- new filter instance +function filter.new(handler) -- init an filter instance - local self = {_HANDLER = handler} + local self = table.inherit(filter) - -- inherit the interfaces of filter - for k, v in pairs(filter) do - if type(v) == "function" then - self[k] = v - end - end + -- save handler + self._HANDLER = handler -- ok return self diff --git a/xmake/core/base/interpreter.lua b/xmake/core/base/interpreter.lua index 97be6a9e7..47b4d02a7 100644 --- a/xmake/core/base/interpreter.lua +++ b/xmake/core/base/interpreter.lua @@ -742,7 +742,7 @@ function interpreter:api_register_on_script(scope_kind, prefix, ...) local implementation = function (self, scope, name, script) -- make sandbox instance with the given script - local instance, errors = sandbox.new(script, self) + local instance, errors = sandbox.new(script, self:filter(), self:rootdir()) if not instance then os.raise("on_%s(): %s", name, errors) end diff --git a/xmake/core/project/project.lua b/xmake/core/project/project.lua index 9bcbec092..52e9c4b8e 100644 --- a/xmake/core/project/project.lua +++ b/xmake/core/project/project.lua @@ -442,7 +442,7 @@ function project._interpreter() interp:api_register("add_pkgs", interpreter.api_builtin_add_subdirs) -- set filter - interp:filter_set(filter.init(function (variable) + interp:filter_set(filter.new(function (variable) -- check assert(variable) diff --git a/xmake/core/project/task.lua b/xmake/core/project/task.lua index 22cee9714..98cf00454 100644 --- a/xmake/core/project/task.lua +++ b/xmake/core/project/task.lua @@ -175,7 +175,7 @@ function task._interpreter() , "before") -- set filter - interp:filter_set(filter.init(function (variable) + interp:filter_set(filter.new(function (variable) -- check assert(variable) @@ -188,6 +188,7 @@ function task._interpreter() local maps = { host = xmake._HOST + , nuldev = xmake._NULDEV , tmpdir = os.tmpdir() , curdir = os.curdir() , globaldir = global.directory() @@ -239,7 +240,7 @@ function task._bind(tasks) if type(opt) == "function" then -- make sandbox instance with the given script - local instance, errors = sandbox.new(opt, interp) + local instance, errors = sandbox.new(opt, interp:filter(), interp:rootdir()) if not instance then return false, errors end @@ -271,7 +272,7 @@ function task._bind(tasks) if type(description) == "function" then -- make sandbox instance with the given script - local instance, errors = sandbox.new(description, interp) + local instance, errors = sandbox.new(description, interp:filter(), interp:rootdir()) if not instance then return false, errors end diff --git a/xmake/core/project/template.lua b/xmake/core/project/template.lua index 30ee76952..4ed035fd9 100644 --- a/xmake/core/project/template.lua +++ b/xmake/core/project/template.lua @@ -171,7 +171,7 @@ function template.create(language, templateid, targetname) assert(interp) -- set filter - interp:filter_set(filter.init(function (variable) + interp:filter_set(filter.new(function (variable) -- init maps local maps = diff --git a/xmake/tools/gcc.lua b/xmake/core/sandbox/modules/_g.lua index c1e1b9622..124f65c61 100755..100644 --- a/xmake/tools/gcc.lua +++ b/xmake/core/sandbox/modules/_g.lua @@ -17,7 +17,9 @@ -- Copyright (C) 2015 - 2016, ruki All rights reserved. -- -- @author ruki --- @file gcc.lua +-- @file _g.lua -- +-- return new instance +return {} diff --git a/xmake/core/sandbox/modules/import.lua b/xmake/core/sandbox/modules/import.lua index 2b423613c..2a01f7282 100644 --- a/xmake/core/sandbox/modules/import.lua +++ b/xmake/core/sandbox/modules/import.lua @@ -69,27 +69,8 @@ function sandbox_import._loadfile(filepath, instance) return nil, errors end - -- backup the scope variables first - local scope_public = getfenv(instance:script()) - local scope_backup = {} - table.copy2(scope_backup, scope_public) - - -- load module with sandbox - local ok, errors = sandbox.load(instance:script()) - if not ok then - return nil, errors - end - - -- only export new public functions - local result = {} - for k, v in pairs(scope_public) do - if type(v) == "function" and not k:startswith("_") and scope_backup[k] == nil then - result[k] = v - end - end - - -- get module - return result + -- import module + return instance:import() end -- load module without sandbox diff --git a/xmake/core/sandbox/sandbox.lua b/xmake/core/sandbox/sandbox.lua index 880e803e4..c4da87b05 100644 --- a/xmake/core/sandbox/sandbox.lua +++ b/xmake/core/sandbox/sandbox.lua @@ -151,10 +151,10 @@ function sandbox._new() end -- new a sandbox instance with the given script -function sandbox.new(script, interp) +function sandbox.new(script, filter, rootdir) -- check - assert(script and interp) + assert(script) -- new instance local self = sandbox._new() @@ -163,10 +163,10 @@ function sandbox.new(script, interp) assert(self and self._PUBLIC and self._PRIVATE) -- save filter - self._PRIVATE._FILTER = interp:filter() + self._PRIVATE._FILTER = filter -- save root directory - self._PRIVATE._ROOTDIR = interp:rootdir() + self._PRIVATE._ROOTDIR = rootdir -- this script is module name? import it first if type(script) == "string" then @@ -242,6 +242,41 @@ function sandbox:fork(script) return instance end +-- load script and import module +function sandbox:import() + + -- this module has been imported? + if self._PRIVATE._MODULE then + return self._PRIVATE._MODULE + end + + -- backup the scope variables first + local scope_public = getfenv(self:script()) + local scope_backup = {} + table.copy2(scope_backup, scope_public) + + -- load module with sandbox + local ok, errors = sandbox.load(self:script()) + if not ok then + return nil, errors + end + + -- only export new public functions + local module = {} + for k, v in pairs(scope_public) do + if type(v) == "function" and not k:startswith("_") and scope_backup[k] == nil then + module[k] = v + end + end + + -- save module + self._PRIVATE._MODULE = module + + -- ok + return module + +end + -- get script from the given sandbox function sandbox:script() diff --git a/xmake/core/tool/tool.lua b/xmake/core/tool/tool.lua new file mode 100644 index 000000000..4a4a1db26 --- /dev/null +++ b/xmake/core/tool/tool.lua @@ -0,0 +1,237 @@ +--!The Automatic Cross-platform Build Tool +-- +-- XMake is free software; you can redistribute it and/or modify +-- it under the terms of the GNU Lesser General Public License as published by +-- the Free Software Foundation; either version 2.1 of the License, or +-- (at your option) any later version. +-- +-- XMake is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU Lesser General Public License +-- along with XMake; +-- If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a> +-- +-- Copyright (C) 2015 - 2016, ruki All rights reserved. +-- +-- @author ruki +-- @file tool.lua +-- + +-- define module: tool +local tool = tool or {} + +-- load modules +local os = require("base/os") +local path = require("base/path") +local utils = require("base/utils") +local string = require("base/string") +local filter = require("base/filter") +local config = require("project/config") +local global = require("project/global") +local platform = require("platform/platform") + +-- the directories of tools +function tool._directories(name) + + -- the kinds + local kinds = + { + cc = "compiler" + , cxx = "compiler" + , mm = "compiler" + , mxx = "compiler" + , sc = "compiler" + , ar = "archiver" + , sh = "linker" + , ld = "linker" + } + + -- get kind sub-directory + local subdir = kinds[name] + assert(subdir) + + -- the directories + return { path.join(path.join(config.directory(), "tools"), subdir) + , path.join(path.join(global.directory(), "tools"), subdir) + , path.join(path.join(xmake._PROGRAM_DIR, "tools"), subdir) + } +end + +-- match the tool name +function tool._match(name, toolname) + + -- match full? ok + if name == toolname then return 100 end + + -- match the last word? ok + if name:find(toolname .. "$") then return 80 end + + -- match the partial word? ok + if name:find("%-" .. toolname) then return 60 end + + -- contains it? ok + if name:find(toolname, 1, true) then return 30 end + + -- not matched + return 0 +end + +-- find tool from the given root directory and name +function tool._find(root, name) + + -- attempt to get it directly first + local filepath = string.format("%s/%s.lua", root, name) + if os.isfile(filepath) then + return filepath + end + + -- make the lower name + name = name:lower() + + -- get all tool files + local file_ok = nil + local score_maxn = 0 + local files = os.match(string.format("%s/*.lua", root)) + for _, file in ipairs(files) do + + -- the tool name + local toolname = path.basename(file) + + -- found it? + if toolname and toolname ~= "tool" then + + -- match score + local score = tool._match(name, toolname:lower()) + + -- ok? + if score >= 100 then return file end + + -- select the file with the max score + if score > score_maxn then + file_ok = file + score_maxn = score + end + end + end + + -- ok? + return file_ok +end + +-- the tool filter +function tool._filter() + + -- new filter + return filter.new(function (variable) + + -- check + assert(variable) + + -- init maps + local maps = + { + host = xmake._HOST + , nuldev = xmake._NULDEV + , tmpdir = os.tmpdir() + , curdir = os.curdir() + } + + -- map it + return maps[variable] + + end) + +end + +-- load the given tool from the given name(.e.g cc, ar, ld, sh, ..) +function tool.load(name) + + -- get the shell name + local shellname = platform.tool(name) + if not shellname then + return nil, string.format("cannot get tool for %s", name) + end + + -- get it directly from cache dirst + tool._TOOLS = tool._TOOLS or {} + if tool._TOOLS[name] then + return tool._TOOLS[name] + end + + -- find the tool script path + local toolpath = nil + local toolname = path.basename(shellname) + for _, dir in ipairs(tool._directories(name)) do + + -- find this directory + toolpath = tool._find(dir, toolname) + if toolpath then + break + end + + end + + -- not exists? + if not toolpath or not os.isfile(toolpath) then + return nil, string.format("%s not found!", shellname) + end + + -- load script + local script, errors = loadfile(toolpath) + if script then + + -- make sandbox instance with the given script + local instance, errors = sandbox.new(script, tool._filter(), path.directory(toolpath)) + if not instance then + return nil, errors + end + + -- import the tool module + local module, errors = instance:import() + if not module then + return nil, errors + end + + -- init the tool module + if module and module.init then + module.init(shellname) + end + + -- save tool to the cache + tool._TOOLS[name] = module + + -- ok? + return module + end + + -- failed + return nil, errors +end + +-- check the tool and return the absolute path if exists +function tool.check(name, dirs) + + -- check + assert(name) + + -- attempt to run it directly first + if os.execute(string.format("%s > %s 2>&1", name, xmake._NULDEV)) ~= 0x7f00 then + return name + end + + -- attempt to get it from the given directories + for _, dir in ipairs(table.wrap(dirs)) do + + -- check it + local toolpath = path.translate(string.format("%s/%s", dir, name)) + if os.isfile(toolpath) and os.execute(string.format("%s > %s 2>&1", toolpath, xmake._NULDEV)) ~= 0x7f00 then + return toolpath + end + end +end + +-- return module: tool +return tool diff --git a/xmake/tools/compiler/gcc.lua b/xmake/tools/compiler/gcc.lua new file mode 100755 index 000000000..44f77cf43 --- /dev/null +++ b/xmake/tools/compiler/gcc.lua @@ -0,0 +1,119 @@ +--!The Automatic Cross-platform Build Tool +-- +-- XMake is free software; you can redistribute it and/or modify +-- it under the terms of the GNU Lesser General Public License as published by +-- the Free Software Foundation; either version 2.1 of the License, or +-- (at your option) any later version. +-- +-- XMake is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU Lesser General Public License +-- along with XMake; +-- If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a> +-- +-- Copyright (C) 2015 - 2016, ruki All rights reserved. +-- +-- @author ruki +-- @file gcc.lua +-- + +-- init it +function init(shellname) + + -- save the shell name + _g.shellname = shellname or "gcc" + + -- init mxflags + _g.mxflags = { "-fmessage-length=0" + , "-pipe" + , "-fpascal-strings" + , "\"-DIBOutlet=__attribute__((iboutlet))\"" + , "\"-DIBOutletCollection(ClassName)=__attribute__((iboutletcollection(ClassName)))\"" + , "\"-DIBAction=void)__attribute__((ibaction)\""} + + -- init shflags + _g.shflags = { "-shared", "-fPIC" } + + -- init cxflags for the kind: shared + _g.shared = {} + _g.shared.cxflags = {"-fPIC"} + + -- init flags map + _g.mapflags = + { + -- warnings + ["-W1"] = "-Wall" + , ["-W2"] = "-Wall" + , ["-W3"] = "-Wall" + + -- strip + , ["-s"] = "-s" + , ["-S"] = "-S" + + } +end + +-- get the property +function get(name) + + -- get it + return _g[name] +end + +-- make the define flag +function define(macro) + + -- make it + return "-D" .. macro:gsub("\"", "\\\"") +end + +-- make the undefine flag +function undefine(macro) + + -- make it + return "-U" .. macro +end + +-- make the includedir flag +function includedir(dir) + + -- make it + return "-I" .. dir +end + +-- make the command +function command(srcfile, objfile, flags, logfile) + + -- redirect + local redirect = "" + if logfile then redirect = format(" > %s 2>&1", logfile) end + + -- make it + return format("%s -c %s -o %s %s%s", _g.shellname, flags, objfile, srcfile, redirect) +end + +-- check the given flags +function check(flags) + + -- done + local ok = false + try + { + function () + + -- check it + os.run("%s %s -S -o $(nuldev) -xc $(nuldev) > $(nuldev) 2>&1", _g.shellname, flags) + + -- ok + ok = true + + end + } + + -- ok? + return ok +end + |
