diff options
| author | ruki <[email protected]> | 2017-07-27 19:27:12 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2017-07-27 19:27:12 +0800 |
| commit | 6f2c9ecd0d7ea9f2fbfab79b6960eb1274ca816a (patch) | |
| tree | 322b4e7ba82e82ce8a6d0c4b56d044bbcde2d010 | |
| parent | 84defbee206dd2d810070bfae7b7e269a3445896 (diff) | |
impl compile pch for gcc
| -rw-r--r-- | xmake/actions/build/kinds/object.lua | 38 | ||||
| -rw-r--r-- | xmake/core/language/language.lua | 13 | ||||
| -rw-r--r-- | xmake/core/project/target.lua | 43 | ||||
| -rw-r--r-- | xmake/core/sandbox/modules/import/core/language/language.lua | 13 | ||||
| -rw-r--r-- | xmake/core/tool/builder.lua | 4 | ||||
| -rw-r--r-- | xmake/languages/c++/api.lua | 2 | ||||
| -rw-r--r-- | xmake/languages/c++/xmake.lua | 1 | ||||
| -rw-r--r-- | xmake/languages/objc++/api.lua | 2 | ||||
| -rw-r--r-- | xmake/languages/objc++/xmake.lua | 1 | ||||
| -rw-r--r-- | xmake/modules/core/tools/gcc.lua | 113 |
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 |
