| 1 | #!/bin/sh
 | 
| 2 | #
 | 
| 3 | # POSIX shell script to detect target system properties required by Oil.
 | 
| 4 | # Distributed with the source tarball.
 | 
| 5 | #
 | 
| 6 | # The only library Oil needs is readline.
 | 
| 7 | #
 | 
| 8 | # External utilities used: cc
 | 
| 9 | #
 | 
| 10 | # TODO: Should be able to run this from another directory.
 | 
| 11 | #
 | 
| 12 | # Other settings: LTO, PGO?  Consider moving prefix, LTO, PGO to build and
 | 
| 13 | # install steps.
 | 
| 14 | 
 | 
| 15 | TMP=${TMPDIR:-/tmp}  # Assume that any system has $TMPDIR set or /tmp exists
 | 
| 16 | readonly TMP  # POSIX sh supports 'readonly'
 | 
| 17 | 
 | 
| 18 | log() {
 | 
| 19 |   echo "$0: $@" 1>&2
 | 
| 20 | }
 | 
| 21 | 
 | 
| 22 | info() {
 | 
| 23 |   echo "$0 INFO: $@" 1>&2
 | 
| 24 | }
 | 
| 25 | 
 | 
| 26 | die() {
 | 
| 27 |   echo "$0 ERROR: $@" 1>&2
 | 
| 28 |   exit 1
 | 
| 29 | }
 | 
| 30 | 
 | 
| 31 | show_help() {
 | 
| 32 |   cat <<'EOF'
 | 
| 33 | Usage: ./configure [OPTION...]
 | 
| 34 | 
 | 
| 35 | Detects system settings before a build of Oil.
 | 
| 36 | 
 | 
| 37 | Installation directories:
 | 
| 38 |   --prefix=PREFIX               Prefix for the bin/ directory [/usr/local]
 | 
| 39 |   --datarootdir=DATAROOTDIR     Prefix for data files, including man page [PREFIX/share]
 | 
| 40 | 
 | 
| 41 | Optional features:
 | 
| 42 |   --with-readline               Fail unless readline is available.
 | 
| 43 |   --without-readline            Don't compile with readline, even if it's available.
 | 
| 44 |                                 The shell won't have any interactive features.
 | 
| 45 |   --readline=DIR                An alternative readline installation to link against
 | 
| 46 |   --with-systemtap-sdt          Fail unless systemtap-sdt is available.
 | 
| 47 |   --without-systemtap-sdt       Don't compile with systemtap-sdt, even if it's available.
 | 
| 48 | EOF
 | 
| 49 | }
 | 
| 50 | 
 | 
| 51 | # This script roughly follows the GNU Standards
 | 
| 52 | # https://www.gnu.org/prep/standards/html_node/Configuration.html
 | 
| 53 | # https://www.gnu.org/prep/standards/html_node/Directory-Variables.html
 | 
| 54 | #
 | 
| 55 | # Default installation is /usr/local/bin/oil, but this can be changed with
 | 
| 56 | # --prefix.
 | 
| 57 | #
 | 
| 58 | # While this script only uses a handful of the standard directory variables
 | 
| 59 | # listed on the above documents, it accepts most of them in the --arg=value
 | 
| 60 | # form as noops. This helps automated build-systems passing preconfigured
 | 
| 61 | # sets of arguments to configure oil.
 | 
| 62 | FLAG_prefix='/usr/local'
 | 
| 63 | FLAG_datarootdir=''  # default initialized after processing flags
 | 
| 64 | FLAG_with_readline=''  # Fail if it's not available.
 | 
| 65 | FLAG_without_readline=''  # Don't even check if it's available
 | 
| 66 | FLAG_readline=''
 | 
| 67 | FLAG_with_systemtap_sdt=''  # Fail if it's not available.
 | 
| 68 | FLAG_without_systemtap_sdt=''  # Don't even check if it's available
 | 
| 69 | 
 | 
| 70 | # These variables are set by detect_readline and used by echo_cpp and
 | 
| 71 | # echo_shell_vars
 | 
| 72 | detected_deps=''
 | 
| 73 | have_readline=''
 | 
| 74 | readline_dir=''
 | 
| 75 | 
 | 
| 76 | have_systemtap_sdt=''
 | 
| 77 | 
 | 
| 78 | parse_flags() {
 | 
| 79 |   while true; do
 | 
| 80 |     case "$1" in
 | 
| 81 |       '')
 | 
