diff options
| author | ruki <[email protected]> | 2016-04-13 10:13:37 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2016-04-13 10:13:37 +0800 |
| commit | 097a0d5eb612d898fb8de01d6db7760aed947b4b (patch) | |
| tree | 9c2ad3ffe67da1663953f9b7097721e96156cb18 | |
| parent | 833bfb207b3f924eaa81feb496cf74e6223d0041 (diff) | |
throw os.run errors
| -rwxr-xr-x | xmake/actions/config/makefile.lua | 2 | ||||
| -rw-r--r-- | xmake/core/base/os.lua | 27 | ||||
| -rw-r--r-- | xmake/core/project/option.lua | 168 | ||||
| -rw-r--r-- | xmake/core/project/project.lua | 1 | ||||
| -rw-r--r-- | xmake/core/project/target.lua | 26 | ||||
| -rw-r--r-- | xmake/core/sandbox/modules/os.lua | 14 | ||||
| -rw-r--r-- | xmake/core/tool/compiler.lua | 421 | ||||
| -rw-r--r-- | xmake/core/tool/tool.lua | 172 | ||||
| -rwxr-xr-x | xmake/tools/compiler/clang.lua | 132 | ||||
| -rwxr-xr-x | xmake/tools/compiler/gcc.lua | 8 |
10 files changed, 920 insertions, 51 deletions
diff --git a/xmake/actions/config/makefile.lua b/xmake/actions/config/makefile.lua index e0b66bd8b..b65b8a7b0 100755 --- a/xmake/actions/config/makefile.lua +++ b/xmake/actions/config/makefile.lua @@ -93,7 +93,7 @@ function _make_object(makefile, target, srcfile, objfile) -- make command local ccache = tool.shellname("ccache") local compiler = target:compiler(srcfile) - local cmd = compiler:makecmd(target, srcfile, objfile, _logfile()) + local cmd = compiler:command(target, srcfile, objfile, _logfile()) if ccache then cmd = ccache:append(cmd, " ") end diff --git a/xmake/core/base/os.lua b/xmake/core/base/os.lua index 1cdcd0e08..dfec6dc1d 100644 --- a/xmake/core/base/os.lua +++ b/xmake/core/base/os.lua @@ -24,6 +24,7 @@ local os = os or {} -- load modules +local io = require("base/io") local path = require("base/path") local utils = require("base/utils") local string = require("base/string") @@ -230,6 +231,32 @@ function os.cd(dir) return true end +-- run shell +function os.run(cmd, ...) + + -- make temporary log file + local log = os.tmpname() + + -- run command + if 0 ~= os.execute(cmd .. string.format(" > %s 2>&1", log)) then + + -- make errors + local errors = string.format("%s\nrun: %s failed!", io.readall(log), cmd) + + -- remove the temporary log file + os.rm(log) + + -- failed + return false, errors + end + + -- remove the temporary log file + os.rm(log) + + -- ok + return true +end + -- raise an exception and abort the current script -- -- the parent function will capture it if we uses pcall or xpcall diff --git a/xmake/core/project/option.lua b/xmake/core/project/option.lua index 9be17f801..4cea021c4 100644 --- a/xmake/core/project/option.lua +++ b/xmake/core/project/option.lua @@ -24,13 +24,165 @@ local option = option or {} -- load modules +local io = require("base/io") local os = require("base/os") local path = require("base/path") local table = require("base/table") local utils = require("base/utils") +local option_ = require("base/option") local cache = require("project/cache")("local.option") local linker = require("platform/linker") -local compiler = require("platform/compiler") +local compiler = require("tool/compiler") + +-- check include +function option:_check_include(include, srcpath, objpath) + + -- check + assert(srcpath and objpath) + + -- open the checking source file + local srcfile = io.open(srcpath, "w") + if not srcfile then + return false + end + + -- make include + if include then + srcfile:print("#include <%s>\n", include) + end + + -- make the main function header + srcfile:print("int main(int argc, char** argv)") + srcfile:print("{") + srcfile:print(" return 0;") + srcfile:print("}") + + -- exit this file + srcfile:close() + + -- load the compiler instance + local instance = compiler.load(srcpath) + if not instance then + return false + end + + -- attempt to run this command + local ok, errors = instance:run(instance:command(self, srcpath, objpath)) + if not ok and option_.get("verbose") then + print(errors) + end + + -- ok? + return ok +end + +-- check function +function option:_check_function(interface, srcpath, objpath) + + -- check + assert(interface) + + -- open the checking source file + local srcfile = io.open(srcpath, "w") + if not srcfile then + return false + end + + -- load the compiler instance + local instance = compiler.load(srcpath) + if not instance then + return false + end + + -- make includes + local includes = nil + if instance:kind() == "cc" then includes = self:get("cincludes") + elseif instance:kind() == "cxx" then includes = self:get("cxxincludes") + end + if includes then + for _, include in ipairs(table.wrap(includes)) do + srcfile:print("#include <%s>", include) + end + srcfile:print("") + end + + -- make the main function header + srcfile:print("int main(int argc, char** argv)") + srcfile:print("{") + + -- make interfaces + srcfile:print(" volatile void* p%s = (void*)&%s;\n", interface, interface) + + -- make the main function tailer + srcfile:print(" return 0;") + srcfile:print("}") + + -- exit this file + srcfile:close() + + -- execute the compile command + local ok, errors = instance:run(instance:command(self, srcpath, objpath)) + if not ok and option_.get("verbose") then + print(errors) + end + + -- ok? + return ok +end + +-- check typedef +function option:_check_typedef(typedef, srcpath, objpath) + + -- check + assert(typedef) + + -- open the checking source file + local srcfile = io.open(srcpath, "w") + if not srcfile then + return false + end + + -- load the compiler instance + local instance = compiler.load(srcpath) + if not instance then + return false + end + + -- make includes + local includes = nil + if instance:kind() == "cc" then includes = self:get("cincludes") + elseif instance:kind() == "cxx" then includes = self:get("cxxincludes") + end + if includes then + for _, include in ipairs(table.wrap(includes)) do + srcfile:print("#include <%s>", include) + end + srcfile:print("") + end + + -- make the main function header + srcfile:print("int main(int argc, char** argv)") + srcfile:print("{") + + -- make interfaces + srcfile:print(" typedef %s __type_xxx;\n", typedef) + + -- make the main function tailer + srcfile:print(" return 0;") + srcfile:print("}") + + -- exit this file + srcfile:close() + + -- execute the compile command + local ok, errors = instance:run(instance:command(self, srcpath, objpath)) + if not ok and option_.get("verbose") then + print(errors) + end + + -- ok? + return ok +end -- check option for checking links function option:_check_links(cfile, objectfile, targetfile) @@ -51,7 +203,7 @@ function option:_check_links(cfile, objectfile, targetfile) end -- only for compile a object file - local ok = compiler.check_include(self, nil, cfile, objectfile) + local ok = self:_check_include(nil, cfile, objectfile) -- check link if ok then ok = linker.check_links(self, cfile, objectfile, targetfile) end @@ -77,7 +229,7 @@ function option:_check_cincludes(cfile, objectfile) if option._CHECKED_CINCLUDES[cinclude] then return true end -- check cinclude - local ok = compiler.check_include(self, cinclude, cfile, objectfile) + local ok = self:_check_include(cinclude, cfile, objectfile) -- trace utils.printf("checking for the c include %s ... %s", cinclude, utils.ifelse(ok, "ok", "no")) @@ -104,7 +256,7 @@ function option:_check_cxxincludes(cxxfile, objectfile) if option._CHECKED_CXXINCLUDES[cinclude] then return true end -- check cinclude - local ok = compiler.check_include(self, cxxinclude, cxxfile, objectfile) + local ok = self:_check_include(cxxinclude, cxxfile, objectfile) -- trace utils.printf("checking for the c++ include %s ... %s", cxxinclude, utils.ifelse(ok, "ok", "no")) @@ -127,7 +279,7 @@ function option:_check_cfuncs(cfile, objectfile, targetfile) for _, cfunc in ipairs(table.wrap(self:get("cfuncs"))) do -- check function - local ok = compiler.check_function(self, cfunc, cfile, objectfile) + local ok = self:_check_function(cfunc, cfile, objectfile) -- check link if ok and self:get("links") then ok = linker.check_links(self, cfile, objectfile, targetfile) end @@ -150,7 +302,7 @@ function option:_check_cxxfuncs(cxxfile, objectfile, targetfile) for _, cxxfunc in ipairs(table.wrap(self:get("cxxfuncs"))) do -- check function - local ok = compiler.check_function(self, cxxfunc, cxxfile, objectfile) + local ok = self:_check_function(cxxfunc, cxxfile, objectfile) -- check link if ok and self:get("links") then ok = linker.check_links(self, cxxfile, objectfile, targetfile) end @@ -173,7 +325,7 @@ function option:_check_ctypes(cfile, objectfile, targetfile) for _, ctype in ipairs(table.wrap(self:get("ctypes"))) do -- check type - local ok = compiler.check_typedef(self, ctype, cfile, objectfile) + local ok = self:_check_typedef(ctype, cfile, objectfile) -- trace utils.printf("checking for the c type %s ... %s", ctype, utils.ifelse(ok, "ok", "no")) @@ -193,7 +345,7 @@ function option:_check_cxxtypes(cxxfile, objectfile, targetfile) for _, cxxtype in ipairs(table.wrap(self:get("cxxtypes"))) do -- check type - local ok = compiler.check_typedef(self, cxxtype, cxxfile, objectfile) + local ok = self:_check_typedef(cxxtype, cxxfile, objectfile) -- trace utils.printf("checking for the c++ type %s ... %s", cxxtype, utils.ifelse(ok, "ok", "no")) diff --git a/xmake/core/project/project.lua b/xmake/core/project/project.lua index 52e9c4b8e..c52b52a05 100644 --- a/xmake/core/project/project.lua +++ b/xmake/core/project/project.lua @@ -36,7 +36,6 @@ local config = require("project/config") local option = require("project/option") local deprecated_project = require("project/deprecated/project") local linker = require("platform/linker") -local compiler = require("platform/compiler") local platform = require("platform/platform") -- the current os is belong to the given os? diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index 834e9f456..42a4df4bf 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -30,7 +30,7 @@ local table = require("base/table") local option = require("project/option") local config = require("project/config") local linker = require("platform/linker") -local compiler = require("platform/compiler") +local compiler = require("tool/compiler") local platform = require("platform/platform") -- get the filename from the given name and kind @@ -47,7 +47,7 @@ function target.filename(name, kind) end -- get the target info -function target.get(self, infoname) +function target:get(infoname) -- check assert(self and self._INFO and infoname) @@ -57,14 +57,14 @@ function target.get(self, infoname) end -- get the target name -function target.name(self) +function target:name() -- get it return self._NAME end -- get the linker -function target.linker(self) +function target:linker() -- check assert(self) @@ -81,13 +81,13 @@ function target.linker(self) end -- get the compiler with the given source file -function target.compiler(self, srcfile) +function target:compiler(srcfile) -- check assert(self and srcfile) - -- init the linker from the given kind - local result, errors = compiler.init(srcfile) + -- load the compiler + local result, errors = compiler.load(srcfile) if not result then os.raise(errors) end @@ -98,7 +98,7 @@ function target.compiler(self, srcfile) end -- get the options -function target.options(self) +function target:options() -- the options local options = {} @@ -117,7 +117,7 @@ function target.options(self) end -- get the object file directory -function target.objectdir(self) +function target:objectdir() -- check assert(self) @@ -135,7 +135,7 @@ function target.objectdir(self) end -- get the target file -function target.targetfile(self) +function target:targetfile() -- check assert(self) @@ -153,7 +153,7 @@ function target.targetfile(self) end -- get the source files -function target.sourcefiles(self) +function target:sourcefiles() -- check assert(self) @@ -212,7 +212,7 @@ function target.sourcefiles(self) end -- get the object files -function target.objectfiles(self) +function target:objectfiles() -- check assert(self) @@ -261,7 +261,7 @@ function target.objectfiles(self) end -- get the header files -function target.headerfiles(self) +function target:headerfiles() -- check assert(self) diff --git a/xmake/core/sandbox/modules/os.lua b/xmake/core/sandbox/modules/os.lua index a05e26939..44bef94e1 100644 --- a/xmake/core/sandbox/modules/os.lua +++ b/xmake/core/sandbox/modules/os.lua @@ -165,17 +165,11 @@ function sandbox_os.run(cmd, ...) -- make command cmd = vformat(cmd, ...) - -- make temporary log file - local log = os.tmpname() - - -- run command - if 0 ~= os.execute(cmd .. string.format(" > %s 2>&1", log)) then - io.cat(log) - os.raise("run: %s failed!", cmd) + -- run it + local ok, errors = os.run(cmd) + if not ok then + os.raise(errors) end - - -- remove the temporary log file - os.rm(log) end -- match files or directories diff --git a/xmake/core/tool/compiler.lua b/xmake/core/tool/compiler.lua new file mode 100644 index 000000000..9ffe21253 --- /dev/null +++ b/xmake/core/tool/compiler.lua @@ -0,0 +1,421 @@ +--!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 compiler.lua +-- + +-- define module +local compiler = compiler or {} + +-- load modules +local io = require("base/io") +local path = require("base/path") +local utils = require("base/utils") +local table = require("base/table") +local string = require("base/string") +local config = require("project/config") +local tool = require("tool/tool") +local platform = require("platform/platform") + +-- get the current tool +function compiler:_tool() + + -- get it + return self._TOOL +end + +-- get the current flag names +function compiler:_flagnames() + + -- get it + return self._FLAGNAMES +end + +-- get the compiler kind of the source file +function compiler._kind_of_file(srcfile) + + -- get the source file type + local filetype = path.extension(srcfile) + if not filetype then + return nil + end + + -- the kinds + local kinds = + { + [".c"] = "cc" + , [".cc"] = "cxx" + , [".cpp"] = "cxx" + , [".m"] = "mm" + , [".mm"] = "mxx" + , [".s"] = "as" + , [".asm"] = "as" + , [".swift"] = "sc" + } + + -- get kind + return kinds[filetype:lower()] +end + +-- get the flags +function compiler:_flags(target) + + -- get the target key + local key = tostring(target) + + -- get it directly from cache dirst + self._FLAGS = self._FLAGS or {} + if self._FLAGS[key] then + return self._FLAGS[key] + end + + -- add flags from the configure + local flags = {} + self:_addflags_from_config(flags) + + -- add flags from the target + self:_addflags_from_target(flags, target) + + -- add flags from the platform + self:_addflags_from_platform(flags) + + -- add flags from the compiler + self:_addflags_from_compiler(flags, target:get("kind")) + + -- remove repeat + flags = table.unique(flags) + + -- merge flags + flags = table.concat(flags, " "):trim() + + -- save flags + self._FLAGS[key] = flags + + -- get it + return flags +end + +-- map gcc flag to the given compiler flag +function compiler:_mapflag(flag, mapflags) + + -- attempt to map it directly + local flag_mapped = mapflags[flag] + if flag_mapped then + return flag_mapped + end + + -- find and replace it using pattern + for k, v in pairs(mapflags) do + local flag_mapped, count = flag:gsub("^" .. k .. "$", function (w) return v end) + if flag_mapped and count ~= 0 then + return utils.ifelse(#flag_mapped ~= 0, flag_mapped, nil) + end + end + + -- return it directly + return flag +end + +-- map gcc flags to the given compiler flags +function compiler:_mapflags(flags) + + -- wrap flags first + flags = table.wrap(flags) + + -- the compiler tool + local ctool = self:_tool() + + -- done + local results = {} + local mapflags = ctool:get("mapflags") + if mapflags then + + -- map flags + for _, flag in pairs(flags) do + local flag_mapped = self:_mapflag(flag, mapflags) + if flag_mapped then + table.insert(results, flag_mapped) + end + end + + else + + -- check flags + for _, flag in pairs(flags) do + if ctool:check(flag) then + table.insert(results, flag) + end + end + + end + + -- ok? + return results +end + +-- get the named flags +function compiler:_named_flags(names, flags) + + -- map it + local flags_mapped = {} + for _, name in ipairs(table.wrap(names)) do + table.join2(flags_mapped, self:_mapflags(flags[name])) + end + + -- get it + return flags_mapped +end + +-- add flags from the configure +function compiler:_addflags_from_config(flags) + + -- done + for _, flagname in ipairs(self:_flagnames()) do + table.join2(flags, config.get(flagname)) + end +end + +-- add flags from the target +function compiler:_addflags_from_target(flags, target) + + -- the compiler tool + local ctool = self:_tool() + + -- add the target flags + for _, flagname in ipairs(self:_flagnames()) do + table.join2(flags, self:_mapflags(target:get(flagname))) + end + + -- add the symbols flags + table.join2(flags, self:_named_flags(target:get("symbols"), { debug = "-g" + , hidden = "-fvisibility=hidden" + })) + + -- add the warning flags + table.join2(flags, self:_named_flags(target:get("warnings"), { none = "-w" + , less = "-W1" + , more = "-W3" + , all = "-Wall" + , error = "-Werror" + })) + + -- add the optimize flags + table.join2(flags, self:_named_flags(target:get("optimize"), { none = "-O0" + , fast = "-O1" + , faster = "-O2" + , fastest = "-O3" + , smallest = "-Os" + , aggressive = "-Ofast" + })) + + -- add the vector extensions flags + table.join2(flags, self:_named_flags(target:get("vectorexts"), { mmx = "-mmmx" + , sse = "-msse" + , sse2 = "-msse2" + , sse3 = "-msse3" + , ssse3 = "-mssse3" + , avx = "-mavx" + , avx2 = "-mavx2" + , neon = "-mfpu=neon" + })) + + -- add the language flags + local languages = {} + for _, flagname in ipairs(self:_flagnames()) do + if flagname == "cflags" or flagname == "mflags" then + table.join2(languages, { ansi = "-ansi" + , c89 = "-std=c89" + , gnu89 = "-std=gnu89" + , c99 = "-std=c99" + , gnu99 = "-std=gnu99" + , c11 = "-std=c11" + , gnu11 = "-std=gnu11" + }) + elseif flagname == "cxxflags" or flagname == "mxxflags" then + table.join2(languages, { cxx98 = "-std=c++98" + , gnuxx98 = "-std=gnu++98" + , cxx11 = "-std=c++11" + , gnuxx11 = "-std=gnu++11" + , cxx14 = "-std=c++14" + , gnuxx14 = "-std=gnu++14" + }) + end + end + table.join2(flags, self:_named_flags(target:get("languages"), languages)) + + -- add the includedirs flags + for _, includedir in ipairs(table.wrap(target:get("includedirs"))) do + table.join2(flags, ctool:includedir(includedir)) + end + + -- add the defines flags + for _, define in ipairs(table.wrap(target:get("defines"))) do + table.join2(flags, ctool:define(define)) + end + + -- append the undefines flags + for _, undefine in ipairs(table.wrap(target:get("undefines"))) do + table.join2(flags, ctool:undefine(undefine)) + end + + -- for target options? + if target.options then + + -- add the flags for the target options + for name, opt in pairs(target:options()) do + + -- add the flags from the option + self:_addflags_from_target(flags, opt) + + -- append the defines flags + for _, define in ipairs(table.wrap(opt:get("defines_if_ok"))) do + table.join2(flags, ctool:define(define)) + end + + -- append the undefines flags + for _, undefine in ipairs(table.wrap(opt:get("undefines_if_ok"))) do + table.join2(flags, ctool:undefine(undefine)) + end + end + end +end + +-- add flags from the platform +function compiler:_addflags_from_platform(flags) + + -- the compiler tool + local ctool = self:_tool() + + -- add flags + for _, flagname in ipairs(self:_flagnames()) do + table.join2(flags, self:_mapflags(platform.get(flagname))) + end + + -- add the includedirs flags + for _, includedir in ipairs(table.wrap(platform.get("includedirs"))) do + table.join2(flags, ctool:includedir(includedir)) + end + + -- add the defines flags + for _, define in ipairs(table.wrap(platform.get("defines"))) do + table.join2(flags, ctool:define(define)) + end + + -- append the undefines flags + for _, undefine in ipairs(table.wrap(platform.get("undefines"))) do + table.join2(flags, ctool:undefine(undefine)) + end +end + +-- add flags from the compiler +function compiler:_addflags_from_compiler(flags, kind) + + -- the compiler tool + local ctool = self:_tool() + + -- done + for _, flagname in ipairs(self:_flagnames()) do + + -- add compiler.xxflags + table.join2(flags, ctool:get(flagname)) + + -- add compiler.kind.xxflags + if kind ~= nil and ctool:get(kind) ~= nil then + table.join2(flags, ctool:get(kind)[flagname]) + end + end +end + +-- get the current kind +function compiler:kind() + + -- get it + return self._KIND +end + +-- load the compiler from the given source file +function compiler.load(srcfile) + + -- get the compiler kind + local kind = compiler._kind_of_file(srcfile) + if not kind then + return nil, string.format("unknown source file: %s", srcfile) + end + + -- get it directly from cache dirst + compiler._INSTANCES = compiler._INSTANCES or {} + if compiler._INSTANCES[kind] then + return compiler._INSTANCES[kind] + end + + -- new instance + local instance = table.inherit(compiler) + + -- load the compiler tool from the source file type + local result, errors = tool.load(kind) + if not result then + return nil, errors + end + + -- save tool + instance._TOOL = result + + -- save kind + instance._KIND = kind + + -- save flagnames + local flagnames = + { + cc = { "cxflags", "cflags" } + , cxx = { "cxflags", "cxxflags" } + , mm = { "mxflags", "mflags" } + , mxx = { "mxflags", "mxxflags" } + , as = { "asflags" } + , sc = { "scflags" } + } + instance._FLAGNAMES = flagnames[kind] + + -- check + if not instance._FLAGNAMES then + return nil, string.format("unknown compiler for kind: %s", kind) + end + + -- save this instance + compiler._INSTANCES[kind] = instance + + -- ok + return instance +end + +-- run the command +function compiler:run(cmd) + + -- get it + return self:_tool():run(cmd) +end + +-- get the command +function compiler:command(target, srcfile, objfile, logfile) + + -- get it + return self:_tool():command(srcfile, objfile, self:_flags(target), logfile) +end + +-- return module +return compiler diff --git a/xmake/core/tool/tool.lua b/xmake/core/tool/tool.lua index 4a4a1db26..fcfc28b1e 100644 --- a/xmake/core/tool/tool.lua +++ b/xmake/core/tool/tool.lua @@ -20,19 +20,146 @@ -- @file tool.lua -- --- define module: tool -local tool = tool or {} +-- define module +local tool = tool or {} +local _module = _module or {} -- load modules local os = require("base/os") local path = require("base/path") local utils = require("base/utils") +local table = require("base/table") local string = require("base/string") local filter = require("base/filter") local config = require("project/config") local global = require("project/global") +local sandbox = require("sandbox/sandbox") local platform = require("platform/platform") +-- get the property +function _module:get(name) + + -- the interface + local interface = self._INTERFACE + assert(interface) + + -- check + if not interface.get then + return + end + + -- get it + return interface.get(name) +end + +-- make the define flag +function _module:define(macro) + + -- the interface + local interface = self._INTERFACE + assert(interface) + + -- check + if not interface.define then + return + end + + -- make it + return interface.define(macro) +end + +-- make the undefine flag +function _module:undefine(macro) + + -- the interface + local interface = self._INTERFACE + assert(interface) + + -- check + if not interface.undefine then + return + end + + -- make it + return interface.undefine(macro) +end + +-- make the includedir flag +function _module:includedir(dir) + + -- the interface + local interface = self._INTERFACE + assert(interface) + + -- check + if not interface.includedir then + return + end + + -- make it + return interface.includedir(dir) +end + +-- make the command +function _module:command(srcfile, objfile, flags, logfile) + + -- the interface + local interface = self._INTERFACE + assert(interface and interface.command) + + -- make it + return interface.command(srcfile, objfile, flags, logfile) +end + +-- check the given flags +function _module:check(flags) + + -- the interface + local interface = self._INTERFACE + assert(interface) + + -- no check? + if not interface.check then + return true + end + + -- have been checked? return it directly + interface.checked = interface.checked or {} + if interface.checked[flags] ~= nil then + return interface.checked[flags] + end + + -- check it + local ok, results = sandbox.load(interface.check, flags) + if not ok then + os.raise(results) + end + + -- save the checked result + interface.checked[flags] = results + + -- ok? + return ok +end + +-- run the command +function _module:run(cmd, ...) + + -- the private + local interface = self._INTERFACE + assert(interface) + + -- no run interface? + if not interface.run then + + -- run it + return os.run(cmd, ...) + end + + -- run it + return sandbox.load(interface.run, cmd, ...) +end + -- the directories of tools function tool._directories(name) @@ -146,25 +273,30 @@ function tool._filter() end --- load the given tool from the given name(.e.g cc, ar, ld, sh, ..) -function tool.load(name) +-- load the given tool from the given kind +-- +-- the kinds: +-- +-- .e.g cc, cxx, mm, mxx, as, ar, ld, sh, .. +-- +function tool.load(kind) -- get the shell name - local shellname = platform.tool(name) + local shellname = platform.tool(kind) if not shellname then - return nil, string.format("cannot get tool for %s", name) + return nil, string.format("cannot get tool for %s", kind) end -- get it directly from cache dirst tool._TOOLS = tool._TOOLS or {} - if tool._TOOLS[name] then - return tool._TOOLS[name] + if tool._TOOLS[kind] then + return tool._TOOLS[kind] end -- find the tool script path local toolpath = nil local toolname = path.basename(shellname) - for _, dir in ipairs(tool._directories(name)) do + for _, dir in ipairs(tool._directories(kind)) do -- find this directory toolpath = tool._find(dir, toolname) @@ -196,15 +328,19 @@ function tool.load(name) end -- init the tool module - if module and module.init then + if module.init then module.init(shellname) end + + -- wrap this module + local result = table.inherit(_module) + result._INTERFACE = module -- save tool to the cache - tool._TOOLS[name] = module + tool._TOOLS[kind] = result -- ok? - return module + return result end -- failed @@ -212,26 +348,26 @@ function tool.load(name) end -- check the tool and return the absolute path if exists -function tool.check(name, dirs) +function tool.check(shellname, dirs) -- check - assert(name) + assert(shellname) -- attempt to run it directly first - if os.execute(string.format("%s > %s 2>&1", name, xmake._NULDEV)) ~= 0x7f00 then - return name + if os.execute(string.format("%s > %s 2>&1", shellname, xmake._NULDEV)) ~= 0x7f00 then + return shellname 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)) + local toolpath = path.translate(string.format("%s/%s", dir, shellname)) 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 module return tool diff --git a/xmake/tools/compiler/clang.lua b/xmake/tools/compiler/clang.lua new file mode 100755 index 000000000..90dd4150b --- /dev/null +++ b/xmake/tools/compiler/clang.lua @@ -0,0 +1,132 @@ +--!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 clang.lua +-- + +-- init it +function init(shellname) + + -- save the shell name + _g.shellname = shellname or "clang" + + -- 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 = { "-dynamiclib", "-fPIC" } + + -- suppress warning + _g.cxflags = {"-Qunused-arguments"} + _g.mxflags = {"-Qunused-arguments"} + _g.asflags = {"-Qunused-arguments"} + + -- 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"] = "-Wl,-S" + , ["-S"] = "-Wl,-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 + +-- run the command +function run(cmd, ...) + + -- run it + os.run(cmd, ...) + +end + diff --git a/xmake/tools/compiler/gcc.lua b/xmake/tools/compiler/gcc.lua index 44f77cf43..72fb8aede 100755 --- a/xmake/tools/compiler/gcc.lua +++ b/xmake/tools/compiler/gcc.lua @@ -117,3 +117,11 @@ function check(flags) return ok end +-- run the command +function run(cmd, ...) + + -- check it + os.run(cmd, ...) + +end + |
