Note that there are some explanatory texts on larger screens.

plurals
  1. POSeparate compilation of interdependent C modules
    primarykey
    data
    text
    <p>Suppose we have a collection of interdependent C modules and we want to create a GNU Makefile for <em>separate compilation</em> of them for a few different builds (e.g., unit tests, user tools, multiple editions).</p> <p>Each module, while being essential for the complete application, is intended to be used separately or in any reasonable combination with other modules ‒ always exposing the most featured API resulting from the availability of components provided by other modules selected for a particular build.</p> <p>For the sake of a minimal and complete example, let's assume that our program has three modules (red, green and blue) with all possible conditional functionalities toggled by means of <em>conditional compilation</em>. Each module has two such conditional blocks, each of which enabled by the presence of one of two possible neighbours. This gives us three possible single builds (Red, Green, Blue), three double builds (Cyan, Magenta, Yellow) and one triple build (White) ‒ each containing a dedicated main program (Core) built on top of the set of profided features. </p> <p><strong>Desired situation</strong></p> <p><a href="https://i.stack.imgur.com/7xjl9.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/7xjl9.png" alt="desired situation"></a></p> <p>Figure 1 shows the three modules (<code>mod_red.c</code>, <code>mod_green.c</code> and <code>mod_blue.c</code> «RGB»); three areas of cross-module functionality (cyan, magenta and yellow «CMY») implemented <em>within</em> the adjacent modules; and three cores (white, with physical dependencies «RGB» on big, sharpened tops and logical dependencies «CMY» on small tops). Each direction (out of six) denotes a functionality aspect, so the CMY tops pointing out of the main triangle suggest that the synergy may provide additional features.</p> <p>The desired Makefile is expected to provide recipes for all possible builds, thus use four versions of each of the three modules and seven different cores. It should also be smart enough to avoid brutal solution (full block of <code>gcc</code> commands for each recipe) and to keep the advantages of separate compilation.</p> <p>Without separate compilation the problem is easy (at least for unilateral dependencies): main program includes necessary sources and the dependent blocks are enabled by preprocessor flags, e.g. those set by other modules' include guards. With separate compilation, however, the set of modules comprising a particular build is unknown to the compiler.</p> <p><strong>Manual approach</strong></p> <p>The desired situation could be achieved manually with the shell commands listed below.</p> <pre><code># Single objects: gcc -c -o mod_green.o mod_green.c # Double objects gcc -c -include mod_blue.h -o mod_red+B.o mod_red.c gcc -c -include mod_red.h -o mod_blue+R.o mod_blue.c # Triple objects gcc -c -include mod_green.h -include mod_blue.h -o mod_red+G+B.o mod_red.c gcc -c -include mod_red.h -include mod_blue.h -o mod_green+R+B.o mod_green.c gcc -c -include mod_red.h -include mod_green.h -o mod_blue+R+G.o mod_blue.c # Builds gcc -o green green.c mod_green.o gcc -o magenta magenta.c mod_red+B.o mod_blue+R.o gcc -o white white.c mod_red+G+B.o mod_green+R+B.o mod_blue+R+G.o </code></pre> <p>As for the desired situation, this example shows only the three representative builds: Green, Magenta and White. Others are formed analogously.</p> <p><strong>Classic approach</strong></p> <p><a href="https://i.stack.imgur.com/9DaQU.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/9DaQU.png" alt="enter image description here"></a></p> <p>With a classic Makefile solution the Green build stays the same, but the other two have missing logical dependencies (i.e., the CMY-provided symbols). It is so because the building process is currently (and usually) defined as follows:</p> <pre><code>white: white.c mod_red.o mod_green.o mod_blue.o gcc -o $@ $^ magenta: magenta.c mod_blue.o mod_red.o gcc -o $@ $^ green: green.c mod_green.o gcc -o $@ $^ %.o: %.c gcc -c -o $@ $&lt; </code></pre> <p>Here the problem is clearly exposed: the last rule does not distinguish between particular builds ‒ the context is lost. Also, I need to end up with different binary versions of each module to satisfy different builds. What is the proper way to do it?</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload