Fossil SCM

fossil-scm / autosetup / system.tcl
Source Blame History 412 lines
f476744… drh 1 # Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
f476744… drh 2 # All rights reserved
f476744… drh 3
f476744… drh 4 # @synopsis:
f476744… drh 5 #
f476744… drh 6 # This module supports common system interrogation and options
51d006f… stephan 7 # such as '--host', '--build', '--prefix', and setting 'srcdir', 'builddir', and 'EXEEXT'.
c5e4100… jan.nijtmans 8 #
51d006f… stephan 9 # It also support the "feature" naming convention, where searching
51d006f… stephan 10 # for a feature such as 'sys/type.h' defines 'HAVE_SYS_TYPES_H'.
c5e4100… jan.nijtmans 11 #
51d006f… stephan 12 # It defines the following variables, based on '--prefix' unless overridden by the user:
64a2b0d… drh 13 #
c5e4100… jan.nijtmans 14 ## datadir
c5e4100… jan.nijtmans 15 ## sysconfdir
c5e4100… jan.nijtmans 16 ## sharedstatedir
c5e4100… jan.nijtmans 17 ## localstatedir
c5e4100… jan.nijtmans 18 ## infodir
c5e4100… jan.nijtmans 19 ## mandir
c5e4100… jan.nijtmans 20 ## includedir
51d006f… stephan 21 #
370c263… stephan 22 # If '--prefix' is not supplied, it defaults to '/usr/local' unless 'options-defaults { prefix ... }' is used *before*
51d006f… stephan 23 # including the 'system' module.
c5e4100… jan.nijtmans 24
51d006f… stephan 25 if {[is-defined defaultprefix]} {
51d006f… stephan 26 user-notice "Note: defaultprefix is deprecated. Use options-defaults to set default options"
51d006f… stephan 27 options-defaults [list prefix [get-define defaultprefix]]
51d006f… stephan 28 }
c5e4100… jan.nijtmans 29
370c263… stephan 30 options {
f476744… drh 31 host:host-alias => {a complete or partial cpu-vendor-opsys for the system where
f476744… drh 32 the application will run (defaults to the same value as --build)}
f476744… drh 33 build:build-alias => {a complete or partial cpu-vendor-opsys for the system
f476744… drh 34 where the application will be built (defaults to the
f476744… drh 35 result of running config.guess)}
51d006f… stephan 36 prefix:dir=/usr/local => {the target directory for the build (default: '@default@')}
f476744… drh 37
64a2b0d… drh 38 # These (hidden) options are supported for autoconf/automake compatibility
64a2b0d… drh 39 exec-prefix:
64a2b0d… drh 40 bindir:
64a2b0d… drh 41 sbindir:
f476744… drh 42 includedir:
f476744… drh 43 mandir:
f476744… drh 44 infodir:
f476744… drh 45 libexecdir:
64a2b0d… drh 46 datadir:
64a2b0d… drh 47 libdir:
f476744… drh 48 sysconfdir:
64a2b0d… drh 49 sharedstatedir:
f476744… drh 50 localstatedir:
51d006f… stephan 51 runstatedir:
f476744… drh 52 maintainer-mode=0
f476744… drh 53 dependency-tracking=0
51d006f… stephan 54 silent-rules=0
370c263… stephan 55 program-prefix:
370c263… stephan 56 program-suffix:
370c263… stephan 57 program-transform-name:
370c263… stephan 58 }
f476744… drh 59
51d006f… stephan 60 # @check-feature name { script }
51d006f… stephan 61 #
51d006f… stephan 62 # defines feature '$name' to the return value of '$script',
51d006f… stephan 63 # which should be 1 if found or 0 if not found.
51d006f… stephan 64 #
51d006f… stephan 65 # e.g. the following will define 'HAVE_CONST' to 0 or 1.
f476744… drh 66 #
51d006f… stephan 67 ## check-feature const {
51d006f… stephan 68 ## cctest -code {const int _x = 0;}
51d006f… stephan 69 ## }
f476744… drh 70 proc check-feature {name code} {
f476744… drh 71 msg-checking "Checking for $name..."
f476744… drh 72 set r [uplevel 1 $code]
f476744… drh 73 define-feature $name $r
f476744… drh 74 if {$r} {
f476744… drh 75 msg-result "ok"
f476744… drh 76 } else {
f476744… drh 77 msg-result "not found"
f476744… drh 78 }
f476744… drh 79 return $r
f476744… drh 80 }
f476744… drh 81
f476744… drh 82 # @have-feature name ?default=0?
f476744… drh 83 #
51d006f… stephan 84 # Returns the value of feature '$name' if defined, or '$default' if not.
51d006f… stephan 85 #
51d006f… stephan 86 # See 'feature-define-name' for how the "feature" name
51d006f… stephan 87 # is translated into the "define" name.
f476744… drh 88 #
f476744… drh 89 proc have-feature {name {default 0}} {
f476744… drh 90 get-define [feature-define-name $name] $default
f476744… drh 91 }
f476744… drh 92
f476744… drh 93 # @define-feature name ?value=1?
f476744… drh 94 #
51d006f… stephan 95 # Sets the feature 'define' to '$value'.
51d006f… stephan 96 #
51d006f… stephan 97 # See 'feature-define-name' for how the "feature" name
51d006f… stephan 98 # is translated into the "define" name.
f476744… drh 99 #
f476744… drh 100 proc define-feature {name {value 1}} {
f476744… drh 101 define [feature-define-name $name] $value
f476744… drh 102 }
f476744… drh 103
f476744… drh 104 # @feature-checked name
f476744… drh 105 #
51d006f… stephan 106 # Returns 1 if feature '$name' has been checked, whether true or not.
f476744… drh 107 #
f476744… drh 108 proc feature-checked {name} {
f476744… drh 109 is-defined [feature-define-name $name]
f476744… drh 110 }
f476744… drh 111
f476744… drh 112 # @feature-define-name name ?prefix=HAVE_?
f476744… drh 113 #
51d006f… stephan 114 # Converts a "feature" name to the corresponding "define",
51d006f… stephan 115 # e.g. 'sys/stat.h' becomes 'HAVE_SYS_STAT_H'.
f476744… drh 116 #
51d006f… stephan 117 # Converts '*' to 'P' and all non-alphanumeric to underscore.
f476744… drh 118 #
f476744… drh 119 proc feature-define-name {name {prefix HAVE_}} {
f476744… drh 120 string toupper $prefix[regsub -all {[^a-zA-Z0-9]} [regsub -all {[*]} $name p] _]
f476744… drh 121 }
f476744… drh 122
51d006f… stephan 123 # @write-if-changed filename contents ?script?
51d006f… stephan 124 #
51d006f… stephan 125 # If '$filename' doesn't exist, or it's contents are different to '$contents',
51d006f… stephan 126 # the file is written and '$script' is evaluated.
51d006f… stephan 127 #
f476744… drh 128 # Otherwise a "file is unchanged" message is displayed.
f476744… drh 129 proc write-if-changed {file buf {script {}}} {
f476744… drh 130 set old [readfile $file ""]
f476744… drh 131 if {$old eq $buf && [file exists $file]} {
f476744… drh 132 msg-result "$file is unchanged"
f476744… drh 133 } else {
f476744… drh 134 writefile $file $buf\n
f476744… drh 135 uplevel 1 $script
f476744… drh 136 }
f476744… drh 137 }
f476744… drh 138
51d006f… stephan 139
51d006f… stephan 140 # @include-file infile mapping
51d006f… stephan 141 #
51d006f… stephan 142 # The core of make-template, called recursively for each @include
51d006f… stephan 143 # directive found within that template so that this proc's result
51d006f… stephan 144 # is the fully-expanded template.
51d006f… stephan 145 #
51d006f… stephan 146 # The mapping parameter is how we expand @varname@ within the template.
51d006f… stephan 147 # We do that inline within this step only for @include directives which
51d006f… stephan 148 # can have variables in the filename arg. A separate substitution pass
51d006f… stephan 149 # happens when this recursive function returns, expanding the rest of
51d006f… stephan 150 # the variables.
51d006f… stephan 151 #
51d006f… stephan 152 proc include-file {infile mapping} {
51d006f… stephan 153 # A stack of true/false conditions, one for each nested conditional
51d006f… stephan 154 # starting with "true"
51d006f… stephan 155 set condstack {1}
51d006f… stephan 156 set result {}
51d006f… stephan 157 set linenum 0
51d006f… stephan 158 foreach line [split [readfile $infile] \n] {
51d006f… stephan 159 incr linenum
51d006f… stephan 160 if {[regexp {^@(if|else|endif)(\s*)(.*)} $line -> condtype condspace condargs]} {
51d006f… stephan 161 if {$condtype eq "if"} {
51d006f… stephan 162 if {[string length $condspace] == 0} {
51d006f… stephan 163 autosetup-error "$infile:$linenum: Invalid expression: $line"
51d006f… stephan 164 }
51d006f… stephan 165 if {[llength $condargs] == 1} {
51d006f… stephan 166 # ABC => [get-define ABC] ni {0 ""}
51d006f… stephan 167 # !ABC => [get-define ABC] in {0 ""}
51d006f… stephan 168 lassign $condargs condvar
51d006f… stephan 169 if {[regexp {^!(.*)} $condvar -> condvar]} {
51d006f… stephan 170 set op in
51d006f… stephan 171 } else {
51d006f… stephan 172 set op ni
51d006f… stephan 173 }
51d006f… stephan 174 set condexpr "\[[list get-define $condvar]\] $op {0 {}}"
51d006f… stephan 175 } else {
51d006f… stephan 176 # Translate alphanumeric ABC into [get-define ABC] and leave the
51d006f… stephan 177 # rest of the expression untouched
51d006f… stephan 178 regsub -all {([A-Z][[:alnum:]_]*)} $condargs {[get-define \1]} condexpr
51d006f… stephan 179 }
51d006f… stephan 180 if {[catch [list expr $condexpr] condval]} {
51d006f… stephan 181 dputs $condval
51d006f… stephan 182 autosetup-error "$infile:$linenum: Invalid expression: $line"
51d006f… stephan 183 }
51d006f… stephan 184 dputs "@$condtype: $condexpr => $condval"
51d006f… stephan 185 }
51d006f… stephan 186 if {$condtype ne "if"} {
51d006f… stephan 187 if {[llength $condstack] <= 1} {
51d006f… stephan 188 autosetup-error "$infile:$linenum: Error: @$condtype missing @if"
51d006f… stephan 189 } elseif {[string length $condargs] && [string index $condargs 0] ne "#"} {
51d006f… stephan 190 autosetup-error "$infile:$linenum: Error: Extra arguments after @$condtype"
51d006f… stephan 191 }
51d006f… stephan 192 }
51d006f… stephan 193 switch -exact $condtype {
51d006f… stephan 194 if {
51d006f… stephan 195 # push condval
51d006f… stephan 196 lappend condstack $condval
51d006f… stephan 197 }
51d006f… stephan 198 else {
51d006f… stephan 199 # Toggle the last entry
51d006f… stephan 200 set condval [lpop condstack]
51d006f… stephan 201 set condval [expr {!$condval}]
51d006f… stephan 202 lappend condstack $condval
51d006f… stephan 203 }
51d006f… stephan 204 endif {
51d006f… stephan 205 if {[llength $condstack] == 0} {
51d006f… stephan 206 user-notice "$infile:$linenum: Error: @endif missing @if"
51d006f… stephan 207 }
51d006f… stephan 208 lpop condstack
51d006f… stephan 209 }
51d006f… stephan 210 }
51d006f… stephan 211 continue
370c263… stephan 212 }
370c263… stephan 213 # Only continue if the stack contains all "true"
370c263… stephan 214 if {"0" in $condstack} {
370c263… stephan 215 continue
370c263… stephan 216 }
370c263… stephan 217 if {[regexp {^@include\s+(.*)} $line -> filearg]} {
51d006f… stephan 218 set incfile [string map $mapping $filearg]
51d006f… stephan 219 if {[file exists $incfile]} {
51d006f… stephan 220 lappend ::autosetup(deps) [file-normalize $incfile]
51d006f… stephan 221 lappend result {*}[include-file $incfile $mapping]
51d006f… stephan 222 } else {
51d006f… stephan 223 user-error "$infile:$linenum: Include file $incfile is missing"
51d006f… stephan 224 }
51d006f… stephan 225 continue
51d006f… stephan 226 }
370c263… stephan 227 if {[regexp {^@define\s+(\w+)\s+(.*)} $line -> var val]} {
370c263… stephan 228 define $var $val
51d006f… stephan 229 continue
51d006f… stephan 230 }
51d006f… stephan 231 lappend result $line
51d006f… stephan 232 }
51d006f… stephan 233 return $result
51d006f… stephan 234 }
51d006f… stephan 235
51d006f… stephan 236
f476744… drh 237 # @make-template template ?outfile?
f476744… drh 238 #
51d006f… stephan 239 # Reads the input file '<srcdir>/$template' and writes the output file '$outfile'
51d006f… stephan 240 # (unless unchanged).
51d006f… stephan 241 # If '$outfile' is blank/omitted, '$template' should end with '.in' which
f476744… drh 242 # is removed to create the output file name.
f476744… drh 243 #
51d006f… stephan 244 # Each pattern of the form '@define@' is replaced with the corresponding
51d006f… stephan 245 # "define", if it exists, or left unchanged if not.
51d006f… stephan 246 #
51d006f… stephan 247 # The special value '@srcdir@' is substituted with the relative
f476744… drh 248 # path to the source directory from the directory where the output
51d006f… stephan 249 # file is created, while the special value '@top_srcdir@' is substituted
b2e6a23… mistachkin 250 # with the relative path to the top level source directory.
64a2b0d… drh 251 #
64a2b0d… drh 252 # Conditional sections may be specified as follows:
51d006f… stephan 253 ## @if NAME eq "value"
64a2b0d… drh 254 ## lines
64a2b0d… drh 255 ## @else
64a2b0d… drh 256 ## lines
64a2b0d… drh 257 ## @endif
64a2b0d… drh 258 #
51d006f… stephan 259 # Where 'NAME' is a defined variable name and '@else' is optional.
51d006f… stephan 260 # Note that variables names *must* start with an uppercase letter.
64a2b0d… drh 261 # If the expression does not match, all lines through '@endif' are ignored.
64a2b0d… drh 262 #
64a2b0d… drh 263 # The alternative forms may also be used:
51d006f… stephan 264 ## @if NAME (true if the variable is defined, but not empty and not "0")
51d006f… stephan 265 ## @if !NAME (opposite of the form above)
51d006f… stephan 266 ## @if <general-tcl-expression>
64a2b0d… drh 267 #
51d006f… stephan 268 # In the general Tcl expression, any words beginning with an uppercase letter
51d006f… stephan 269 # are translated into [get-define NAME]
64a2b0d… drh 270 #
51d006f… stephan 271 # Expressions may be nested
f476744… drh 272 #
f476744… drh 273 proc make-template {template {out {}}} {
f476744… drh 274 set infile [file join $::autosetup(srcdir) $template]
f476744… drh 275
f476744… drh 276 if {![file exists $infile]} {
f476744… drh 277 user-error "Template $template is missing"
f476744… drh 278 }
f476744… drh 279
f476744… drh 280 # Define this as late as possible
f476744… drh 281 define AUTODEPS $::autosetup(deps)
f476744… drh 282
f476744… drh 283 if {$out eq ""} {
f476744… drh 284 if {[file ext $template] ne ".in"} {
f476744… drh 285 autosetup-error "make_template $template has no target file and can't guess"
f476744… drh 286 }
f476744… drh 287 set out [file rootname $template]
f476744… drh 288 }
f476744… drh 289
f476744… drh 290 set outdir [file dirname $out]
f476744… drh 291
f476744… drh 292 # Make sure the directory exists
f476744… drh 293 file mkdir $outdir
f476744… drh 294
b2e6a23… mistachkin 295 # Set up srcdir and top_srcdir to be relative to the target dir
b2e6a23… mistachkin 296 define srcdir [relative-path [file join $::autosetup(srcdir) $outdir] $outdir]
b2e6a23… mistachkin 297 define top_srcdir [relative-path $::autosetup(srcdir) $outdir]
b2e6a23… mistachkin 298
51d006f… stephan 299 # Build map from global defines to their values so they can be
51d006f… stephan 300 # substituted into @include file names.
51d006f… stephan 301 proc build-define-mapping {} {
51d006f… stephan 302 set mapping {}
51d006f… stephan 303 foreach {n v} [array get ::define] {
51d006f… stephan 304 lappend mapping @$n@ $v
51d006f… stephan 305 }
51d006f… stephan 306 return $mapping
51d006f… stephan 307 }
51d006f… stephan 308 set mapping [build-define-mapping]
51d006f… stephan 309
51d006f… stephan 310 set result [include-file $infile $mapping]
51d006f… stephan 311
51d006f… stephan 312 # Rebuild the define mapping in case we ran across @define
51d006f… stephan 313 # directives in the template or a file it @included, then
51d006f… stephan 314 # apply that mapping to the expanded template.
51d006f… stephan 315 set mapping [build-define-mapping]
51d006f… stephan 316 write-if-changed $out [string map $mapping [join $result \n]] {
51d006f… stephan 317 msg-result "Created [relative-path $out] from [relative-path $template]"
51d006f… stephan 318 }
f476744… drh 319 }
f476744… drh 320
f476744… drh 321 # build/host tuples and cross-compilation prefix
51d006f… stephan 322 opt-str build build ""
f476744… drh 323 define build_alias $build
f476744… drh 324 if {$build eq ""} {
f476744… drh 325 define build [config_guess]
f476744… drh 326 } else {
f476744… drh 327 define build [config_sub $build]
f476744… drh 328 }
f476744… drh 329
51d006f… stephan 330 opt-str host host ""
f476744… drh 331 define host_alias $host
f476744… drh 332 if {$host eq ""} {
f476744… drh 333 define host [get-define build]
f476744… drh 334 set cross ""
f476744… drh 335 } else {
f476744… drh 336 define host [config_sub $host]
f476744… drh 337 set cross $host-
f476744… drh 338 }
f476744… drh 339 define cross [get-env CROSS $cross]
f476744… drh 340
51d006f… stephan 341 # build/host _cpu, _vendor and _os
51d006f… stephan 342 foreach type {build host} {
51d006f… stephan 343 set v [get-define $type]
51d006f… stephan 344 if {![regexp {^([^-]+)-([^-]+)-(.*)$} $v -> cpu vendor os]} {
51d006f… stephan 345 user-error "Invalid canonical $type: $v"
51d006f… stephan 346 }
51d006f… stephan 347 define ${type}_cpu $cpu
51d006f… stephan 348 define ${type}_vendor $vendor
51d006f… stephan 349 define ${type}_os $os
51d006f… stephan 350 }
51d006f… stephan 351
51d006f… stephan 352 opt-str prefix prefix /usr/local
f476744… drh 353
f476744… drh 354 # These are for compatibility with autoconf
f476744… drh 355 define target [get-define host]
f476744… drh 356 define prefix $prefix
f476744… drh 357 define builddir $autosetup(builddir)
f476744… drh 358 define srcdir $autosetup(srcdir)
51d006f… stephan 359 define top_srcdir $autosetup(srcdir)
51d006f… stephan 360 define abs_top_srcdir [file-normalize $autosetup(srcdir)]
51d006f… stephan 361 define abs_top_builddir [file-normalize $autosetup(builddir)]
64a2b0d… drh 362
64a2b0d… drh 363 # autoconf supports all of these
51d006f… stephan 364 define exec_prefix [opt-str exec-prefix exec_prefix $prefix]
dd13b0e… drh 365 foreach {name defpath} {
dd13b0e… drh 366 bindir /bin
dd13b0e… drh 367 sbindir /sbin
dd13b0e… drh 368 libexecdir /libexec
dd13b0e… drh 369 libdir /lib
dd13b0e… drh 370 } {
51d006f… stephan 371 define $name [opt-str $name o $exec_prefix$defpath]
dd13b0e… drh 372 }
64a2b0d… drh 373 foreach {name defpath} {
dd13b0e… drh 374 datadir /share
dd13b0e… drh 375 sharedstatedir /com
dd13b0e… drh 376 infodir /share/info
dd13b0e… drh 377 mandir /share/man
dd13b0e… drh 378 includedir /include
64a2b0d… drh 379 } {
51d006f… stephan 380 define $name [opt-str $name o $prefix$defpath]
51d006f… stephan 381 }
51d006f… stephan 382 if {$prefix ne {/usr}} {
51d006f… stephan 383 opt-str sysconfdir sysconfdir $prefix/etc
51d006f… stephan 384 } else {
51d006f… stephan 385 opt-str sysconfdir sysconfdir /etc
64a2b0d… drh 386 }
51d006f… stephan 387 define sysconfdir $sysconfdir
51d006f… stephan 388
51d006f… stephan 389 define localstatedir [opt-str localstatedir o /var]
51d006f… stephan 390 define runstatedir [opt-str runstatedir o /run]
f476744… drh 391
f476744… drh 392 define SHELL [get-env SHELL [find-an-executable sh bash ksh]]
51d006f… stephan 393
51d006f… stephan 394 # These could be used to generate Makefiles following some automake conventions
51d006f… stephan 395 define AM_SILENT_RULES [opt-bool silent-rules]
51d006f… stephan 396 define AM_MAINTAINER_MODE [opt-bool maintainer-mode]
51d006f… stephan 397 define AM_DEPENDENCY_TRACKING [opt-bool dependency-tracking]
63daf14… drh 398
f476744… drh 399 # Windows vs. non-Windows
f476744… drh 400 switch -glob -- [get-define host] {
63daf14… drh 401 *-*-ming* - *-*-cygwin - *-*-msys {
f476744… drh 402 define-feature windows
f476744… drh 403 define EXEEXT .exe
f476744… drh 404 }
f476744… drh 405 default {
f476744… drh 406 define EXEEXT ""
f476744… drh 407 }
f476744… drh 408 }
f476744… drh 409
f476744… drh 410 # Display
f476744… drh 411 msg-result "Host System...[get-define host]"
f476744… drh 412 msg-result "Build System...[get-define build]"

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button