-
Notifications
You must be signed in to change notification settings - Fork 265
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
Add an option to disable long file names #528
Conversation
Thank you for this pull request! This seems to be fallout from the change in #524/#525. Could you explain a bit under which circumstances this problem occurs? Is this mainly a Windows thing? I am not the biggest fan of adding a new option that requires the user to figure out the correct combination of flags. I am also a bit unhappy about making parallel processing impossible in the general case, even though it's a niche feature right now. I think it might be better to run gcov once to discover available options, and then use the |
I discovered this issue investigating on a more generic problem, that upgrading from llvm 11 to 12 broke coverage generation on some file in our project (only files generated in our build folder which is not contained in the source tree). Starting from I already tried the Hence expect for a custom option I have no idea how to handle this issue 😕 |
Thank you for that background info. It looks like my suggestion of TL;DR: I don't think we need In GCC: expand source codestatic string
make_gcov_file_name (const char *input_name, const char *src_name)
{
string str;
/* When hashing filenames, we shorten them by only using the filename
component and appending a hash of the full (mangled) pathname. */
if (flag_hash_filenames)
str = (string (mangle_name (src_name)) + "##"
+ get_md5sum (src_name) + ".gcov");
else
{
if (flag_long_names && input_name && strcmp (src_name, input_name) != 0)
{
str += mangle_name (input_name);
str += "##";
}
str += mangle_name (src_name);
str += ".gcov";
}
return str;
} Pseudocode: def make_gcov_file_name(gcda_path, source_path, options) -> str:
if options.hash_filenames:
return (mangle(source_path, options.preserve_paths)
+ "##" + md5(source_path) + ".gcov")
coverage_path = ""
if options.long_filenames and gcda_path != source_path:
coverage_path += mangle(gcda_path, options.preserve_paths) + "##"
coverage_path += mangle(source_path, options.preserve_paths) + ".gcov"
return coverage_path In LLVM/Clang expand source codestd::string Context::getCoveragePath(StringRef filename,
StringRef mainFilename) const {
if (options.NoOutput)
// This is probably a bug in gcov, but when -n is specified, paths aren't
// mangled at all, and the -l and -p options are ignored. Here, we do the
// same.
return std::string(filename);
std::string CoveragePath;
if (options.LongFileNames && !filename.equals(mainFilename))
CoveragePath =
mangleCoveragePath(mainFilename, options.PreservePaths) + "##";
CoveragePath += mangleCoveragePath(filename, options.PreservePaths);
if (options.HashFilenames) {
MD5 Hasher;
MD5::MD5Result Result;
Hasher.update(filename.str());
Hasher.final(Result);
CoveragePath += "##" + std::string(Result.digest());
}
CoveragePath += ".gcov";
return CoveragePath;
} Pseudocode: def get_coverage_path(source_path, gcda_path, options) -> str:
coverage_path = ""
if options.long_file_names and (gcda_path != source_path):
coverage_path = mangle(gcda_path, options.preserve_paths) + "##"
coverage_path += mangle(source_path, options.preserve_paths)
if options.hash_filenames:
coverage_path += md5(source_path)
return coverage_path + ".gcov" In either case, the def mangle(path, preserve_paths) -> str:
if preserve_paths:
return path.replace('/', '#')
else:
return basename(path) So at least llvm-cov and GCC gcov seem consistent with each other. The problem is that If we were to add
Let there be a project directory that contains a
At this point, I think the best resolution is the following:
cc @Spacetown I need your thoughts on this. |
@ebmmy Could you try the following patch? gcov_options = [
"--branch-counts",
"--branch-probabilities",
- "--preserve-paths",
- "--long-file-names",
+ "--hash-filenames",
] |
Thanks for the really detailed explanation ! Based on your input I updated this PR. I think the |
@latk I'm with you to remove the option, adding a BIG comment to the directory lock with a link to this PR.
Of course a cache is needed because the result is fixed and e.g. on Windows starting a process can take up to 500ms. Other solutions (https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=cmd):
BTW: The max length in Windows is MAX_PATH which is defined to 260. |
I'll rework this PR with a cache and using Regarding path limitation maybe I was not clear on my problem. The issue I get is running on WSL2 which is, as far as I know, not limited by |
@latk I tested with your patch and I get the expected coverage report with long filename issue 👍 |
@ebmmy But the cache for the used options is missing. |
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.
The cache for the help output is missing.
Please update the |
41cd898
to
3735df5
Compare
@latk Can you take a look at my changes to wrap the |
Codecov Report
@@ Coverage Diff @@
## master #528 +/- ##
==========================================
- Coverage 96.18% 96.09% -0.09%
==========================================
Files 22 22
Lines 2934 2969 +35
Branches 544 554 +10
==========================================
+ Hits 2822 2853 +31
- Misses 49 51 +2
- Partials 63 65 +2
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report at Codecov.
|
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 looks reasonable, let's merge it. Any issues that I see are more stylistic nitpicks and I can change them later. (I have been toying with some refactorings to see what recent Python versions have to offer, since Python 3.6 was EOL'd last week).
For example, I'd probably change:
- naming conventions
- a more functional (less OOP) approach
- using
subprocess.run()
instead ofPopen()
(we used to not do this as run() was only added in Python 3.6) - raising an error if not at least one --help option works
But again, those are nitpicks that are not pressing.
The only important change we need before merging is to document the new behaviour and add a changelog item. Since we never made any promised about which gcov command line arguments we used, mentioning it as an improvement in the changelog might be sufficient.
I'll update the changeling and add the used options. |
3735df5
to
65dba87
Compare
E.g.
This was just a subjective remark about my personal preferences. I find stateful objects difficult because every method has to consider the valid object states (is the cache already initialized or not). The more functional approach is to only create an object if it is fully valid. Sketch: class GcovOptions:
_instance: CachedGcovOptions = None
@classmethod
def get_cached(cls, options) -> CachedGcovOptions:
if not cached_instance_is_valid():
cls._instance = cls(options)
return cls._instance
def __init__(self, option):
self.foo = ...
self.bar = ...
# methods can assume self to be fully initialized,
# don't have to check any fields
def whatever(self): ...
GcovOptions.get_cached(options).whatever() # example usage This looks quite similar to your solution, but harmonizes much better with type checkers and IDE features like autocomplete. But I'm just saying this to broadcast values (typechecking is nice, minimal use of mutable class variables is nice), not to suggest a change that should be implemented as part of this PR. It is more important to me that the queue of pending PRs becomes more reasonable so that I can try my hand at some cross-cutting changes without invalidating other work.
Thanks for that. But now the changelog only mentions that the documentation changed, not that we made a change to stay within file system limitations. Or is that unnecessary because gcovr 5.0 didn't use |
I think this is unnecessary because it's a regression change after the 5.0. On the other hand if a project had problems with long file names in 5.0 this can be solved by using the option I was also not sure how to document this in the changelog. The changelog lists the improvements since 5.0 and thats only a fix of such an improvement. The problem here is that it seems that some users are using the master branch in production and for them it's a change. Maybe we can list also regression fixes e.g.
And as a step of the release process go throug the changelog and remove such regression fixes. |
Using tho option
--long-file-names
withllvm-cov
leads to file name larger than 255 characters on our setup and makesgcovr
unusable. Hence this PR adding an option to disable it.