Skip to content
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

Idea: Use order-only prerequisites for $(OBJPATH) #8

Closed
torpesco opened this issue Apr 16, 2013 · 4 comments
Closed

Idea: Use order-only prerequisites for $(OBJPATH) #8

torpesco opened this issue Apr 16, 2013 · 4 comments

Comments

@torpesco
Copy link

I made a change in nonrec-make to match what we'd done in another project that specifies different directories for build output, following the GNU Make manual: http://www.gnu.org/software/make/manual/make.html#Prerequisite-Types

All references to $(OBJPATH)/.fake_file were changed to just $(OBJPATH), and the rule to create the directory was changed to a simple mkdir -p:

diff --git a/mk/def_rules.mk b/mk/def_rules.mk
index 54b0794..d1c7368 100644
--- a/mk/def_rules.mk
+++ b/mk/def_rules.mk
@@ -61,10 +54,9 @@ LINK.cc = $(call echo_cmd,LINK $@) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) $(T
 %.CPPFLAGS : %
        @echo $(CPPFLAGS)

-# In this build system all objects are in a separate directory and
-# I make sure this directory exists by the dependency on this fake file
-%/$(OBJDIR)/.fake_file:
-       @[ -d $(dir $@) ] || mkdir -p $(dir $@); touch $@
+# Create the output directory for build targets.
+%/$(OBJDIR):
+       @mkdir -p $@

 # Generic rules.  Again, since the output is in different directory than
 # source files I cannot count on the built in make rules.  So I keep

Dependencies were changed to order-only:

 define skeleton
-$(OBJPATH)/%.o: $(1)/%.cpp $(OBJPATH)/.fake_file
+$(OBJPATH)/%.o: $(1)/%.cpp | $(OBJPATH)
        $(value COMPILECMD)

-$(OBJPATH)/%.o: $(1)/%.cc $(OBJPATH)/.fake_file
+$(OBJPATH)/%.o: $(1)/%.cc | $(OBJPATH)
        $(value COMPILECMD)

-$(OBJPATH)/%.o: $(1)/%.c $(OBJPATH)/.fake_file
+$(OBJPATH)/%.o: $(1)/%.c | $(OBJPATH)
        $(value COMPILECMD)

...and in skel.mk's tgt_rule:

-$(1): $$(abs_deps) $(if $(findstring $(OBJDIR),$(1)),$(OBJPATH)/.fake_file,)
+$(1): $$(abs_deps) $(if $(findstring $(OBJDIR),$(1)),| $(OBJPATH),)

In footer.mk, the clean target removes $(OBJPATH):

@@ -77,7 +82,7 @@ clean_$(d) :
 else
 clean_$(d) : clean_extra_$(d)
 endif
-       rm -f $(TOP_BUILD_DIR)$(subst clean_,,$@)/$(OBJDIR)/*
+       rm -rf $(TOP_BUILD_DIR)$(subst clean_,,$@)/$(OBJDIR)

 # clean_extra is meant for the extra output that is generated in source
 # directory (e.g. generated source from lex/yacc) so I'm not using
@aostruszka
Copy link
Owner

I like that!

I'm going to "pull" that from you. With minor changes: I'm going to keep the clean target intact. This target is meant to clean all "objects" only. In case of using separate build directories for different build modes your rule will only delete one such subdirectory (e.g. obj/debug while keeping obj/release and obj/profile). Deletion of separate objdirs is meant as a job for dist_clean target.

Thank you! I never liked the .fake_file solution and I know that I've read about order-only prerequisites but it seems that when I read about that my .fake_file dislike was buried somewhere else in my brain and it never clicked with "aha" moment.

Best regards
Andrzej

@aostruszka
Copy link
Owner

Uploaded now f3f07d8.
Please take a look at that (it is on eval_hdr branch for now - this will be merged to master once I hear some feedback about that proposal :)).
I'm closing this one.

Regards
Andrzej

@torpesco
Copy link
Author

Hi Andrzej,

Personally, I like the proposal. =P Realized seeing it that I forgot to go back to update ?R and ^R in mine.

It took me a bit to understand the .SECONDARY target for $(OBJPATH). In the other project we have with output directories, we don't use .SECONDARY, and it's fine. The one difference I see is that instead of "| $(OBJPATH)" on the %.o : %.c lines, we have a separate $(OBJS): | $(OBJPATH) line -- more like the make manual.

Any idea why in one method $(OBJPATH) is treated as intermediate, and in the other it's not?

Thanks,
James.

@aostruszka
Copy link
Owner

James

Initially I removed the .SECONDARY for OBJPATH but then I ran that on my examples and it turned out that make considers those directories as intermediate products (as you've mentioned) and then tries to remove them at the end giving a bunch of error messages.

I have not yet understood why they are considered intermediate targets, so for now I'm going to keep it like it is.
If you'll have some insight then don't hesitate and share it with me :)

Regards
Andrzej

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants