tup vs make
Posted: Tue May 09, 2017 4:44 pm
(I'm splitting this away from this topic so that it can stay focused)
OK, I took an honest look at the tup documentation today. I have several concerns about whether tup is really the best tool for me for a Hobby OS project (I'm sure it will work extremely well for something far less complicated). I can boil my concerns down to 2 key differences between the way tup and make approach builds. Disclaimer: I did not actually download and try it.
Before I get into these differences, I feel a more concrete explanation of how I use make regularly is in order. I am currently targeting 3 architectures: i686, x86_64, and rpi2b. I am currently working on a stage 3 loader to put the processor into its native/target state before passing control to the kernel. Obviously, with distinct targets like this, there is both architecture-specific code and common code; I do not work on everything at the same time. The same will be the case with the kernel. Also, I am planning on a microkernel, so there will be lots of modules to maintain as well.
So, given these goals, I will be making several different styles of targets (and 'target' is a apropos description for what I want to do) as I go through an evening's development. Some of these are:
* `make <arch>` -- refresh all modules for that architecture
* `make <module>` -- refresh that module for all architectures
* `make <arch>-<module>` -- refresh the module for the architecture
* `make <arch>-iso` -- refresh an iso image (or disk image) for the architecture
* `make run-<arch> -- refresh the image and launch it with qemu with the proper parameters
* `make all` -- refresh everything up to but not including the iso images
Bottom-up builds versus top-down builds
* tup wants to refresh everything based on what has changed. This is a fantastic goal in theory, but the reality of how I code and run my builds is that I will work in one architecture (or module) and build many times before I think I can switch gears and move into another architecture. I think tup risks cluttering up the specific build results I am looking for with irrelevant noise.
* Now, the way I organize my build structure is that I could provide a full path to the target file I want to build, such as 'bin/rpi2b/loader.elf'. That is a more typing than I want to do when I can easily type 'rpi2b-loader' as an alias. I know there are more ways to handle this, but I think I address those below.
Overall, this represents a significant challenge to my very comfortable workflow.
No .PHONY targets
* When making something as complicated as an .iso image, I will have to invoke tup multiple times to build all the targets I want to include and then make the image itself. If I add a new module, I have to go through add that new module into the proper scripts. This maintenance is one thing I am very much against.
* tup takes the position that these are orthogonal to the concern of building a project. Anything that would be expressed in a .PHONY target in a makefile is really supposed to be a script to begin with. OK....
* Where to I place the make-run-i686.sh script? Should these be added to my own ~/bin directory? No my favorite option since I am now making project-specific tools globally available to my user -- undesirable results will occur.
* How about adding a project utils folder to my path (I already have one of those; I can just dump everything in there). Again, not a great answer as these become globally available.
* Now, to be fair, I could consider adding ./utils to my path and keep the scope of the possible issues narrow...
* I could also clutter up the root of my project with these which is the lowest risk of cross-contamination, but then I have to type "./" before any script I want to execute.
* I could also create my own ~/bin/make.sh that would reorganize the command into something that would work for real (such as changing `make run-rpi2b` into `utils/make-run-rpi2b.sh', but then what I have really need to use make?
* I could also...
OK, so there are lots of technical ways to solve the scripting issue. The point is that none of them really appeal to me.
Now, this is not to say that I am opposed to tup. Quite the contrary. I just do not think that it is the right tool for the job; you wouldn't use a picture hammer to frame a house.
I'm sure I have misunderstood some things -- I'm open to the discussion.
OK, I took an honest look at the tup documentation today. I have several concerns about whether tup is really the best tool for me for a Hobby OS project (I'm sure it will work extremely well for something far less complicated). I can boil my concerns down to 2 key differences between the way tup and make approach builds. Disclaimer: I did not actually download and try it.
Before I get into these differences, I feel a more concrete explanation of how I use make regularly is in order. I am currently targeting 3 architectures: i686, x86_64, and rpi2b. I am currently working on a stage 3 loader to put the processor into its native/target state before passing control to the kernel. Obviously, with distinct targets like this, there is both architecture-specific code and common code; I do not work on everything at the same time. The same will be the case with the kernel. Also, I am planning on a microkernel, so there will be lots of modules to maintain as well.
So, given these goals, I will be making several different styles of targets (and 'target' is a apropos description for what I want to do) as I go through an evening's development. Some of these are:
* `make <arch>` -- refresh all modules for that architecture
* `make <module>` -- refresh that module for all architectures
* `make <arch>-<module>` -- refresh the module for the architecture
* `make <arch>-iso` -- refresh an iso image (or disk image) for the architecture
* `make run-<arch> -- refresh the image and launch it with qemu with the proper parameters
* `make all` -- refresh everything up to but not including the iso images
Bottom-up builds versus top-down builds
* tup wants to refresh everything based on what has changed. This is a fantastic goal in theory, but the reality of how I code and run my builds is that I will work in one architecture (or module) and build many times before I think I can switch gears and move into another architecture. I think tup risks cluttering up the specific build results I am looking for with irrelevant noise.
* Now, the way I organize my build structure is that I could provide a full path to the target file I want to build, such as 'bin/rpi2b/loader.elf'. That is a more typing than I want to do when I can easily type 'rpi2b-loader' as an alias. I know there are more ways to handle this, but I think I address those below.
Overall, this represents a significant challenge to my very comfortable workflow.
No .PHONY targets
* When making something as complicated as an .iso image, I will have to invoke tup multiple times to build all the targets I want to include and then make the image itself. If I add a new module, I have to go through add that new module into the proper scripts. This maintenance is one thing I am very much against.
* tup takes the position that these are orthogonal to the concern of building a project. Anything that would be expressed in a .PHONY target in a makefile is really supposed to be a script to begin with. OK....
* Where to I place the make-run-i686.sh script? Should these be added to my own ~/bin directory? No my favorite option since I am now making project-specific tools globally available to my user -- undesirable results will occur.
* How about adding a project utils folder to my path (I already have one of those; I can just dump everything in there). Again, not a great answer as these become globally available.
* Now, to be fair, I could consider adding ./utils to my path and keep the scope of the possible issues narrow...
* I could also clutter up the root of my project with these which is the lowest risk of cross-contamination, but then I have to type "./" before any script I want to execute.
* I could also create my own ~/bin/make.sh that would reorganize the command into something that would work for real (such as changing `make run-rpi2b` into `utils/make-run-rpi2b.sh', but then what I have really need to use make?
* I could also...
OK, so there are lots of technical ways to solve the scripting issue. The point is that none of them really appeal to me.
Now, this is not to say that I am opposed to tup. Quite the contrary. I just do not think that it is the right tool for the job; you wouldn't use a picture hammer to frame a house.
I'm sure I have misunderstood some things -- I'm open to the discussion.