diff options
| author | ruki <[email protected]> | 2016-04-14 09:24:24 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2016-04-14 09:24:24 +0800 |
| commit | 9e736d8b83930330edaee2958b4c66093ca87e37 (patch) | |
| tree | cefcd89bbc72f1aac02535699f97626560be12ab | |
| parent | 733935aec221c1bce476e7cfea7b5e64d280f71e (diff) | |
reimpl compiler and linker
| -rwxr-xr-x | xmake/actions/config/makefile.lua | 6 | ||||
| -rw-r--r-- | xmake/core/platform/compiler.lua | 588 | ||||
| -rw-r--r-- | xmake/core/platform/linker.lua | 391 | ||||
| -rw-r--r-- | xmake/core/project/option.lua | 51 | ||||
| -rw-r--r-- | xmake/core/project/project.lua | 1 | ||||
| -rw-r--r-- | xmake/core/project/target.lua | 38 | ||||
| -rw-r--r-- | xmake/core/tool/compiler.lua | 88 | ||||
| -rw-r--r-- | xmake/core/tool/linker.lua | 358 | ||||
| -rw-r--r-- | xmake/core/tool/tool.lua | 39 | ||||
| -rwxr-xr-x | xmake/tools/compiler/gcc.lua | 4 | ||||
| -rw-r--r-- | xmake/tools/linker/ar.lua | 44 | ||||
| -rwxr-xr-x | xmake/tools/linker/clang++.lua | 33 | ||||
| -rwxr-xr-x | xmake/tools/linker/clang.lua | 40 | ||||
| -rwxr-xr-x | xmake/tools/linker/g++.lua | 33 | ||||
| -rwxr-xr-x | xmake/tools/linker/gcc.lua | 95 | ||||
| -rw-r--r-- | xmake/tools/make.lua | 76 |
16 files changed, 842 insertions, 1043 deletions
diff --git a/xmake/actions/config/makefile.lua b/xmake/actions/config/makefile.lua index b65b8a7b0..fa7525a79 100755 --- a/xmake/actions/config/makefile.lua +++ b/xmake/actions/config/makefile.lua @@ -21,7 +21,7 @@ -- -- imports -import("core.platform.tool") +import("core.tool.tool") import("core.project.project") -- get log makefile @@ -157,12 +157,12 @@ function _make_target(makefile, target) -- make the command local linker = target:linker() - local cmd = linker:makecmd(target, objfiles, targetfile, _logfile()) + local cmd = linker:command(target, objfiles, targetfile, _logfile()) -- make the verbose info local verbose = cmd:encode() if verbose and #verbose > 256 then - verbose = linker:makecmd(target, {target.filename("*", "object")}, targetfile) + verbose = linker:command(target, target.filename("*", "object"), targetfile) verbose = verbose:encode() end diff --git a/xmake/core/platform/compiler.lua b/xmake/core/platform/compiler.lua deleted file mode 100644 index e703ef933..000000000 --- a/xmake/core/platform/compiler.lua +++ /dev/null @@ -1,588 +0,0 @@ ---!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 option = require("base/option") -local config = require("project/config") -local tool = require("platform/tool") -local platform = require("platform/platform") - --- map gcc flag to the given compiler flag -function compiler._mapflag(self, flag) - - -- check - assert(self._TOOL.mapflags and flag) - - -- attempt to map it directly - local flag_mapped = self._TOOL.mapflags[flag] - if flag_mapped and type(flag_mapped) == "string" then - return flag_mapped - end - - -- find and replace it using pattern - for k, v in pairs(self._TOOL.mapflags) do - local flag_mapped, count = flag:gsub("^" .. k .. "$", function (w) - if type(v) == "function" then - return v(self, w) - else - return v - end - 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(self, flags) - - -- check - assert(self) - - -- wrap flags first - flags = table.wrap(flags) - - -- need not map flags? return it directly - if not self._TOOL.mapflags then - return flags - end - - -- map flags - local flags_mapped = {} - for _, flag in pairs(flags) do - -- map it - local flag_mapped = compiler._mapflag(self, flag) - if flag_mapped then - table.insert(flags_mapped, flag_mapped) - end - end - - -- ok? - return flags_mapped -end - --- get the compiler flags from names -function compiler._getflags(self, names, flags) - - -- check - assert(flags) - - -- the mapped flags - local flags_mapped = {} - - -- wrap it first - names = table.wrap(names) - for _, name in ipairs(names) do - table.join2(flags_mapped, compiler._mapflags(self, flags[name])) - end - - -- get it - return flags_mapped -end - --- add flags from the compiler -function compiler._addflags_from_compiler(self, flags, flagnames, kind) - - -- check - assert(self and flags and flagnames) - - -- done - for _, flagname in ipairs(flagnames) do - - -- add compiler.xxflags - table.join2(flags, self._TOOL[flagname]) - - -- add compiler.kind.xxflags - if kind ~= nil and self._TOOL[kind] ~= nil then - table.join2(flags, self._TOOL[kind][flagname]) - end - end -end - --- add flags from the configure -function compiler._addflags_from_config(self, flags, flagnames) - - -- check - assert(self and flags and flagnames) - - -- done - for _, flagname in ipairs(flagnames) do - table.join2(flags, config.get(flagname)) - end -end - --- add flags from the platform -function compiler._addflags_from_platform(self, flags, flagnames) - - -- check - assert(self and flags and flagnames) - - -- add flags - for _, flagname in ipairs(flagnames) do - table.join2(flags, compiler._mapflags(self, platform.get(flagname))) - end - - -- add the includedirs flags - if self._TOOL.flag_includedir then - for _, includedir in ipairs(table.wrap(platform.get("includedirs"))) do - table.join2(flags, self._TOOL:flag_includedir(includedir)) - end - end - - -- add the defines flags - if self._TOOL.flag_define then - for _, define in ipairs(table.wrap(platform.get("defines"))) do - table.join2(flags, self._TOOL:flag_define(define)) - end - end - - -- append the undefines flags - if self._TOOL.flag_undefine then - for _, undefine in ipairs(table.wrap(platform.get("undefines"))) do - table.join2(flags, self._TOOL:flag_undefine(undefine)) - end - end -end - --- TODO optimize speed, cache it --- add flags from the target -function compiler._addflags_from_target(self, flags, flagnames, target) - - -- check - assert(self and flags and flagnames and target) - - -- add the target flags from the current project - for _, flagname in ipairs(flagnames) do - table.join2(flags, compiler._mapflags(self, target:get(flagname))) - end - - -- add the symbols flags from the current project - table.join2(flags, compiler._getflags(self, target:get("symbols"), { debug = "-g" - , hidden = "-fvisibility=hidden" - })) - - -- add the warning flags from the current project - table.join2(flags, compiler._getflags(self, target:get("warnings"), { none = "-w" - , less = "-W1" - , more = "-W3" - , all = "-Wall" - , error = "-Werror" - })) - - -- add the optimize flags from the current project - table.join2(flags, compiler._getflags(self, target:get("optimize"), { none = "-O0" - , fast = "-O1" - , faster = "-O2" - , fastest = "-O3" - , smallest = "-Os" - , aggressive = "-Ofast" - })) - - -- add the vector extensions flags from the current project - table.join2(flags, compiler._getflags(self, target:get("vectorexts"), { mmx = "-mmmx" - , sse = "-msse" - , sse2 = "-msse2" - , sse3 = "-msse3" - , ssse3 = "-mssse3" - , avx = "-mavx" - , avx2 = "-mavx2" - , neon = "-mfpu=neon" - })) - - -- add the language flags from the current project - local languages = {} - for _, flagname in ipairs(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, compiler._getflags(self, target:get("languages"), languages)) - - -- add the includedirs flags from the current project - if self._TOOL.flag_includedir then - for _, includedir in ipairs(table.wrap(target:get("includedirs"))) do - table.join2(flags, self._TOOL:flag_includedir(includedir)) - end - end - - -- add the defines flags from the current project - if self._TOOL.flag_define then - for _, define in ipairs(table.wrap(target:get("defines"))) do - table.join2(flags, self._TOOL:flag_define(define)) - end - end - - -- append the undefines flags from the current project - if self._TOOL.flag_undefine then - for _, undefine in ipairs(table.wrap(target:get("undefines"))) do - table.join2(flags, self._TOOL:flag_undefine(undefine)) - end - end - - -- is target? - 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, flagnames, opt) - - -- append the defines flags - if self._TOOL.flag_define then - for _, define in ipairs(table.wrap(opt:get("defines_if_ok"))) do - table.join2(flags, self._TOOL:flag_define(define)) - end - end - - -- append the undefines flags - if self._TOOL.flag_undefine then - for _, undefine in ipairs(table.wrap(opt:get("undefines_if_ok"))) do - table.join2(flags, self._TOOL:flag_undefine(undefine)) - end - end - end - end -end - --- add flags from the option -function compiler._addflags_from_option(self, flags, flagnames, opt) - - -- check - assert(self and flags and flagnames and opt) - - -- add the flags from the option - self:_addflags_from_target(flags, flagnames, opt) - -end - --- make the compile command for option -function compiler._make_for_option(self, opt, srcfile, objfile, logfile) - - -- check - assert(self and self._TOOL and opt) - - -- the flag names - local flagnames = compiler._flagnames(self._KIND) - assert(flagnames) - - -- init flags - local flags = {} - - -- add flags from the configure - compiler._addflags_from_config(self, flags, flagnames) - - -- add flags from the option - compiler._addflags_from_option(self, flags, flagnames, opt) - - -- add flags from the platform - compiler._addflags_from_platform(self, flags, flagnames) - - -- add flags from the compiler - compiler._addflags_from_compiler(self, flags, flagnames) - - -- remove repeat - flags = table.unique(flags) - - -- execute the compile command - return self._TOOL:command_compile(srcfile, objfile, table.concat(flags, " "):trim(), logfile) -end - --- get the flag names from the given compiler name -function compiler._flagnames(name) - - -- check - assert(name) - - -- the flag names - local flagnames = nil - if name == "cc" then flagnames = { "cxflags", "cflags" } - elseif name == "cxx" then flagnames = { "cxflags", "cxxflags" } - elseif name == "mm" then flagnames = { "mxflags", "mflags" } - elseif name == "mxx" then flagnames = { "mxflags", "mxxflags" } - elseif name == "as" then flagnames = { "asflags" } - elseif name == "sc" then flagnames = { "scflags" } - else - -- error - utils.error("unknown compiler: %s", name) - return - end - - -- ok - return flagnames -end - --- get the compiler kind from the source file type -function compiler._kind(srcfile) - - -- get the source file type - local filetype = path.extension(srcfile) - if not filetype then - return nil - end - - -- get the lower file type - filetype = filetype:lower() - - -- get the compiler kind - local kind = nil - if filetype == ".c" then kind = "cc" - elseif filetype == ".cpp" or filetype == ".cc" then kind = "cxx" - elseif filetype == ".m" then kind = "mm" - elseif filetype == ".mm" then kind = "mxx" - elseif filetype == ".s" or filetype == ".asm" then kind = "as" - elseif filetype == ".swift" then kind = "sc" - elseif filetype == ".a" or filetype == ".lib" then kind = "lib" - elseif filetype == ".o" or filetype == ".obj" then kind = "obj" - end - - -- ok - return kind -end - --- init the compiler from the given source file -function compiler.init(srcfile) - - -- get the compiler kind - local kind = compiler._kind(srcfile) - if not kind then - return nil, string.format("unknown source file: %s", srcfile) - end - - -- init instance - local instance = table.inherit(compiler) - - -- ignore "*.a/lib" and "*.o/obj" kind - if kind == "lib" or kind == "obj" then - return instance - end - - -- get compiler tool from the source file type - instance._TOOL, errors = tool.get(kind) - if instance._TOOL then - - -- invalid compiler - if not instance._TOOL.command_compile then - return nil, string.format("invalid compiler for %s", kind) - end - - -- save kind - instance._KIND = kind - else - return nil, errors - end - - -- ok - return instance -end - --- get flags from the given flag names -function compiler.flags(self, flagnames, target) - - -- init flags - local flags = {} - - -- add flags from the configure - self:_addflags_from_config(flags, flagnames) - - -- add flags from the target - self:_addflags_from_target(flags, flagnames, target) - - -- add flags from the platform - self:_addflags_from_platform(flags, flagnames) - - -- add flags from the compiler - self:_addflags_from_compiler(flags, flagnames, target:get("kind")) - - -- remove repeat - flags = table.unique(flags) - - -- ok? - return flags -end - --- make the compile command -function compiler.makecmd(self, target, srcfile, objfile, logfile) - - -- check - assert(self and self._TOOL and target) - - -- the flag names - local flagnames = compiler._flagnames(self._KIND) - assert(flagnames) - - -- get flags - local flags = self:flags(flagnames, target) - - -- make the compile command - return self._TOOL:command_compile(srcfile, objfile, table.concat(flags, " "):trim(), logfile) -end - --- check include for the project option -function compiler.check_include(opt, include, srcpath, objpath) - - -- check - assert(opt and srcpath and objpath) - - -- open the checking source file - local srcfile = io.open(srcpath, "w") - if not srcfile then return 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() - - -- get the compiler - local self = compiler.init(srcpath) - if not self then return end - - -- execute the compile command - return self._TOOL:main(self:_make_for_option(opt, srcpath, objpath, utils.ifelse(option.get("verbose"), nil, xmake._NULDEV))) -end - --- check function for the project option -function compiler.check_function(opt, interface, srcpath, objpath) - - -- check - assert(opt and interface) - - -- open the checking source file - local srcfile = io.open(srcpath, "w") - if not srcfile then return end - - -- get the compiler - local self = compiler.init(srcpath) - if not self then return end - - -- make includes - local includes = nil - if self._KIND == "cc" then includes = opt:get("cincludes") - elseif self._KIND == "cxx" then includes = opt: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 - return self._TOOL:main(self:_make_for_option(opt, srcpath, objpath, utils.ifelse(option.get("verbose"), nil, xmake._NULDEV))) -end - --- check typedef for the project option -function compiler.check_typedef(opt, typedef, srcpath, objpath) - - -- check - assert(opt and typedef) - - -- open the checking source file - local srcfile = io.open(srcpath, "w") - if not srcfile then return end - - -- get the compiler - local self = compiler.init(srcpath) - if not self then return end - - -- make includes - local includes = nil - if self._KIND == "cc" then includes = opt:get("cincludes") - elseif self._KIND == "cxx" then includes = opt: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 - return self._TOOL:main(self:_make_for_option(opt, srcpath, objpath, utils.ifelse(option.get("verbose"), nil, xmake._NULDEV))) -end - --- return module -return compiler diff --git a/xmake/core/platform/linker.lua b/xmake/core/platform/linker.lua deleted file mode 100644 index 7849ed638..000000000 --- a/xmake/core/platform/linker.lua +++ /dev/null @@ -1,391 +0,0 @@ ---!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 linker.lua --- - --- define module -local linker = linker or {} - --- load modules -local utils = require("base/utils") -local table = require("base/table") -local string = require("base/string") -local option = require("base/option") -local config = require("project/config") -local compiler = require("platform/compiler") -local tool = require("platform/tool") -local platform = require("platform/platform") - --- map gcc flag to the given linker flag -function linker._mapflag(self, flag) - - -- check - assert(self._TOOL.mapflags and flag) - - -- attempt to map it directly - local flag_mapped = self._TOOL.mapflags[flag] - if flag_mapped and type(flag_mapped) == "string" then - return flag_mapped - end - - -- find and replace it using pattern - for k, v in pairs(self._TOOL.mapflags) do - local flag_mapped, count = flag:gsub("^" .. k .. "$", function (w) - if type(v) == "function" then - return v(self, w) - else - return v - end - 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 linker flags -function linker._mapflags(self, flags) - - -- check - assert(self) - - -- wrap flags first - flags = table.wrap(flags) - - -- need not map flags? return it directly - if not self._TOOL.mapflags then - return flags - end - - -- map flags - local flags_mapped = {} - for _, flag in pairs(flags) do - -- map it - local flag_mapped = linker._mapflag(self, flag) - if flag_mapped then - table.insert(flags_mapped, flag_mapped) - end - end - - -- ok? - return flags_mapped -end - --- get the linker flags from names -function linker._getflags(self, names, flags) - - -- check - assert(flags) - - -- the mapped flags - local flags_mapped = {} - - -- wrap it first - names = table.wrap(names) - for _, name in ipairs(names) do - table.join2(flags_mapped, linker._mapflags(self, flags[name])) - end - - -- get it - return flags_mapped -end - - --- add flags from the links -function linker._addflags_from_links(self, flags, links) - - -- check - assert(self and flags and links) - - -- done - if self._TOOL.flag_link then - for _, link in ipairs(table.wrap(links)) do - table.join2(flags, self._TOOL:flag_link(link)) - end - end -end - --- add flags from the linker -function linker._addflags_from_linker(self, flags, flagname) - - -- check - assert(self and flags and flagname) - - -- done - table.join2(flags, self._TOOL[flagname]) -end - --- add flags from the compiler -function linker._addflags_from_compiler(self, flags, flagname, srcfiles) - - -- check - assert(self and flags and flagname) - - -- add the flags for compiler - local flags_for_compiler = {} - if srcfiles then - for _, srcfile in ipairs(table.wrap(srcfiles)) do - - -- init a compiler instance - local c, errors = compiler.init(srcfile) - if not c then - -- error - utils.error(errors) - return - end - - -- add flags - table.join2(flags_for_compiler, c[flagname]) - end - end - - -- done - table.join2(flags, table.unique(flags_for_compiler)) -end - --- add flags from the configure -function linker._addflags_from_config(self, flags, flagname) - - -- check - assert(self and flags and flagname) - - -- done - table.join2(flags, config.get(flagname)) -end - --- add flags from the platform -function linker._addflags_from_platform(self, flags, flagname) - - -- check - assert(self and flags and flagname) - - -- add flags - table.join2(flags, linker._mapflags(self, platform.get(flagname))) - - -- add the linkdirs flags - if self._TOOL.flag_linkdir then - for _, linkdir in ipairs(table.wrap(platform.get("linkdirs"))) do - table.join2(flags, self._TOOL:flag_linkdir(linkdir)) - end - end - - -- add the links flags - if self._TOOL.flag_link then - for _, link in ipairs(table.wrap(platform.get("links"))) do - table.join2(flags, self._TOOL:flag_link(link)) - end - end -end - --- add flags from the target -function linker._addflags_from_target(self, flags, flagname, target) - - -- check - assert(self and flags and flagname and target) - - -- add the target flags from the current project - table.join2(flags, linker._mapflags(self, target[flagname])) - - -- add the linkdirs flags from the current project - if self._TOOL.flag_linkdir then - for _, linkdir in ipairs(table.wrap(target:get("linkdirs"))) do - table.join2(flags, self._TOOL:flag_linkdir(linkdir)) - end - end - - -- add the links flags from the current project - if self._TOOL.flag_link then - for _, link in ipairs(table.wrap(target:get("links"))) do - table.join2(flags, self._TOOL:flag_link(link)) - end - end - - -- add the flags for the target options - for _, opt in pairs(target:options()) do - - -- add the flags from the option - table.join2(flags, linker._mapflags(self, opt:get(flagname))) - - -- add the linkdirs flags from the option - if self._TOOL.flag_linkdir then - for _, linkdir in ipairs(table.wrap(opt:get("linkdirs"))) do - table.join2(flags, self._TOOL:flag_linkdir(linkdir)) - end - end - - -- add the links flags from the option - if self._TOOL.flag_link then - for _, link in ipairs(table.wrap(opt:get("links"))) do - table.join2(flags, self._TOOL:flag_link(link)) - end - end - end - - -- add the flags from the configure - table.join2(flags, linker._mapflags(self, config.get(flagname))) - - -- add the strip flags from the current project - table.join2(flags, linker._getflags(self, target:get("strip"), { debug = "-S" - , all = "-s" - })) -end - --- add flags from the option -function linker._addflags_from_option(self, flags, flagname, opt) - - -- check - assert(self and flags and flagname and opt) - - -- append the option flags - table.join2(flags, linker._mapflags(self, opt:get("flagname"))) - - -- append the linkdirs flags - if opt:get("linkdirs") and self._TOOL.flag_linkdir then - for _, linkdir in ipairs(table.wrap(opt:get("linkdirs"))) do - table.join2(flags, self._TOOL:flag_linkdir(linkdir)) - end - end -end - --- init a linker instance from the given kind -function linker.init(kind) - - -- check - assert(kind) - - -- get the linker name from the kind - local name = nil - if kind == "binary" then name = "ld" - elseif kind == "static" then name = "ar" - elseif kind == "shared" then name = "sh" - else - return nil, string.format("unknown kind: %s for linker", kind) - end - - -- init instance - local instance = table.inherit(linker) - - -- get the linker tool - instance._TOOL, errors = tool.get(name) - if not instance._TOOL then - return nil, errors - end - - -- ok? - return instance -end - --- get flags from the given flag name -function linker.flags(self, flagname, target) - - -- init flags - local flags = {} - - -- add flags from the configure - self:_addflags_from_config(flags, flagname) - - -- add flags from the target - self:_addflags_from_target(flags, flagname, target) - - -- add flags from the platform - self:_addflags_from_platform(flags, flagname) - - -- add flags from the compiler - self:_addflags_from_compiler(flags, flagname, target:sourcefiles()) - - -- add flags from the linker - self:_addflags_from_linker(flags, flagname) - - -- remove repeat - flags = table.unique(flags) - - -- ok? - return flags -end - --- make the link command -function linker.makecmd(self, target, objfiles, targetfile, logfile) - - -- check - assert(self and self._TOOL and target) - - -- the target kind - local kind = target:get("kind") or "" - - -- the flag name - local flagname = nil - if kind == "binary" then flagname = "ldflags" - elseif kind == "static" then flagname = "arflags" - elseif kind == "shared" then flagname = "shflags" - else - -- error - os.raise("unknown type for linker: %s", kind) - end - - -- get flags - local flags = self:flags(flagname, target) - - -- make the link command - return self._TOOL:command_link(table.concat(objfiles, " "), targetfile, table.concat(flags, " "):trim(), logfile) -end - --- check link for the project option -function linker.check_links(opt, sourcefile, objectfile, targetfile) - - -- check - assert(opt and objectfile and targetfile) - - -- init the linker - local self = linker.init("binary") - assert(self and self._TOOL) - - -- init flags - local flags = {} - - -- add flags from the configure - linker._addflags_from_config(self, flags, "ldflags") - - -- add flags from the option - linker._addflags_from_option(self, flags, "ldflags", opt) - - -- add flags from the platform - linker._addflags_from_platform(self, flags, "ldflags") - - -- add flags from the links - linker._addflags_from_links(self, flags, opt:get("links")) - - -- add flags from the compiler - linker._addflags_from_compiler(self, flags, "ldflags", sourcefile) - - -- add flags from the linker - linker._addflags_from_linker(self, flags, "ldflags") - - -- remove repeat - flags = table.unique(flags) - - -- execute the link command - return self._TOOL:main(self._TOOL:command_link(objectfile, targetfile, table.concat(flags, " "):trim(), utils.ifelse(option.get("verbose"), nil, xmake._NULDEV))) -end - --- return module -return linker diff --git a/xmake/core/project/option.lua b/xmake/core/project/option.lua index 4cea021c4..c74fc4279 100644 --- a/xmake/core/project/option.lua +++ b/xmake/core/project/option.lua @@ -31,9 +31,34 @@ 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 linker = require("tool/linker") local compiler = require("tool/compiler") +-- check link +function option:_check_link(sourcefile, objectfile, targetfile) + + -- check + assert(sourcefile and objectfile and targetfile) + + -- update source kinds + self._SOURCEKINDS = compiler.kind_of_file(sourcefile) + + -- load the linker instance + local instance = linker.load("binary") + if not instance then + return false + end + + -- attempt to run this command + local ok, errors = instance:run(instance:command(self, objectfile, targetfile)) + if not ok and option_.get("verbose") then + print(errors) + end + + -- ok? + return ok +end + -- check include function option:_check_include(include, srcpath, objpath) @@ -61,7 +86,7 @@ function option:_check_include(include, srcpath, objpath) srcfile:close() -- load the compiler instance - local instance = compiler.load(srcpath) + local instance = compiler.load(compiler.kind_of_file(srcpath)) if not instance then return false end @@ -89,7 +114,7 @@ function option:_check_function(interface, srcpath, objpath) end -- load the compiler instance - local instance = compiler.load(srcpath) + local instance = compiler.load(compiler.kind_of_file(srcpath)) if not instance then return false end @@ -143,7 +168,7 @@ function option:_check_typedef(typedef, srcpath, objpath) end -- load the compiler instance - local instance = compiler.load(srcpath) + local instance = compiler.load(compiler.kind_of_file(srcpath)) if not instance then return false end @@ -206,7 +231,7 @@ function option:_check_links(cfile, objectfile, targetfile) local ok = self:_check_include(nil, cfile, objectfile) -- check link - if ok then ok = linker.check_links(self, cfile, objectfile, targetfile) end + if ok then ok = self:_check_link(cfile, objectfile, targetfile) end -- trace utils.printf("checking for the links %s ... %s", links_str, utils.ifelse(ok, "ok", "no")) @@ -282,7 +307,7 @@ function option:_check_cfuncs(cfile, objectfile, targetfile) 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 + if ok and self:get("links") then ok = self:_check_link(cfile, objectfile, targetfile) end -- trace utils.printf("checking for the c function %s ... %s", cfunc, utils.ifelse(ok, "ok", "no")) @@ -305,7 +330,7 @@ function option:_check_cxxfuncs(cxxfile, objectfile, targetfile) 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 + if ok and self:get("links") then ok = self:_check_link(cxxfile, objectfile, targetfile) end -- trace utils.printf("checking for the c++ function %s ... %s", cxxfunc, utils.ifelse(ok, "ok", "no")) @@ -441,5 +466,17 @@ function option.load(name) return instance end +-- get the kinds of sourcefiles +function option:sourcekinds() + + -- cached? return it directly + if self._SOURCEKINDS then + return self._SOURCEKINDS + end + + -- ok? + return {"cc", "cxx"} +end + -- return module return option diff --git a/xmake/core/project/project.lua b/xmake/core/project/project.lua index c52b52a05..252e75ab6 100644 --- a/xmake/core/project/project.lua +++ b/xmake/core/project/project.lua @@ -35,7 +35,6 @@ local target = require("project/target") local config = require("project/config") local option = require("project/option") local deprecated_project = require("project/deprecated/project") -local linker = require("platform/linker") 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 42a4df4bf..ef170fa4f 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -29,7 +29,7 @@ local path = require("base/path") local table = require("base/table") local option = require("project/option") local config = require("project/config") -local linker = require("platform/linker") +local linker = require("tool/linker") local compiler = require("tool/compiler") local platform = require("platform/platform") @@ -70,7 +70,7 @@ function target:linker() assert(self) -- init the linker from the given kind - local result, errors = linker.init(self:get("kind")) + local result, errors = linker.load(self:get("kind")) if not result then os.raise(errors) end @@ -87,7 +87,7 @@ function target:compiler(srcfile) assert(self and srcfile) -- load the compiler - local result, errors = compiler.load(srcfile) + local result, errors = compiler.load(compiler.kind_of_file(srcfile)) if not result then os.raise(errors) end @@ -311,6 +311,38 @@ function target:headerfiles() return srcheaders, dstheaders end +-- get the kinds of sourcefiles +-- +-- .e.g cc cxx mm mxx as ... +-- +function target:sourcekinds() + + -- cached? return it directly + if self._SOURCEKINDS then + return self._SOURCEKINDS + end + + -- make kinds + local kinds = {} + for _, sourcefile in pairs(self:sourcefiles()) do + + -- get kind + local kind = compiler.kind_of_file(sourcefile) + if kind then + table.insert(kinds, kind) + end + end + + -- remove repeat + kinds = table.unique(kinds) + + -- cache it + self._SOURCEKINDS = kinds + + -- ok? + return kinds +end + -- return module return target diff --git a/xmake/core/tool/compiler.lua b/xmake/core/tool/compiler.lua index 294a9c6c0..34510efd0 100644 --- a/xmake/core/tool/compiler.lua +++ b/xmake/core/tool/compiler.lua @@ -30,8 +30,8 @@ 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") +local tool = require("tool/tool") -- get the current tool function compiler:_tool() @@ -47,32 +47,6 @@ function compiler:_flagnames() 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) @@ -280,7 +254,7 @@ function compiler:_addflags_from_target(flags, target) if target.options then -- add the flags for the target options - for name, opt in pairs(target:options()) do + for _, opt in pairs(target:options()) do -- add the flags from the option self:_addflags_from_target(flags, opt) @@ -344,6 +318,32 @@ function compiler:_addflags_from_compiler(flags, kind) end 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 current kind function compiler:kind() @@ -351,26 +351,23 @@ function compiler:kind() return self._KIND end --- load the compiler from the given source file -function compiler.load(srcfile) +-- load the compiler from the given source kind +function compiler.load(sourcekind) - -- 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 + -- check + assert(sourcekind) -- get it directly from cache dirst compiler._INSTANCES = compiler._INSTANCES or {} - if compiler._INSTANCES[kind] then - return compiler._INSTANCES[kind] + if compiler._INSTANCES[sourcekind] then + return compiler._INSTANCES[sourcekind] end -- new instance local instance = table.inherit(compiler) -- load the compiler tool from the source file type - local result, errors = tool.load(kind) + local result, errors = tool.load(sourcekind) if not result then return nil, errors end @@ -379,7 +376,7 @@ function compiler.load(srcfile) instance._TOOL = result -- save kind - instance._KIND = kind + instance._KIND = sourcekind -- save flagnames local flagnames = @@ -391,20 +388,27 @@ function compiler.load(srcfile) , as = { "asflags" } , sc = { "scflags" } } - instance._FLAGNAMES = flagnames[kind] + instance._FLAGNAMES = flagnames[sourcekind] -- check if not instance._FLAGNAMES then - return nil, string.format("unknown compiler for kind: %s", kind) + return nil, string.format("unknown compiler for kind: %s", sourcekind) end -- save this instance - compiler._INSTANCES[kind] = instance + compiler._INSTANCES[sourcekind] = instance -- ok return instance end +-- get properties of the tool +function compiler:get(name) + + -- get it + return self:_tool():get(name) +end + -- run the command function compiler:run(cmd) diff --git a/xmake/core/tool/linker.lua b/xmake/core/tool/linker.lua new file mode 100644 index 000000000..482c3c8a3 --- /dev/null +++ b/xmake/core/tool/linker.lua @@ -0,0 +1,358 @@ +--!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 linker.lua +-- + +-- define module +local linker = linker 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 platform = require("platform/platform") +local tool = require("tool/tool") +local compiler = require("tool/compiler") + +-- get the current tool +function linker:_tool() + + -- get it + return self._TOOL +end + +-- get the current flag name +function linker:_flagname() + + -- get it + return self._FLAGNAME +end + +-- get the link kind of the target kind +function linker._kind_of_target(targetkind) + + -- the kinds + local kinds = + { + ["binary"] = "ld" + , ["static"] = "ar" + , ["shared"] = "sh" + } + + -- get kind + return kinds[targetkind] +end + +-- get the flags +function linker:_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:sourcekinds()) + + -- add flags from the linker + self:_addflags_from_linker(flags) + + -- 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 linker flag +function linker:_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 + + -- check it + if self:_tool():check(flag) then + return flag + end +end + +-- map gcc flags to the given linker flags +function linker:_mapflags(flags) + + -- wrap flags first + flags = table.wrap(flags) + + -- the linker 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 linker:_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 linker:_addflags_from_config(flags) + + -- done + table.join2(flags, config.get(self:_flagname())) +end + +-- add flags from the target +function linker:_addflags_from_target(flags, target) + + -- the compiler tool + local ctool = self:_tool() + + -- add the target flags + table.join2(flags, self:_mapflags(target:get(self:_flagname()))) + + -- add the linkdirs flags + for _, linkdir in ipairs(table.wrap(target:get("linkdirs"))) do + table.join2(flags, ctool:linkdir(linkdir)) + end + + -- add the links flags + for _, link in ipairs(table.wrap(target:get("links"))) do + table.join2(flags, ctool:link(link)) + end + + -- for target options? + if target.options then + + -- add the flags for the target options + for _, opt in pairs(target:options()) do + + -- add the flags from the option + table.join2(flags, self:_mapflags(opt:get(self:_flagname()))) + + -- add the linkdirs flags from the option + for _, linkdir in ipairs(table.wrap(opt:get("linkdirs"))) do + table.join2(flags, ctool:linkdir(linkdir)) + end + + -- add the links flags from the option + for _, link in ipairs(table.wrap(opt:get("links"))) do + table.join2(flags, ctool:link(link)) + end + end + end + + -- add the strip flags + table.join2(flags, self:_named_flags(target:get("strip"), { debug = "-S" + , all = "-s" + })) +end + +-- add flags from the platform +function linker:_addflags_from_platform(flags) + + -- the compiler tool + local ctool = self:_tool() + + -- add flags + table.join2(flags, self:_mapflags(platform.get(self:_flagname()))) + + -- add the linkdirs flags + for _, linkdir in ipairs(table.wrap(platform.get("linkdirs"))) do + table.join2(flags, ctool:linkdir(linkdir)) + end + + -- add the links flags + for _, link in ipairs(table.wrap(platform.get("links"))) do + table.join2(flags, ctool:link(link)) + end +end + +-- add flags from the compiler +function linker:_addflags_from_compiler(flags, srckinds) + + -- done + local flags_of_compiler = {} + for _, srckind in ipairs(table.wrap(srckinds)) do + + -- load compiler + local instance, errors = compiler.load(srckind) + if instance then + table.join2(flags_of_compiler, instance:get(self:_flagname())) + end + end + + -- add flags + table.join2(flags, table.unique(flags_of_compiler)) +end + +-- add flags from the linker +function linker:_addflags_from_linker(flags) + + -- done + table.join2(flags, self:_tool():get(self:_flagname())) +end + +-- get the current kind +function linker:kind() + + -- get it + return self._KIND +end + +-- load the linker from the given target kind +function linker.load(targetkind) + + -- get the linker kind + local kind = linker._kind_of_target(targetkind) + if not kind then + return nil, string.format("unknown target kind: %s", targetkind) + end + + -- get it directly from cache dirst + linker._INSTANCES = linker._INSTANCES or {} + if linker._INSTANCES[kind] then + return linker._INSTANCES[kind] + end + + -- new instance + local instance = table.inherit(linker) + + -- load the linker 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 flagname + local flagname = + { + ld = "ldflags" + , ar = "arflags" + , sh = "shflags" + } + instance._FLAGNAME = flagname[kind] + + -- check + if not instance._FLAGNAME then + return nil, string.format("unknown linker for kind: %s", kind) + end + + -- save this instance + linker._INSTANCES[kind] = instance + + -- ok + return instance +end + +-- get properties of the tool +function linker:get(name) + + -- get it + return self:_tool():get(name) +end + +-- run the command +function linker:run(cmd) + + -- get it + return self:_tool():run(cmd) +end + +-- get the command +function linker:command(target, objfiles, targetfile, logfile) + + -- get it + return self:_tool():command(table.concat(table.wrap(objfiles), " "), targetfile, self:_flags(target), logfile) +end + +-- return module +return linker diff --git a/xmake/core/tool/tool.lua b/xmake/core/tool/tool.lua index bca361388..75ef33a22 100644 --- a/xmake/core/tool/tool.lua +++ b/xmake/core/tool/tool.lua @@ -100,6 +100,39 @@ function _module:includedir(dir) return interface.includedir(dir) end +-- make the link flag +function _module:link(lib) + + -- the interface + local interface = self._INTERFACE + assert(interface) + + -- check + if not interface.link then + return + end + + -- make it + return interface.link(lib) +end + +-- TODO wrap dynamic +-- make the linkdir flag +function _module:linkdir(dir) + + -- the interface + local interface = self._INTERFACE + assert(interface) + + -- check + if not interface.linkdir then + return + end + + -- make it + return interface.linkdir(dir) +end + -- make the command function _module:command(srcfile, objfile, flags, logfile) @@ -174,15 +207,13 @@ function tool._directories(name) , mm = "compiler" , mxx = "compiler" , sc = "compiler" - , ar = "archiver" + , ar = "linker" , sh = "linker" , ld = "linker" - , make = "other" } -- get kind sub-directory - local subdir = kinds[name] - assert(subdir) + local subdir = kinds[name] or "" -- the directories return { path.join(path.join(config.directory(), "tools"), subdir) diff --git a/xmake/tools/compiler/gcc.lua b/xmake/tools/compiler/gcc.lua index 9d6e8a484..437948610 100755 --- a/xmake/tools/compiler/gcc.lua +++ b/xmake/tools/compiler/gcc.lua @@ -45,10 +45,6 @@ function init(shellname) ["-W1"] = "-Wall" , ["-W2"] = "-Wall" , ["-W3"] = "-Wall" - - -- strip - , ["-s"] = "-s" - , ["-S"] = "-S" } end diff --git a/xmake/tools/linker/ar.lua b/xmake/tools/linker/ar.lua new file mode 100644 index 000000000..12beaab0a --- /dev/null +++ b/xmake/tools/linker/ar.lua @@ -0,0 +1,44 @@ +--!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 ar.lua +-- + +-- init it +function init(shellname) + + -- save the shell name + _g.shellname = shellname or "ar" + + -- init arflags + _g.arflags = { "-crs" } + +end + +-- make the command +function command(objfiles, targetfile, flags, logfile) + + -- redirect + local redirect = "" + if logfile then redirect = format(" > %s 2>&1", logfile) end + + -- make it + return format("%s %s %s %s%s", _g.shellname, flags, targetfile, objfiles, redirect) +end + diff --git a/xmake/tools/linker/clang++.lua b/xmake/tools/linker/clang++.lua new file mode 100755 index 000000000..6b2feaa2f --- /dev/null +++ b/xmake/tools/linker/clang++.lua @@ -0,0 +1,33 @@ +--!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 +-- + +-- inherit clang +inherit("clang") + +-- init it +function init(shellname) + + -- init super + _super.init(shellname or "clang++") + +end + diff --git a/xmake/tools/linker/clang.lua b/xmake/tools/linker/clang.lua new file mode 100755 index 000000000..712b578e3 --- /dev/null +++ b/xmake/tools/linker/clang.lua @@ -0,0 +1,40 @@ +--!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 +-- + +-- inherit gcc +inherit("gcc") + +-- init it +function init(shellname) + + -- init super + _super.init(shellname or "clang") + + -- init shflags + _super._g.shflags = { "-dynamiclib", "-fPIC" } + + -- init flags map + _super._g.mapflags["-s"] = "-Wl,-S" + _super._g.mapflags["-S"] = "-Wl,-S" + +end + diff --git a/xmake/tools/linker/g++.lua b/xmake/tools/linker/g++.lua new file mode 100755 index 000000000..7b2837b8e --- /dev/null +++ b/xmake/tools/linker/g++.lua @@ -0,0 +1,33 @@ +--!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 g++.lua +-- + +-- inherit gcc +inherit("gcc") + +-- init it +function init(shellname) + + -- init super + _super.init(shellname or "g++") + +end + diff --git a/xmake/tools/linker/gcc.lua b/xmake/tools/linker/gcc.lua new file mode 100755 index 000000000..6bc839768 --- /dev/null +++ b/xmake/tools/linker/gcc.lua @@ -0,0 +1,95 @@ +--!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 shflags + _g.shflags = { "-shared", "-fPIC" } + + -- init flags map + _g.mapflags = + { + -- strip + ["-s"] = "-s" + , ["-S"] = "-S" + + } +end + +-- get the property +function get(name) + + -- get it + return _g[name] +end + +-- make the link flag +function link(lib) + + -- make it + return "-l" .. lib +end + +-- make the linkdir flag +function linkdir(dir) + + -- make it + return "-L" .. dir +end + +-- make the command +function command(objfiles, targetfile, flags, logfile) + + -- redirect + local redirect = "" + if logfile then redirect = format(" > %s 2>&1", logfile) end + + -- make it + return format("%s -o %s %s %s%s", _g.shellname, targetfile, objfiles, flags, 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 + diff --git a/xmake/tools/make.lua b/xmake/tools/make.lua new file mode 100644 index 000000000..8cab41067 --- /dev/null +++ b/xmake/tools/make.lua @@ -0,0 +1,76 @@ +--!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 make.lua +-- + +-- imports +import("core.base.option") + +-- init it +function init(shellname) + + -- save name + _g.shellname = shellname or "make" + +end + +-- run it +function run(makefile, target, jobs) + + -- enable jobs? + if jobs ~= nil then + if tonumber(jobs) ~= 0 then + jobs = "-j" .. jobs + else + jobs = "-j" + end + else + jobs = "" + end + + -- is verbose? + local verbose = ifelse(option.get("verbose"), "-v", "") + + -- run it + local ok = nil + if makefile and os.isfile(makefile) then + ok = os.execute("%s -r %s -f %s %s VERBOSE=%s", _g.shellname, jobs, makefile, target or "", verbose) + else + ok = os.execute("%s -r %s %s VERBOSE=%s", _g.shellname, jobs, target or "", verbose) + end + + -- failed + if ok ~= 0 then + + -- attempt to run it again for getting the error logs without jobs + if makefile and os.isfile(makefile) then + ok = os.execute("%s -r -f %s %s VERBOSE=%s", _g.shellname, makefile, target or "", verbose) + else + ok = os.execute("%s -r %s VERBOSE=%s", _g.shellname, target or "", verbose) + end + + end + + -- always failed? + if ok ~= 0 then + raise(ok) + end + +end |
