summaryrefslogtreecommitdiff
path: root/xmake/modules/private/cache/build_cache.lua
diff options
context:
space:
mode:
authorruki <[email protected]>2022-05-20 23:05:19 +0800
committerGitHub <[email protected]>2022-05-20 23:05:19 +0800
commit6cf488d207c3009aba6319759a2cc2fb6aa7a405 (patch)
treec61583cf363192611d4f0be291b9e1fbe8afd2ab /xmake/modules/private/cache/build_cache.lua
parentc6218b9b4cd17babf15fa46dbc65e895ace3e7d7 (diff)
parentd63ce0e016b58d03519f957d7ac9f36494c73486 (diff)
Merge pull request #2361 from xmake-io/buildcache
Add build cache instead of ccache
Diffstat (limited to 'xmake/modules/private/cache/build_cache.lua')
-rw-r--r--xmake/modules/private/cache/build_cache.lua83
1 files changed, 74 insertions, 9 deletions
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