summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2016-04-11 14:08:47 +0800
committerruki <[email protected]>2016-04-11 14:08:47 +0800
commit833bfb207b3f924eaa81feb496cf74e6223d0041 (patch)
tree0b1774ba14cbe63ecb6eb347deea19975f2c8554
parent71296f55db2d5b0a9249592c3428797708cd0683 (diff)
add new tool module
-rw-r--r--xmake/core/base/deprecated/interpreter.lua2
-rw-r--r--xmake/core/base/filter.lua14
-rw-r--r--xmake/core/base/interpreter.lua2
-rw-r--r--xmake/core/project/project.lua2
-rw-r--r--xmake/core/project/task.lua7
-rw-r--r--xmake/core/project/template.lua2
-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.lua23
-rw-r--r--xmake/core/sandbox/sandbox.lua43
-rw-r--r--xmake/core/tool/tool.lua237
-rwxr-xr-xxmake/tools/compiler/gcc.lua119
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
+