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
Fix rdmd --makedep(end|file) (issues 12351 and 12354) #122
Fix rdmd --makedep(end|file) (issues 12351 and 12354) #122
Conversation
// --build-only implies the user would like a binary in the program's directory | ||
if (buildOnly && !exe) | ||
// If there is no -of the user would like a binary in the program's directory | ||
if (!exe) |
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.
I would appreciate if someone can take a look at this bit in particular. I hope is true and the buildOnly
check was only there for historical reasons.
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.
No this isn't right, rdmd should not pollute the current directory with executables if -of
isn't used, it should use a temp folder instead.
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.
@andralex: requesting confirmation on this.
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.
No, you are right, is leaving the binary there with this change even if -of
is not used.
Will fix, but I don't think the fix will be particularly pretty :S
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.
BTW, the rdmd test program is not checking this :P
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.
If there is no -of the user would like a binary in the program's directory
Absolutely, this is wrong. If there is no -of
and no --build-only
, the user just wants to run the program, and rdmd
needs to build to the temporary directory.
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 test suite should probably check that rdmd isn't leaving any junk in the program's directory, unless the user asked for it.
I just added 2 more commits to definitely fix this feature. I updated the PR title and description. I'll take a look at what you say, but I had the impression the binary is not moved even with this change. I'll confirm. |
Does --makedepend even make sense without -of / -od? I think it should imply it. |
How can you imply |
OK, new commit pushed, all my tests look good now. |
// --build-only implies the user would like a binary in the program's directory | ||
if (buildOnly && !exe) | ||
exe = exeDirname ~ dirSeparator; | ||
makeDepTarget = exe; |
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.
Can you restructure the code so the new behavior is more encapsulated? --makedep*
isn't part of the usual rdmd operation, the code is a bit difficult to understand as it is
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.
As I just said, maybe is more sane to just require -of
when --makedep*
is used and forget about all this mess.
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.
Requiring -of
or -od
sounds good to me. Even better than implying them, I think.
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.
yeah, I'll do that, I'll require -of
, if you want to create a makefile, you really need to specify the target name. Make is too sensitive to guess anything.
Updated, let's see if this one is a keeper :D |
@@ -139,6 +139,14 @@ int main(string[] args) | |||
if (bailout) return 0; | |||
if (dryRun) chatty = true; // dry-run implies chatty | |||
|
|||
if ((makeDepend || makeDepFile) && (!exe || exe.endsWith(dirSeparator))) |
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.
exe.endsWith(dirSeparator)
Why not reuse the existing logic which calculates exe
if -od
is set? I don't see any reason why something should work with only -of
but not -od
.
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.
At lines 188-196
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.
Just move the check inside writeDeps
(e.g. enforce(exe, "Executable location is not specified");
). The calls to it are conveniently located after the point where exe
is calculated if -of
or -od
are set, but before the point where it is calculated if it's going to be in a temporary directory.
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.
Why not reuse the existing logic which calculates exe if -od is set? I don't see any reason why something should work with only -of but not -od.
Is a simplification because I don't see is realistic to use -od
with --makedep*
and it greatly simplifies the code. I would keep it like this and if anybody needs it in the future it can be extended. I have the feeling nobody ever will (famous last words :P).
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.
Just move the check inside writeDeps (e.g. enforce(exe, "Executable location is not specified");).
If I do this I have to take care again about the added paths to the target, which is really annoying for something probably nobody will ever use.
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.
Are these cases in the test suite?
No. But here is an example. I know is a very bizarre corner case, but as I said before I stumbled to this problem in the past and is no fun to debug.
$ cd /tmp
$ mkdir make
$ cat <<EOT > Makefile
./../make/.././t:
echo t > $@
../t: blah
EOT
$ make ./../make/.././t
echo t > ../make/.././t
$ make ../t
make: *** No rule to make target `blah', needed by `../t'. Stop.
So as you can see, ./../make/.././t
and ../t
targets are treated differently. If you have -od./../make/.././ ./../make/.././t.d
and you normalize the path, you'll get ../t
for the binary, but the source will be ./../make/.././t.d
, so depending on how you call make ./../make/.././t
or make ../t
it will work or not.
I know it might work for 99.9% of the cases, but my point is it's still weak and provide absolutely 0 advantage (when you write a makefile you know how your target should be named and you should use -of
).
Adding a convoluted case like this to the tests is overkill and so is trying to figure out a more sane case that also fails, this is why I'm not willing to spend a lot more time on this.
I would like to settle with something, rdmd
right now is completely broken to calculate dependencies, this PR in any form (with or without accept -od
) will bring it to usefulness (although I strongly believe accepting -od
is the wrong approach).
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.
Well, I just don't think this is a good argument, I mean you're pushing hard for a fix to a specific case but don't want to add a test to it, and the refactoring I suggested seems like an obvious one that any next guy who comes along might do and break your case.
Anyway, if you're OK with that, I guess I have no objections.
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.
and the refactoring I suggested seems like an obvious one that any next guy who comes along might do and break your case.
This is a fair point, I can add a comment mentioning this and pointing to the discussion. Seriously, adding test cases for these kind of corner cases would be extremely time consuming, is killing a fly with a bazooka.
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.
Was the plan to add an entire make file or something? I think just checking that rdmd isn't mangling the paths in unexpected ways would be enough, no?
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.
Was the plan to add an entire make file or something?
I don't understand what do you mean by this.
I think just checking that rdmd isn't mangling the paths in unexpected ways would be enough, no?
Yes, but is not so simple, the problem is the input data for the test :)
And I'm really, really sorry but I don't have the time to dedicate to build a good rdmd test suite. I think I did a fair job by testing what I changed, but I think making a proper test suite for rdmd is beyond the scope of this PR.
What happened to stripping the leading |
Yeah, the test-suite was implemented fairly recently. RDMD has grown quite organically, it doesn't have a feature list except what the help screen says. :) |
If I require That is only necessary for target names synthesized by |
Updated adding a comment to clarify why we only support |
@@ -139,6 +139,21 @@ int main(string[] args) | |||
if (bailout) return 0; | |||
if (dryRun) chatty = true; // dry-run implies chatty | |||
|
|||
/* Only -of is supported because Make is very suceptible to file names, and |
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.
susceptible
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.
Thanks, fixed.
The way the feature worked was to list the main source file as depending on its own transitive imports. Then it was assumed the makefile would have a rule that made the exe dependent on the main source file. Like this:
Usually the generated part is included from a different file. With that setup:
Please confirm that by this diff the proposed setup is:
With the proposed setup, things work more or less the same except there's no need to write the first line in the makefile by hand. Is that correct? |
I'm sorry to break it to you but this makefile is broken. Just try it. build it, then main.d:
touch $@ Which is clearly a hack and changes the timestamp of With this change, if you already used acme: main.d
rdmd --build-only -of$@ main.d You could replace I would strongly recommend to use acme : main.d
rdmd --build-only --makedepfile deps -of$@ $(firstword $(filter %.d,$^))
-include deps |
… target Having the source file as the target for the dependencies on a Makefile is useless, as there is no rule to rebuild the source file, Make can't use that information at all. To a have a meaningful target name, now --makedep* options require -of to be present too.
…for all source files Now rdmd --makedep(end|file) will print an empty rule for each source file.
The current format is not very human friendly and also makes doing simple checks for testing quite hard. The new format is based on GCC's format, and it looks like this: target: \ source1.d \ source2.d \ source1.d: source2.d:
you're right, thanks for the explanation |
…arget Fix rdmd --makedep(end|file) (issues 12351 and 12354)
This pull request basically makes
rdmd --makedep(end|file)
useful. I don't know if anybody used it before (checking it does work), because I have no idea how it could have worked.Basically this fixes 2 important issues (use the binary produced as the target instead of the source file, and list all the dependencies as empty targets to avoid make errors if you remove a file). Also the output format is improved to make it both more testeable and human-readable.