| 82 |         break
 | 
| 83 |         ;;
 | 
| 84 |       --help)
 | 
| 85 |         # TODO: Fill out help
 | 
| 86 |         show_help
 | 
| 87 |         exit 0
 | 
| 88 |         ;;
 | 
| 89 | 
 | 
| 90 |       --with-readline)
 | 
| 91 |         FLAG_with_readline=1
 | 
| 92 |         ;;
 | 
| 93 | 
 | 
| 94 |       --without-readline)
 | 
| 95 |         FLAG_without_readline=1
 | 
| 96 |         ;;
 | 
| 97 | 
 | 
| 98 |       --readline=*)
 | 
| 99 |         FLAG_readline="${1#*=}"
 | 
| 100 |         ;;
 | 
| 101 |       --readline)
 | 
| 102 |         if test $# -eq 1; then
 | 
| 103 |           die "--readline requires an argument"
 | 
| 104 |         fi
 | 
| 105 |         shift
 | 
| 106 |         FLAG_readline=$1
 | 
| 107 |         ;;
 | 
| 108 | 
 | 
| 109 |       --with-systemtap_sdt)
 | 
| 110 |         FLAG_with_systemtap_sdt=1
 | 
| 111 |         ;;
 | 
| 112 | 
 | 
| 113 |       --without-systemtap_sdt)
 | 
| 114 |         FLAG_without_systemtap_sdt=1
 | 
| 115 |         ;;
 | 
| 116 | 
 | 
| 117 |       # TODO: Maybe prefix only needs to be part of the install step?  I'm not
 | 
| 118 |       # sure if we need it for building anything.
 | 
| 119 |       --prefix=*)
 | 
| 120 |         FLAG_prefix="${1#*=}"
 | 
| 121 |         ;;
 | 
| 122 |       --prefix)
 | 
| 123 |         if test $# -eq 1; then
 | 
| 124 |           die "--prefix requires an argument"
 | 
| 125 |         fi
 | 
| 126 |         shift
 | 
| 127 |         FLAG_prefix=$1
 | 
| 128 |         ;;
 | 
| 129 | 
 | 
| 130 |       # Following autoconf's spelling of --mandir
 | 
| 131 |       --datarootdir=*)
 | 
| 132 |         FLAG_datarootdir="${1#*=}"
 | 
| 133 |         ;;
 | 
| 134 |       --datarootdir)
 | 
| 135 |         if test $# -eq 1; then
 | 
| 136 |           die "--datarootdir requires an argument"
 | 
| 137 |         fi
 | 
| 138 |         shift
 | 
| 139 |         FLAG_datarootdir=$1
 | 
| 140 |         ;;
 | 
| 141 | 
 | 
| 142 |       --with-*|--enable-*)
 | 
| 143 |         info "Argument '$1' not used by this configure script"
 | 
| 144 |         ;;
 | 
| 145 | 
 | 
| 146 |       --build=*|--host=*)
 | 
| 147 |         info "Argument '$1' not used by this configure script"
 | 
| 148 |         ;;
 | 
| 149 | 
 | 
| 150 |       --exec-prefix=*|--bindir=*|--sbindir=*|--libexecdir=*|--sysconfdir=*)
 | 
| 151 |         info "Argument '$1' not used by this configure script"
 | 
| 152 |         ;;
 | 
| 153 |       --sharedstatedir=*|--localstatedir=*|--runstatedir=*)
 | 
| 154 |         info "Argument '$1' not used by this configure script"
 | 
| 155 |         ;;
 | 
| 156 |       --libdir=*|--includedir=*|--oldincludedir=*)
 | 
| 157 |         info "Argument '$1' not used by this configure script"
 | 
| 158 |         ;;
 | 
| 159 |       --datadir=*|--infodir=*|--localedir=*|--mandir=*|--docdir=*)
 | 
| 160 |         info "Argument '$1' not used by this configure script"
 | 
| 161 |         ;;
 | 
| 162 |       --htmldir=*|--dvidir=*|--pdfdir=*|--psdir=*)
 | 
| 163 |         info "Argument '$1' not used by this configure script"
 | 
| 164 |         ;;
 | 
| 165 | 
 | 
| 166 |       *)
 | 
| 167 |         die "Invalid argument '$1'"
 | 
| 168 |         ;;
 | 
| 169 |     esac
 | 
| 170 |     shift
 | 
| 171 |   done
 | 
