Simplifying Mk includes
Introduction
In the Ports system we have some ports that are depended upon by large numbers of other ports, and thus sometimes have large amounts of boilerplate that needs to be duplicated in many ports.
Historically the solution has been to create a shared Mk resource, called bsd.${appname}.mk and place it either in ports/Mk, or the MASTERDIR of the main port. To avoid having the trouble of deciding where to put the .include directive in the port's Makefile, USE_ variables have been defined in bsd.port.mk to include these files for the porter.
Problems
Practical issues
Every new bsd.*.mk file requires an exp-run because of adding the new USE_ flag to bsd.port.mk ports/159288
- Some inclusions in bsd.port.mk are in the pre- section, some are in the post- section. They also break in horrible ways if they aren't included in the correct place. Using a bsd.include.mk will force any new Mk files to be included in the same place (at the bottom of the pre-section should work well), rather than being scattered about.
For a little confusion, have a look at these two examples from the point of view of a prospective port maintainer Why can't I check the version of openldap and bsd.port.mk likes emacs better than openldap.
Style issues
- USE flags for the most part are logically named; USE_PHP causes bsd.php.mk to be included, but others are a little more strange; there are eight ways to include bsd.tcl.mk
Historical issues
- bsd.perl.mk is still not conditionally included -- it must be chugged through on every invocation of make in the ports tree. Moving the include logic to a single place should make the job a little easier since less is interfered with.
Proposal
The new file, bsd.include.mk will contain any code to handle inclusion of ports/Mk/*, and the repetitions of code can be reduced;
in lieu of:
.if defined(USE_OPENSSL)
.include "${PORTSDIR}/Mk/bsd.openssl.mk"
.endif
.if defined(USE_EMACS)
.include "${PORTSDIR}/Mk/bsd.emacs.mk"
.endifwe can instead use:
.for _useflag in openssl emacs gnustep php java ocaml
. if defined (USE_${_useflag:U})
. include "${PORTSDIR}/Mk/bsd.${_useflag}.mk"
. endif
.endformeaning that creating a new USE flag is no harder than simply adding the name to the end of the .for loop -- as well as enforcing consistency in USE naming.
We can also move conditionally included files to a plugins/ subdirectory (to be painted before the bikes go in it), ending up with a file hierarchy under ports/Mk that looks something like this: [tree deleted]
Implementation
This needs to be incremental in its introduction.
First, the code from bsd.port.mk for includes needs to be extracted and put into a separate file to keep the include code simple and maintainable, rather than its current state of being scattered around bsd.port.mk. ports/160361
Any ports that .include mk files from ${PORTSDIR} directly need to use USE_ flags instead.
- Finally change the inclusion blocks into a .for loop as described above.
We will have bsd.perl.mk included conditionally sometime before Hell freezes over.