summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2015-06-01 10:03:16 +0800
committerruki <[email protected]>2015-06-01 10:09:10 +0800
commit7381a36a64f50a6db22155ebce996351201b90cb (patch)
treefea64527b0cf27c3d00691752ceca2a678546646
parenta32ad41a1812ad88043c0ecd0a09301267de9871 (diff)
add linker and make link command
-rw-r--r--tests/console/xmake.xproj8
-rw-r--r--xmake/scripts/base/makefile.lua113
-rw-r--r--xmake/scripts/linker/_ar.lua51
-rw-r--r--xmake/scripts/linker/_clang.lua58
-rw-r--r--xmake/scripts/linker/linker.lua171
-rw-r--r--xmake/scripts/platform/macosx/_macosx.lua6
-rw-r--r--xmake/scripts/platform/platform.lua35
-rw-r--r--xmake/scripts/platform/windows/_windows.lua2
8 files changed, 374 insertions, 70 deletions
diff --git a/tests/console/xmake.xproj b/tests/console/xmake.xproj
index b1aeba5df..aae24e89e 100644
--- a/tests/console/xmake.xproj
+++ b/tests/console/xmake.xproj
@@ -50,7 +50,7 @@ project: console
target: demo_c
{
- kind: console
+ kind: binary
deps: hello1
files: src/demo/*.c
links: hello1
@@ -67,7 +67,7 @@ project: console
target: demo_cpp
{
- kind: console
+ kind: binary
deps: hello2
files: src/demo/*.cpp
links: hello2
@@ -78,7 +78,7 @@ project: console
target: demo_objc
{
- kind: console
+ kind: binary
deps: hello3
files: src/demo/*.m
links: hello3
@@ -89,7 +89,7 @@ project: console
target: demo_objcpp
{
- kind: console
+ kind: binary
deps: hello3
files: src/demo/*.mm
mxflags: -DHELLO3
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