| 172 | 
 | 
| 173 |   # If not set, fallback to --prefix
 | 
| 174 |   FLAG_datarootdir=${FLAG_datarootdir:-$FLAG_prefix/share}
 | 
| 175 | }
 | 
| 176 | 
 | 
| 177 | # No output file, no logging, no stderr.
 | 
| 178 | # TODO: Maybe send stdout/stderr to config.log?
 | 
| 179 | cc_quiet() {
 | 
| 180 |   cc "$@" -o /dev/null >/dev/null 2>&1
 | 
| 181 | }
 | 
| 182 | 
 | 
| 183 | cc_or_die() {
 | 
| 184 |   if ! cc "$@" >$TMP/cc.log 2>&1; then
 | 
| 185 |     log "Error running 'cc $@':"
 | 
| 186 |     cat $TMP/cc.log
 | 
| 187 |     die "Fatal compile error running feature test"
 | 
| 188 |   fi
 | 
| 189 | }
 | 
| 190 | 
 | 
| 191 | # Check if a given program compiles
 | 
| 192 | cc_statement() {
 | 
| 193 |   local pp_var="$1"
 | 
| 194 |   local prog="$2"
 | 
| 195 |   local includes="$3"
 | 
| 196 | 
 | 
| 197 |   cat >$TMP/cc_statement.c <<EOF
 | 
| 198 | $includes
 | 
| 199 | int main() {
 | 
| 200 |   $prog
 | 
| 201 | }
 | 
| 202 | EOF
 | 
| 203 |   # Return exit code of compiler
 | 
| 204 |   if cc_quiet $TMP/cc_statement.c; then
 | 
| 205 |     echo "#define $pp_var 1"
 | 
| 206 |     return 0
 | 
| 207 |   else
 | 
| 208 |     return 1
 | 
| 209 |   fi
 | 
| 210 | }
 | 
| 211 | 
 | 
| 212 | # Check if a given library is installed via compilation
 | 
| 213 | cc_header_file() {
 | 
| 214 |   local pp_var="$1"
 | 
| 215 |   local c_lib="$2"
 | 
| 216 | 
 | 
| 217 |   cc_statement "$pp_var" 'return 0;' "#include <$c_lib>"
 | 
| 218 | }
 | 
| 219 | 
 | 
| 220 | detect_readline() {
 | 
| 221 |   detected_deps=1  # for assertions in echo_shell_vars and echo_cpp
 | 
| 222 | 
 | 
| 223 |   # User disabled readline
 | 
| 224 |   if test -n "$FLAG_without_readline"; then
 | 
| 225 |     # have_readline remains false
 | 
| 226 |     return
 | 
| 227 |   fi
 | 
| 228 | 
 | 
| 229 |   # User requested specific location
 | 
| 230 |   if test -n "$FLAG_readline"; then
 | 
| 231 |     if cc_quiet build/detect-readline.c \
 | 
| 232 |       -L "$FLAG_readline/lib" \
 | 
| 233 |       -I "$FLAG_readline/include" \
 | 
| 234 |       -l readline; then
 | 
| 235 | 
 | 
| 236 |       readline_dir="$FLAG_readline"
 | 
| 237 |       have_readline=1
 | 
| 238 |     fi
 | 
| 239 |     return
 | 
| 240 |   fi
 | 
| 241 | 
 | 
| 242 |   # Detect in default location
 | 
| 243 |   if cc_quiet build/detect-readline.c -l readline; then
 | 
| 244 |     have_readline=1
 | 
| 245 |     return
 | 
| 246 |   fi
 | 
| 247 | 
 | 
| 248 |   # User requested that it be found
 | 
| 249 |   if test "$FLAG_with_readline" = 1 && test "$have_readline" != 1; then
 | 
| 250 |     die 'readline was not detected on the system (--with-readline passed).'
 | 
| 251 |   fi
 | 
| 252 | }
 | 
| 253 | 
 | 
| 254 | detect_systemtap_sdt() {
 | 
| 255 |   detected_deps=1  # for assertions in echo_shell_vars and echo_cpp
 | 
| 256 | 
 | 
| 257 |   if test -n "$FLAG_without_systemtap_sdt"; then
 | 
| 258 |     return
 | 
| 259 |   fi
 | 
| 260 | 
 | 
| 261 |   if cc_quiet build/detect-systemtap-sdt.c; then
 | 
| 262 |     have_systemtap_sdt=1
 | 
| 263 |     return
 | 
| 264 |   fi
 | 
| 265 | }
 | 
