diff options
| author | ruki <[email protected]> | 2015-06-01 10:03:16 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2015-06-01 10:09:10 +0800 |
| commit | 7381a36a64f50a6db22155ebce996351201b90cb (patch) | |
| tree | fea64527b0cf27c3d00691752ceca2a678546646 /xmake/scripts | |
| parent | a32ad41a1812ad88043c0ecd0a09301267de9871 (diff) | |
add linker and make link command
Diffstat (limited to 'xmake/scripts')
| -rw-r--r-- | xmake/scripts/base/makefile.lua | 113 | ||||
| -rw-r--r-- | xmake/scripts/linker/_ar.lua | 51 | ||||
| -rw-r--r-- | xmake/scripts/linker/_clang.lua | 58 | ||||
| -rw-r--r-- | xmake/scripts/linker/linker.lua | 171 | ||||
| -rw-r--r-- | xmake/scripts/platform/macosx/_macosx.lua | 6 | ||||
| -rw-r--r-- | xmake/scripts/platform/platform.lua | 35 | ||||
| -rw-r--r-- | xmake/scripts/platform/windows/_windows.lua | 2 |
7 files changed, 370 insertions, 66 deletions
diff --git a/xmake/scripts/base/makefile.lua b/xmake/scripts/base/makefile.lua index 160d65bf7..7d873665b 100644 --- a/xmake/scripts/base/makefile.lua +++ b/xmake/scripts/base/makefile.lua @@ -32,6 +32,27 @@ local config = require("base/config") local project = require("base/project") local platform = require("platform/platform") +-- get the linker from the given kind +function makefile._linker(kind) + + -- init linkers + makefile._LINKERS = makefile._LINKERS or {} + local linkers = makefile._LINKERS + + -- return it directly if the linker has been cached + local l = linkers[kind] + if l then return l end + + -- get compiler from the current platform + l = platform.linker(kind) + + -- cache this compiler + linkers[kind] = l + + -- ok + return l +end + -- get the compiler from the given source file function makefile._compiler(srcfile) @@ -54,7 +75,7 @@ function makefile._compiler(srcfile) else return nil, string.format("unknown file type: %s", filetype) end - -- init compiler + -- init compilers makefile._COMPILERS = makefile._COMPILERS or {} local compilers = makefile._COMPILERS @@ -126,17 +147,13 @@ function makefile._objfiles(name, srcfiles) local buildir = config.get("buildir") assert(buildir) - -- the object file format - local format = platform.format("object") - assert(format) - -- make object files local i = 1 local objfiles = {} for _, srcfile in ipairs(srcfiles) do -- make object file - local objfile = string.format("%s/%s/%s/%s%s%s", buildir, name, path.directory(srcfile), format[1], path.basename(srcfile), format[2]) + local objfile = string.format("%s/%s/%s/%s", buildir, name, path.directory(srcfile), platform.filename(path.basename(srcfile), "object")) -- save it objfiles[i] = path.translate(objfile) @@ -148,43 +165,22 @@ function makefile._objfiles(name, srcfiles) return objfiles end --- make the console to the makefile -function makefile._make_console(file, target, objfiles) - - -- check - assert(file and target and objfiles) - - -- make it - file:write(string.format("\techo console\n")) +-- get target file for the given target name and kind +function makefile._targetfile(name, kind) - -- ok - return true -end - --- make the static library to the makefile -function makefile._make_static(file, target, objfiles) - -- check - assert(file and target and objfiles) - - -- make it - file:write(string.format("\techo static\n")) + assert(name and kind) - -- ok - return true -end - --- make the shared library to the makefile -function makefile._make_shared(file, target, objfiles) - - -- check - assert(file and target and objfiles) - - -- make it - file:write(string.format("\techo shared\n")) + -- the build directory + local buildir = config.get("buildir") + assert(buildir) + + -- the target file name + local filename = platform.filename(name, kind) + assert(filename) - -- ok - return true + -- make the target file path + return buildir .. "/" .. name .. "/" .. filename end -- make the object to the makefile @@ -253,10 +249,26 @@ function makefile._make_target(file, name, target) local objfiles = makefile._objfiles(name, srcfiles) assert(srcfiles and objfiles) + -- get target file + local targetfile = makefile._targetfile(name, target.kind) + assert(targetfile) + + -- the linker + local l = makefile._linker(target.kind) + assert(l) + + -- the make command + local make_command = l["make_" .. target.kind] + if not make_command then + -- error + utils.error("the target kind: %s in not surpported now!", target.kind) + return false + end + -- make head file:write(string.format("%s:", name)) - -- make dependence for target + -- make dependence for the dependent targets if target.deps then local deps = utils.wrap(target.deps) for _, dep in ipairs(deps) do @@ -273,24 +285,9 @@ function makefile._make_target(file, name, target) file:write("\n") -- make body - local ok = false - if target.kind == "console" then - ok = makefile._make_console(file, target, objfiles) - elseif target.kind == "static" then - ok = makefile._make_static(file, target, objfiles) - elseif target.kind == "shared" then - ok = makefile._make_shared(file, target, objfiles) - else - -- error - utils.error("the target kind: %s in not surpported now!", target.kind) - return false - end - - -- error? - if not ok then - utils.error("make target with kind: %s failed!", target.kind) - return false - end + file:write(string.format("\t@echo [%s]: linking %s\n", config.get("mode"), path.filename(targetfile))) + file:write(string.format("\t@xmake l mkdir %s\n", path.directory(targetfile))) + file:write(string.format("\t@%s\n", make_command(l, objfiles, targetfile, ""))) -- make tail file:write("\n") diff --git a/xmake/scripts/linker/_ar.lua b/xmake/scripts/linker/_ar.lua new file mode 100644 index 000000000..39aeadc56 --- /dev/null +++ b/xmake/scripts/linker/_ar.lua @@ -0,0 +1,51 @@ +--!The Automatic Cross-_ar 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) 2009 - 2015, ruki All rights reserved. +-- +-- @author ruki +-- @file _ar.lua +-- + +-- define module: _ar +local _ar = _ar or {} + +-- load modules +local utils = require("base/utils") +local string = require("base/string") +local config = require("base/config") + +-- init the linker +function _ar._init(configs) + +end + +-- make the static library command +function _ar._make_static(configs, objfiles, targetfile, flags) + + -- make it + return string.format("%s -crs %s %s %s", configs.name, flags, targetfile, table.concat(objfiles)) +end + +-- map gcc flag to the current linker flag +function _ar._mapflag(configs, flag) + + -- ok + return flag +end + +-- return module: _ar +return _ar diff --git a/xmake/scripts/linker/_clang.lua b/xmake/scripts/linker/_clang.lua new file mode 100644 index 000000000..062bbc455 --- /dev/null +++ b/xmake/scripts/linker/_clang.lua @@ -0,0 +1,58 @@ +--!The Automatic Cross-_clang 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) 2009 - 2015, ruki All rights reserved. +-- +-- @author ruki +-- @file _clang.lua +-- + +-- define module: _clang +local _clang = _clang or {} + +-- load modules +local utils = require("base/utils") +local string = require("base/string") +local config = require("base/config") + +-- init the linker +function _clang._init(configs) + +end + +-- make the binary command +function _clang._make_binary(configs, objfiles, targetfile, flags) + + -- make it + return string.format("%s -o%s %s %s", configs.name, table.concat(objfiles), targetfile, flags) +end + +-- make the shared library command +function _clang._make_shared(configs, objfiles, targetfile, flags) + + -- make it + return string.format("%s -dynamiclib -o%s %s %s", configs.name, table.concat(objfiles), targetfile, flags) +end + +-- map gcc flag to the current linker flag +function _clang._mapflag(configs, flag) + + -- ok + return flag +end + +-- return module: _clang +return _clang diff --git a/xmake/scripts/linker/linker.lua b/xmake/scripts/linker/linker.lua new file mode 100644 index 000000000..9f3cfe184 --- /dev/null +++ b/xmake/scripts/linker/linker.lua @@ -0,0 +1,171 @@ +--!The Automatic Cross-linker 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) 2009 - 2015, ruki All rights reserved. +-- +-- @author ruki +-- @file linker.lua +-- + +-- define module: linker +local linker = linker or {} + +-- load modules +local utils = require("base/utils") +local string = require("base/string") +local config = require("base/config") + +-- get the configure from the given name +function linker._get(self, name) + + -- check + assert(self and name); + + -- the linker configure + local configs = self._CONFIGS + assert(configs) + + -- get it + return configs[name] +end + +-- make the binary command +function linker._make_binary(self, objfiles, targetfile, flags) + + -- check + assert(self and self._make_binary) + + -- the configure + local configs = self._CONFIGS + assert(configs) + + -- make it + return self._make_binary(configs, objfiles, targetfile, flags) +end + +-- make the static library command +function linker._make_static(self, objfiles, targetfile, flags) + + -- check + assert(self and self._make_static) + + -- the configure + local configs = self._CONFIGS + assert(configs) + + -- make it + return self._make_static(configs, objfiles, targetfile, flags) +end + +-- make the shared library command +function linker._make_shared(self, objfiles, targetfile, flags) + + -- check + assert(self and self._make_shared) + + -- the configure + local configs = self._CONFIGS + assert(configs) + + -- make it + return self._make_shared(configs, objfiles, targetfile, flags) +end + +-- map gcc flags to the given linker flags +function linker._mapflags(self, flags) + + -- check + assert(self and flags); + + -- need not map flags? return it directly + if not self.mapflag then + return flags + end + + -- the configure + local configs = self._CONFIGS + assert(configs) + + -- map flags + local flags_mapped = {} + for _, flag in pairs(flags) do + -- map it + local flag_mapped = self._mapflag(configs, flag) + if flag_mapped then + flags_mapped[table.getn(flags_mapped) + 1] = flag_mapped + end + end + + -- ok? + return flag_mapped +end + +-- load the given linker +function linker.load(name) + + -- check + assert(name and type(name) == "string") + + -- gcc? + local module = nil + if name:find("gcc", 1, true) then module = "gcc" + -- clang? + elseif name:find("clang", 1, true) then module = "clang" + -- ar? + elseif name:find("ar", 1, true) then module = "ar" + -- cl.exe? + elseif name:find("link.exe", 1, true) then module = "msvc" + -- unknown? + else + -- error + utils.error("unknown linker: %s", name) + return nil + end + + -- load the given linker + local l = require("linker/_" .. module) + if not l then + return nil + end + + -- the linker has been loaded? return it directly + if l._CONFIGS then + return l + end + + -- make the linker configure + l._CONFIGS = {} + local configs = l._CONFIGS + + -- init the linker name + configs.name = name + + -- init the linker configure + l._init(configs) + + -- init interfaces + l["get"] = linker._get + l["mapflags"] = linker._mapflags + l["make_binary"] = linker._make_binary + l["make_static"] = linker._make_static + l["make_shared"] = linker._make_shared + + -- ok? + return l +end + +-- return module: linker +return linker diff --git a/xmake/scripts/platform/macosx/_macosx.lua b/xmake/scripts/platform/macosx/_macosx.lua index 85b2822a1..b23204224 100644 --- a/xmake/scripts/platform/macosx/_macosx.lua +++ b/xmake/scripts/platform/macosx/_macosx.lua @@ -51,6 +51,12 @@ function _macosx.make(configs) configs.compiler.mm = config.get("mm") or configs.compiler.cc configs.compiler.mxx = config.get("mxx") or configs.compiler.cxx + -- init the linker + configs.linker = {} + configs.linker.binary = config.get("ld") or "xcrun -sdk macosx clang++" + configs.linker.static = config.get("ar") or "xcrun -sdk macosx ar" + configs.linker.shared = config.get("ld") or "xcrun -sdk macosx clang++" + -- init xcode sdk directory configs.xcode_sdkdir = config.get("xcode_dir") .. "/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX" .. config.get("xcode_sdkver") .. ".sdk" end diff --git a/xmake/scripts/platform/platform.lua b/xmake/scripts/platform/platform.lua index 920aeab14..57f50576c 100644 --- a/xmake/scripts/platform/platform.lua +++ b/xmake/scripts/platform/platform.lua @@ -28,6 +28,7 @@ local os = require("base/os") local path = require("base/path") local utils = require("base/utils") local config = require("base/config") +local linker = require("linker/linker") local compiler = require("compiler/compiler") -- load the given platform @@ -86,18 +87,38 @@ function platform.get(name) end end --- get the format from the given kind -function platform.format(kind) +-- get the filename from the given name and kind +function platform.filename(name, kind) -- check - assert(kind) + assert(name and kind) + + -- get formats + local formats = platform.get("format") + assert(formats) -- get format - local format = platform.get("format") - assert(format) + local format = formats[kind] or {"", ""} + + -- make it + return format[1] .. name .. format[2] +end + +-- get the linker from the given name +function platform.linker(name) + + -- check + assert(name) + + -- get linker + local c = platform.get("linker") + assert(c) - -- get it - return format[kind] or {"", ""} + -- load linker + c = c[name] + if c then + return linker.load(c) + end end -- get the compiler from the given name diff --git a/xmake/scripts/platform/windows/_windows.lua b/xmake/scripts/platform/windows/_windows.lua index 576160719..a2feb23fa 100644 --- a/xmake/scripts/platform/windows/_windows.lua +++ b/xmake/scripts/platform/windows/_windows.lua @@ -43,7 +43,7 @@ function _windows.make(configs) configs.format.static = {"", ".lib"} configs.format.object = {"", ".obj"} configs.format.shared = {"", ".dll"} - configs.format.console = {"", ".exe"} + configs.format.execute = {"", ".exe"} end -- get the option menu for action: xmake config or global |
