summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2017-03-02 10:46:55 +0800
committerruki <[email protected]>2017-03-02 10:47:07 +0800
commit84bd8688218ab1d028eece27cef155b80bc32789 (patch)
treea6d70638c79d8a7bff660a98bbd6186f691d444b
parent2db00e130e92302f04eaba6e4c2936fe0879b5fc (diff)
improve makefile generator
-rw-r--r--xmake/core/language/language.lua42
-rw-r--r--xmake/core/sandbox/modules/import/core/language/language.lua7
-rw-r--r--xmake/core/sandbox/modules/io.lua14
-rwxr-xr-xxmake/plugins/project/makefile/makefile.lua92
4 files changed, 140 insertions, 15 deletions
diff --git a/xmake/core/language/language.lua b/xmake/core/language/language.lua
index 1b2eff42c..1c39272e6 100644
--- a/xmake/core/language/language.lua
+++ b/xmake/core/language/language.lua
@@ -631,5 +631,47 @@ function language.linkerinfos_of(targetkind, sourcekinds)
return nil, string.format("no suitable linker for %s.{%s}", targetkind, table.concat(sourcekinds, ' '))
end
+-- get language target kinds
+--
+-- .e.g
+--
+-- {
+-- binary = {"ld", "gc-ld", "dc-ld"}
+-- , static = {"ar", "gc-ar", "dc-ar"}
+-- , shared = {"sh", "dc-sh"}
+-- }
+--
+function language.targetkinds()
+
+ -- attempt to get it from cache
+ if language._TARGETKINDS then
+ return language._TARGETKINDS
+ end
+
+ -- load all languages
+ local languages, errors = language.load()
+ if not languages then
+ os.raise(errors)
+ end
+
+ -- merge all for each language
+ local targetkinds = {}
+ for name, instance in pairs(languages) do
+ for targetkind, linkerkind in pairs(instance:targetkinds()) do
+ targetkinds[targetkind] = targetkinds[targetkind] or {}
+ table.insert(targetkinds[targetkind], linkerkind)
+ end
+ end
+ for targetkind, linkerkinds in pairs(targetkinds) do
+ targetkinds[targetkind] = table.unique(linkerkinds)
+ end
+
+ -- cache it
+ language._TARGETKINDS = targetkinds
+
+ -- ok
+ return targetkinds
+end
+
-- return module
return language
diff --git a/xmake/core/sandbox/modules/import/core/language/language.lua b/xmake/core/sandbox/modules/import/core/language/language.lua
index c65516661..98494d6e5 100644
--- a/xmake/core/sandbox/modules/import/core/language/language.lua
+++ b/xmake/core/sandbox/modules/import/core/language/language.lua
@@ -36,6 +36,13 @@ function sandbox_core_language.extensions()
return language.extensions()
end
+-- get the target kinds of all languages
+function sandbox_core_language.targetkinds()
+
+ -- get it
+ return language.targetkinds()
+end
+
-- get the source kinds of all languages
function sandbox_core_language.sourcekinds()
diff --git a/xmake/core/sandbox/modules/io.lua b/xmake/core/sandbox/modules/io.lua
index eb66397ca..7a34cc649 100644
--- a/xmake/core/sandbox/modules/io.lua
+++ b/xmake/core/sandbox/modules/io.lua
@@ -25,6 +25,7 @@
-- load modules
local io = require("base/io")
local utils = require("base/utils")
+local string = require("base/string")
local raise = require("sandbox/modules/raise")
local vformat = require("sandbox/modules/vformat")
@@ -89,6 +90,9 @@ function sandbox_io.open(filepath, mode)
file.print = sandbox_io._print
file.printf = sandbox_io._printf
+ -- add writef with format
+ file.writef = sandbox_io._writef
+
-- ok?
return file
end
@@ -187,6 +191,16 @@ function sandbox_io._printf(self, ...)
return self._FILE:write(vformat(...))
end
+-- writef file
+function sandbox_io._writef(self, ...)
+
+ -- check
+ assert(self._FILE)
+
+ -- printf it
+ return self._FILE:write(string.format(...))
+end
+
-- cat the given file
function sandbox_io.cat(filepath, linecount)
diff --git a/xmake/plugins/project/makefile/makefile.lua b/xmake/plugins/project/makefile/makefile.lua
index 99c685368..7350a9b4e 100755
--- a/xmake/plugins/project/makefile/makefile.lua
+++ b/xmake/plugins/project/makefile/makefile.lua
@@ -27,6 +27,7 @@ import("core.tool.tool")
import("core.tool.compiler")
import("core.project.config")
import("core.project.project")
+import("core.language.language")
-- get log makefile
function _logfile()
@@ -48,9 +49,6 @@ end
-- copy file
function _cp(makefile, sourcefile, targetfile)
- -- ensure the destinate directory
- _mkdir(makefile, path.directory(targetfile))
-
-- copy file
if config.get("plat") == "windows" then
makefile:print("\t@copy /Y %s %s > /null 2>&1", sourcefile, targetfile)
@@ -90,20 +88,29 @@ end
-- make the object
function _make_object(makefile, target, sourcefile, objectfile)
- -- get the source file type
- local filetype = path.extension(sourcefile):lower()
+ -- get the source file kind
+ local sourcekind = language.sourcekind_of(sourcefile)
-- make the object for the *.o/obj source makefile
- if filetype == ".o" or filetype == ".obj" then
+ if sourcekind == "obj" then
return _make_object_for_object(makefile, target, sourcefile, objectfile)
-- make the object for the *.[a|lib] source file
- elseif filetype == ".a" or filetype == ".lib" then
+ elseif sourcekind == "lib" then
return _make_object_for_static(makefile, target, sourcefile, objectfile)
end
+ -- get shellname name
+ local shellname = tool.shellname(sourcekind)
+
-- make command
local command = compiler.compcmd(sourcefile, objectfile, target)
+ -- replace shellname to $(XX)
+ local p, e = command:find(shellname, 1, true)
+ if p then
+ command = format("%s$(%s)%s", command:sub(1, p - 1), sourcekind:upper(), command:sub(e + 1))
+ end
+
-- make head
makefile:printf("%s:", objectfile)
@@ -113,7 +120,7 @@ function _make_object(makefile, target, sourcefile, objectfile)
-- make body
makefile:print("\t@echo %scompiling.$(mode) %s", ifelse(config.get("ccache"), "ccache ", ""), sourcefile)
_mkdir(makefile, path.directory(objectfile))
- makefile:print("\t@%s > %s 2>&1", command, _logfile())
+ makefile:writef("\t@%s > %s 2>&1\n", command, _logfile())
-- make tail
makefile:print("")
@@ -136,9 +143,18 @@ function _make_single_object(makefile, target, sourcekind, sourcebatch)
local objectfiles = sourcebatch.objectfiles
local incdepfiles = sourcebatch.incdepfiles
+ -- get shellname name
+ local shellname = tool.shellname(sourcekind)
+
-- make command
local command = compiler.compcmd(sourcefiles, objectfiles, target, sourcekind)
+ -- replace shellname to $(XX)
+ local p, e = command:find(shellname, 1, true)
+ if p then
+ command = format("%s$(%s)%s", command:sub(1, p - 1), sourcekind:upper(), command:sub(e + 1))
+ end
+
-- make head
makefile:printf("%s:", objectfiles)
@@ -153,7 +169,7 @@ function _make_single_object(makefile, target, sourcekind, sourcebatch)
makefile:print("\t@echo %scompiling.$(mode) %s", ifelse(config.get("ccache"), "ccache ", ""), sourcefile)
end
_mkdir(makefile, path.directory(objectfiles))
- makefile:print("\t@%s > %s 2>&1", command, _logfile())
+ makefile:writef("\t@%s > %s 2>&1\n", command, _logfile())
-- make tail
makefile:print("")
@@ -183,13 +199,37 @@ function _make_target(makefile, target)
-- make dependence end
makefile:print("")
+ -- get linker kind
+ local linkerkind = target:linker():get("kind")
+
+ -- get shellname
+ local shellname = tool.shellname(linkerkind)
+
+ -- get command
+ local command = target:linkcmd()
+
+ -- replace shellname to $(XX)
+ local p, e = command:find(shellname, 1, true)
+ if p then
+ command = format("%s$(%s)%s", command:sub(1, p - 1), (linkerkind:upper():gsub('%-', '_')), command:sub(e + 1))
+ end
+
-- make body
makefile:print("\t@echo linking.$(mode) %s", path.filename(targetfile))
_mkdir(makefile, path.directory(targetfile))
- makefile:print("\t@%s > %s 2>&1", target:linkcmd(), _logfile())
+ makefile:writef("\t@%s > %s 2>&1\n", command, _logfile())
- -- make headers
+ -- make header directories
+ local dstheaderdirs = {}
local srcheaders, dstheaders = target:headerfiles()
+ for _, dstheader in ipairs(dstheaders) do
+ dstheaderdirs[path.directory(dstheader)] = true
+ end
+ for dstheaderdir, _ in pairs(dstheaderdirs) do
+ _mkdir(makefile, dstheaderdir)
+ end
+
+ -- copy headers
if srcheaders and dstheaders then
local i = 1
for _, srcheader in ipairs(srcheaders) do
@@ -223,14 +263,36 @@ end
-- make all
function _make_all(makefile)
- -- make all first
+ -- make variables for source kinds
+ for sourcekind, _ in pairs(language.sourcekinds()) do
+ local shellname = tool.shellname(sourcekind)
+ if shellname and shellname ~= "" then
+ makefile:print("%s=%s", sourcekind:upper(), shellname)
+ end
+ end
+ makefile:print("")
+
+ -- make variables for linker kinds
+ local linkerkinds = {}
+ for _, _linkerkinds in pairs(language.targetkinds()) do
+ table.join2(linkerkinds, _linkerkinds)
+ end
+ for _, linkerkind in ipairs(table.unique(linkerkinds)) do
+ local shellname = tool.shellname(linkerkind)
+ if shellname and shellname ~= "" then
+ makefile:print("%s=%s", (linkerkind:upper():gsub('%-', '_')), shellname)
+ end
+ end
+ makefile:print("")
+
+ -- make all
local all = ""
- for targetname, _ in pairs(project.targets()) do
+ for targetname, target in pairs(project.targets()) do
-- append the target name to all
all = all .. " " .. targetname
end
- makefile:printf("all: %s\n\n", all)
- makefile:printf(".PHONY: all %s\n\n", all)
+ makefile:print("all: %s\n", all)
+ makefile:print(".PHONY: all %s\n", all)
-- make it for all targets
for _, target in pairs(project.targets()) do