1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
|
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!--#include virtual="/SSIfragment/indahed.shtml" -->
<link href="manual.css" rel="stylesheet" type="text/css" />
<title>Comfignat</title>
<meta name="Author" xml:lang="sv" content="Björn Persson" />
</head>
<body>
<!--#include virtual="/SSIfragment/huvud.shtml" -->
<h1>Comfignat</h1>
<p>Comfignat is common, convenient, command-line-controlled compile-time
configuration of software built with the
<a href="http://gcc.gnu.org/onlinedocs/gnat_ugn_unw/">GNAT tools</a> on
Unix-like operating systems. It consists of a makefile foundation to be
included by your makefile, and an abstract GNAT project file to be imported by
your project files.
Leveraging <a href="https://www.gnu.org/software/make/">GNU Make</a> and
<a href="http://gcc.gnu.org/onlinedocs/gnat_ugn_unw/Preprocessing-with-gnatprep.html">Gnatprep</a>,
Comfignat adds the flexibility that GNAT project files lack, so that programs
and libraries whose build systems are built around Comfignat can easily be
configured for all sorts of use cases. Comfignat also helps with configuration
and installation of files that GNAT project files don't handle, so that the
build system can install the whole software package, not just the compiled
files. At the same time Comfignat greatly reduces the amount of Make code that
needs to be written for every new project.</p>
<h2 id="features">Features</h2>
<ul>
<li><p>Users and distributions can build and install the software with the
traditional commands “<samp>make</samp>” and
“<samp>make install</samp>”.</p></li>
<li><p>All aspects of the build are fully configurable through directory
variables, program-name variables and options variables. These configuration
variables are compatible with the
<a href="https://www.gnu.org/prep/standards/html_node/Makefile-Conventions.html">GNU
Coding Standards</a>.</p></li>
<li><p><var><a href="https://www.gnu.org/prep/standards/html_node/DESTDIR.html">DESTDIR</a></var>
is supported, so installation can be done to a staging directory or directly
to the target system.</p></li>
<li><p>Configuration variables can be saved in a file and will then be used in
every subsequent Make invocation. This is convenient in particular for
developers who can configure debugging options or nonstandard paths in their
development environments.</p></li>
<li><p>The build can be controlled entirely from a command prompt, which means
that it can be scripted. There is no need to edit or patch configuration files.
This is important in particular for distributions with automated build
systems.</p></li>
<li><p>Users who build and install from source do not need to run a
configuration script. They can do any configuration they need directly in the
Make command.</p></li>
<li><p>Directories projects are supported. A directories project is a
GNAT project file that defines directory variables for use by other project
files. If a directories project is provided, then Comfignat will configure the
project files to use the directory variables it defines.</p></li>
<li><p>Out-of-tree building is supported. There can be several separate build
directories with different configurations.</p></li>
<li><p>Multiarch operating systems are supported. Library instances built for
different architectures can coexist in a computer system if the system provides
a directories project that refers to different directories depending on the
target architecture.</p></li>
<li><p>Relocatable binary packages can be built. Comfignat can be instructed to
convert the directory variables into relative pathnames and configure the
project files with those, so that the installed directory tree as a whole can
be moved to another location in the filesystem without breaking the project
files.</p></li>
<li><p><a href="http://gcc.gnu.org/onlinedocs/gnat_ugn_unw/The-GNAT-Make-Program-gnatmake.html">Gnatmake</a>
and <a href="http://docs.adacore.com/gprbuild-docs/html/gprbuild_ug.html">GPRbuild</a>
are both supported, which makes Comfignat suitable for both mixed-language
projects and pure Ada projects.</p></li>
<li><p>The Make code that is needed to do all of this is generic, so that only
a minimal amount of Make code needs to be written for each project. An
uncomplicated project may need only two or three lines of Make code to build
and install the software itself. Test suites, documentation et cetera add to
this.</p></li>
<li><p>Make is not a hard requirement. Comfignat uses some advanced features of
GNU Make that may not be supported by other clones and forks of Make. If a
system's native Make doesn't have those features and GNU Make isn't available,
then it's possible to bypass Make and run first Gnatprep and then Gnatmake or
GPRbuild manually. It's less convenient to build that way though, files that the
GNAT tools don't handle must then be installed in some other way, and some of
the features listed here are lost.</p></li>
</ul>
<h2 id="download">Download</h2>
<p>The code is available for download
<a href="https://www.xn--rombobjrn-67a.se/Comfignat/download">as a tarball</a>,
and is also
<a href="https://www.xn--rombobjrn-67a.se/git/comfignat">browsable</a>.</p>
<h3 id="license">License</h3>
<p>The following applies to all of Comfignat including this document:</p>
<p>Copyright 2013 - 2016 Björn Persson, Bjorn@Rombobjörn.se</p>
<p>This material is provided as is, with absolutely no warranty expressed
or implied. Any use is at your own risk.</p>
<p>Permission is hereby granted to use or copy these files
for any purpose, provided the above notices are retained on all copies.
Permission to modify the code and to distribute modified code is granted,
provided the above notices are retained, and a notice that the code was
modified is included with the above copyright notice.</p>
<h2 id="quickstart">Getting Started</h2>
<p>This is the least that you have to do to use Comfignat:</p>
<ul>
<li><p>Copy the files
<a href="comfignat.gpr.gp"><var>comfignat.gpr.gp</var></a>,
<a href="comfignat.mk"><var>comfignat.mk</var></a> and
<a href="INSTALL"><var>INSTALL</var></a> to your source tree.</p></li>
<li><p>Write a GNAT project file to control the build. Import
“<samp>comfignat.gpr</samp>” (without “<samp>.gp</samp>”) and use the variables
that the project <var>Comfignat</var> defines.</p>
<ul>
<li><p>Use <var>Comfignat.Objdir</var> for <var>Object_Dir</var>.</p></li>
<li><p>If your project file builds a program, then use
<var>Comfignat.Stage_Bindir</var> for <var>Exec_Dir</var> (or,
<a href="#where_programs">in some cases</a>, a subdirectory of
<var>Comfignat.Stage_Libexecdir</var>).</p></li>
<li><p>If your project file builds a library, then use a subdirectory of
<var>Comfignat.Stage_Includedir</var> for <var>Library_Src_Dir</var>,
<var>Comfignat.Stage_Libdir</var> for <var>Library_Dir</var>, and a
subdirectory of <var>Comfignat.Stage_Alidir</var> for
<var>Library_ALI_Dir</var>.</p></li>
</ul>
</li>
<li><p>If your project is a library, then write a project file for other
projects to import to use the library. Give it a filename that ends with
“<samp>.gpr.gp</samp>”. It will be run through Gnatprep to generate the actual
project file without the “<samp>.gp</samp>” suffix. Make it import the project
file that the preprocessor symbol <var>Directories_GPR</var> specifies, but
only if <var>Directories_GPR</var> is defined. Do not import
<var>comfignat.gpr</var>. Use the symbol <var>Includedir</var> in the value of
<var>Source_Dirs</var>, use <var>Libdir</var> for <var>Library_Dir</var>, and
use <var>Alidir</var> as part of <var>Library_ALI_Dir</var>.</p></li>
<li><p>Write a makefile that includes <var>comfignat.mk</var>. The makefile
shall set the variable <var>build_GPRs</var> to the filename of the
build-controlling project file. For a library it shall also set the variable
<var>usage_GPRs</var> to the filename that the usage project file will have
after preprocessing. That's all that is required of the makefile. Everything
else is optional.</p></li>
</ul>
<h3 id="quickstart_example">Example</h3>
<p>Here's a complete set of project files and makefile containing everything
that is necessary for building an uncomplicated shared library and installing
it where the user wants it:</p>
<div class="example file"><h5><code>build_example.gpr</code></h5>
<pre class="gpr">with "comfignat.gpr";
library project Build_Example is
for Library_Name use "example";
for Library_Kind use "dynamic";
for Library_Version use "libexample.so.1";
for Library_Interface use ("Example");
for Object_Dir use Comfignat.Objdir;
for Library_Src_Dir use Comfignat.Stage_Includedir & "/example";
for Library_Dir use Comfignat.Stage_Libdir;
for Library_ALI_Dir use Comfignat.Stage_Alidir & "/example";
end Build_Example;</pre></div>
<div class="example file"><h5><code>example.gpr.gp</code></h5>
<pre class="gpr">#if Directories_GPR'Defined then
with $Directories_GPR;
#end if;
library project Example is
for Library_Name use "example";
for Library_Kind use "dynamic";
for Source_Dirs use ($Includedir & "/example");
for Library_Dir use $Libdir;
for Library_ALI_Dir use $Alidir & "/example";
for Externally_Built use "true";
end Example;</pre></div>
<div class="example file"><h5><code>Makefile</code></h5>
<pre class="make">include comfignat.mk
build_GPRs = build_example.gpr
usage_GPRs = example.gpr</pre></div>
<h2 id="howto">How to Use Comfignat</h2>
<h3 id="directory_variables">Directory Variables</h3>
<p>During the build, the files that will be installed are collected in a
directory structure under a staging directory whose name is held in the
variable <var>stagedir</var>. In the installation step that whole directory
structure is copied to the directory specified in <var>DESTDIR</var>, or to the
root directory if <var>DESTDIR</var> is empty.</p>
<p>Comfignat defines several directory variables that control where in the
target filesystem different kinds of files will get installed and where
applications write their files at run time. Distributions and installing users
are expected to override these variables according to their filesystem layout.
They are available as Make variables to makefiles that include
<var>comfignat.mk</var>, as GNAT project variables to build project files that
import <var>comfignat.gpr</var>, and as preprocessor symbols to usage project
files that are preprocessed with Gnatprep. The build project variables are
suitable for embedding in programs where the directory names are needed at run
time. In project files most of these variables are relative pathnames when a
<a href="#relocatable">relocatable package</a> is built. Otherwise they are
absolute. In makefiles they are always absolute.</p>
<p>Another set of directory variables, which are derived from the first set but
have the prefix “<var>stage_</var>” in their names, specify the directories
under the staging directory where the files shall be written during the build.
These variables are available to makefiles and build project files. Build
projects shall use them in the attributes that control where generated files
are placed. They are always absolute pathnames.</p>
<p>A third set, with the prefix “<var>Make_</var>”, are relative versions of
the staging directory variables. These are meant for use in Make targets,
prerequisites and other places where Make expects space-separated lists. This
mitigates the problem that Make has with spaces in filenames. Using a relative
pathname hides the pathname of the parent directory from Make so that spaces
in that part of the pathname don't cause Make to read it as a list of multiple
filenames. (In recipes it's usually possible to use quotes around a pathname to
ensure that it won't be read as a space-separated list, so there the
“<var>stage_</var>” variables should work.) These variables are only available
to makefiles.</p>
<p>The directory <var>objdir</var> is meant for intermediate files, and
<var>srcdir</var> and <var>builddir</var> are used to support
<a href="#build_directories">separate build directories</a>. For Make targets
and prerequisites there are <var>Make_stagedir</var>, <var>Make_objdir</var>,
<var>Make_srcdir</var> and <var>Make_builddir</var></p>
<h4 id="where">Where to Place Files</h4>
<h5 id="where_programs">Programs</h5>
<ul>
<li><p>Programs that can be run from a command prompt shall be placed in
<var>Comfignat.Stage_Bindir</var> by build project files. Any executable files
that aren't built with GNAT tools shall be placed in <var>stage_bindir</var> by
makefiles.</p></li>
<li><p>Programs that are only to be run by other programs, not by users, shall
be placed under a separate subdirectory of
<var>Comfignat.Stage_Libexecdir</var> by build project files – or under
<var>stage_libexecdir</var> by makefiles. Programs that need to invoke such
programs shall have <var>Comfignat.Libexecdir</var> compiled in.</p></li>
</ul>
<h5 id="where_libraries">Libraries</h5>
<ul>
<li><p>Ada specifications, C headers and other source files that are needed for
compilation of other software that uses your libraries shall be placed under
<var>Comfignat.Stage_Includedir</var> by build project files, usually under a
separate subdirectory. Usage project files shall get the directory from the
preprocessor symbol <var>Includedir</var>. These files should normally be
architecture-independent.</p></li>
<li><p>If you have architecture-specific source files that you need to make
available to other software that uses your libraries, then you should restructure
your code to encapsulate the architecture-specific bits in the compiled code
and keep the API clean. But if you really must install such files, then you may
put them under a separate subdirectory of <var>stage_archincludedir</var>.
Usage project files shall get the directory from the preprocessor symbol
<var>Archincludedir</var>.</p></li>
<li><p>Binary libraries shall be placed in <var>Comfignat.Stage_Libdir</var>
by build project files. Usage project files shall get the directory from the
preprocessor symbol <var>Libdir</var>.</p></li>
<li><p>Ada library information (ALI) files shall be placed under a separate
subdirectory of <var>Comfignat.Stage_Alidir</var> by build project files. Usage
project files shall get the directory from the preprocessor symbol
<var>Alidir</var>.</p></li>
<li><p>Other architecture-specific files shall usually be placed under a
separate subdirectory of <var>stage_libdir</var>. (It will be the same
subdirectory that ALI files are placed in when
<var>alidir</var> = <var>libdir</var>.) Programs shall look for them under
<var>Comfignat.Libdir</var>.</p></li>
<li><p>Comfignat automatically puts usage project files in
<var>stage_gprdir</var>.</p></li>
</ul>
<h5 id="where_data">Data</h5>
<ul>
<li><p>Idiosyncratic read-only architecture-independent data files shall be
placed under a separate subdirectory of <var>stage_datadir</var>. Programs
shall look for them under <var>Comfignat.Datadir</var>.</p></li>
<li><p>Locale-specific message catalogs shall be placed in the appropriate
subdirectories under <var>stage_localedir</var>. Programs shall look for them
under <var>Comfignat.Localedir</var>.</p></li>
<li><p>Configuration files – host-specific data files that aren't modified in
the normal course of their use but may be modified by system administrators –
shall be placed under <var>stage_sysconfdir</var>. If there are several they
should probably be under a separate subdirectory. Programs shall look for them
under <var>Comfignat.Sysconfdir</var>.</p></li>
<li><p>Idiosyncratic variable data files shall be placed under a separate
subdirectory of <var>stage_statedir</var>. Programs shall read and write them
under <var>Comfignat.Statedir</var>.</p></li>
<li><p>If your program keeps cached data files that it can regenerate if they
are deleted, then those files shall be kept under a separate subdirectory of
<var>Comfignat.Cachedir</var>. You won't install cached files but you may want
to create the subdirectory under <var>stage_cachedir</var>.</p></li>
<li><p>Log files shall be written under <var>Comfignat.Logdir</var>. You won't
install log files but you may want to create a separate subdirectory under
<var>stage_logdir</var> if your program writes its own log files.</p></li>
</ul>
<h5 id="where_documentation">Documentation</h5>
<ul>
<li><p>Documentation in the Man format shall be placed in the appropriate
subdirectories under <var>stage_mandir</var>.</p></li>
<li><p>Documentation in the Info format shall be placed in
<var>stage_infodir</var>.</p></li>
<li><p>Other documentation files shall be placed under a separate subdirectory of
<var>stage_miscdocdir</var>.</p></li>
</ul>
<h5 id="where_system">System State</h5>
<ul>
<li><p>Small files that take part in describing the state of the system and
that exist only while the program is running, such as process identifier files
and transient Unix-domain sockets, shall be sought and created under
<var>Comfignat.Runstatedir</var>. (This is <strong>not</strong> the place for
temporary files in general.)</p></li>
<li><p>Lock files that are used to prevent multiple programs from trying to
access a device or other resource at the same time shall be sought and created
under <var>Comfignat.Lockdir</var>.</p></li>
</ul>
<h5 id="where_intermediate">Intermediate Files</h5>
<ul>
<li><p>It is recommended to keep intermediate files in <var>objdir</var>. Then
Comfignat automatically knows how to delete them in
<a href="#target_clean">“<samp>make clean</samp>”</a>. Build project files
shall use <var>Comfignat.Objdir</var> for <var>Object_Dir</var>. Makefiles may
use <var>Make_objdir</var>.</p></li>
</ul>
<h3 id="directories_projects">Directories Projects</h3>
<p>A directories project is a GNAT project file that defines directory
variables for use by other project files. It may be defined by an operating
system and contain the standard directories on that system, or it may be
written by a system administrator to encode local policy. Comfignat configures
project files to use a directories project if the Make variable
<var>dirgpr</var> is set on the command line.</p>
<p>A Comfignat-compatible directories project shall define the following
variables:</p>
<dl>
<dt><var>Hardware_Platform</var></dt>
<dd>A short string, suitable for use in filenames, that identifies the current
target architecture.</dd>
<dt><var>Bindir</var></dt>
<dd>The directory for programs that can be run from a command prompt.</dd>
<dt><var>Libexecdir</var></dt>
<dd>The parent of applications' separate application-specific directories for
programs that are intended to be run by other programs rather than by
users.</dd>
<dt><var>Includedir</var></dt>
<dd>The top-level directory for (normally architecture-independent) source
files to be used in the compilation of software using libraries.</dd>
<dt><var>Archincludedir</var></dt>
<dd>The parent of libraries' separate library-specific directories for
architecture-specific source files to be used in the compilation of software
using libraries, for any libraries that absolutely must install such
files.</dd>
<dt><var>Libdir</var></dt>
<dd>The directory for binary libraries to be used by other software, and the
top-level directory for other architecture-specific files.</dd>
<dt><var>Alidir</var></dt>
<dd>The parent of libraries' separate library-specific directories for
Ada library information files.</dd>
</dl>
<p>Here's an example of what a directories project may look like:</p>
<pre class="example gpr">abstract project System_Directories is
type Platform_Type is ("i386", "x86_64", "ppc", "ppc64", "ia64");
Hardware_Platform : Platform_Type := external ("HARDWARE_PLATFORM");
case Hardware_Platform is
when "i386" | "ppc" | "ia64" =>
Lib := "lib";
when "x86_64" | "ppc64" =>
Lib := "lib64";
end case;
Libdir := "/usr/" & Lib;
Bindir := "/usr/bin";
Libexecdir := "/usr/libexec";
Includedir := "/usr/include";
Alidir := Libdir;
Archincludedir := Libdir & "/include";
end System_Directories;</pre>
<p>This directories project belongs in a multiarch operating system where
libraries are kept in either <var>/usr/lib</var> or <var>/usr/lib64</var>
depending on which architecture they are compiled for. The directories project
sets <var>Libdir</var>, <var>Alidir</var> and <var>Archincludedir</var>
to the right directories for the target architecture based
on an environment variable. A library project that uses this directories
project will therefore automatically adapt to the current target architecture,
so that 32-bit and 64-bit instances of the library can be installed in parallel
and the right library will be used in every build.</p>
<h3 id="library_type">Shared and Static Libraries</h3>
<p>Many libraries can be built either as a shared library or as a static
library. To enable this, use the variable <var>Comfignat.Library_Type</var> for
<var>Library_Kind</var> in the build-controlling project file, and the
preprocessor symbol <var>Library_Type</var> in the usage project file. The
default will then be to build a shared library, but installing users and
distributions can build a static library instead by setting
<var>library_type</var> to “<samp>static</samp>” on the Make command line.
The possible values of <var>Library_Type</var> are the same as for
<var>Library_Kind</var>: “<samp>dynamic</samp>”, “<samp>static</samp>”, and
“<samp>relocatable</samp>” which is an alias for “<samp>dynamic</samp>”.</p>
<p>It may be necessary to also use <var>Comfignat.Library_Type</var> in a case
construction to set certain attributes only for one kind of library. It may for
example be desirable to set <var>Library_Interface</var> for a shared library
but not for a static library, to get the best automatic elaboration in both
cases. Here's a project file fragment that sets <var>Library_Version</var> and
<var>Library_Interface</var> only when building a shared library:</p>
<pre class="example gpr"> for Library_Kind use Comfignat.Library_Type;
case Comfignat.Library_Type is
when "dynamic" | "relocatable" =>
for Library_Version use "libexample.so.1";
for Library_Interface use ("Example");
when "static" =>
null;
end case;</pre>
<p>It is also possible to build both a shared and a static library in the same
Make invocation by overriding <var>LIBRARY_TYPE</var> on the builder command
line:</p>
<pre class="example make">base: build_example.gpr
${build_GPR} -margs -XLIBRARY_TYPE=dynamic
${build_GPR} -margs -XLIBRARY_TYPE=static</pre>
<h3 id="options">Options</h3>
<p>Your software may have optional features or properties that can be enabled
or disabled at build time. Comfignat can help you define options for those.
Each option is represented as a Make variable whose value can be
“<samp>true</samp>” or “<samp>false</samp>”, which installing users and
distributions are expected to override on the command line. The names of these
variables should be listed in the variable <var>options</var>. Each option
should also be assigned a default value, unless it shall be mandatory to always
set it on the command line. Comfignat will check that the variables listed in
<var>options</var> have valid Boolean values.</p>
<p>Here's a makefile fragment that defines two options:</p>
<pre class="example make">options = enable_frobnicator atomic_doodads
enable_frobnicator = false
atomic_doodads = true</pre>
<p>Options listed in <var>options</var> will be conveyed as preprocessor
symbols to preprocessed files and as external variables to build project
files.</p>
<h3 id="relocatable">Relocatable Packages</h3>
<p>A relocatable software package is a directory tree with programs and/or
libraries that can be installed anywhere in a filesystem and function from
there without recompilation. Such software can't use embedded absolute
pathnames to refer to files in the package. Pathnames embedded in the files
must be relative to some directory in the relocatable package.</p>
<p>If the Make variable <var>relocatable_package</var> is set to
“<samp>true</samp>” on the command line, then Comfignat will use relative
pathnames in preprocessor symbols and GNAT project variables for embedding. In
usage project files the pathnames will be relative to <var>gprdir</var> so that
the project file will reference the right directories regardless of how the
package is relocated (as long as the package is moved as a whole and not
rearranged internally). In build project files most directory variables will be
relative to <var>bindir</var>. Provided that a program can find out the
pathname of its own executable file, it can get <var>bindir</var> as the
directory part of that, and then find the other directories relative to that
directory. <var>bindir</var> will instead be relative to <var>libexecdir</var>
so that a helper program in <var>libexecdir</var> can find <var>bindir</var>
and then find the other directories from there.</p>
<p>Only <var>runstatedir</var> and <var>lockdir</var> are always absolute
pathnames. Those directories belong to the operating system and are used for
communication between subsystems. It wouldn't make sense for an application to
have its own <var>runstatedir</var>.</p>
<h3 id="build_tools">Build Tools and their Arguments</h3>
<p>There are several options variables that let installing users and
distributions control which arguments the build tools are invoked with. They
have names that end with “<var>FLAGS</var>”, and are documented in
<a href="INSTALL"><var>INSTALL</var></a>.
The value of <var>GNATFLAGS</var> is a combination of the
other options variables and must not be modified in a way that disregards the
other variables. Apart from that restriction you can assign default values to
optional arguments in these variables, but be sure to do the assignments with
“<samp>?=</samp>” so that environment variables can override your defaults.</p>
<p>The value of <var>Gnatprep_arguments</var> will be passed to Gnatprep when a
file is preprocessed, and <var>builder_arguments</var> will be passed to
GPRbuild or Gnatmake when a project is built. These variables are not meant to
be overridden by users. They may be used for preprocessor symbols, external
variables for project files or other arguments that are essential for the build
to work. (Essential arguments may of course also be specified in build project
files.) Global default values for optional arguments should be set in the
options variables instead.</p>
<p>The program-name variables <var>GNATPREP</var> and <var>GNAT_BUILDER</var>
allow installing users and distributions to control the commands that invoke
the build tools, for example to use a specific version or a wrapper. You can
set <var>GNAT_BUILDER</var> to “<samp>gnatmake</samp>” if you want to build
with Gnatmake instead of GPRbuild by default, but again be sure to do the
assignment with “<samp>?=</samp>” so that environment variables can override
your default.</p>
<h3 id="configuration">Persistent Configuration</h3>
<p>Those Make variables that installing users are expected to change can be
configured persistently. Run “<samp>make configure</samp>” with some variables
set on the command line or in the environment. Those variables will then be
saved in a file named <var>comfignat_configuration.mk</var>, which will be
loaded in all subsequent Make invocations. Additional variables can be
configured incrementally. Make variables that can be overridden by environment
variables can also be configured from the environment, whereas those variables
that can only be overridden on the command line can only be configured from the
command line. In subsequent Make invocations environment variables
override values that were configured from the environment, and variables set on
the command line override all configured values. The configuration can be
erased with “<samp>make unconfigure</samp>” or as a part of
“<samp>make distclean</samp>”.</p>
<p>The command “<samp>make show_configuration</samp>” may be used to view the
current configuration. It outputs the configured variables in Make assignment
syntax, but easier to read than the actual configuration file. Variables that
were configured from the command line are shown as ordinary assignments with
“<samp>=</samp>”, and those that were configured from the environment are shown
as conditional assignments with “<samp>?=</samp>”.</p>
<p>The variables that can be configured are listed in the variable
<var>configuration_variables</var>. The variables listed in <var>options</var>
are included. You can make additional variables configurable by appending their
names to <var>configuration_variables</var>.</p>
<h3 id="build_directories">Separate Build Directories</h3>
<p>Instead of building in the source tree you can use a separate build
directory. All generated files will then be written under the build directory
and the source tree will not be modified. You can have several build
directories with different configuration files in them. To set up a new build
directory, run “<samp>make configure builddir=/some/pathname</samp>”. The
variable <var>builddir</var> will not be saved in the configuration; instead a
configuration file will be written in the specified directory. A makefile will
also be written in the build directory unless there is one already. This
generated makefile will delegate all commands to the main makefile in the
source directory so that Make can conveniently be invoked from the build
directory.</p>
<p>If you use separate build directories, then you should do all your builds in
separate build directories and not build anything in the source directory. If
there are generated files with the same name both in the source directory and
in the build directory, then the wrong file may be used in some cases.</p>
<p>If a build project file is preprocessed with Gnatprep, then the preprocessed
file will be in the build directory, so it can't refer to source directories
with pathnames relative to the project file or rely on the source files being
in the same directory as the project file. The preprocessor symbol
<var>Srcdir</var> must be used in the value of <var>Source_Dirs</var>. Its
value is the directory where <var>comfignat.mk</var> is, which is usually the
root of the source tree. Here's an example:</p>
<pre class="example gpr">for Source_Dirs use ($Srcdir & "/tools");</pre>
<h3 id="rules">Writing Make Rules</h3>
<h4 id="building_projects">Building GNAT Projects</h4>
<p>The projects that are listed in <var>build_GPRs</var> will be built by
default. Any other project needs a rule to control when it is built. Such a
rule shall use the variable <var>build_GPR</var> in its recipe.
<var>build_GPR</var> contains a command that performs a build controlled by the
first project file among the rule's prerequisites. The command is affected by
<a href="#build_tools">program-name and options variables</a>, along with
<var>builder_arguments</var> and <a href="#options"><var>options</var></a>.
A library that comes with some demo programs might have a rule like this to
build the demos only on explicit request (also ensuring that the library has
been built first):</p>
<pre class="example make">demo_programs: demos.gpr build
${build_GPR}</pre>
<h4 id="making_directories">Making Directories</h4>
<p>There is no need to write rules to make directories. Comfignat has a pattern
rule that matches all pathnames that end with a slash, and creates the
directory and its ancestors. Just specify the directory as an order-only
prerequisite and be sure to append a slash. This rule ensures that the
directory <var>data</var> exists before the file <var>db</var> is written:</p>
<pre class="example make">${Make_statedir}/example/data/db: | ${Make_statedir}/example/data/
echo stuff > $@</pre>
<h3 id="targets">Make Targets</h3>
<p>These phony targets are defined in <var>comfignat.mk</var>:</p>
<dl>
<dt id="target_build"><var>build</var></dt>
<dd><p>This is what a plain “<samp>make</samp>” will do (unless your makefile
defines some other target before it includes <var>comfignat.mk</var>). By
default it builds and stages the build projects that are listed in
<var>build_GPRs</var>, and preprocesses and stages any usage project files that
are listed in <var>usage_GPRs</var>. You may add additional prerequisites if
there are other things that should be built and installed by default, for
example documentation:</p>
<pre class="example make">build: man html pdf</pre></dd>
<dt id="target_install"><var>install</var></dt>
<dd><p>If a user unpacks a source package and immediately runs
“<samp>make install</samp>”, then the <var>build</var> target is built and then
installed. If some files have already been staged in the staging directory,
then “<samp>make install</samp>” doesn't rebuild anything but just copies the
staged directory structure to the directory specified in <var>DESTDIR</var>, or
to the root directory if <var>DESTDIR</var> is empty.</p></dd>
<dt id="target_all"><var>all</var></dt>
<dd><p>By default <var>all</var> is the same as <var>build</var>, but you may
add additional prerequisites to it if you have optional components that
shouldn't be built by default. Such targets will be built by
“<samp>make all</samp>” but not by a plain “<samp>make</samp>”:</p>
<pre class="example make">all: demo_programs auxiliary_tools</pre></dd>
<dt id="target_base"><var>base</var></dt>
<dd><p>This builds and stages the build projects that are listed in
<var>build_GPRs</var>, but does not do everything that <var>build</var> does.
It can be used to bypass targets that you don't want to rebuild all the time
when you're programming. Any targets that you do want to rebuild every time may
be added as prerequisites.</p></dd>
<dt id="target_preprocess"><var>preprocess</var></dt>
<dd><p>This preprocesses files that need to be preprocessed before projects are
built.</p></dd>
<dt id="target_postinstall"><var>postinstall</var></dt>
<dd><p>You may add a recipe to <var>postinstall</var> if there are commands
that need to be run on the target system after the files have been installed.
This will typically be commands that modify existing files on the target
system. Normally “<samp>make install</samp>” runs <var>postinstall</var> after
installing the files when <var>DESTDIR</var> is empty, but skips it when a
directory is specified in <var>DESTDIR</var>, because such commands need to be
run on the target system, not on a build server. Installing users can override
this default behaviour by setting <var>do_postinstall</var> to
“<samp>true</samp>” or “<samp>false</samp>”.</p></dd>
<dt id="target_preinstall"><var>preinstall</var></dt>
<dd><p>This is like <var>postinstall</var> except that it's run before the
files are installed, not after. Installing users can control it with
<var>do_preinstall</var>.</p></dd>
<dt id="target_install_files"><var>install_files</var></dt>
<dd><p>You may add a recipe to <var>install_files</var> if any files have to be
written, deleted or moved after the staged directory tree has been copied.
Avoid using this if possible. It's better to stage all the files correctly
under the staging directory in the build phase, but this hook exists if you
really need it for some workaround.</p></dd>
<dt id="target_configure"><var>configure</var></dt>
<dd><p>“<samp>make configure</samp>” is used to set values in the
<a href="#configuration">persistent configuration</a> and to set up a
<a href="#build_directories">separate build directory</a>. This is a
double-colon rule so you can add your own <var>configure</var> recipe in case
you need to configure things that can't easily be expressed as Make
variables.</p></dd>
<dt id="target_show_configuration"><var>show_configuration</var></dt>
<dd><p>“<samp>make show_configuration</samp>” outputs the configured variables
in the <a href="#configuration">persistent configuration</a>. This is a
double-colon rule so you can add your own <var>show_configuration</var> recipe
to accompany your own <var>configure</var> recipe.</p></dd>
<dt id="target_unconfigure"><var>unconfigure</var></dt>
<dd><p>This deletes the configuration file that “<samp>make configure</samp>”
writes. This is a double-colon rule. If you add your own <var>configure</var>
recipe that writes additional configuration files, then you should also add an
<var>unconfigure</var> recipe to delete those files.</p></dd>
<dt id="target_clean"><var>clean</var></dt>
<dd><p>This deletes all files that are normally created by building the
software, but preserves the configuration. It's a double-colon rule so you can
add your own <var>clean</var> recipe to delete files that your recipes
generate.</p></dd>
<dt id="target_distclean"><var>distclean</var></dt>
<dd><p>This deletes all files that are normally created by configuring or
building the software. In an unpacked source tree where builds have been done
but no other files have been created, “<samp>make distclean</samp>” leaves only
the files that were in the source package. In a
<a href="#build_directories">separate build directory</a> it leaves only the
delegating makefile.</p></dd>
</dl>
<h3 id="installation_instructions">Adjusting the Installation Instructions</h3>
<p>After writing your makefile and project files, you should adapt the
installation instructions in <var>INSTALL</var> to your project. The file will
be useful to users as-is, but it will be more helpful if you edit it. Put the
title of your project in the heading, add information about optional features
and testing, and delete parts that don't apply to your project.</p>
<h2 id="news">News</h2>
<h3 id="news_1.5">Noteworthy Changes in Version 1.5</h3>
<ul>
<li><p>The variable Library_Type was added to help with writing build project
files that allow installing users to choose whether to build a shared or static
library.</p></li>
</ul>
<h3 id="news_1.4">Noteworthy Changes in Version 1.4</h3>
<ul>
<li><p>The names of variables for use in Make rules were changed to begin with
“<var>Make_</var>” instead of “<var>make_</var>”. The old names were too
confusing as they looked like commands rather than variables.</p></li>
<li><p>The Make targets <var>preinstall</var>, <var>postinstall</var> and
<var>install_files</var> were added.</p></li>
<li><p>The predefined phony targets were explicitly marked as phony so that a
file with the same name won't break them.</p></li>
</ul>
<h3 id="news_1.3">Noteworthy Changes in Version 1.3</h3>
<ul>
<li><p>A testsuite was introduced in this version.</p></li>
<li><p>A problem with spaces in pathnames was mitigated by using relative
pathnames in places where Make expects a space-separated list. Thus Make
doesn't see the names of parent directories, so spaces in those names don't
cause any problems.</p></li>
</ul>
<h3 id="news_1.2">Noteworthy Changes in Version 1.2</h3>
<ul>
<li><p>The interaction between directory variables and directories projects was
corrected so that a directories project overrides the default values of some
directory variables, but an explicitly set Make variable overrides the
corresponding variable in the directories project.</p></li>
<li><p>The directory variables <var>alidir</var> and <var>archincludedir</var>
were added.</p></li>
<li><p>The directory variable <var>runtimedir</var> was renamed to
<var>runstatedir</var> to keep Comfignat compatible with the GNU Coding
Standards.</p></li>
<li><p><var>Comfignat.Bindir</var> was made relative to
<var>Comfignat.Libexecdir</var> when relocatable_package is true.</p></li>
<li><p>Comfignat's behaviour in sub-Makes was fixed so that subprocesses
working in subdirectories use the right build and staging directories.</p></li>
<li><p>The options variable <var>GNATPREPFLAGS</var> was added.</p></li>
<li><p>The ability to save environment variables in the persistent
configuration was added.</p></li>
<li><p>The pattern rule for making directories was added.</p></li>
<li><p>The Make targets <var>all</var>, <var>base</var> and
<var>show_configuration</var> were added.</p></li>
</ul>
<!--#include virtual="/SSIfragment/giltig.shtml" -->
</body>
</html>
|