| 266 | 
 | 
| 267 | echo_shell_vars() {
 | 
| 268 |   if test "$detected_deps" != 1; then
 | 
| 269 |     die 'called echo_shell_vars before detecting readline.'
 | 
| 270 |   fi
 | 
| 271 |   if test "$have_readline" = 1; then
 | 
| 272 |     echo 'HAVE_READLINE=1'
 | 
| 273 |     echo "READLINE_DIR=$readline_dir"
 | 
| 274 |   else
 | 
| 275 |     echo 'HAVE_READLINE='
 | 
| 276 |     # Present a consistent interface to build/ninja-rules-cpp.sh
 | 
| 277 |     echo 'READLINE_DIR='
 | 
| 278 |   fi
 | 
| 279 |   if test "$have_systemtap_sdt" = 1; then
 | 
| 280 |     echo 'HAVE_SYSTEMTAP_SDT=1'
 | 
| 281 |   else
 | 
| 282 |     echo 'HAVE_SYSTEMTAP_SDT='
 | 
| 283 |   fi
 | 
| 284 |   echo "PREFIX=$FLAG_prefix"
 | 
| 285 |   echo "DATAROOTDIR=$FLAG_datarootdir"
 | 
| 286 |   if cc_quiet build/detect-cc.c -Wl,--gc-sections; then
 | 
| 287 |     echo 'STRIP_FLAGS=--gc-sections'
 | 
| 288 |   elif cc_quiet build/detect-cc.c -Wl,-dead_strip; then
 | 
| 289 |     echo 'STRIP_FLAGS=-dead_strip'
 | 
| 290 |   fi
 | 
| 291 | }
 | 
| 292 | 
 | 
| 293 | # c.m4 AC_LANG_INT_SAVE
 | 
| 294 | cc_print_expr() {
 | 
| 295 |   local c_expr="$1"
 | 
| 296 |   cat >$TMP/print_expr.c <<EOF
 | 
| 297 | #include <stdio.h>
 | 
| 298 | #include <sys/types.h>  /* size_t, pid_t */
 | 
| 299 | 
 | 
| 300 | int main() {
 | 
| 301 |   printf("%lu", $c_expr);
 | 
| 302 | }
 | 
| 303 | EOF
 | 
| 304 |   cc_or_die -o $TMP/print_expr $TMP/print_expr.c
 | 
| 305 |   $TMP/print_expr > $TMP/print_expr.out
 | 
| 306 | }
 | 
| 307 | 
 | 
| 308 | # Shell note:
 | 
| 309 | # - local is not POSIX, but most shells have it.
 | 
| 310 | # C note:
 | 
| 311 | # - autoconf uses ac_fn_compute_int (in sh) aka AC_COMPUTE_INT (in m4).
 | 
| 312 | #   - it uses different tests when cross compiling.
 | 
| 313 | #   - cross-compiling does binary search?
 | 
| 314 | #   - other one does AC_LANG_INT_SAVE
 | 
| 315 | #     - generates a C program that outputs to conftest.val!
 | 
| 316 | #     - well why not use exit code?
 | 
| 317 | # - QEMU configure doesn't do any tests
 | 
| 318 | 
 | 
| 319 | # Hm, don't bother with cross compiling case for now.
 | 
| 320 | 
 | 
| 321 | # Check if the size of a type is greater than a certain integer.
 | 
| 322 | check_sizeof() {
 | 
| 323 |   local pp_var="$1"
 | 
| 324 |   local c_type="$2"
 | 
| 325 |   local min_bytes="$3"
 | 
| 326 | 
 | 
| 327 |   cc_print_expr "sizeof($c_type)"
 | 
| 328 | 
 | 
| 329 |   local actual_bytes
 | 
| 330 |   actual_bytes=$(cat $TMP/print_expr.out)
 | 
| 331 | 
 | 
| 332 |   if test -n "$min_bytes" && test "$actual_bytes" -lt "$min_bytes"; then
 | 
| 333 |     die "sizeof($c_type) should be at least $min_bytes; got $actual_bytes"
 | 
| 334 |   fi
 | 
| 335 | 
 | 
| 336 |   # Echo to stdout!
 | 
| 337 |   echo "#define $pp_var $actual_bytes"
 | 
| 338 | }
 | 
| 339 | 
 | 
