aostruszka / nonrec-make

Non-recursive make template for GNU make

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Install example

gigadude opened this issue · comments

I ended up figuring out that the following code added to the top-level Makefile:

INSTALLABLES = $(filter-out %.o,$(call subtree_tgts,$(d)))

install :
    @echo "example install libs: $(filter %.$(SOEXT),$(INSTALLABLES)) -> $(TOP)/$(HOST_ARCH)/lib"
    @echo "example install exes: $(filter-out %.a %.$(SOEXT),$(INSTALLABLES)) -> $(TOP)/$(HOST_ARCH)/bin"

does what I'd like for installing products. It might be nice to have an example install rule (maybe better worked out, with dependencies in the top bin/lib directory) as well as an example of generated code (i.e. a header generated with a Perl script).

Also I'd suggest that the default be to process the subtree under the current directory, and use "make dir" to make only that subdirectory's targets (principle of least surprise compared to a typical recursive makefile build).

gigadude

Thanks for request. So far my biggest project where I was using this (many libs, dirs with subdirs) was to crosscompile everything into a single monolithic binary for ppc which was later uploaded to target or tested on qemu. I'll keep this open and will think about that more. For now I have some comments:

  1. Your solution might be working for you but it is not good as a general one. For example if you apply this to ex1 it will not work correctly. You can see what subtree_tgts are there by adding simple echo rule to Rules.top there. Notice e.g. that all *.o from subdirectories of Dir_1 that are archived inside dir1_lib.a are included also in the result. This is not really what you'd like to achieve since only dir1_lib.a should be a installable target there.
  2. From my limited experience with installing you usually carefully pick what is the target that should be installed.

As I've said I'll think about this more and will get back to you.

As for your last suggestion I'm reluctant to switching the default - the whole point of using non recursive make is to build correct dependency tree and rely on it. However I'll make it easier to switch default and will define new 'dir' target and all one would have to do to switch default is to point ".DEFAULT_GOAL" to either "dir" or "tree" in Makefile.

Best regards
Andrzej

I didn't like the install solution much either, I'm thinking that per-Rules.mk explicit

INSTALL_XXX = foo bar baz

(where XXX is something like BIN, LIB, INC etc) might be the way to go. I'm also going to need a separate "deploy" target in my case. I think if you come up with a general convention concerning how to add command-like targets to your system it would be helpful.

As for the "build current dir only" default, it's minor and easily tuned to local preferences, but typically you set up hierarchy to reflect related entities which may or may not have actual dependencies between them. For example you have a hack to allow a make in a directory which only contains sub-directories to go one level deeper because you expect a directory full of things in sub-directories to just get built when you type "make". IMO the general expectation will be for recursive behavior with "build only this current directory and its dependencies" as a special target, but as you point out that's easily fixed.

Gigadude

I've just found some time and uploaded something. Please take a look at this and let me know if this addresses your needs. Reading your comment now I see that I've missed INC. Could you give me most generic example you can think of for those includes installation? And the same for other installation targets - I mean is current proposal generic enough to cover your needs?

Best regards
Andrzej

I was just working on the same thing :-)

I've forked here: https://github.com/gigadude/nonrec-make

I've merged in your changes and backed out mine re: the INSTALL_* targets.
I think the INSTALL_INC should work the way INSTALL_DOC works but with
an include rather than doc directory as its target. All of this needs some thinking
with respect to the other feature I've been working on:

I've taken a stab at supporting variant builds (release/debug/prof as examples).
I had to do some ugly things to tgt_rule:

define tgt_rule
bmd := $$(lastword $$(subst /, ,$$(dir $1)))
bmd_deps := $$(filter $$(addprefix %/$$(bmd)/,$$(notdir $$(DEPS_$(1)))),$$(DEPS_$(1)))
abs_deps := $$(filter /%,$$(bmd_deps))
rel_deps := $$(filter-out /%,$$(DEPS_$(1)))
abs_deps += $$(addprefix $(dir $1),$$(rel_deps))
-include $$(addsuffix .d,$$(basename $$(abs_deps)))
$(1): BUILD_MODE := $$(bmd)
$(1): $$(abs_deps) $$(dir $1).fake_file
    $$(or $$(CMD_$(1)),$$(MAKECMD$$(suffix $$@)),$$(DEFAULT_MAKECMD))
endef

BUILD_MODE pulls in extra flags for the compilers/linkers. It seems to be working when I
take a look at the verbose output but there are probably better ways to do it (e.g. having the
mode as a prefix on the DEPS_* etc. variables instead of doing the filtering I'm doing).

One useful trick is that specifying a set of one or more modes on the make command line
creates a mk/buildmode.mk file which remembers the last setting you used, so doing a
make debug followed by a make automatically limits you to the debug variant (that logic
is in the top-level Makefile). The same thing would be nice for make verbose|quiet and other
per-user preferences.

BTW the CLEAN* targets currently nuke the entire object directory (they should really
only nuke the build mode's outputs but it was 4am when I called it a night).

I've decided to make you a competition with this "build mode" :) - please take a look at bc861bc and let me know what you think.

I envisioned such functionality and how it should work so this change is rather minor. However I have not predicted that someone would like to make more than one specific build at a time. I'm rather satisfied with current solution - do you really need to have say "debug" and "profile" compiled with just one make invocation?

Current setting is good for following mode of operation:

  1. export BUILD_MODE=debug
  2. make
  3. test/debug/code/make/...
  4. Once the functionality is working then switch BUILD_MODE to "profile" (either one time in make invocation or better in default)
  5. profile/code/make/...
  6. Everything good, then just "make BUILD_MODE:=release"

Give it a try and let me know your opinion.

Best regards
Andrzej

It's pretty useful to build all variants in parallel (slightly less overhead for the build regression system). I can also imagine running a whole set of cross-compiles for hosted builds in parallel would be nice. Finally if I'm trying to track down an issue that only pops up in one variant it's nice to not have to remember to build both by hand as I'm making changes (I've been bitten by debugging with an out-of-date build variant before).

I haven't had a chance to look at your change yet, but I did find what I think is a nice simplification for creating the output directories, just brute-forcing mkdir -p's into the recipes for each target:

mkoutdir = @mkdir -p $(dir $@)

%.somerule: $(real_deps_only)
    $(value mkoutdir)
    $(COMPILE...)

This avoids nasty .fake_file dependency issues and I bet is faster than having make think about every output directory.

Latest version uses a nifty trick to avoid the extra shell overhead of mkdir:

mkoutdir_ = @mkdir -p $(dir $@)
mkoutdir = $(mkoutdir_$(wildcard $(dir $@)))

Gigadude

I'm closing this issue since it originally was for examples of how to install. I've now uploaded some changes (e88e142) that generalize what I've used for this example. There are now three categories of per directory vars that user can define (verbatim / with OBJPATH prepended / with dir prepended - if value is not absolute path).

It is now up to user to choose which vars to define (as a suggestion I've used names that were previously introduced: INSTALL_BIN/LIB/DOC and I've added this missing INSTALL_INC to DIR_VARS). This solution, together with get_subtree macro should be generic enough to cover all (or at least majority) needs.

As to .fake_file dependencies I'll take a look at what you have - current solution seems to be workable/OK however I'm not very fond of it.

As to the parallel building of various modes - I'm a bit skeptic about that, so I'll wait and will monitor your updates. If you come up with something sexy then I'll pull that :D.

Best regards
Andrzej