expr: prevent stack overflow
[jimtcl.git] / autosetup / system.tcl
blob56054b4f3e1580a9702e043f4d47315497f764c6
1 # Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
2 # All rights reserved
4 # @synopsis:
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:
14 ## datadir
15 ## sysconfdir
16 ## sharedstatedir
17 ## localstatedir
18 ## infodir
19 ## mandir
20 ## includedir
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
39 exec-prefix:
40 bindir:
41 sbindir:
42 includedir:
43 mandir:
44 infodir:
45 libexecdir:
46 datadir:
47 libdir:
48 sysconfdir:
49 sharedstatedir:
50 localstatedir:
51 maintainer-mode=0
52 dependency-tracking=0
53 silent-rules=0
56 # @check-feature name { script }
58 # defines feature '$name' to the return value of '$script',
59 # which should be 1 if found or 0 if not found.
61 # e.g. the following will define 'HAVE_CONST' to 0 or 1.
63 ## check-feature const {
64 ## cctest -code {const int _x = 0;}
65 ## }
66 proc check-feature {name code} {
67 msg-checking "Checking for $name..."
68 set r [uplevel 1 $code]
69 define-feature $name $r
70 if {$r} {
71 msg-result "ok"
72 } else {
73 msg-result "not found"
75 return $r
78 # @have-feature name ?default=0?
80 # Returns the value of feature '$name' if defined, or '$default' if not.
82 # See 'feature-define-name' for how the "feature" name
83 # is translated into the "define" name.
85 proc have-feature {name {default 0}} {
86 get-define [feature-define-name $name] $default
89 # @define-feature name ?value=1?
91 # Sets the feature 'define' to '$value'.
93 # See 'feature-define-name' for how the "feature" name
94 # is translated into the "define" name.
96 proc define-feature {name {value 1}} {
97 define [feature-define-name $name] $value
100 # @feature-checked name
102 # Returns 1 if feature '$name' has been checked, whether true or not.
104 proc feature-checked {name} {
105 is-defined [feature-define-name $name]
108 # @feature-define-name name ?prefix=HAVE_?
110 # Converts a "feature" name to the corresponding "define",
111 # e.g. 'sys/stat.h' becomes 'HAVE_SYS_STAT_H'.
113 # Converts '*' to 'P' and all non-alphanumeric to underscore.
115 proc feature-define-name {name {prefix HAVE_}} {
116 string toupper $prefix[regsub -all {[^a-zA-Z0-9]} [regsub -all {[*]} $name p] _]
119 # @write-if-changed filename contents ?script?
121 # If '$filename' doesn't exist, or it's contents are different to '$contents',
122 # the file is written and '$script' is evaluated.
124 # Otherwise a "file is unchanged" message is displayed.
125 proc write-if-changed {file buf {script {}}} {
126 set old [readfile $file ""]
127 if {$old eq $buf && [file exists $file]} {
128 msg-result "$file is unchanged"
129 } else {
130 writefile $file $buf\n
131 uplevel 1 $script
135 # @make-template template ?outfile?
137 # Reads the input file '<srcdir>/$template' and writes the output file '$outfile'
138 # (unless unchanged).
139 # If '$outfile' is blank/omitted, '$template' should end with '.in' which
140 # is removed to create the output file name.
142 # Each pattern of the form '@define@' is replaced with the corresponding
143 # "define", if it exists, or left unchanged if not.
145 # The special value '@srcdir@' is substituted with the relative
146 # path to the source directory from the directory where the output
147 # file is created, while the special value '@top_srcdir@' is substituted
148 # with the relative path to the top level source directory.
150 # Conditional sections may be specified as follows:
151 ## @if name == value
152 ## lines
153 ## @else
154 ## lines
155 ## @endif
157 # Where 'name' is a defined variable name and '@else' is optional.
158 # If the expression does not match, all lines through '@endif' are ignored.
160 # The alternative forms may also be used:
161 ## @if name
162 ## @if name != value
164 # Where the first form is true if the variable is defined, but not empty nor 0.
166 # Currently these expressions can't be nested.
168 proc make-template {template {out {}}} {
169 set infile [file join $::autosetup(srcdir) $template]
171 if {![file exists $infile]} {
172 user-error "Template $template is missing"
175 # Define this as late as possible
176 define AUTODEPS $::autosetup(deps)
178 if {$out eq ""} {
179 if {[file ext $template] ne ".in"} {
180 autosetup-error "make_template $template has no target file and can't guess"
182 set out [file rootname $template]
185 set outdir [file dirname $out]
187 # Make sure the directory exists
188 file mkdir $outdir
190 # Set up srcdir and top_srcdir to be relative to the target dir
191 define srcdir [relative-path [file join $::autosetup(srcdir) $outdir] $outdir]
192 define top_srcdir [relative-path $::autosetup(srcdir) $outdir]
194 set mapping {}
195 foreach {n v} [array get ::define] {
196 lappend mapping @$n@ $v
198 set result {}
199 foreach line [split [readfile $infile] \n] {
200 if {[info exists cond]} {
201 set l [string trimright $line]
202 if {$l eq "@endif"} {
203 unset cond
204 continue
206 if {$l eq "@else"} {
207 set cond [expr {!$cond}]
208 continue
210 if {$cond} {
211 lappend result $line
213 continue
215 if {[regexp {^@if\s+(\w+)(.*)} $line -> name expression]} {
216 lassign $expression equal value
217 set varval [get-define $name ""]
218 if {$equal eq ""} {
219 set cond [expr {$varval ni {"" 0}}]
220 } else {
221 set cond [expr {$varval eq $value}]
222 if {$equal ne "=="} {
223 set cond [expr {!$cond}]
226 continue
228 lappend result $line
230 write-if-changed $out [string map $mapping [join $result \n]] {
231 msg-result "Created [relative-path $out] from [relative-path $template]"
235 # build/host tuples and cross-compilation prefix
236 opt-str build build ""
237 define build_alias $build
238 if {$build eq ""} {
239 define build [config_guess]
240 } else {
241 define build [config_sub $build]
244 opt-str host host ""
245 define host_alias $host
246 if {$host eq ""} {
247 define host [get-define build]
248 set cross ""
249 } else {
250 define host [config_sub $host]
251 set cross $host-
253 define cross [get-env CROSS $cross]
255 # build/host _cpu, _vendor and _os
256 foreach type {build host} {
257 set v [get-define $type]
258 if {![regexp {^([^-]+)-([^-]+)-(.*)$} $v -> cpu vendor os]} {
259 user-error "Invalid canonical $type: $v"
261 define ${type}_cpu $cpu
262 define ${type}_vendor $vendor
263 define ${type}_os $os
266 opt-str prefix prefix /usr/local
268 # These are for compatibility with autoconf
269 define target [get-define host]
270 define prefix $prefix
271 define builddir $autosetup(builddir)
272 define srcdir $autosetup(srcdir)
273 define top_srcdir $autosetup(srcdir)
274 define abs_top_srcdir [file-normalize $autosetup(srcdir)]
275 define abs_top_builddir [file-normalize $autosetup(builddir)]
277 # autoconf supports all of these
278 define exec_prefix [opt-str exec-prefix exec_prefix $prefix]
279 foreach {name defpath} {
280 bindir /bin
281 sbindir /sbin
282 libexecdir /libexec
283 libdir /lib
285 define $name [opt-str $name o $exec_prefix$defpath]
287 foreach {name defpath} {
288 datadir /share
289 sharedstatedir /com
290 infodir /share/info
291 mandir /share/man
292 includedir /include
294 define $name [opt-str $name o $prefix$defpath]
296 if {$prefix ne {/usr}} {
297 opt-str sysconfdir sysconfdir $prefix/etc
298 } else {
299 opt-str sysconfdir sysconfdir /etc
301 define sysconfdir $sysconfdir
303 define localstatedir [opt-str localstatedir o /var]
305 define SHELL [get-env SHELL [find-an-executable sh bash ksh]]
307 # These could be used to generate Makefiles following some automake conventions
308 define AM_SILENT_RULES [opt-bool silent-rules]
309 define AM_MAINTAINER_MODE [opt-bool maintainer-mode]
310 define AM_DEPENDENCY_TRACKING [opt-bool dependency-tracking]
312 # Windows vs. non-Windows
313 switch -glob -- [get-define host] {
314 *-*-ming* - *-*-cygwin - *-*-msys {
315 define-feature windows
316 define EXEEXT .exe
318 default {
319 define EXEEXT ""
323 # Display
324 msg-result "Host System...[get-define host]"
325 msg-result "Build System...[get-define build]"