1 # Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
6 # This module supports common system interrogation and options
7 # such as '--host', '--build', '--prefix', and setting 'srcdir', 'builddir', and 'EXEEXT'.
9 # It also support the "feature" naming convention, where searching
10 # for a feature such as 'sys/type.h' defines 'HAVE_SYS_TYPES_H'.
12 # It defines the following variables, based on '--prefix' unless overridden by the user:
22 # If '--prefix' is not supplied, it defaults to '/usr/local' unless 'defaultprefix' is defined *before*
23 # including the 'system' module.
25 if {[is-defined defaultprefix
]} {
26 user-notice
"Note: defaultprefix is deprecated. Use options-defaults to set default options"
27 options-defaults
[list prefix
[get-define defaultprefix
]]
30 module-options
[subst -noc -nob {
31 host
:host-alias
=> {a complete or partial cpu-vendor-opsys
for the system where
32 the application will run
(defaults to the same value as
--build)}
33 build
:build-alias
=> {a complete or partial cpu-vendor-opsys
for the system
34 where the application will be built
(defaults to the
35 result of running config.guess
)}
36 prefix
:dir
=/usr
/local
=> {the target directory
for the build
(default: '
@default@'
)}
38 # These (hidden) options are supported for autoconf/automake compatibility
57 # @check-feature name { script }
59 # defines feature '$name' to the return value of '$script',
60 # which should be 1 if found or 0 if not found.
62 # e.g. the following will define 'HAVE_CONST' to 0 or 1.
64 ## check-feature const {
65 ## cctest -code {const int _x = 0;}
67 proc check-feature
{name code
} {
68 msg-checking
"Checking for $name..."
69 set r
[uplevel 1 $code]
70 define-feature
$name $r
74 msg-result
"not found"
79 # @have-feature name ?default=0?
81 # Returns the value of feature '$name' if defined, or '$default' if not.
83 # See 'feature-define-name' for how the "feature" name
84 # is translated into the "define" name.
86 proc have-feature
{name
{default 0}} {
87 get-define
[feature-define-name
$name] $default
90 # @define-feature name ?value=1?
92 # Sets the feature 'define' to '$value'.
94 # See 'feature-define-name' for how the "feature" name
95 # is translated into the "define" name.
97 proc define-feature
{name
{value
1}} {
98 define
[feature-define-name
$name] $value
101 # @feature-checked name
103 # Returns 1 if feature '$name' has been checked, whether true or not.
105 proc feature-checked
{name
} {
106 is-defined
[feature-define-name
$name]
109 # @feature-define-name name ?prefix=HAVE_?
111 # Converts a "feature" name to the corresponding "define",
112 # e.g. 'sys/stat.h' becomes 'HAVE_SYS_STAT_H'.
114 # Converts '*' to 'P' and all non-alphanumeric to underscore.
116 proc feature-define-name
{name
{prefix HAVE_
}} {
117 string toupper
$prefix[regsub -all {[^a-zA-Z0-9
]} [regsub -all {[*]} $name p
] _
]
120 # @write-if-changed filename contents ?script?
122 # If '$filename' doesn't exist, or it's contents are different to '$contents',
123 # the file is written and '$script' is evaluated.
125 # Otherwise a "file is unchanged" message is displayed.
126 proc write-if-changed
{file buf
{script
{}}} {
127 set old
[readfile
$file ""]
128 if {$old eq
$buf && [file exists
$file]} {
129 msg-result
"$file is unchanged"
131 writefile
$file $buf\n
137 # @include-file infile mapping
139 # The core of make-template, called recursively for each @include
140 # directive found within that template so that this proc's result
141 # is the fully-expanded template.
143 # The mapping parameter is how we expand @varname@ within the template.
144 # We do that inline within this step only for @include directives which
145 # can have variables in the filename arg. A separate substitution pass
146 # happens when this recursive function returns, expanding the rest of
149 proc include-file
{infile mapping
} {
150 # A stack of true/false conditions, one for each nested conditional
151 # starting with "true"
155 foreach line
[split [readfile
$infile] \n] {
157 if {[regexp {^
@(if|
else|endif
)(\s
*)(.
*)} $line -> condtype condspace condargs
]} {
158 if {$condtype eq
"if"} {
159 if {[string length
$condspace] == 0} {
160 autosetup-error
"$infile:$linenum: Invalid expression: $line"
162 if {[llength $condargs] == 1} {
163 # ABC => [get-define ABC] ni {0 ""}
164 # !ABC => [get-define ABC] in {0 ""}
165 lassign
$condargs condvar
166 if {[regexp {^
!(.
*)} $condvar -> condvar
]} {
171 set condexpr
"\[[list get-define $condvar]\] $op {0 {}}"
173 # Translate alphanumeric ABC into [get-define ABC] and leave the
174 # rest of the expression untouched
175 regsub -all {([A-Z
][[:alnum
:]_
]*)} $condargs {[get-define
\1]} condexpr
177 if {[catch [list expr $condexpr] condval
]} {
179 autosetup-error
"$infile:$linenum: Invalid expression: $line"
181 dputs
"@$condtype: $condexpr => $condval"
183 if {$condtype ne
"if"} {
184 if {[llength $condstack] <= 1} {
185 autosetup-error
"$infile:$linenum: Error: @$condtype missing @if"
186 } elseif
{[string length
$condargs] && [string index
$condargs 0] ne
"#"} {
187 autosetup-error
"$infile:$linenum: Error: Extra arguments after @$condtype"
190 switch -exact $condtype {
193 lappend condstack
$condval
196 # Toggle the last entry
197 set condval
[lpop condstack
]
198 set condval
[expr {!$condval}]
199 lappend condstack
$condval
202 if {[llength $condstack] == 0} {
203 user-notice
"$infile:$linenum: Error: @endif missing @if"
209 } elseif
{[regexp {^
@include
\s
+(.
*)} $line -> filearg
]} {
210 set incfile
[string map
$mapping $filearg]
211 if {[file exists
$incfile]} {
212 lappend ::autosetup(deps
) [file-normalize
$incfile]
213 lappend result
{*}[include-file
$incfile $mapping]
215 user-error
"$infile:$linenum: Include file $incfile is missing"
218 } elseif
{[regexp {^
@define
\s
+(\w
+)\s
+(.
*)} $line -> var val
]} {
222 # Only output this line if the stack contains all "true"
223 if {"0" in
$condstack} {
232 # @make-template template ?outfile?
234 # Reads the input file '<srcdir>/$template' and writes the output file '$outfile'
235 # (unless unchanged).
236 # If '$outfile' is blank/omitted, '$template' should end with '.in' which
237 # is removed to create the output file name.
239 # Each pattern of the form '@define@' is replaced with the corresponding
240 # "define", if it exists, or left unchanged if not.
242 # The special value '@srcdir@' is substituted with the relative
243 # path to the source directory from the directory where the output
244 # file is created, while the special value '@top_srcdir@' is substituted
245 # with the relative path to the top level source directory.
247 # Conditional sections may be specified as follows:
248 ## @if NAME eq "value"
254 # Where 'NAME' is a defined variable name and '@else' is optional.
255 # Note that variables names *must* start with an uppercase letter.
256 # If the expression does not match, all lines through '@endif' are ignored.
258 # The alternative forms may also be used:
259 ## @if NAME (true if the variable is defined, but not empty and not "0")
260 ## @if !NAME (opposite of the form above)
261 ## @if <general-tcl-expression>
263 # In the general Tcl expression, any words beginning with an uppercase letter
264 # are translated into [get-define NAME]
266 # Expressions may be nested
268 proc make-template
{template
{out
{}}} {
269 set infile
[file join $::autosetup(srcdir
) $template]
271 if {![file exists
$infile]} {
272 user-error
"Template $template is missing"
275 # Define this as late as possible
276 define AUTODEPS
$::autosetup(deps
)
279 if {[file ext
$template] ne
".in"} {
280 autosetup-error
"make_template $template has no target file and can't guess"
282 set out
[file rootname
$template]
285 set outdir
[file dirname
$out]
287 # Make sure the directory exists
290 # Set up srcdir and top_srcdir to be relative to the target dir
291 define srcdir
[relative-path
[file join $::autosetup(srcdir
) $outdir] $outdir]
292 define top_srcdir
[relative-path
$::autosetup(srcdir
) $outdir]
294 # Build map from global defines to their values so they can be
295 # substituted into @include file names.
296 proc build-define-mapping
{} {
298 foreach {n v
} [array get
::define] {
299 lappend mapping
@$n@ $v
303 set mapping
[build-define-mapping
]
305 set result
[include-file
$infile $mapping]
307 # Rebuild the define mapping in case we ran across @define
308 # directives in the template or a file it @included, then
309 # apply that mapping to the expanded template.
310 set mapping
[build-define-mapping
]
311 write-if-changed
$out [string map
$mapping [join $result \n]] {
312 msg-result
"Created [relative-path $out] from [relative-path $template]"
316 # build/host tuples and cross-compilation prefix
317 opt-str build build
""
318 define build_alias
$build
320 define build
[config_guess
]
322 define build
[config_sub
$build]
326 define host_alias
$host
328 define host
[get-define build
]
331 define host
[config_sub
$host]
334 define cross
[get-env CROSS
$cross]
336 # build/host _cpu, _vendor and _os
337 foreach type
{build host
} {
338 set v
[get-define
$type]
339 if {![regexp {^
([^
-]+)-([^
-]+)-(.
*)$} $v -> cpu vendor os
]} {
340 user-error
"Invalid canonical $type: $v"
342 define
${type
}_cpu
$cpu
343 define
${type
}_vendor
$vendor
344 define
${type
}_os
$os
347 opt-str prefix prefix
/usr
/local
349 # These are for compatibility with autoconf
350 define target
[get-define host
]
351 define prefix
$prefix
352 define builddir
$autosetup(builddir
)
353 define srcdir
$autosetup(srcdir
)
354 define top_srcdir
$autosetup(srcdir
)
355 define abs_top_srcdir
[file-normalize
$autosetup(srcdir
)]
356 define abs_top_builddir
[file-normalize
$autosetup(builddir
)]
358 # autoconf supports all of these
359 define exec_prefix
[opt-str exec-prefix exec_prefix
$prefix]
360 foreach {name defpath
} {
366 define
$name [opt-str
$name o
$exec_prefix$defpath]
368 foreach {name defpath
} {
375 define
$name [opt-str
$name o
$prefix$defpath]
377 if {$prefix ne
{/usr
}} {
378 opt-str sysconfdir sysconfdir
$prefix/etc
380 opt-str sysconfdir sysconfdir
/etc
382 define sysconfdir
$sysconfdir
384 define localstatedir
[opt-str localstatedir o
/var
]
385 define runstatedir
[opt-str runstatedir o
/run
]
387 define SHELL
[get-env SHELL
[find-an-executable sh bash ksh
]]
389 # These could be used to generate Makefiles following some automake conventions
390 define AM_SILENT_RULES
[opt-bool silent-rules
]
391 define AM_MAINTAINER_MODE
[opt-bool maintainer-mode
]
392 define AM_DEPENDENCY_TRACKING
[opt-bool dependency-tracking
]
394 # Windows vs. non-Windows
395 switch -glob -- [get-define host
] {
396 *-*-ming* - *-*-cygwin - *-*-msys {
397 define-feature windows
406 msg-result
"Host System...[get-define host]"
407 msg-result
"Build System...[get-define build]"