| 340 | detect_c_language() {
 | 
| 341 |   # This is the equivalent of AC_CHECK_SIZEOF(int, 4)
 | 
| 342 |   check_sizeof SIZEOF_INT 'int' 4
 | 
| 343 |   check_sizeof SIZEOF_LONG 'long' 4
 | 
| 344 |   check_sizeof SIZEOF_VOID_P 'void *' 4
 | 
| 345 |   check_sizeof SIZEOF_SHORT 'short' 2
 | 
| 346 |   check_sizeof SIZEOF_FLOAT 'float' 4
 | 
| 347 |   check_sizeof SIZEOF_DOUBLE 'double' 8
 | 
| 348 | 
 | 
| 349 |   check_sizeof SIZEOF_SIZE_T 'size_t' 4
 | 
| 350 | 
 | 
| 351 |   # NOTE: This might only be relevant for large file support, which we don't
 | 
| 352 |   # have.
 | 
| 353 |   check_sizeof SIZEOF_FPOS_T 'fpos_t' 4
 | 
| 354 |   check_sizeof SIZEOF_PID_T 'pid_t' 4
 | 
| 355 | 
 | 
| 356 |   check_sizeof SIZEOF_OFF_T 'off_t' ''
 | 
| 357 |   # autoconf checks if we have time.h, but the check isn't used.  We just
 | 
| 358 |   # assume it's there.
 | 
| 359 |   check_sizeof SIZEOF_TIME_T 'time_t' ''
 | 
| 360 | 
 | 
| 361 |   if cc_statement HAVE_LONG_LONG 'long long x; x = (long long)0;'
 | 
| 362 |   then
 | 
| 363 |     check_sizeof SIZEOF_LONG_LONG 'long long' 8
 | 
| 364 |   fi
 | 
| 365 |   if cc_statement HAVE_LONG_DOUBLE 'long double x; x = (long double)0;'
 | 
| 366 |   then
 | 
| 367 |     check_sizeof SIZEOF_LONG_DOUBLE 'long double' 8
 | 
| 368 |   fi
 | 
| 369 | 
 | 
| 370 |   if cc_statement HAVE_C99_BOOL '_Bool x; x = (_Bool)0;'
 | 
| 371 |   then
 | 
| 372 |     # NOTE: this is mainly used in ctypes.h, which we might not need.
 | 
| 373 |     check_sizeof SIZEOF__BOOL '_Bool' 1
 | 
| 374 |   fi
 | 
| 375 |   # NOTE: Python also has a check for C99 uintptr_t.  Just assume we don't
 | 
| 376 |   # have it?
 | 
| 377 | 
 | 
| 378 |   #if cc_statement HAVE_C99_BOOL 'wchar_t x; x = (wchar_t)0;'
 | 
| 379 |   #then
 | 
| 380 |   #  check_sizeof SIZEOF_WCHAR_T 'wchar_t' 4
 | 
| 381 |   #fi
 | 
| 382 | 
 | 
| 383 |   # TODO: Detect header and size.
 | 
| 384 |   echo '#define HAVE_WCHAR_H 1'
 | 
| 385 |   echo '#define SIZEOF_WCHAR_T 4'
 | 
| 386 | 
 | 
| 387 |   cat >$TMP/detect_va_list.c <<EOF
 | 
| 388 | #include <stdarg.h>  /* C89 */
 | 
| 389 | int main() {
 | 
| 390 |   va_list list1, list2;
 | 
| 391 |   list1 = list2;
 | 
| 392 | }
 | 
| 393 | EOF
 | 
| 394 |   if cc_quiet $TMP/detect_va_list.c; then
 | 
| 395 |     echo ''  # not an array
 | 
| 396 |   else
 | 
| 397 |     echo '#define VA_LIST_IS_ARRAY 1'
 | 
| 398 |   fi
 | 
| 399 | 
 | 
| 400 |   # TODO: are these feature checks really necessary, or can we
 | 
| 401 |   # strip these out of posixmodule.c entirely?
 | 
| 402 |   cc_header_file HAVE_PTY_H 'pty.h'
 | 
| 403 |   cc_header_file HAVE_LIBUTIL_H 'libutil.h'
 | 
| 404 |   cc_header_file HAVE_UTIL_H 'util.h'
 | 
| 405 | 
 | 
| 406 |   # TODO: are these feature checks really necessary?
 | 
| 407 |   cc_statement HAVE_STAT_TV_NSEC \
 | 
| 408 |     'struct stat st; st.st_mtim.tv_nsec = 1; return 0;' \
 | 
| 409 |     '#include <sys/stat.h>'
 | 
| 410 |   cc_statement HAVE_STAT_TV_NSEC2 \
 | 
| 411 |     'struct stat st; st.st_mtimespec.tv_nsec = 1; return 0;' \
 | 
| 412 |     '#include <sys/stat.h>'
 | 
| 413 | }
 | 
