summaryrefslogtreecommitdiff
path: root/build/aclocal.enable.m4
blob: bcff013b08f3d301780c7d040c0e53f81c40ba0b (plain)
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
dnl
dnl These are the facilities for enable/disabling various features,
dnl and for collecting CFLAGS/LIBS and generating per feature .pc
dnl files, assembling list of source files to compile, creating
dnl cairo-features.h and other generated files, etc...
dnl

dnl ===========================================================================

dnl
dnl Used to force cache invalidation
dnl
m4_define([cr_cache_version], [6])

dnl
dnl Define a macro to enable features
dnl  - Macro: _CAIRO_ENABLE (ID, NAME, WHAT, DEFAULT, COMMANDS)
dnl
dnl where:
dnl
dnl	ID is the sub-namespace in function names, eg. "ft" for cairo_ft_...
dnl	NAME is the human-readable name of the feature, eg. "FreeType font"
dnl	WHAT is the type of feature:
dnl		"surface" for surface backends
dnl		"font" for font backends
dnl		"functions" for set of functions
dnl		"" for private configurations
dnl	DEFAULT is the default state of the feature:
dnl		"no" for experimental features, eg. your favorite new backend
dnl		"yes" for recommended features, eg. png functions
dnl		"auto" for other supported features, eg. xlib surface backend
dnl		"always" for mandatory features (can't be disabled), eg. image surface backend
dnl	COMMANDS are run to check whether the feature can be enabled.  Their
dnl		result may be cached, so user should not count on them being run.
dnl		They should set use_$(ID) to something other than yes if the
dnl		feature cannot be built, eg. "no (requires SomeThing)".  It then
dnl		should also set $(ID)_REQUIRES/CFLAGS/LIBS/...
dnl		appropriately.  Look at the macro definition for more details,
dnl		or ask if in doubt.
dnl
AC_DEFUN([_CAIRO_ENABLE],
[dnl
	dnl Sanity check ID
	m4_if(
		[$1],
		m4_tolower(AS_TR_SH([$1])),
		,
		[m4_fatal([invalid feature name `$1'])]
	)dnl
	m4_pushdef([cr_feature], [$1])dnl
	m4_pushdef([cr_feature_name], m4_normalize([$2]))dnl
	m4_pushdef([cr_feature_what], m4_normalize([$3]))dnl
	m4_pushdef([cr_feature_default], m4_normalize([$4]))dnl
	m4_pushdef([cr_feature_commands], [$5])dnl
	m4_pushdef([cr_feature_commands_len], m4_len([$5]))dnl
	dnl
	m4_pushdef([cr_feature_arg], m4_translit([$1],_,-))dnl
	dnl
	dnl Sanity check default
	m4_case(
		cr_feature_default,
		[no],,
		[yes],,
		[auto],,
		[always],,
		[m4_fatal([Invalid default value `]cr_feature_default[' for feature `]cr_feature['])]
	)dnl
	dnl
	m4_if(cr_feature_default, [always],
	[dnl
		enable_$1=yes
	],[dnl
		AC_ARG_ENABLE(cr_feature_arg,
			      AS_HELP_STRING([--enable-]cr_feature_arg[=@<:@no/auto/yes@:>@],
					     [Enable cairo's ]cr_feature_name[ feature @<:@default=]cr_feature_default[@:>@]),
			      enable_$1=$enableval, enable_$1=cr_feature_default)
	])dnl
	dnl
	AS_CASE([$enable_$1],
	[no],[dnl
		use_$1="no (disabled, use --enable-cr_feature_arg to enable)"
	],dnl
	[yes|auto],[dnl
		dnl Cache invalidating:
		dnl
		dnl To be extremely user-friendly, we discard cache results if
		dnl any of the following conditions happens:
		dnl
		dnl   - Global cache version changes
		dnl     This is used to force a cache invalidation for these
		dnl     macros
		dnl
		dnl   - Set of cached variables changes
		dnl     (XXX should also do if the default value of such
		dnl     variables changes.  Argh...)
		dnl
		dnl   - Length of the COMMANDS string changes!
		dnl     (This is much more friendly to the cache than caching
		dnl     the commands string itself.  Note that this still does
		dnl     not catch all valid cases where we should be
		dnl     invalidting.  For example if COMMANDS uses
		dnl     variables/macros defined outside, we don't detect changes
		dnl     in those variables.  Also doesn't detect in-place
		dnl     modifications like bumping verson numbers.
		dnl     Just modify COMMANDS in an obvious way to force recheck.
		dnl     Hashing sounds a bit too harsh to do here...)
		dnl
		dnl  - If feature is requested and cached results for enabling
		dnl    feature is no.  We are going to terminate with an error
		dnl    if this happens anyway, so we can be more friendly by
		dnl    assuming that user installed some missing pieces since
		dnl    last time and so we recheck.  Although even in that
		dnl    case other cached values probably get in the way...
		dnl
		AS_IF([test "x$cairo_cv_[]$1[]_cache_version" != "x[]cr_cache_version" -o \
			    "x$cairo_cv_[]$1[]_cache_commands_len" != "x[]cr_feature_commands_len" -o \
			    "x$cairo_cv_[]$1[]_cache_vars" != "x[]_CAIRO_FEATURE_VARS"],
		      [unset cairo_cv_[]$1[]_use])
		AS_IF([test "x$enable_$1" = xyes -a "x$cairo_cv_[]$1[]_use" != xyes],
		      [unset cairo_cv_[]$1[]_use])

		AC_CACHE_CHECK([for cairo's ]cr_feature_name[ feature], cairo_cv_[]$1[]_use,
		[dnl
			echo
			use_[]$1=yes
			CAIRO_FEATURE_VARS_FOREACH(cr_var, [cr_feature[_]cr_var[=]_CAIRO_SH_ESCAPE_UNQUOTED(m4_do([cr_var_default_]cr_var[_value]))]m4_newline)
			cr_feature_commands
			cairo_cv_[]$1[]_use=$use_[]$1
			cairo_cv_[]$1[]_cache_vars="_CAIRO_FEATURE_VARS"
			cairo_cv_[]$1[]_cache_commands_len="cr_feature_commands_len"
			cairo_cv_[]$1[]_cache_version="cr_cache_version"
			CAIRO_FEATURE_VARS_FOREACH([cr_var], [[cairo_cv_]cr_feature[_]cr_var[=$]cr_feature[_]cr_var]m4_newline)
			AC_MSG_CHECKING([whether cairo's ]cr_feature_name[ feature could be enabled])
		])dnl

		use_[]$1=$cairo_cv_[]$1[]_use

		AS_IF([test "x$enable_$1" = "xyes" -a "x$use_$1" != xyes],
		[dnl
			AC_MSG_ERROR(
				m4_case(cr_feature_default,
					[always],	[mandatory],
					[yes],		[recommended],
					,		[requested]
				) cr_feature_name[ feature could not be enabled])
		])dnl
	],dnl
	[dnl	
		AC_MSG_ERROR([invalid argument passed to --enable-]cr_feature_arg[: `$use_$1', should be one of @<:@no/auto/yes@:>@])
	])dnl

	AS_IF([test "x$use_$1" = "xyes"],
	[dnl
		CAIRO_FEATURE_VARS_FOREACH([cr_var], [cr_feature[_]cr_var[=$cairo_cv_]cr_feature[_]cr_var]m4_newline)
		CAIRO_ACCUMULATED_FEATURE_VARS_FOREACH([cr_var],
		[dnl
			CAIRO_ACCUMULATE_UNQUOTED_BEFORE(cr_var, [$]cr_feature[_]cr_var)
		])dnl
	],[dnl
		dnl If not enabled, empty the vars so no one accidentally uses them.
		CAIRO_FEATURE_VARS_FOREACH([cr_var], [cr_feature[_]cr_var[=$cairo_cv_]cr_feature[_]cr_var]m4_newline)
	])dnl

	_CAIRO_FEATURE_HOOKS(cr_feature, cr_feature_name, cr_feature_default, cr_feature_what)dnl

	m4_popdef([cr_feature])dnl
	m4_popdef([cr_feature_name])dnl
	m4_popdef([cr_feature_what])dnl
	m4_popdef([cr_feature_default])dnl
	m4_popdef([cr_feature_commands])dnl
	m4_popdef([cr_feature_commands_len])dnl
	m4_popdef([cr_feature_arg])dnl
])


dnl ===========================================================================

m4_define([_CAIRO_FEATURE_VARS])

dnl
dnl CAIRO_FEATURE_VARS_REGISTER(VARS, DEFAULT-VALUE=[])
dnl
dnl Registers variables to be collected from feature-enabling code segments.
dnl VARS should be a whitespace-separate list of variable names.
dnl
dnl DEFAULT-VALUE is m4 macros to set default value of VARS
dnl
AC_DEFUN([CAIRO_FEATURE_VARS_REGISTER],
[dnl
	m4_foreach_w([cr_var], [$1],
		     [m4_append_uniq([_CAIRO_FEATURE_VARS], cr_var, [ ],,
				     [m4_fatal([Feature variable `]cr_var[' already registered])])])dnl
	m4_foreach_w([cr_var], [$1],
	[dnl
		m4_define([cr_var_default_]cr_var[_value], m4_default([$2],[[$ac_env_[]]cr_feature[[]_]]cr_var[[_value]]))dnl
	])dnl
])

dnl
dnl CAIRO_FEATURE_VARS_FOREACH(VAR, COMMANDS)
dnl 
dnl Run COMMANDS for each registered feature variable.
dnl Defines VAR to the variable being processed.
dnl
AC_DEFUN([CAIRO_FEATURE_VARS_FOREACH],
[dnl
	m4_foreach_w([$1], _CAIRO_FEATURE_VARS, [$2])dnl
])


dnl ===========================================================================

m4_define([_CAIRO_ACCUMULATORS])dnl

m4_define([_CAIRO_ACCUMULATORS_REGISTER],
[dnl
	m4_foreach_w([cr_var], [$1],
		     [m4_append_uniq([_CAIRO_ACCUMULATORS], cr_var, [ ],,
				     [m4_fatal([Accumulator `]cr_var[' already registered])])])dnl
	m4_foreach_w([cr_var], [$1], [m4_define([cr_acc_]cr_var[_sep], [$2])])dnl
	m4_foreach_w([cr_var], [$1], [[CAIRO_]cr_var[=$3]]m4_newline)dnl
	m4_foreach_w([cr_var], [$1], [m4_pattern_allow([CAIRO_]cr_var)])dnl
])dnl

m4_define([_CAIRO_SH_ESCAPE],['m4_bpatsubst([$1],['],[\\'])'])dnl
m4_define([_CAIRO_SH_ESCAPE_UNQUOTED],["m4_bpatsubst([$1],["],[\\"])"])dnl

dnl
dnl CAIRO_ACCUMULATORS_REGISTER(VARS, SEPARATOR=[], INITIAL-VALUE=[])
dnl
dnl Registers accumulators.  An accumulator is a shell variable that can
dnl be accumulated to.  The macros take care of adding a SEPARATOR between
dnl accumulated values.
dnl
dnl VARS should be a whitespace-separate list of variable names.  The actual
dnl shell variable resulting for each variable is prefixed with CAIRO_.
dnl
AC_DEFUN([CAIRO_ACCUMULATORS_REGISTER],
[dnl
	_CAIRO_ACCUMULATORS_REGISTER([$1],[$2],_CAIRO_SH_ESCAPE([$3]))dnl
])dnl

dnl
dnl Like CAIRO_ACCUMULATORS_REGISTER but INITIAL-VALUE is left unquoted,
dnl so it can reference other shell variables for example.
dnl
AC_DEFUN([CAIRO_ACCUMULATORS_REGISTER_UNQUOTED],
[dnl
	_CAIRO_ACCUMULATORS_REGISTER([$1],[$2],_CAIRO_SH_ESCAPE_UNQUOTED([$3]))dnl
])dnl

m4_define([_CAIRO_ACCUMULATOR_CHECK],
[dnl
        m4_ifdef([cr_acc_$1_sep],,[m4_fatal([Accumulator `]$1[' not defined.])])dnl
])dnl

m4_define([_CAIRO_ACCUMULATE],
[dnl
	_CAIRO_ACCUMULATOR_CHECK([$1])dnl
	m4_ifval([$2], [$3]m4_newline)dnl
])dnl

dnl
dnl CAIRO_ACCUMULATE(VAR, VALUE)
dnl
dnl Appends VALUE to accumulator VAR
dnl
AC_DEFUN([CAIRO_ACCUMULATE],
[dnl
	_CAIRO_ACCUMULATE([$1], [$2], [CAIRO_$1="${CAIRO_$1}]m4_do([cr_acc_$1_sep])["_CAIRO_SH_ESCAPE([$2])])dnl
])dnl

dnl
dnl CAIRO_ACCUMULATE_BEFORE(VAR, VALUE)
dnl
dnl Prepends VALUE to accumulator VAR
dnl
AC_DEFUN([CAIRO_ACCUMULATE_BEFORE],
[dnl
	_CAIRO_ACCUMULATE([$1], [$2], [CAIRO_$1=_CAIRO_SH_ESCAPE([$2])"]m4_do([cr_acc_$1_sep])[${CAIRO_$1}"])dnl
])dnl

m4_define([_CAIRO_ACCUMULATE_UNQUOTED],
[dnl
	_CAIRO_ACCUMULATOR_CHECK([$1])dnl
	m4_ifval([$2], [m4_bmatch([$2],[[$]],[test -n "$2" &&]) $3]m4_newline)dnl
])dnl

dnl
dnl CAIRO_ACCUMULATE_UNQUOTED(VAR, VALUE)
dnl
dnl Like CAIRO_ACCUMULATE but VALUE is left unquoted,
dnl so it can reference other shell variables for example.
dnl
AC_DEFUN([CAIRO_ACCUMULATE_UNQUOTED],
[dnl
	_CAIRO_ACCUMULATE_UNQUOTED([$1], [$2], [CAIRO_$1="${CAIRO_$1}]m4_do([cr_acc_$1_sep])["]_CAIRO_SH_ESCAPE_UNQUOTED([$2]))dnl
])dnl

dnl
dnl CAIRO_ACCUMULATE_UNQUOTED_BEFORE(VAR, VALUE)
dnl
dnl Like CAIRO_ACCUMULATE_BEFORE but VALUE is left unquoted,
dnl so it can reference other shell variables for example.
dnl
AC_DEFUN([CAIRO_ACCUMULATE_UNQUOTED_BEFORE],
[dnl
	_CAIRO_ACCUMULATE_UNQUOTED([$1], [$2], [CAIRO_$1=]_CAIRO_SH_ESCAPE_UNQUOTED([$2])["]m4_do([cr_acc_$1_sep])[${CAIRO_$1}"])dnl
])dnl

dnl
dnl CAIRO_ACCUMULATE_UNQUOTED_UNCHECKED(VAR, VALUE)
dnl
dnl Like CAIRO_ACCUMULATE_UNQUOTED but VALUE is not tested for emptiness.
dnl
AC_DEFUN([CAIRO_ACCUMULATE_UNQUOTED_UNCHECKED],
[dnl
	_CAIRO_ACCUMULATE([$1], [$2], [CAIRO_$1="${CAIRO_$1}]m4_do([cr_acc_$1_sep])["]_CAIRO_SH_ESCAPE_UNQUOTED([$2]))dnl
])dnl

dnl
dnl CAIRO_ACCUMULATE_UNQUOTED_UNCHECKED_BEFORE(VAR, VALUE)
dnl
dnl Like CAIRO_ACCUMULATE_UNQUOTED_BEFORE but VALUE is not tested for emptiness.
dnl
AC_DEFUN([CAIRO_ACCUMULATE_UNQUOTED_BEFORE],
[dnl
	_CAIRO_ACCUMULATE([$1], [$2], [CAIRO_$1=]_CAIRO_SH_ESCAPE_UNQUOTED([$2])["]m4_do([cr_acc_$1_sep])[${CAIRO_$1}"])dnl
])dnl

dnl
dnl CAIRO_ACCUMULATORS_FOREACH(VAR, COMMANDS)
dnl 
dnl Run COMMANDS for each registered accumulator.
dnl Defines VAR to the accumulator being processed.
dnl
AC_DEFUN([CAIRO_ACCUMULATORS_FOREACH],
[dnl
	m4_foreach_w([$1], _CAIRO_ACCUMULATORS, [$2])dnl
])dnl


dnl ===========================================================================

m4_define([_CAIRO_ACCUMULATED_FEATURE_VARS])dnl

dnl
dnl CAIRO_ACCUMULATED_FEATURE_VARS_REGISTER(VARS, DEFAULT-VALUE=[], SEPARATOR=[], INITIAL-VALUE=[])
dnl
dnl Defines VARS as feature variables and accumulators.  Also accumulates
dnl (prepending, not appending) feature values for VARS.
dnl
AC_DEFUN([CAIRO_ACCUMULATED_FEATURE_VARS_REGISTER],
[dnl
	m4_foreach_w([cr_var], [$1],
		     [m4_append_uniq([_CAIRO_ACCUMULATED_FEATURE_VARS], cr_var, [ ],,
				     [m4_fatal([Accumulated feature variable `]cr_var[' already registered])])])dnl
	CAIRO_FEATURE_VARS_REGISTER([$1],[$2])dnl
	CAIRO_ACCUMULATORS_REGISTER_UNQUOTED([$1],[$3],[$4])dnl
])dnl

dnl
dnl CAIRO_ACCUMULATED_FEATURE_VARS_FOREACH(VAR, COMMANDS)
dnl 
dnl Run COMMANDS for each registered accumulated feature variable.
dnl Defines VAR to the variable being processed.
dnl
AC_DEFUN([CAIRO_ACCUMULATED_FEATURE_VARS_FOREACH],
[dnl
	m4_foreach_w([$1], _CAIRO_ACCUMULATED_FEATURE_VARS, [$2])dnl
])dnl

dnl ===========================================================================

dnl
dnl CAIRO_FEATURE_IF_ENABLED(FEATURE=cr_feature, COMMANDS)
dnl
dnl Run COMMANDS if FEATURE is enabled.
dnl
AC_DEFUN([CAIRO_FEATURE_IF_ENABLED],
[dnl
	AS_IF([test "x$use_]m4_default([$1], cr_feature)[" = xyes], [$2], [$3])dnl
])dnl

m4_define([_CAIRO_FEATURE_HOOK_MATCH_SH_BOOL],
[dnl
	m4_case([$1],
		[*],	[$3],
		[no],	[AS_IF([test "x$2" != xyes], [:m4_newline()$3])],
		[yes],	[AS_IF([test "x$2" = xyes], [:m4_newline()$3])],
			[m4_fatal([Invalid ENABLED value `]$1['])])dnl
])dnl

m4_define([_CAIRO_FEATURE_HOOK_MATCH_M4],
[dnl
	m4_case([$1],
		[*],	[$3],
		[$2],	[$3],
		[!$2],	,
			[m4_bmatch([$1], [^!], [$3])])dnl
])dnl

m4_define([_CAIRO_FEATURE_HOOKS])dnl

dnl
dnl CAIRO_FEATURE_HOOK_REGISTER(ENABLED, DEFAULT, WHAT, COMMANDS)
dnl
dnl	ENABLED is the feature enabledness to match
dnl	DEFAULT is the default value of features to match
dnl	WHAT is the type of features to match
dnl	COMMANDS is commands to run for matched features.
dnl
dnl Runs COMMANDS for features matching ENABLED, DEFAULT, and WHAT.
dnl Hooks are run for each feature in the order they are added.
dnl
dnl DEFAULT and WHAT are matched like this:
dnl	[*]	matches all values
dnl	[val]	matches [val]
dnl	[!val]	matches anything other than [val]
dnl
dnl ENABLED is matched like this:
dnl 	[yes]	matches enabled features
dnl 	[no]	matches disabled features
dnl 	[*]	matches all features
dnl
dnl The following macros can be used in COMMANDS:
dnl
dnl	cr_feature expands to the feature id, eg "ft"
dnl	cr_feature_name	expands to the human-readable name of the feature, eg. "FreeType font"
dnl	cr_feature_default expands to the default state of the feature:
dnl		"no" for experimental features, eg. your favorite new backend
dnl		"yes" for recommended features, eg. png functions
dnl		"auto" for other supported features, eg. xlib surface backend
dnl		"always" for mandatory features (can't be disabled), eg. image surface backend
dnl	cr_what expands to the type of feature:
dnl		"surface" for surface backends
dnl		"font" for font backends
dnl		"functions" for set of functions
dnl		"" for private configurations
dnl
dnl These four values are also set as $1 to $4.  To know if feature was
dnl enabled from within COMMANDS, use CAIRO_FEATURE_IF_ENABLED:
dnl
dnl	CAIRO_FEATURE_IF_ENABLED($1, [IF-ENABLED], [IF-DISABLED])
dnl
dnl or compare $use_$1 to string "yes".  As in:
dnl
dnl	AS_IF([test "x$use_$1" = "xyes"], [IF-ENABLED], [IF-DISABLED])
dnl
AC_DEFUN([CAIRO_FEATURE_HOOK_REGISTER],
[dnl
	m4_append([_CAIRO_FEATURE_HOOKS],
	[dnl
		_CAIRO_FEATURE_HOOK_MATCH_M4([$2], cr_feature_default,
		[_CAIRO_FEATURE_HOOK_MATCH_M4([$3], cr_feature_what,
		 [_CAIRO_FEATURE_HOOK_MATCH_SH_BOOL([$1], [$use_]cr_feature,
		  [$4]
		)])])dnl
	], m4_newline)dnl
])dnl