summaryrefslogtreecommitdiff
path: root/xmake/modules/private
diff options
context:
space:
mode:
Diffstat (limited to 'xmake/modules/private')
-rw-r--r--xmake/modules/private/action/build/object.lua9
-rw-r--r--xmake/modules/private/cache/build_cache.lua83
-rw-r--r--xmake/modules/private/service/distcc_build/client.lua57
3 files changed, 118 insertions, 31 deletions
diff --git a/xmake/modules/private/action/build/object.lua b/xmake/modules/private/action/build/object.lua
index 487be763a..b8816f446 100644
--- a/xmake/modules/private/action/build/object.lua
+++ b/xmake/modules/private/action/build/object.lua
@@ -23,7 +23,7 @@ import("core.base.option")
import("core.theme.theme")
import("core.tool.compiler")
import("core.project.depend")
-import("private.tools.ccache")
+import("private.cache.build_cache")
import("private.async.runjobs")
import("utils.progress")
import("private.service.distcc_build.client", {alias = "distcc_build_client"})
@@ -61,11 +61,12 @@ function _do_build_file(target, sourcefile, opt)
-- exists ccache or distcc?
local prefix = ""
- if distcc_build_client.is_distccjob() and distcc_build_client.singleton():has_freejobs() then
- prefix = "distcc "
- elseif ccache.exists() then
+ if build_cache.is_enabled() and build_cache.is_supported(sourcekind) then
prefix = "ccache "
end
+ if distcc_build_client.is_distccjob() and distcc_build_client.singleton():has_freejobs() then
+ prefix = prefix .. "distcc "
+ end
-- trace progress info
if not opt.quiet then
diff --git a/xmake/modules/private/cache/build_cache.lua b/xmake/modules/private/cache/build_cache.lua
index 629c903a3..d2180ab58 100644
--- a/xmake/modules/private/cache/build_cache.lua
+++ b/xmake/modules/private/cache/build_cache.lua
@@ -19,10 +19,12 @@
--
-- imports
+import("core.base.bytes")
+import("core.base.hashset")
import("core.project.config")
-- is enabled?
-function enabled()
+function is_enabled()
local build_cache = _g.build_cache
if build_cache == nil then
build_cache = config.get("ccache") or false
@@ -31,24 +33,42 @@ function enabled()
return build_cache or false
end
+-- is supported?
+function is_supported(sourcekind)
+ local sourcekinds = _g.sourcekinds
+ if sourcekinds == nil then
+ sourcekinds = hashset.of("cc", "cxx", "mm", "mxx")
+ _g.sourcekinds = sourcekinds
+ end
+ return sourcekinds:has(sourcekind)
+end
+
-- get cache key
function cachekey(program, cppfile, cppflags, envs)
local items = {program}
- table.join2(items, cppflags)
+ for _, cppflag in ipairs(cppflags) do
+ table.insert(items, cppflag)
+ end
table.sort(items)
- table.insert(items, hash.sha256(cppfile))
+ table.insert(items, hash.xxhash128(cppfile))
if envs then
- for k, v in pairs(table.orderpairs(envs)) do
- table.insert(items, k)
- table.insert(items, v)
+ local basename = path.basename(program)
+ if basename == "cl" then
+ for _, name in ipairs({"WindowsSDKVersion", "VCToolsVersion", "LIB"}) do
+ local val = envs[name]
+ if val then
+ table.insert(items, val)
+ end
+ end
end
end
- return (hash.uuid(table.concat(items, "")):gsub("-", "")):lower()
+ return hash.xxhash128(bytes(table.concat(items, "")))
end
-- get cache root directory
function rootdir()
- return path.join(config.buildir(), ".cache")
+ local cachedir = config.get("ccachedir")
+ return cachedir or path.join(config.buildir(), ".build_cache")
end
-- clean cached files
@@ -61,11 +81,28 @@ function hitrate()
local hit_count = (_g.hit_count or 0)
local total_count = (_g.total_count or 0)
if total_count > 0 then
- return hit_count * 100 / total_count
+ return math.floor(hit_count * 100 / total_count)
end
return 0
end
+-- dump stats
+function dump_stats()
+ local hit_count = (_g.hit_count or 0)
+ local total_count = (_g.total_count or 0)
+ local newfiles_count = (_g.newfiles_count or 0)
+ local preprocess_error_count = (_g.preprocess_error_count or 0)
+ vprint("")
+ vprint("build cache stats:")
+ vprint("cache directory: %s", rootdir())
+ vprint("cache hit rate: %d%%", hitrate())
+ vprint("cache hit: %d", hit_count)
+ vprint("cache miss: %d", total_count - hit_count)
+ vprint("new cached files: %d", newfiles_count)
+ vprint("preprocess failed: %d", preprocess_error_count)
+ vprint("")
+end
+
-- get object file
function get(cachekey)
_g.total_count = (_g.total_count or 0) + 1
@@ -80,4 +117,32 @@ end
function put(cachekey, objectfile)
local objectfile_cached = path.join(rootdir(), cachekey:sub(1, 2):lower(), cachekey)
os.cp(objectfile, objectfile_cached)
+ _g.newfiles_count = (_g.newfiles_count or 0) + 1
+end
+
+-- build with cache
+function build(program, argv, opt)
+
+ -- do preprocess
+ opt = opt or {}
+ local preprocess = assert(opt.preprocess, "preprocessor not found!")
+ local compile = assert(opt.compile, "compiler not found!")
+ local cppinfo = preprocess(program, argv, opt)
+ if cppinfo then
+ local cachekey = cachekey(program, cppinfo.cppfile, cppinfo.cppflags, opt.envs)
+ local objectfile_cached = get(cachekey)
+ if objectfile_cached then
+ os.cp(objectfile_cached, cppinfo.objectfile)
+ else
+ -- do compile
+ compile(program, cppinfo, opt)
+ if cachekey then
+ put(cachekey, cppinfo.objectfile)
+ end
+ end
+ os.rm(cppinfo.cppfile)
+ else
+ _g.preprocess_error_count = (_g.preprocess_error_count or 0) + 1
+ end
+ return cppinfo
end
diff --git a/xmake/modules/private/service/distcc_build/client.lua b/xmake/modules/private/service/distcc_build/client.lua
index da0f17dd8..6a6486323 100644
--- a/xmake/modules/private/service/distcc_build/client.lua
+++ b/xmake/modules/private/service/distcc_build/client.lua
@@ -232,25 +232,32 @@ function distcc_build_client:compile(program, argv, opt)
-- do preprocess
opt = opt or {}
local preprocess = assert(opt.preprocess, "preprocessor not found!")
- local outdata, errdata, sourcefile, objectfile, cppfile, cppflags = preprocess(program, argv, opt)
-
- -- get objectfile from the build cache first
- local cached = false
- local cachekey
- if build_cache.enabled() then
- cachekey = build_cache.cachekey(program, cppfile, cppflags, opt.envs)
- local objectfile_cached = build_cache.get(cachekey)
- if objectfile_cached then
- os.cp(objectfile_cached, objectfile)
- cached = true
+ local cppinfo = preprocess(program, argv, opt)
+ local build_in_local = false
+ if cppinfo then
+ -- get objectfile from the build cache first
+ local cached = false
+ local cachekey
+ if build_cache.is_enabled() then
+ cachekey = build_cache.cachekey(program, cppinfo.cppfile, cppinfo.cppflags, opt.envs)
+ local objectfile_cached = build_cache.get(cachekey)
+ if objectfile_cached then
+ os.cp(objectfile_cached, cppinfo.objectfile)
+ cached = true
+ end
end
- end
- -- do distcc compilation
- if not cached then
- session:compile(sourcefile, objectfile, cppfile, cppflags, opt)
- if cachekey then
- build_cache.put(cachekey, objectfile)
+ -- do distcc compilation
+ if not cached then
+ -- we just compile the large preprocessed file in remote
+ if os.filesize(cppinfo.cppfile) > 4096 then
+ session:compile(cppinfo.sourcefile, cppinfo.objectfile, cppinfo.cppfile, cppinfo.cppflags, opt)
+ if cachekey then
+ build_cache.put(cachekey, cppinfo.objectfile)
+ end
+ else
+ build_in_local = true
+ end
end
end
@@ -259,7 +266,21 @@ function distcc_build_client:compile(program, argv, opt)
-- unlock this host
self:_host_status_unlock(host)
- return outdata, errdata
+
+ -- build in local
+ if build_in_local then
+ if cppinfo and build_in_local then
+ local compile = assert(opt.compile, "compiler not found!")
+ compile(program, cppinfo, opt)
+ if build_cache.is_enabled() then
+ local cachekey = build_cache.cachekey(program, cppinfo.cppfile, cppinfo.cppflags, opt.envs)
+ if cachekey then
+ build_cache.put(cachekey, cppinfo.objectfile)
+ end
+ end
+ end
+ end
+ return cppinfo
end
-- get the status