Makefile.include: replace $(USEPKG:%=$(BINDIR)/%.a) target #9935
Makefile.include: replace $(USEPKG:%=$(BINDIR)/%.a) target #9935jnohlgard merged 3 commits intoRIOT-OS:masterfrom
Conversation
ae13071 to
d5f23fd
Compare
|
The test application also works in master, as nothing uses the file, but the file does not exist after building in |
Makefile.include
Outdated
| _SUBMAKE_LIBS = $(filter-out $(BINDIR)/$(APPLICATION_MODULE).a $(USEPKG:%=$(BINDIR)/%.a) $(APPDEPS), $(BASELIBS)) | ||
| $(_SUBMAKE_LIBS): $(BINDIR)/$(APPLICATION_MODULE).a $(USEPKG:%=$(BINDIR)/%.a) | ||
| _SUBMAKE_LIBS = $(filter-out $(BINDIR)/$(APPLICATION_MODULE).a $(APPDEPS), $(BASELIBS)) | ||
| $(_SUBMAKE_LIBS): $(BINDIR)/$(APPLICATION_MODULE).a | pkg-build |
There was a problem hiding this comment.
@cladmi Does this correctly detect when a file is modified in the pkg?
This is an order-only prerequisite which is also a .PHONY, which is unfamiliar territory for me. We need to be certain that this does not cause make to assume that the target is up to date when the pkg files have been modified.
There was a problem hiding this comment.
@gebart For me order-only .PHONY prerequisite is something you execute everytime but you still check the file timestamp.
I used an 'order-only' because building it should not invalidate the other files timestamp, it is not its role here.
My train of thoughts here is:
- ELFFILE is rebuilt if files in
$(BASELIBS)changed (but also depend on FORCE, so it is rebuilt everytime to ensure it is rebuilt if we change one of the variables) - These lines say that "Files in
$(BASELIBS)are generated by executing the$(BINDIR)/$(APPLICATION_MODULE).aandpkg-buildtargets. - The target
$(BINDIR)/$(APPLICATION_MODULE).a, that in fact generate most of the targets in$(BASELIBS), currently depends on FORCE to rebuild it everytime - The target
pkg-buildis.PHONYso rebuilt everytime
So now, they are all always executed.
I just put it order-only as for me, it is the same behavior as before, execute it every time (there was $(USEPKG:%=$(BINDIR)/%.a): $(BUILDDEPS) FORCE before) but still consider the generated files timestamps.
Currently it also does not really change anything as $(BUILDDEPS) contains .PHONY targets so forces rebuilding anyway. I may be able to change it to an order-only target, just a bit worried of the make clean all -j case.
There was a problem hiding this comment.
What I am confused about is how make treats the indirect dependencies via the order only prereq. Does make treat the .a file as needing a rebuild, or do we introduce a race here?
I know that the elf is always relinked in the current implementation of the build system, but that is not really what we want to do when nothing has changed, so it is necessary that the dependencies are correct or we are likely to introduce hidden problems that will bite us in the future.
There was a problem hiding this comment.
I tested on a smaller makefile and you are right, make does not always re-evaluate the .a files timestamp after the order-only .PHONY target.
At least, it does not if there is only one target in the list of targets, if there is more than one, it does re-evaluate them after executing the order-only .PHONY target.
It is even lazier than what I thought, which makes sense, it does not re-evaluate the .a files timestamp even if it depends on a target that modifies another file than the target name.
So currently it only works because there are more than one target in _SUBMAKE_LIBS and if not it would because of the FORCE dependencies everywhere.
I will replace with a normal dependency here as the order-only does not currently add anything and only introduces confusion.
Testing
Details of testing showing the state in master, (except without FORCE everywhere and only one target):
.PHONY: all clean FORCE
all: app.elf
app.elf: pkg-sub.a pkg.a applications.a
cat $^ > $@
pkg-sub.a: pkg.a applications.a
pkg.a: FORCE
echo '1' > pkg-sub.a
applications.a: FORCE
echo '2' > pkg.a
test -f $@ || echo '3' > $@
clean:
rm -f *.a *.elfNow if you do
$ make clean
rm -f *.a *.elf
$ make
echo '1' > pkg-sub.a
echo '2' > pkg.a
test -f applications.a || echo '3' > applications.a
cat pkg-sub.a pkg.a applications.a > app.elf
$ make
echo '1' > pkg-sub.a
echo '2' > pkg.a
test -f applications.a || echo '3' > applications.a
$ make
echo '1' > pkg-sub.a
echo '2' > pkg.a
test -f applications.a || echo '3' > applications.a
cat pkg-sub.a pkg.a applications.a > app.elf
$ make
echo '1' > pkg-sub.a
echo '2' > pkg.a
test -f applications.a || echo '3' > applications.aWe have an applications.a target that does not change the file if it is up to date and also create the pkg.a archive. The pkg.a creates another one. And the final application is not linked half of the times.
And yes we have the case in our build system with for example the nordic_softdevice_ble archive that is not built by the $(USEPKG:%=$(BINDIR)/%.a) target.
$ make --no-print-directory BOARD=nrf52dk -C examples/gnrc_networking ${PWD}/examples/gnrc_networking/bin/nrf52dk/nordic_softdevice_ble.a
/home/cladmi/git/work/RIOT/Makefile.dep:87: nordic_softdevice_ble: Disabling router modules: gnrc_ipv6_router_default gnrc_rpl auto_init_gnrc_rpl netstats_rpl
make[1]: Nothing to be done for 'Makefile.include'.
/home/cladmi/git/work/RIOT/dist/tools/dlcache/dlcache.sh: getting "https://developer.nordicsemi.com/nRF5_IoT_SDK/nRF5_IoT_SDK_v0.9.x/nrf5_iot_sdk_3288530.zip" from cache
rm -rf /home/cladmi/git/work/RIOT/examples/gnrc_networking/bin/pkg/nrf52dk/nordic_softdevice_ble/src
mkdir -p /home/cladmi/git/work/RIOT/examples/gnrc_networking/bin/pkg/nrf52dk/nordic_softdevice_ble/src
rm /home/cladmi/git/work/RIOT/examples/gnrc_networking/bin/pkg/nrf52dk/nordic_softdevice_ble/src/components/ble/common/ble_conn_params.c
cat /home/cladmi/git/work/RIOT/pkg/nordic_softdevice_ble/Makefile.module > /home/cladmi/git/work/RIOT/examples/gnrc_networking/bin/pkg/nrf52dk/nordic_softdevice_ble/src/components/softdevice/common/softdevice_handler/Makefile
echo "MODULE=ble_common" > /home/cladmi/git/work/RIOT/examples/gnrc_networking/bin/pkg/nrf52dk/nordic_softdevice_ble/src/components/ble/common/Makefile
cat /home/cladmi/git/work/RIOT/pkg/nordic_softdevice_ble/Makefile.module >> /home/cladmi/git/work/RIOT/examples/gnrc_networking/bin/pkg/nrf52dk/nordic_softdevice_ble/src/components/ble/common/Makefile
cat /home/cladmi/git/work/RIOT/pkg/nordic_softdevice_ble/Makefile.module > /home/cladmi/git/work/RIOT/examples/gnrc_networking/bin/pkg/nrf52dk/nordic_softdevice_ble/src/components/iot/ble_ipsp/Makefile
touch /home/cladmi/git/work/RIOT/examples/gnrc_networking/bin/pkg/nrf52dk/nordic_softdevice_ble/src/.extracted
"make" -C /home/cladmi/git/work/RIOT/pkg/nordic_softdevice_ble
cp /home/cladmi/git/work/RIOT/examples/gnrc_networking/bin/pkg/nrf52dk/nordic_softdevice_ble/src/components/iot/ble_6lowpan/lib/ble_6lowpan.a /home/cladmi/git/work/RIOT/examples/gnrc_networking/bin/nrf52dk/ble_6lowpan.a
cp /home/cladmi/git/work/RIOT/examples/gnrc_networking/bin/pkg/nrf52dk/nordic_softdevice_ble/src/components/softdevice/s1xx_iot/s1xx-iot-prototype3_nrf52_softdevice.hex /home/cladmi/git/work/RIOT/examples/gnrc_networking/bin/nrf52dk/softdevice.hex
$ ls ${PWD}/examples/gnrc_networking/bin/nrf52dk/nordic_softdevice_ble.a
ls: cannot access '/home/cladmi/git/work/RIOT/examples/gnrc_networking/bin/nrf52dk/nordic_softdevice_ble.a': No such file or directoryIt is build by having $(RIOTBASE)/pkg/nordic_softdevice_ble/src in DIRS.
|
Is this really the right way to go? |
|
@gebart I know, that is in my TODO pipeline to remove the FORCE and I started the process some time ago. It just takes many steps. Before they were all I explain below why I go with this only. It's not perfect and would gladly adapt or take yours if you have a better solution. The problems with the current rule, is that it is wrong that each
Keeping this wrong rule is for me worst than having it defined as a .PHONY target. I replaced the For me this current change is required for the To give some history context, in march there were no file target to build the libraries, the elffile, the binfile, all were just a "bash script" block f64de06#diff-ebbb3165b3276a049759e5cb4e04d6a4 |
|
My real way to go later that I thing about, is to define a variable for each module Even add some And to remove the |
jnohlgard
left a comment
There was a problem hiding this comment.
Thanks for the detailed explanation. I understand that this is a step on the way to a more robust build environment. ACK
|
please squash |
|
Thanks for the thorough review, I really appreciate that you challenged it. I will try to summarize in the commit message. |
Explicit the target name so the stem can be extracted.
BINDIR has already have been created by `pkg-prepare` and the real build directory for the package will be created by the make target itself.
|
I will try to push it on top of the |
58deb7e to
5cf91d3
Compare
|
I tried to summarize the explanation in the last commit, please tell if you want me to adapt it. |
|
Looks fine, please squash |
|
For me they are split in independent commits and do some cleanup before doing the final "big" change, so would rather keep them, they all correctly compile However I can remove the "NEEDS SQUASHING" label that I set because I had a "TEST REMOVE ME" commit. |
|
I will just push them on the |
|
I can also change |
5cf91d3 to
513fc42
Compare
|
I amended the last commit with the following change to be more close to what was before. diff --git a/Makefile.include b/Makefile.include
index 9f0352f86..dc336ef57 100644
--- a/Makefile.include
+++ b/Makefile.include
@@ -430,7 +430,7 @@ endif # RIOTNOLINK
$(ELFFILE): $(BASELIBS)
$(Q)$(_LINK) -o $@
-$(BINDIR)/$(APPLICATION_MODULE).a: $(BUILDDEPS) pkg-build
+$(BINDIR)/$(APPLICATION_MODULE).a: pkg-build $(BUILDDEPS)
$(Q)DIRS="$(DIRS)" "$(MAKE)" -C $(APPDIR) -f $(RIOTMAKE)/application.inc.mk
$(BINDIR)/$(APPLICATION_MODULE).a: FORCE |
It fixes issues with the current rule that it is wrong that each `$(BINDIR)/pkgname.a` is built by going in the package directory: * `nordic_softdevice_ble.a` is built using `DIRS` and so the `$(APPLICATION_MODULE).a` target. * It prevents having packages that are pseudomodules, which may be required to only use one "library" part of a package. It also simplifies handling changes in 'ld -r' PR that could produce objects instead of archives for packages. Limitation of the current implementation ---------------------------------------- It removes rules being 'file' target and makes them depend on `.PHONY` targets so always forces re-build. But having a file target whose file is silently generated by another target does not trigger a rebuild in Make. They may have been declared as `order-only` prerequisites but as there are some edge-cases that may not always work and does not currently add anything, it was decided to keep them as normal prerequisites until it can be globally solved.
513fc42 to
4652cb2
Compare
|
👍 |
|
Thanks for reviewing. |
Contribution description
Replace the per package archive file target by phony targets.
This allows at the same time to correctly describe PSEUDOMODULES packages as they should not be file targets and prepares for build system changes where some packages could produce objects
instead of archives for the 'ld -r' PR.
Having an explicit file target here was not adding anything.
Testing procedure
If all applications build without problem even in parallel mode and the test application commit also build, everything should be ok.
Issues/PRs references