-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
makefiles: Generate proper dependency files when using ccache #12840
makefiles: Generate proper dependency files when using ccache #12840
Conversation
When CCACHE_BASEDIR variable is set, ccache rewrites absolute paths into relative paths before computing the hash that identifies the compilation for all the paths under that directory. The problem is that those paths are also used when the compiler is called, so the generated dependency files (*.d) will have a relative path to the object files, and thus, it will not match our rule for compiling (we use absolute paths). As dependency files define the targets this way, any change on its dependencies (e.g. an included header file) will not re-trigger a build.
I confirm that this fixes #12807 for my setup (ccache 3.7.6) |
this probably breaks ci caching... |
Ok lets see. If does increase build time we will need either add something in RIOT (maybe a |
This will affect local caching when building in multiple directories, but I guess that's preferable to broken depencencies. |
build time was 31min (+50%), I'll trigger a rebuild. |
That could actually be caused by the new "-MQ" option (which would cause cache misses edit only in the beginning), not by messing up caching. A couple of rebuilds would show. |
27 minutes says murdock. Let's trigger again. |
I have a script that creates per-branch ccache stats for murdock, which I used for debugging the "-g" issue before. I'll run it for this PR (and current master) once the current run went through. |
29min. Will get some cache stats now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is OK from my side.
By passing the -MT flag with the absolute path to the object we make sure that the compiler generates dependency files with rules that match our building rules.
f3c97b3
to
dc84584
Compare
@kaspar030 thanks a lot for this! It was really helpful. @cgundogan I added the apostrophes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, tested on my local setup and murdock also seems to agree with it. ACK from my side. Let's run it a last time by murdock (with the apostrophe fix included).
Thanks everyone for testing and reviewing! |
Contribution description
In #12807 it has been reported that when a change is made in a header file (which is a dependency of a given object file) make does not take this into account, in consequence it does not re-trigger a build.
The cause of this issue are the dependency files generated by the compiler (placed under
$(BINDIR)/$(MODULE)/<filename>.d
). When ccache is used, if theCCACHE_BASEDIR
environmental variable is set, then it will turn all paths into relative (see ccache docs). This has the advantage of allowing one to reuse the cache across multiple RIOT folders, but in our case it passes a relative path to the object in the call to gcc.Here you can see a snippet of ccache log, the actual call to gcc. Note that paths are relative:
ccache log on master
The compiler then will generate rules with relative paths:
main.d file with relative path to object
The dependency files are included then in
Makefile.base
, but as the rules do not match out pattern in the objects rule, the objects are not updated when a dependency (e.g. a header file) is changed.To solve this problem, we need absolute paths in the targets of the *.d files. While using ccache 3.6 I managed this just by not setting
CCACHE_BASEDIR
, so paths would be absolute. @cgundogan reported that this does not seem to fix the issue for version 3.7.6. That is why I modified the gcc flags to pass an explicit absolute path as the target of the generated rule (only doing this for ccache does not solve the issue, as it detects the path and relativizes it). This should not affect users who don't use ccache.With this PR, dependency files have absolute paths, and any changes to the files the objects depend on will be taken into account.
main.d with this PR
Not setting
CCACHE_BASEDIR
will have the side effect of not sharing the cache between different RIOT folders that the user may have. If the user really wants this (and does not care about having to clean for every build), the variable can always be set externally.Testing procedure
Run the test under these two conditions:
CCACHE
environmental variable set: this depends on your installation.CCACHE_DISABLE
TIP: To check if ccache is being used you can run
ccache -s
to see the statistics, the last access will change every time it's used.Test:
Using the example application provided in #12807 (or a similar example):
rm -Rf bin
in the application directory.make all term
. You should see the current value in of the header file.main.d
file has an absolute path to the object.make all term
(NO CLEAN).main.o
should be the only object re-built, and the number should be updated.Issues/PRs references
Fixes #12807