Fix issue 16746 - Please output Makefile-style depfiles for ninja and make#6961
Fix issue 16746 - Please output Makefile-style depfiles for ninja and make#6961eigenraven wants to merge 1 commit intodlang:masterfrom
Conversation
|
Thanks for your pull request and interest in making D better, @KubaSz! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.
Please see CONTRIBUTING.md for more information. If you have addressed all reviews or aren't sure how to proceed, don't hesitate to ping us with a simple comment. Bugzilla references
Testing this PR locallyIf you don't have a local development environment setup, you can use Digger to test this PR: dub fetch digger
dub run digger -- build "master + dmd#6961" |
|
Seems like |
src/ddmd/expression.d
Outdated
| ob.writestring(")"); | ||
| ob.writenl(); | ||
| } | ||
| if (global.params.makeDeps !is null) |
There was a problem hiding this comment.
I've added an import expression to the test file, this should cover these lines.
FYI, gdc compiled test uses GC allocation, not bump-the-pointer. So this means that there is a genuine logic bug in the implementation. |
src/ddmd/mars.d
Outdated
| depBuffer.writeByte(' '); | ||
| } | ||
| auto depf = File(outpath); | ||
| depf.setbuffer(cast(void*)depBuffer.data, depBuffer.offset); |
There was a problem hiding this comment.
This is normally why there's a double free. File is freeing the buffer owned by OutBuffer. You need to tell depf._ref = 1.
There was a problem hiding this comment.
Fixed. This is my first encounter with dmd's code, so sorry that I didn't notice the _ref field in File.
src/ddmd/globals.h
Outdated
| const char *hdr_ext; // for D 'header' import files | ||
| const char *json_ext; // for JSON files | ||
| const char *map_ext; // for .map files | ||
| const char *makedep_ext; // for make-style dependency files |
There was a problem hiding this comment.
All _ext fields should just go. There is no need for them.
src/ddmd/mars.d
Outdated
| if(global.params.makeDeps !is null) | ||
| error(Loc(), "-M/-MD can only be provided once!"); | ||
| global.params.makeDeps = new Strings(); | ||
| break; |
There was a problem hiding this comment.
-MD writes deps to a file implicitly.
src/ddmd/globals.d
Outdated
|
|
||
| const(char)* makeDepsFile; // filename for make-style dependencies output | ||
| const(char)* makeDepsTarget; // the generated make target name | ||
| Array!(const(char)*)* makeDeps; // array of paths that the compiled module(s) depend on |
There was a problem hiding this comment.
I wonder if these are strictly needed, or we should start requesting that new driver-only fields be added privately in mars.d so as to not affect other backends.
There was a problem hiding this comment.
The makeDeps field could be private, but the File and Target can be useful for other drivers to input their commandline options to dmdfe. I've basically followed what changes the -deps option that was already built into dmd introduced, so that's why I added these fields here.
9303ba1 to
5a5ba85
Compare
MartinNowak
left a comment
There was a problem hiding this comment.
Thanks, interesting PR :).
While dmd's command line is weird, it doesn't become better by adopting switches with different conventions. Please make your additions consistent with existing switches.
Furthermore this apparently cannot generate multiple output deps files, we need sth. that also works with multiple source and output files, while also working with parallel compilation (can't write everything into one file).
src/ddmd/mars.d
Outdated
| -J=<directory> look for string imports also in directory | ||
| -L=<linkerflag> pass linkerflag to link | ||
| -lib generate library rather than object files | ||
| -M generate make-style dependency file, generates no other output files |
There was a problem hiding this comment.
Dmd already has -o- to turn off object file generation.
src/ddmd/mars.d
Outdated
| -M generate make-style dependency file, generates no other output files | ||
| -MD generate make-style dependency file | ||
| -MF=<filename> specifies the dependency output file | ||
| -MT=<name> specifies the name of the target rule in the dependencies file |
There was a problem hiding this comment.
This differs quite a lot from dmd's other options, look at -H, -Hd, -Hf, -op, -D.
In particular you want to be able to specify an output folder with -Md and obey -op, and use -Mf instead of -MF.
Please make sure to not mixup dependency and deps file in the explanation.
There was a problem hiding this comment.
Not sure how -MT could work for multiple object files in one compilation (not a typical make use-case though possible).
src/ddmd/mars.d
Outdated
| const(char)* mtarget = global.params.makeDepsTarget; | ||
| if (!outpath) | ||
| { | ||
| outpath = FileName.forceExt((*global.params.objfiles)[0], "dep"); |
There was a problem hiding this comment.
You're sure there are object files when we run with -o-?
Better generate your own paths.
src/ddmd/mars.d
Outdated
| global.params.makeDeps = new Strings(); | ||
| break; | ||
| case 'F': | ||
| if(p[3] != '=' || p[4] == '\0') |
There was a problem hiding this comment.
We do not use = for any of the path arguments, just -Hffile.di for example.
| grep 'makedeps.sh' ${RESULTS_DIR}/compilable/makedeps2.dep || exit 1 | ||
| grep 'makedeps_a.d' ${RESULTS_DIR}/compilable/makedeps2.dep || exit 1 | ||
| grep 'object.d' ${RESULTS_DIR}/compilable/makedeps2.dep || exit 1 | ||
| grep '__entrypoint' ${RESULTS_DIR}/compilable/makedeps2.dep && exit 1 |
There was a problem hiding this comment.
You might want to include colon (:) in your grep searches.
5a5ba85 to
b34bb82
Compare
|
Sorry for the long delay in fixing my PR, I had a surgery and needed time to recover. I've pushed the fixes now:
|
fdb975b to
62a9086
Compare
62a9086 to
9f597ca
Compare
|
I have rebased the PR against the current master branch. |
|
Any news on this? It's kind of important to make splitbuilds work out of the box in Automake, Meson & Co. |
|
Would it be possible for you to re-review this PR? @MartinNowak @ibuclaw |
9f597ca to
35581f5
Compare
|
Rebased against master. |
src/dmd/globals.d
Outdated
| bool doMakeDeps; // generate make-style dependencies file | ||
| const(char)* makeDepsFile; // filename for make-style dependencies output | ||
| const(char)* makeDepsDir; // directory for make-style dependencies output | ||
| const(char)* makeDepsTarget; // the make target name |
There was a problem hiding this comment.
All new public symbols should have Ddoc comments.
src/dmd/globals.d
Outdated
| bool doMakeDeps; // generate make-style dependencies file | ||
| const(char)* makeDepsFile; // filename for make-style dependencies output | ||
| const(char)* makeDepsDir; // directory for make-style dependencies output | ||
| const(char)* makeDepsTarget; // the make target name |
There was a problem hiding this comment.
Can these const(char)* fields be made into D strings, i.e. const(char)[]? On the C++ side an ABI compatible struct can be used.
There was a problem hiding this comment.
As much as I'd like this to happen, I don't think it's fair to ask a contributor to break the current status quo.
Such a change should be done on its own.
| Dsymbols* decldefs; // top level declarations for this Module | ||
|
|
||
| Modules aimports; // all imported modules | ||
| Strings astringImports; // all string-imported files |
There was a problem hiding this comment.
Perhaps this can be an array of const(char)[] and an ABI compatible struct on the C++ side.
There was a problem hiding this comment.
Same comment about the status quo. I'd like to replace the Array aliases as much as the next guy, but I don't think we should put that kind of weight on this PR.
There was a problem hiding this comment.
I also think that this is not really in the scope of this PR, and I think a "standard" way to do it (perhaps with predefined structs for most common array typs) should be defined first and a refactor PR could be done with that in place.
There was a problem hiding this comment.
Then it will never happen and at the same time we’re adding more code that needs to change later 😞
src/dmd/mars.d
Outdated
| { | ||
| auto mpath = m.srcfile.toString(); | ||
| // Skip modules already in the table, add self | ||
| if (moduleImportedPaths.insert(mpath.ptr, mpath.length, null) is null) |
There was a problem hiding this comment.
Please add an overload to insert that takes const(char)[] instead of a pointer and length.
src/dmd/root/filename.d
Outdated
| return str; | ||
| } | ||
|
|
||
| extern (D) const(char)[] toString() const pure |
There was a problem hiding this comment.
Can be made nothrow.
| extern (D) const(char)[] toString() pure const | ||
| { | ||
| return name.toString(); | ||
| } |
There was a problem hiding this comment.
Can be made nothrow.
| extern (C++) const(char)* toChars() pure | ||
| extern (C++) const(char)* toChars() pure const | ||
| { | ||
| return name.toChars(); |
There was a problem hiding this comment.
Can be made nothrow, I assume.
src/dmd/mars.d
Outdated
| { | ||
| // no actual file is created, uses just the path | ||
| File* objfile = m.setOutfile(global.params.objname, global.params.objdir, m.arg, global.obj_ext); | ||
| escapePathSpaces(&mdout, objfile.toChars()); |
There was a problem hiding this comment.
Please used the newly added toString method instead.
src/dmd/mars.d
Outdated
| // So deps file generation should be moved after the inlinig stage. | ||
| if (global.params.moduleDeps) | ||
| // inlineScan incrementally run semantic3 of each expanded functions. | ||
| // So deps file generation should be moved after the inlinig stage. |
src/dmd/mars.d
Outdated
| { | ||
| const(char)* mpath = m.srcfile.toChars(); | ||
| // Skip modules already in the table, add self | ||
| if(moduleImportedPaths.insert(mpath, strlen(mpath), null) is null) |
src/dmd/utils.d
Outdated
| * buf = Buffer to write the escaped path to | ||
| * fname = Path to escape | ||
| */ | ||
| void escapePathSpaces(OutBuffer* buf, const(char)* fname) |
There was a problem hiding this comment.
Any chance to move this to filename ?
src/dmd/globals.d
Outdated
| bool doMakeDeps; // generate make-style dependencies file | ||
| const(char)* makeDepsFile; // filename for make-style dependencies output | ||
| const(char)* makeDepsDir; // directory for make-style dependencies output | ||
| const(char)* makeDepsTarget; // the make target name |
There was a problem hiding this comment.
As much as I'd like this to happen, I don't think it's fair to ask a contributor to break the current status quo.
Such a change should be done on its own.
| Dsymbols* decldefs; // top level declarations for this Module | ||
|
|
||
| Modules aimports; // all imported modules | ||
| Strings astringImports; // all string-imported files |
There was a problem hiding this comment.
Same comment about the status quo. I'd like to replace the Array aliases as much as the next guy, but I don't think we should put that kind of weight on this PR.
|
This PR would also close the issue I filed. On the whole "why makefile dependencies?" front, I'd like to add this: this is required for ninja to work. Reggae only supports ninja by wrapping dmd and offering the necessary functionality. |
|
I thought I'd added a comment here that dmd has the |
|
I think it is too late now to change the behavior of the -deps switch, quite a few tools seem to rely on its format :( |
src/dmd/root/filename.d
Outdated
|
|
||
| extern (D) const(char)[] toString() const pure nothrow | ||
| { | ||
| return str[0 .. strlen(str)]; |
|
So if this is merged, we'll have |
|
The right design is to output the information in a simple format and leave it to tooling to translate to others. Sadly, one little uninspired idea after another, we're here. |
|
And so we arrive at the nightmarish blizzard of switches I so wanted to avoid :-( |
|
Well, at some well-announced point in the future, you could in theory clean up the compiler flags and adjust them to something that you like. |
| // So deps file generation should be moved after the inlinig stage. | ||
| if (global.params.moduleDeps) | ||
| // So deps file generation should be moved after the inlining stage. | ||
| if (global.params.moduleDeps || global.params.doMakeDeps) |
There was a problem hiding this comment.
You probably don't want to reuse -deps functionality as it is no longer useful for make. Analysing code via semantic3OnDependencies also reports local imports that are not used when compiling the code without the -deps option. It can also slow down compilation considerably. See discussion in #6748.
There was a problem hiding this comment.
That was insightful, thank you. I've moved the semantic3OnDependencies call to be done only for the old -deps switch.
995fa60 to
001608b
Compare
001608b to
7556d76
Compare
|
What happened to this PR? Can we get this rebased and back to track again? I really wanted to see this go through to improve the building process with ninja. |
|
It's not in a particularly good shape, adds lots of extra switches with partly redundant functionality (#6961 (comment)). |
|
The basic idea to generate makefile compatible output is good though, maybe just add a |
|
Another implementation, #12011, has been merged into master. |
|
Excellent, many thanks to everyone involved! This helps a lot for project with mixed languages and D with buildsystems using ninja and make :-) |

This adds
-M,-Mffile,-Mddirectory,-Mttargetcommandline options akin to C(++) compilers, and implements generation of make depfiles which can be used by buildsystems such as Ninja, Make or Meson.Link to issue: https://issues.dlang.org/show_bug.cgi?id=16746