summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2017-07-27 19:27:12 +0800
committerruki <[email protected]>2017-07-27 19:27:12 +0800
commit6f2c9ecd0d7ea9f2fbfab79b6960eb1274ca816a (patch)
tree322b4e7ba82e82ce8a6d0c4b56d044bbcde2d010
parent84defbee206dd2d810070bfae7b7e269a3445896 (diff)
impl compile pch for gcc
-rw-r--r--xmake/actions/build/kinds/object.lua38
-rw-r--r--xmake/core/language/language.lua13
-rw-r--r--xmake/core/project/target.lua43
-rw-r--r--xmake/core/sandbox/modules/import/core/language/language.lua13
-rw-r--r--xmake/core/tool/builder.lua4
-rw-r--r--xmake/languages/c++/api.lua2
-rw-r--r--xmake/languages/c++/xmake.lua1
-rw-r--r--xmake/languages/objc++/api.lua2
-rw-r--r--xmake/languages/objc++/xmake.lua1
-rw-r--r--xmake/modules/core/tools/gcc.lua113
10 files changed, 178 insertions, 52 deletions
diff --git a/xmake/actions/build/kinds/object.lua b/xmake/actions/build/kinds/object.lua
index 24429d251..e0a35e29c 100644
--- a/xmake/actions/build/kinds/object.lua
+++ b/xmake/actions/build/kinds/object.lua
@@ -80,15 +80,16 @@ function _build_object(target, buildinfo, index, sourcebatch, ccache)
local sourcefile = sourcebatch.sourcefiles[index]
local objectfile = sourcebatch.objectfiles[index]
local incdepfile = sourcebatch.incdepfiles[index]
+ local sourcekind = sourcebatch.sourcekind
-- calculate percent
local percent = ((buildinfo.targetindex + (_g.sourceindex + index - 1) / _g.sourcecount) * 100 / buildinfo.targetcount)
-- build the object for the *.o/obj source makefile
- if sourcebatch.sourcekind == "obj" then
+ if sourcekind == "obj" then
return _build_from_object(target, sourcefile, objectfile, percent)
-- build the object for the *.[a|lib] source file
- elseif sourcebatch.sourcekind == "lib" then
+ elseif sourcekind == "lib" then
return _build_from_static(target, sourcefile, objectfile, percent)
end
@@ -155,11 +156,11 @@ function _build_object(target, buildinfo, index, sourcebatch, ccache)
-- trace verbose info
if verbose then
- print(compiler.compcmd(sourcefile, objectfile, {target = target}))
+ print(compiler.compcmd(sourcefile, objectfile, {target = target, sourcekind = sourcekind}))
end
-- complie it
- compiler.compile(sourcefile, objectfile, {incdepfiles = incdepfile, target = target})
+ compiler.compile(sourcefile, objectfile, {incdepfiles = incdepfile, target = target, sourcekind = sourcekind})
end
-- build each objects from the given source batch
@@ -221,6 +222,31 @@ function _build_single_object(target, buildinfo, sourcekind, sourcebatch, jobs,
_g.sourceindex = _g.sourceindex + #sourcebatch.sourcefiles
end
+-- build precompiled header (only for c/c++)
+function _build_precompiled_header(target, buildinfo)
+
+ -- get the precompiled header
+ local precompiled_header = target:get("precompiled_header")
+ if not precompiled_header then
+ return
+ end
+
+ -- init sourcekinds
+ local sourcekinds = {[".h"] = "cc", [".hpp"] = "cxx"}
+
+ -- init sourcefile, objectfile and incdepfile
+ local sourcefile = precompiled_header
+ local objectfile = target:pcheaderfile()
+ local incdepfile = objectfile .. ".d"
+ local sourcekind = sourcekinds[path.extension(precompiled_header)] or "cc"
+
+ -- init source batch
+ local sourcebatch = {sourcekind = sourcekind, sourcefiles = {sourcefile}, objectfiles = {objectfile}, incdepfiles = {incdepfile}}
+
+ -- build this precompiled header
+ _build_object(target, buildinfo, 1, sourcebatch, false)
+end
+
-- build objects for the given target
function build(target, buildinfo)
@@ -237,6 +263,9 @@ function build(target, buildinfo)
ccache = find_ccache()
end
+ -- build precompiled header
+ _build_precompiled_header(target, buildinfo)
+
-- build source batches
for sourcekind, sourcebatch in pairs(target:sourcebatches()) do
@@ -245,7 +274,6 @@ function build(target, buildinfo)
-- build single object
_build_single_object(target, buildinfo, sourcekind, sourcebatch, jobs, ccache)
-
else
-- build each objects
diff --git a/xmake/core/language/language.lua b/xmake/core/language/language.lua
index 8bf9395ae..4aa10c5e4 100644
--- a/xmake/core/language/language.lua
+++ b/xmake/core/language/language.lua
@@ -561,6 +561,19 @@ function language.sourcekind_of(sourcefile)
return sourcekind
end
+-- get extension of the source kind
+function language.extension_of(sourcekind)
+
+ -- get extension
+ local extension = table.wrap(language.sourcekinds()[sourcekind])[1]
+ if not extension then
+ return nil, string.format("%s is unknown source kind", sourcekind)
+ end
+
+ -- ok
+ return extension
+end
+
-- get linker infos(kind and flag) of the target kind and the source kinds
function language.linkerinfos_of(targetkind, sourcekinds)
diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua
index f001f1fa2..beb7bfef2 100644
--- a/xmake/core/project/target.lua
+++ b/xmake/core/project/target.lua
@@ -200,9 +200,6 @@ end
-- get the object file directory
function target:objectdir()
- -- check
- assert(self)
-
-- the object directory
local objectdir = self:get("objectdir")
if not objectdir then
@@ -217,17 +214,12 @@ end
-- get the target kind
function target:targetkind()
-
- -- get it
return self:get("kind")
end
-- get the target file
function target:targetfile()
- -- check
- assert(self)
-
-- the target directory
local targetdir = self:get("targetdir") or config.get("buildir")
assert(targetdir and type(targetdir) == "string")
@@ -246,9 +238,6 @@ end
-- get the symbol file
function target:symbolfile()
- -- check
- assert(self)
-
-- the target directory
local targetdir = self:get("targetdir") or config.get("buildir")
assert(targetdir and type(targetdir) == "string")
@@ -274,9 +263,6 @@ end
-- get the source files
function target:sourcefiles()
- -- check
- assert(self)
-
-- cached? return it directly
if self._SOURCEFILES then
return self._SOURCEFILES, false
@@ -320,23 +306,22 @@ function target:sourcefiles()
end
-- match source files
- local srcfiles = os.match(file)
- if #srcfiles == 0 then
+ local results = os.match(file)
+ if #results == 0 then
utils.warning("cannot match add_files(\"%s\")", file)
end
-- process source files
- for _, srcfile in ipairs(srcfiles) do
+ for _, sourcefile in ipairs(results) do
-- convert to the relative path
- if path.is_absolute(srcfile) then
- srcfile = path.relative(srcfile, xmake._PROJECT_DIR)
+ if path.is_absolute(sourcefile) then
+ sourcefile = path.relative(sourcefile, os.projectdir())
end
-- save it
- sourcefiles[i] = srcfile
+ sourcefiles[i] = sourcefile
i = i + 1
-
end
end
@@ -691,6 +676,11 @@ function target:configheader(outputdir)
end
if not configheader then
configheader = self:get("config_h")
+
+ -- mark as deprecated
+ if configheader then
+ deprecated.add("set_config_header(\"%s\", {prefix = \"...\"})", "set_config_h(\"%s\")", configheader)
+ end
end
if not configheader then
return
@@ -719,5 +709,16 @@ function target:configheader(outputdir)
return configheader, outputheader
end
+-- get the precompiled header file (xxx.h.pch)
+function target:pcheaderfile()
+
+ -- get the precompiled header file in the object directory
+ local precompiled_header = self:get("precompiled_header")
+ if precompiled_header then
+ local headerdir = path.directory(precompiled_header):gsub("%.%.", "__")
+ return string.format("%s/%s/%s/%s", self:objectdir(), self:name(), headerdir, path.filename(precompiled_header) .. ".pch")
+ end
+end
+
-- return module
return target
diff --git a/xmake/core/sandbox/modules/import/core/language/language.lua b/xmake/core/sandbox/modules/import/core/language/language.lua
index 49a6abf1e..676cf9a74 100644
--- a/xmake/core/sandbox/modules/import/core/language/language.lua
+++ b/xmake/core/sandbox/modules/import/core/language/language.lua
@@ -111,6 +111,19 @@ function sandbox_core_language.sourcekind_of(sourcefile)
return sourcekind
end
+-- get extension of the source kind
+function sandbox_core_language.extension_of(sourcekind)
+
+ -- get it
+ local extension, errors = language.extension_of(sourcekind)
+ if not extension then
+ raise(errors)
+ end
+
+ -- ok
+ return extension
+end
+
-- get linker info (kind and flag) of the source kinds
function sandbox_core_language.linkerinfo_of(targetkind, sourcekinds)
diff --git a/xmake/core/tool/builder.lua b/xmake/core/tool/builder.lua
index b1269f9ef..23db1044c 100644
--- a/xmake/core/tool/builder.lua
+++ b/xmake/core/tool/builder.lua
@@ -247,13 +247,15 @@ function builder:_addflags_from_language(flags, target)
-- get api name of tool
--
+ -- ignore "nf_" and "_if_ok"
+ --
-- .e.g
--
-- defines => define
-- defines_if_ok => define
-- ...
--
- local apiname = flagname:split('_')[1]
+ local apiname = flagname:gsub("^nf_", ""):gsub("_if_ok$", "")
if apiname:endswith("s") then
apiname = apiname:sub(1, #apiname - 1)
end
diff --git a/xmake/languages/c++/api.lua b/xmake/languages/c++/api.lua
index 78f89ac6f..7d8e7739a 100644
--- a/xmake/languages/c++/api.lua
+++ b/xmake/languages/c++/api.lua
@@ -165,6 +165,7 @@ function apis()
{
-- target.set_xxx
"target.set_config_h_prefix" -- deprecated
+ , "target.set_precompiled_header"
-- target.add_xxx
, "target.add_links"
, "target.add_cflags"
@@ -208,7 +209,6 @@ function apis()
"target.set_headerdir"
, "target.set_config_h" -- deprecated
, "target.set_config_header"
- , "target.set_precompiled_header"
-- target.add_xxx
, "target.add_headers"
, "target.add_linkdirs"
diff --git a/xmake/languages/c++/xmake.lua b/xmake/languages/c++/xmake.lua
index a30b5e3c1..e39dce940 100644
--- a/xmake/languages/c++/xmake.lua
+++ b/xmake/languages/c++/xmake.lua
@@ -67,6 +67,7 @@ language("c++")
, "target.undefines"
, "target.frameworkdirs"
, "target.frameworks"
+ , "target.precompiled_header"
, "option.symbols"
, "option.warnings"
, "option.optimize:check"
diff --git a/xmake/languages/objc++/api.lua b/xmake/languages/objc++/api.lua
index 63e311c33..2d3cbfb03 100644
--- a/xmake/languages/objc++/api.lua
+++ b/xmake/languages/objc++/api.lua
@@ -30,6 +30,7 @@ function apis()
{
-- target.set_xxx
"target.set_config_h_prefix" -- deprecated
+ , "target.set_precompiled_header"
-- target.add_xxx
, "target.add_links"
, "target.add_mflags"
@@ -71,7 +72,6 @@ function apis()
"target.set_headerdir"
, "target.set_config_h" -- deprecated
, "target.set_config_header"
- , "target.set_precompiled_header"
-- target.add_xxx
, "target.add_headers"
, "target.add_linkdirs"
diff --git a/xmake/languages/objc++/xmake.lua b/xmake/languages/objc++/xmake.lua
index 0f5cb3b0a..768d8d400 100644
--- a/xmake/languages/objc++/xmake.lua
+++ b/xmake/languages/objc++/xmake.lua
@@ -67,6 +67,7 @@ language("objc++")
, "target.undefines"
, "target.frameworkdirs"
, "target.frameworks"
+ , "target.precompiled_header"
, "option.symbols"
, "option.warnings"
, "option.optimize:check"
diff --git a/xmake/modules/core/tools/gcc.lua b/xmake/modules/core/tools/gcc.lua
index 8bcf58799..100c19ed7 100644
--- a/xmake/modules/core/tools/gcc.lua
+++ b/xmake/modules/core/tools/gcc.lua
@@ -26,6 +26,7 @@
import("core.base.option")
import("core.project.config")
import("core.project.project")
+import("core.language.language")
import("detect.tools.find_ccache")
-- init it
@@ -249,6 +250,11 @@ function nf_frameworkdir(self, frameworkdir)
return "-F " .. frameworkdir
end
+-- make the precompiled header flag
+function nf_precompiled_header(self, headerfile, target)
+ return "-include " .. headerfile .. " -include-pch " .. target:pcheaderfile()
+end
+
-- make the link arguments list
function linkargv(self, objectfiles, targetkind, targetfile, flags)
return self:program(), table.join("-o", targetfile, objectfiles, flags)
@@ -264,9 +270,92 @@ function link(self, objectfiles, targetkind, targetfile, flags)
os.runv(linkargv(self, objectfiles, targetkind, targetfile, flags))
end
+-- get include deps
+function _include_deps(self, sourcefile, flags)
+
+ -- get it from the cache first
+ _g._INCDEPS = _g._INCDEPS or {}
+ local results = _g._INCDEPS[sourcefile]
+ if results then
+ return results
+ end
+
+ -- the temporary file
+ local tmpfile = os.tmpfile()
+
+ -- generate it
+ os.runv(self:program(), table.join("-c", "-MM", flags or {}, "-o", tmpfile, sourcefile))
+
+ -- translate it
+ results = {}
+ local incdeps = io.readfile(tmpfile)
+ for includefile in string.gmatch(incdeps, "%s+([%w/%.%-%+_%$%.]+)") do
+
+ -- save it if belong to the project
+ if not path.is_absolute(includefile) then
+ table.insert(results, includefile)
+ end
+ end
+
+ -- remove the temporary file
+ os.rm(tmpfile)
+
+ -- ok?
+ return results
+end
+
+-- make the complie arguments list for the precompiled header
+function _compargv1_pch(self, headerfile, objectfile, flags)
+
+ -- init cache key
+ local key = headerfile
+
+ -- make a temporary source file
+ local sourcefile = os.tmpfile() .. language.extension_of(self:kind())
+ io.writefile(sourcefile, format("#include \"%s\"", headerfile))
+
+ -- remove "-include xxx.h" and "-include-pch xxx.pch"
+ local pchflags = {}
+ local include = false
+ for _, flag in ipairs(flags) do
+ if not include and not flag:find("-include", 1, true) then
+ table.insert(pchflags, flag)
+ include = false
+ else
+ include = true
+ end
+ end
+
+ -- get the header file path and include deps
+ local incdeps = {}
+ for _, incdep in ipairs(_include_deps(self, sourcefile, pchflags)) do
+ if incdep:endswith(headerfile) then
+ headerfile = incdep
+ else
+ table.insert(incdeps, incdep)
+ end
+ end
+
+ -- save this include deps to cache
+ _g._INCDEPS = _g._INCDEPS or {}
+ _g._INCDEPS[key] = incdeps
+
+ -- remove files
+ os.tryrm(sourcefile)
+
+ -- make complie arguments list
+ return self:program(), table.join("-c", pchflags, "-o", objectfile, headerfile)
+end
+
-- make the complie arguments list
function _compargv1(self, sourcefile, objectfile, flags)
+ -- precompiled header?
+ local extension = path.extension(sourcefile)
+ if extension == ".h" or extension == ".hpp" then
+ return _compargv1_pch(self, sourcefile, objectfile, flags)
+ end
+
-- get ccache
local ccache = nil
if config.get("ccache") then
@@ -328,29 +417,7 @@ function _compile1(self, sourcefile, objectfile, incdepfile, flags)
-- generate includes file
if incdepfile and self:kind() ~= "as" then
-
- -- the temporary file
- local tmpfile = os.tmpfile()
-
- -- generate it
- os.runv(self:program(), table.join("-c", "-MM", flags or {}, "-o", tmpfile, sourcefile))
-
- -- translate it
- local results = {}
- local incdeps = io.readfile(tmpfile)
- for includefile in string.gmatch(incdeps, "%s+([%w/%.%-%+_%$%.]+)") do
-
- -- save it if belong to the project
- if not path.is_absolute(includefile) then
- table.insert(results, includefile)
- end
- end
-
- -- update it
- io.save(incdepfile, results)
-
- -- remove the temporary file
- os.rm(tmpfile)
+ io.save(incdepfile, _include_deps(self, sourcefile, flags))
end
end