| 414 | 
 | 
| 415 | echo_cpp() {
 | 
| 416 |   if test "$detected_deps" != 1; then
 | 
| 417 |     die 'called echo_cpp before detecting readline.'
 | 
| 418 |   fi
 | 
| 419 |   # Dev builds can use non-portable clock_gettime()
 | 
| 420 |   if test -n "$_OIL_DEV"; then
 | 
| 421 |     echo '#define GC_TIMING 1'
 | 
| 422 |     log 'Turned on -D GC_TIMING because $_OIL_DEV is set'
 | 
| 423 |   fi
 | 
| 424 | 
 | 
| 425 |   if test "$have_readline" = 1; then
 | 
| 426 |     echo '#define HAVE_READLINE 1'
 | 
| 427 |   else
 | 
| 428 |     echo '/* #undef HAVE_READLINE */'
 | 
| 429 |   fi
 | 
| 430 | 
 | 
| 431 |   if test "$have_systemtap_sdt" = 1; then
 | 
| 432 |     echo '#define HAVE_SYSTEMTAP_SDT 1'
 | 
| 433 |   else
 | 
| 434 |     echo '/* #undef HAVE_SYSTEMTAP_SDT */'
 | 
| 435 |   fi
 | 
| 436 | 
 | 
| 437 |   # Check if pwent is callable. E.g. bionic libc (Android) doesn't have it
 | 
| 438 |   if cc_quiet build/detect-pwent.c; then
 | 
| 439 |     echo '#define HAVE_PWENT 1'
 | 
| 440 |   else
 | 
| 441 |     echo '/* #undef HAVE_PWENT */'
 | 
| 442 |   fi
 | 
| 443 | }
 | 
| 444 | 
 | 
| 445 | # Another way of working: set detected-config.mk ?
 | 
| 446 | # And set the default target as oil_readline, oil_no_readline, oil_lto,
 | 
| 447 | # oil_pgo, etc.?
 | 
| 448 | main() {
 | 
| 449 |   parse_flags "$@"  # sets FLAG_*
 | 
| 450 | 
 | 
| 451 |   mkdir -p _build
 | 
| 452 | 
 | 
| 453 |   if ! cc_quiet build/detect-cc.c; then
 | 
| 454 |     die "Couldn't compile a basic C program (cc not installed?)"
 | 
| 455 |   fi
 | 
| 456 | 
 | 
| 457 |   # Sets globals $have_readline and $readline_dir
 | 
| 458 |   detect_readline
 | 
| 459 | 
 | 
| 460 |   detect_systemtap_sdt
 | 
| 461 | 
 | 
| 462 |   # Generate configuration for oil-native
 | 
| 463 |   local cpp_out=_build/detected-cpp-config.h
 | 
| 464 |   echo_cpp > $cpp_out
 | 
| 465 |   log "Wrote $cpp_out"
 | 
| 466 | 
 | 
| 467 |   # Legacy OVM build: shell build actions will 'source
 | 
| 468 |   # _build/detected-config.sh'.  And then adjust flags to compiler (-D, -l,
 | 
| 469 |   # etc.)
 | 
| 470 |   local sh_out=_build/detected-config.sh
 | 
| 471 | 
 | 
| 472 |   echo_shell_vars > $sh_out
 | 
| 473 |   log "Wrote $sh_out"
 | 
| 474 | 
 | 
| 475 |   # Fast mode
 | 
| 476 |   if test -n "$_OIL_DEV"; then
 | 
| 477 |     return
 | 
| 478 |   fi
 | 
| 479 | 
 | 
| 480 |   local c_out=_build/detected-config.h
 | 
| 481 |   detect_c_language > $c_out
 | 
| 482 |   log "Wrote $c_out"
 | 
| 483 | }
 | 
| 484 | 
 | 
| 485 | if test -z "$_OIL_CONFIGURE_TEST"; then
 | 
| 486 |   main "$@"
 | 
| 487 | fi
 |