unified build scheme: a first introduction
authorRichard Levitte <levitte@openssl.org>
Fri, 29 Jan 2016 18:45:51 +0000 (19:45 +0100)
committerRichard Levitte <levitte@openssl.org>
Mon, 1 Feb 2016 11:46:58 +0000 (12:46 +0100)
The "unified" build scheme revolves around small information files,
build.info, which each describe their own bit of everything that needs
to be built, using a mini-language described in Configurations/README.

The information in build.info file contain references to source files
and final result.  Object files are not mentioned at all, they are
simply from source files.  Because of this, all the *_obj items in
Configurations/*.conf are renamed to *_asm_src and the files listed
in the values are change from object files to their corresponding
source files.  For the sake of the other build schemes, Configure
generates corresponding *_obj entries in %target.

Furthermore, the "unified" build scheme supports having a build
directory tree separate from the source directry tree.

All paths in a build.info file is assumed to be relative to its
location, either within the source tree or within the build tree.

Reviewed-by: Andy Polyakov <appro@openssl.org>
Configurations/00-base-templates.conf
Configurations/90-team.conf
Configurations/README
Configure
config
crypto/bn/Makefile.in

index 3ef2141..03a1af9 100644 (file)
@@ -1,23 +1,23 @@
 %targets=(
     BASE => {
        template        => 1,
-       cpuid_obj       => "mem_clr.o",
-       bn_obj          => "bn_asm.o",
-       ec_obj          => "",
-       des_obj         => "des_enc.o fcrypt_b.o",
-       aes_obj         => "aes_core.o aes_cbc.o",
-       bf_obj          => "bf_enc.o",
-       md5_obj         => "",
-       cast_obj        => "c_enc.o",
-       rc4_obj         => "rc4_enc.o rc4_skey.o",
-       rmd160_obj      => "",
-       rc5_obj         => "rc5_enc.o",
-       wp_obj          => "wp_block.o",
-       cmll_obj        => "camellia.o cmll_misc.o cmll_cbc.o",
-       modes_obj       => "",
-       padlock_obj     => "",
-       chacha_obj      => "chacha_enc.o",
-       poly1305_obj    => "",
+       cpuid_asm_src   => "mem_clr.c",
+       bn_asm_src      => "bn_asm.c",
+       ec_asm_src      => "",
+       des_asm_src     => "des_enc.c fcrypt_b.c",
+       aes_asm_src     => "aes_core.c aes_cbc.c",
+       bf_asm_src      => "bf_enc.c",
+       md5_asm_src     => "",
+       cast_asm_src    => "c_enc.c",
+       rc4_asm_src     => "rc4_enc.c rc4_skey.c",
+       rmd160_asm_src  => "",
+       rc5_asm_src     => "rc5_enc.c",
+       wp_asm_src      => "wp_block.c",
+       cmll_asm_src    => "camellia.c cmll_misc.c cmll_cbc.c",
+       modes_asm_src   => "",
+       padlock_asm_src => "",
+       chacha_asm_src  => "chacha_enc.c",
+       poly1305_asm_src        => "",
 
        unistd          => "<unistd.h>",
        shared_target   => "",
        shared_ldflag   => "",
        shared_extension        => "",
        build_scheme    => "unixmake",
+       build_file      => "Makefile",
     },
 
     x86_asm => {
        template        => 1,
-       cpuid_obj       => "x86cpuid.o",
-       bn_obj          => "bn-586.o co-586.o x86-mont.o x86-gf2m.o",
-       ec_obj          => "ecp_nistz256.o ecp_nistz256-x86.o",
-       des_obj         => "des-586.o crypt586.o",
-       aes_obj         => "aes-586.o vpaes-x86.o aesni-x86.o",
-       bf_obj          => "bf-586.o",
-       md5_obj         => "md5-586.o",
-       sha1_obj        => "sha1-586.o sha256-586.o sha512-586.o",
-       rc4_obj         => "rc4-586.o",
-       rmd160_obj      => "rmd-586.o",
-       rc5_obj         => "rc5-586.o",
-       wp_obj          => "wp_block.o wp-mmx.o",
-       cmll_obj        => "cmll-x86.o",
-       modes_obj       => "ghash-x86.o",
-       padlock_obj     => "e_padlock-x86.o"
+       cpuid_asm_src   => "x86cpuid.s",
+       bn_asm_src      => "bn-586.s co-586.s x86-mont.s x86-gf2m.s",
+       ec_asm_src      => "ecp_nistz256.c ecp_nistz256-x86.s",
+       des_asm_src     => "des-586.s crypt586.s",
+       aes_asm_src     => "aes-586.s vpaes-x86.s aesni-x86.s",
+       bf_asm_src      => "bf-586.s",
+       md5_asm_src     => "md5-586.s",
+       cast_asm_src    => "cast-586.s",
+       sha1_asm_src    => "sha1-586.s sha256-586.s sha512-586.s",
+       rc4_asm_src     => "rc4-586.s",
+       rmd160_asm_src  => "rmd-586.s",
+       rc5_asm_src     => "rc5-586.s",
+       wp_asm_src      => "wp_block.c wp-mmx.s",
+       cmll_asm_src    => "cmll-x86.s",
+       modes_asm_src   => "ghash-x86.s",
+       padlock_asm_src => "e_padlock-x86.s",
     },
     x86_elf_asm => {
        template        => 1,
     },
     x86_64_asm => {
        template        => 1,
-       cpuid_obj       => "x86_64cpuid.o",
-       bn_obj          => "x86_64-gcc.o x86_64-mont.o x86_64-mont5.o x86_64-gf2m.o rsaz_exp.o rsaz-x86_64.o rsaz-avx2.o",
-       ec_obj          => "ecp_nistz256.o ecp_nistz256-x86_64.o",
-       aes_obj         => "aes-x86_64.o vpaes-x86_64.o bsaes-x86_64.o aesni-x86_64.o aesni-sha1-x86_64.o aesni-sha256-x86_64.o aesni-mb-x86_64.o",
-       md5_obj         => "md5-x86_64.o",
-       sha1_obj        => "sha1-x86_64.o sha256-x86_64.o sha512-x86_64.o sha1-mb-x86_64.o sha256-mb-x86_64.o",
-       rc4_obj         => "rc4-x86_64.o rc4-md5-x86_64.o",
-       wp_obj          => "wp-x86_64.o",
-       cmll_obj        => "cmll-x86_64.o cmll_misc.o",
-       modes_obj       => "ghash-x86_64.o aesni-gcm-x86_64.o",
-       padlock_obj     => "e_padlock-x86_64.o"
+       cpuid_asm_src   => "x86_64cpuid.s",
+       bn_asm_src      => "asm/x86_64-gcc.c x86_64-mont.s x86_64-mont5.s x86_64-gf2m.s rsaz_exp.c rsaz-x86_64.s rsaz-avx2.s",
+       ec_asm_src      => "ecp_nistz256.c ecp_nistz256-x86_64.s",
+       aes_asm_src     => "aes-x86_64.s vpaes-x86_64.s bsaes-x86_64.s aesni-x86_64.s aesni-sha1-x86_64.s aesni-sha256-x86_64.s aesni-mb-x86_64.s",
+       md5_asm_src     => "md5-x86_64.s",
+       sha1_asm_src    => "sha1-x86_64.s sha256-x86_64.s sha512-x86_64.s sha1-mb-x86_64.s sha256-mb-x86_64.s",
+       rc4_asm_src     => "rc4-x86_64.s rc4-md5-x86_64.s",
+       wp_asm_src      => "wp-x86_64.s",
+       cmll_asm_src    => "cmll-x86_64.s cmll_misc.c",
+       modes_asm_src   => "ghash-x86_64.s aesni-gcm-x86_64.s",
+       padlock_asm_src => "e_padlock-x86_64.s",
     },
     ia64_asm => {
        template        => 1,
-       cpuid_obj       => "ia64cpuid.o",
-       bn_obj          => "bn-ia64.o ia64-mont.o",
-       aes_obj         => "aes_core.o aes_cbc.o aes-ia64.o",
-       md5_obj         => "md5-ia64.o",
-       sha1_obj        => "sha1-ia64.o sha256-ia64.o sha512-ia64.o",
-       rc4_obj         => "rc4-ia64.o rc4_skey.o",
-       modes_obj       => "ghash-ia64.o",
+       cpuid_asm_src   => "ia64cpuid.s",
+       bn_asm_src      => "bn-ia64.s ia64-mont.s",
+       aes_asm_src     => "aes_core.c aes_cbc.c aes-ia64.s",
+       md5_asm_src     => "md5-ia64.s",
+       sha1_asm_src    => "sha1-ia64.s sha256-ia64.s sha512-ia64.s",
+       rc4_asm_src     => "rc4-ia64.s rc4_skey.s",
+       modes_asm_src   => "ghash-ia64.s",
        perlasm_scheme  => "void"
     },
     sparcv9_asm => {
        template        => 1,
-       cpuid_obj       => "sparcv9cap.o sparccpuid.o",
-       bn_obj          => "bn-sparcv9.o sparcv9-mont.o sparcv9a-mont.o vis3-mont.o sparct4-mont.o sparcv9-gf2m.o",
-        ec_obj          => "ecp_nistz256.o ecp_nistz256-sparcv9.o",
-       des_obj         => "des_enc-sparc.o fcrypt_b.o dest4-sparcv9.o",
-       aes_obj         => "aes_core.o aes_cbc.o aes-sparcv9.o aest4-sparcv9.o",
-       md5_obj         => "md5-sparcv9.o",
-       sha1_obj        => "sha1-sparcv9.o sha256-sparcv9.o sha512-sparcv9.o",
-       cmll_obj        => "camellia.o cmll_misc.o cmll_cbc.o cmllt4-sparcv9.o",
-       modes_obj       => "ghash-sparcv9.o",
-       poly1305_obj    => "poly1305-sparcv9.o",
+       cpuid_asm_src   => "sparcv9cap.s sparccpuid.s",
+       bn_asm_src      => "bn-sparcv9.s sparcv9-mont.s sparcv9a-mont.s vis3-mont.s sparct4-mont.s sparcv9-gf2m.s",
+        ec_asm_src      => "ecp_nistz256.c ecp_nistz256-sparcv9.s",
+       des_asm_src     => "des_enc-sparc.s fcrypt_b.c dest4-sparcv9.s",
+       aes_asm_src     => "aes_core.c aes_cbc.c aes-sparcv9.s aest4-sparcv9.s",
+       md5_asm_src     => "md5-sparcv9.s",
+       sha1_asm_src    => "sha1-sparcv9.s sha256-sparcv9.s sha512-sparcv9.s",
+       cmll_asm_src    => "camellia.c cmll_misc.c cmll_cbc.c cmllt4-sparcv9.s",
+       modes_asm_src   => "ghash-sparcv9.s",
+       poly1305_obj    => "poly1305-sparcv9.S",
        perlasm_scheme  => "void"
     },
     sparcv8_asm => {
        template        => 1,
-       cpuid_obj       => "",
-       bn_obj          => "sparcv8.o",
-       des_obj         => "des_enc-sparc.o fcrypt_b.o",
+       cpuid_asm_src   => "",
+       bn_asm_src      => "sparcv8.s",
+       des_asm_src     => "des_enc-sparc.s fcrypt_b.c",
        perlasm_scheme  => "void"
     },
     alpha_asm => {
        template        => 1,
-       cpuid_obj       => "alphacpuid.o",
-       bn_obj          => "bn_asm.o alpha-mont.o",
-       sha1_obj        => "sha1-alpha.o",
-       modes_obj       => "ghash-alpha.o",
+       cpuid_asm_src   => "alphacpuid.s",
+       bn_asm_src      => "bn_asm.s alpha-mont.s",
+       sha1_asm_src    => "sha1-alpha.s",
+       modes_asm_src   => "ghash-alpha.s",
        perlasm_scheme  => "void"
     },
     mips32_asm => {
        template        => 1,
-       bn_obj          => "bn-mips.o mips-mont.o",
-       aes_obj         => "aes_cbc.o aes-mips.o",
-       sha1_obj        => "sha1-mips.o sha256-mips.o",
+       bn_asm_src      => "bn-mips.s mips-mont.s",
+       aes_asm_src     => "aes_cbc.c aes-mips.S",
+       sha1_asm_src    => "sha1-mips.S sha256-mips.S",
     },
     mips64_asm => {
        inherit_from    => [ "mips32_asm" ],
        template        => 1,
-       sha1_obj        => add("sha512-mips.o")
+       sha1_asm_src    => add("sha512-mips.S")
     },
     s390x_asm => {
        template        => 1,
-       cpuid_obj       => "s390xcap.o s390xcpuid.o",
-       bn_obj          => "bn-s390x.o s390x-mont.o s390x-gf2m.o",
-       aes_obj         => "aes-s390x.o aes-ctr.o aes-xts.o",
-       sha1_obj        => "sha1-s390x.o sha256-s390x.o sha512-s390x.o",
-       rc4_obj         => "rc4-s390x.o",
-       modes_obj       => "ghash-s390x.o",
+       cpuid_asm_src   => "s390xcap.s s390xcpuid.s",
+       bn_asm_src      => "bn-s390x.s s390x-mont.s s390x-gf2m.s",
+       aes_asm_src     => "aes-s390x.S aes-ctr.fake aes-xts.fake",
+       sha1_asm_src    => "sha1-s390x.s sha256-s390x.s sha512-s390x.s",
+       rc4_asm_src     => "rc4-s390x.s",
+       modes_asm_src   => "ghash-s390x.s",
     },
     armv4_asm => {
        template        => 1,
-       cpuid_obj       => "armcap.o armv4cpuid.o",
-       bn_obj          => "bn_asm.o armv4-mont.o armv4-gf2m.o",
-       ec_obj          => "ecp_nistz256.o ecp_nistz256-armv4.o",
-       aes_obj         => "aes_cbc.o aes-armv4.o bsaes-armv7.o aesv8-armx.o",
-       sha1_obj        => "sha1-armv4-large.o sha256-armv4.o sha512-armv4.o",
-       modes_obj       => "ghash-armv4.o ghashv8-armx.o",
+       cpuid_asm_src   => "armcap.s armv4cpuid.s",
+       bn_asm_src      => "bn_asm.s armv4-mont.s armv4-gf2m.s",
+       ec_asm_src      => "ecp_nistz256.c ecp_nistz256-armv4.s",
+       aes_asm_src     => "aes_cbc.c aes-armv4.S bsaes-armv7.S aesv8-armx.S",
+       sha1_asm_src    => "sha1-armv4-large.s sha256-armv4.s sha512-armv4.s",
+       modes_asm_src   => "ghash-armv4.s ghashv8-armx.s",
        perlasm_scheme  => "void"
     },
     aarch64_asm => {
        template        => 1,
-       cpuid_obj       => "armcap.o arm64cpuid.o mem_clr.o",
-       ec_obj          => "ecp_nistz256.o ecp_nistz256-armv8.o",
-       bn_obj          => "bn_asm.o armv8-mont.o",
-       aes_obj         => "aes_core.o aes_cbc.o aesv8-armx.o vpaes-armv8.o",
-       sha1_obj        => "sha1-armv8.o sha256-armv8.o sha512-armv8.o",
-       modes_obj       => "ghashv8-armx.o",
+       cpuid_asm_src   => "armcap.s arm64cpuid.s mem_clr.s",
+       ec_asm_src      => "ecp_nistz256.c ecp_nistz256-armv8.s",
+       bn_asm_src      => "bn_asm.s armv8-mont.s",
+       aes_asm_src     => "aes_core.s aes_cbc.s aesv8-armx.s vpaes-armv8.s",
+       sha1_asm_src    => "sha1-armv8.s sha256-armv8.s sha512-armv8.s",
+       modes_asm_src   => "ghashv8-armx.s",
     },
     parisc11_asm => {
        template        => 1,
-       cpuid_obj       => "pariscid.o",
-       bn_obj          => "bn_asm.o parisc-mont.o",
-       aes_obj         => "aes_core.o aes_cbc.o aes-parisc.o",
-       sha1_obj        => "sha1-parisc.o sha256-parisc.o sha512-parisc.o",
-       rc4_obj         => "rc4-parisc.o",
-       modes_obj       => "ghash-parisc.o",
+       cpuid_asm_src   => "pariscid.s",
+       bn_asm_src      => "bn_asm.s parisc-mont.s",
+       aes_asm_src     => "aes_core.c aes_cbc.c aes-parisc.s",
+       sha1_asm_src    => "sha1-parisc.s sha256-parisc.s sha512-parisc.s",
+       rc4_asm_src     => "rc4-parisc.s",
+       modes_asm_src   => "ghash-parisc.s",
        perlasm_scheme  => "32"
     },
     parisc20_64_asm => {
        template        => 1,
        inherit_from    => [ "parisc11_asm" ],
-       bn_obj          => sub { my $r=join(" ",@_); $r=~s/bn_asm/pa-risc2W/; $r; },
        perlasm_scheme  => "64",
     },
     ppc64_asm => {
        template        => 1,
-       cpuid_obj       => "ppccpuid.o ppccap.o",
-       bn_obj          => "bn-ppc.o ppc-mont.o ppc64-mont.o",
-       aes_obj         => "aes_core.o aes_cbc.o aes-ppc.o vpaes-ppc.o aesp8-ppc.o",
-       sha1_obj        => "sha1-ppc.o sha256-ppc.o sha512-ppc.o sha256p8-ppc.o sha512p8-ppc.o",
-       modes_obj       => "ghashp8-ppc.o",
+       cpuid_asm_src   => "ppccpuid.s ppccap.s",
+       bn_asm_src      => "bn-ppc.s ppc-mont.s ppc64-mont.s",
+       aes_asm_src     => "aes_core.c aes_cbc.c aes-ppc.s vpaes-ppc.s aesp8-ppc.s",
+       sha1_asm_src    => "sha1-ppc.s sha256-ppc.s sha512-ppc.s sha256p8-ppc.s sha512p8-ppc.s",
+       modes_asm_src   => "ghashp8-ppc.s",
     },
     ppc32_asm => {
        inherit_from    => [ "ppc64_asm" ],
index 3dee0f1..bb24bdb 100644 (file)
         thread_cflag     => "-D_REENTRANT",
         ex_libs          => "-ldl",
         bn_ops           => "BN_LLONG",
-        cpuid_obj        => "x86cpuid.o",
-        bn_obj           => "bn-586.o co-586.o x86-mont.o",
-        des_obj          => "des-586.o crypt586.o",
-        aes_obj          => "aes_x86core.o aes_cbc.o aesni-x86.o",
-        bf_obj           => "bf-586.o",
-        md5_obj          => "md5-586.o",
-        sha1_obj         => "sha1-586.o sha256-586.o sha512-586.o",
-        cast_obj         => "cast-586.o",
-        rc4_obj          => "rc4-586.o",
-        rmd160_obj       => "rmd-586.o",
-        rc5_obj          => "rc5-586.o",
-        wp_obj           => "wp_block.o wp-mmx.o",
-        modes_obj        => "ghash-x86.o",
-        padlock_obj      => "e_padlock-x86.o",
+        cpuid_asm_src    => "x86cpuid.s",
+        bn_asm_src       => "bn-586.s co-586.s x86-mont.s",
+        des_asm_src      => "des-586.s crypt586.s",
+        aes_asm_src      => "aes_x86core.s aes_cbc.s aesni-x86.s",
+        bf_asm_src       => "bf-586.s",
+        md5_asm_src      => "md5-586.s",
+        sha1_asm_src     => "sha1-586.s sha256-586.s sha512-586.s",
+        cast_asm_src     => "cast-586.s",
+        rc4_asm_src      => "rc4-586.s",
+        rmd160_asm_src   => "rmd-586.s",
+        rc5_asm_src      => "rc5-586.s",
+        wp_asm_src       => "wp_block.s wp-mmx.s",
+        modes_asm_src    => "ghash-x86.s",
+        padlock_asm_src  => "e_padlock-x86.s",
         perlasm_scheme   => "elf",
         dso_scheme       => "dlfcn",
         shared_target    => "linux-shared",
index 5e544b1..ecf2b79 100644 (file)
@@ -105,8 +105,11 @@ In each table entry, the following keys are significant:
                            string in the list is the name of the build
                            scheme.
                            Currently recognised build schemes are
-                           "mk1mf" and "unixmake".  Others may appear
-                           in the future.
+                           "mk1mf" and "unixmake" and "unified".
+                           For the "unified" build scheme, this item
+                           *must* be an array with the first being the
+                           word "unified" and the second being a word
+                           to identify the platform family.
 
         multilib        => On systems that support having multiple
                            implementations of a library (typically a
@@ -146,47 +149,48 @@ In each table entry, the following keys are significant:
                                                 export vars as
                                                 accessor functions.
 
-        cpuid_obj       => assembler implementation of cpuid code as
+        cpuid_asm_src   => assembler implementation of cpuid code as
                            well as OPENSSL_cleanse().
-                           Default to mem_clr.o
-        bn_obj          => assembler implementation of core bignum
+                           Default to mem_clr.c
+        bn_asm_src      => Assembler implementation of core bignum
                            functions.
-                           Defaults to bn_asm.o
-        ec_obj          => assembler implementation of core EC
+                           Defaults to bn_asm.c
+        ec_asm_src      => Assembler implementation of core EC
                            functions.
-        des_obj         => assembler implementation of core DES
+        des_asm_src     => Assembler implementation of core DES
                            encryption functions.
-                           Defaults to 'des_enc.o fcrypt_b.o'
-        aes_obj         => assembler implementation of core AES
+                           Defaults to 'des_enc.c fcrypt_b.c'
+        aes_asm_src     => Assembler implementation of core AES
                            functions.
-                           Defaults to 'aes_core.o aes_cbc.o'
-        bf_obj          => assembler implementation of core BF
+                           Defaults to 'aes_core.c aes_cbc.c'
+        bf_asm_src      => Assembler implementation of core BlowFish
                            functions.
-                           Defaults to 'bf_enc.o'
-        md5_obj         => assembler implementation of core MD5
+                           Defaults to 'bf_enc.c'
+        md5_asm_src     => Assembler implementation of core MD5
                            functions.
-        sha1_obj        => assembler implementation of core SHA1,
+        sha1_asm_src    => Assembler implementation of core SHA1,
                            functions, and also possibly SHA256 and
                            SHA512 ones.
-        cast_obj        => assembler implementation of core BF
+        cast_asm_src    => Assembler implementation of core CAST
                            functions.
-                           Defaults to 'c_enc.o'
-        rc4_obj         => assembler implementation of core BF
+                           Defaults to 'c_enc.c'
+        rc4_asm_src     => Assembler implementation of core RC4
                            functions.
-                           Defaults to 'rc4_enc.o rc4_skey.o'
-        rmd160_obj      => assembler implementation of core RMD160
+                           Defaults to 'rc4_enc.c rc4_skey.c'
+        rmd160_asm_src  => Assembler implementation of core RMD160
                            functions.
-        rc5_obj         => assembler implementation of core RC4
+        rc5_asm_src     => Assembler implementation of core RC5
                            functions.
-                           Defaults to 'rc5_enc.o'
-        wp_obj          => assembler implementation of core WHIRLPOOL
+                           Defaults to 'rc5_enc.c'
+        wp_asm_src      => Assembler implementation of core WHIRLPOOL
                            functions.
-        cmll_obj        => assembler implementation of core CAMELLIA
+        cmll_asm_src    => Assembler implementation of core CAMELLIA
                            functions.
-                           Defaults to 'camellia.o cmll_misc.o cmll_cbc.o'
-        modes_obj       => assembler implementation of the
-                           functions gcm_gmult_4bit and gcm_ghash_4bit.
-        padlock_obj     => assembler implementation of core parts of
+                           Defaults to 'camellia.c cmll_misc.c cmll_cbc.c'
+        modes_asm_src   => Assembler implementation of cipher modes,
+                           currently the functions gcm_gmult_4bit and
+                           gcm_ghash_4bit.
+        padlock_asm_src => Assembler implementation of core parts of
                            the padlock engine.  This is mandatory on
                            any platform where the padlock engine might
                            actually be built.
@@ -255,3 +259,149 @@ values separated by colons.  This use is deprecated.  The string form
 looked like this:
 
    "target" => "{cc}:{cflags}:{unistd}:{thread_cflag}:{sys_id}:{lflags}:{bn_ops}:{cpuid_obj}:{bn_obj}:{ec_obj}:{des_obj}:{aes_obj}:{bf_obj}:{md5_obj}:{sha1_obj}:{cast_obj}:{rc4_obj}:{rmd160_obj}:{rc5_obj}:{wp_obj}:{cmll_obj}:{modes_obj}:{padlock_obj}:{perlasm_scheme}:{dso_scheme}:{shared_target}:{shared_cflag}:{shared_ldflag}:{shared_extension}:{ranlib}:{arflags}:{multilib}"
+
+
+Build info files
+================
+
+The build.info files that are spread over the source tree contain the
+minimum information needed to build and distribute OpenSSL.  It uses a
+simple and yet fairly powerful language to determine what needs to be
+built, from what sources, and other relationships between files.
+
+For every build.info file, all file references are relative to the
+directory of the build.info file for source files, and the
+corresponding build directory for built files if the build tree
+differs from the source tree.
+
+When processed, every line is processed with the perl module
+Text::Template, using the delimiters "{-" and "-}".  The hashes
+%config and %target are passed to the perl fragments, along with
+$sourcedir and $builddir, which are the locations of the source
+directory for the current build.info file and the corresponding build
+directory, all relative to the top of the build tree.
+
+To begin with, things to be built are declared by setting specific
+variables:
+
+    PROGRAMS=foo bar
+    LIBS=libsomething
+    ENGINES=libeng
+    SCRIPTS=myhack
+    EXTRA=file1 file2
+
+Note that the files mentioned for PROGRAMS, LIBS and ENGINES *must* be
+without extensions.  The build file templates will figure them out.
+
+For each thing to be built, it is then possible to say what sources
+they are built from:
+
+    PROGRAMS=foo bar
+    SOURCE[foo]=foo.c common.c
+    SOURCE[bar]=bar.c extra.c common.c
+
+It's also possible to tell some other dependencies:
+
+    DEPEND[foo]=libsomething
+    DEPEND[libbar]=libsomethingelse
+
+(it could be argued that 'libsomething' and 'libsomethingelse' are
+source as well.  However, the files given through SOURCE are expected
+to be located in the source tree while files given through DEPEND are
+expected to be located in the build tree)
+
+For some libraries, we maintain files with public symbols and their
+slot in a transfer vector (important on some platforms).  It can be
+declared like this:
+
+    ORDINALS[libcrypto]=crypto
+
+The value is not the name of the file in question, but rather the
+argument to util/mkdef.pl that indicates which file to use.
+
+One some platforms, shared libraries come with a name that's different
+from their static counterpart.  That's declared as follows:
+
+    SHARED_NAME[libfoo]=cygfoo-{- $config{shlibver} -}
+
+The example is from Cygwin, which has a required naming convention.
+
+Sometimes, it makes sense to rename an output file, for example a
+library:
+
+    RENAME[libfoo]=libbar
+
+That lines has "libfoo" get renamed to "libbar".  While it makes no
+sense at all to just have a rename like that (why not just use
+"libbar" everywhere?), it does make sense when it can be used
+conditionally.  See a little further below for an example.
+
+For any file to be built, it's also possible to tell what extra
+include paths the build of their source files should use:
+
+    INCLUDE[foo]=include
+
+It's possible to have raw build file lines, between BEGINRAW and
+ENDRAW lines as follows:
+
+    BEGINRAW[Makefile(unix)]
+    haha.h: {- $builddir -}/Makefile
+        echo "/* haha */" > haha.h
+    ENDRAW[Makefile(unix)]
+
+The word withing square brackets is the build_file configuration item
+or the build_file configuration item followed by the second word in the
+build_scheme configuration item for the configured target within
+parenthesis as shown above.  For example, with the following relevant
+configuration items:
+
+   build_file   => "build.ninja"
+   build_scheme => [ "unified", "unix" ]
+
+... these lines will be considered:
+
+   BEGINRAW[build.ninja]
+   build haha.h: echo "/* haha */" > haha.h
+   ENDRAW[build.ninja]
+
+   BEGINRAW[build.ninja(unix)]
+   build hoho.h: echo "/* hoho */" > hoho.h
+   ENDRAW[build.ninja(unix)]
+
+See the documentation further up for more information on configuration
+items.
+
+Finally, you can have some simple conditional use of the build.info
+information, looking like this:
+
+    IF[1]
+     something
+    ELSIF[2]
+     something other
+    ELSE
+     something else
+    ENDIF
+
+The expression in square brackets is interpreted as a string in perl,
+and will be seen as true if perl thinks it is, otherwise false.  For
+example, the above would have "something" used, since 1 is true.
+
+Together with the use of Text::Template, this can be used as
+conditions based on something in the passed variables, for example:
+
+    IF[{- $config{no_shared} -}]
+      LIBS=libcrypto
+      SOURCE[libcrypto]=...
+    ELSE
+      LIBS=libfoo
+      SOURCE[libfoo]=...
+    ENDIF
+
+or:
+
+    # VMS has a cultural standard where all libraries are prefixed.
+    # For OpenSSL, the choice is 'ossl_'
+    IF[{- $config{target} =~ /^vms/ -}]
+     RENAME[libcrypto]=ossl_libcrypto
+     RENAME[libssl]=ossl_libssl
+    ENDIF
index 3c2e16a..09c7697 100755 (executable)
--- a/Configure
+++ b/Configure
@@ -10,7 +10,9 @@
 require 5.000;
 use strict;
 use File::Basename;
-use File::Spec::Functions;
+use File::Spec::Functions qw/:DEFAULT abs2rel rel2abs catpath splitpath/;
+use File::Path qw/make_path/;
+use Cwd qw/:DEFAULT realpath/;
 
 # see INSTALL for instructions.
 
@@ -139,6 +141,14 @@ sub resolve_config;
 
 # Information collection #############################################
 
+# Unified build supports separate build dir
+my $srcdir = catdir(realpath(dirname($0))); # catdir ensures local syntax
+my $blddir = catdir(realpath("."));       # catdir ensures local syntax
+my $dofile = abs2rel(catfile($srcdir, "util/dofile.pl"));
+
+$config{sourcedir} = abs2rel($srcdir);
+$config{builddir} = abs2rel($blddir);
+
 # Collect version numbers
 $config{version} = "unknown";
 $config{version_num} = "unknown";
@@ -146,8 +156,7 @@ $config{shlib_version_number} = "unknown";
 $config{shlib_version_history} = "unknown";
 
 collect_information(
-    '<include/openssl/opensslv.h',
-    undef,
+    collect_from_file(catfile($srcdir,'include/openssl/opensslv.h')),
     qr/OPENSSL.VERSION.TEXT.*OpenSSL (\S+) / => sub { $config{version} = $1; },
     qr/OPENSSL.VERSION.NUMBER.*(0x\S+)/             => sub { $config{version_num}=$1 },
     qr/SHLIB_VERSION_NUMBER *"([^"]+)"/             => sub { $config{shlib_version_number}=$1 },
@@ -166,8 +175,8 @@ die "erroneous version information in opensslv.h: ",
 
 # Collect target configurations
 
-my ($vol, $dir, $dummy) = File::Spec->splitpath($0);
-my $pattern = File::Spec->catpath($vol, $dir, "Configurations/*.conf");
+my ($vol, $dir, $dummy) = splitpath($0);
+my $pattern = catpath($vol, catdir($dir, "Configurations"), "*.conf");
 foreach (sort glob($pattern) ) {
     &read_config($_);
 }
@@ -1005,67 +1014,60 @@ if ($target{ranlib} eq "")
        }
 
 if (!$no_asm) {
-    $target{cpuid_obj}=$table{BASE}->{cpuid_obj} if ($config{processor} eq "386");
-    $target{cpuid_obj}.=" uplink.o uplink-x86.o" if ($config{cflags} =~ /-DOPENSSL_USE_APPLINK/);
+    $target{cpuid_asm_src}=$table{BASE}->{cpuid_asm_src} if ($config{processor} eq "386");
+    $target{cpuid_asm_src}.=" uplink.c uplink-x86.s" if ($config{cflags} =~ /-DOPENSSL_USE_APPLINK/);
 
-    $target{bn_obj} =~ s/\w+-gf2m.o// if (defined($disabled{ec2m}));
+    $target{bn_asm_src} =~ s/\w+-gf2m.c// if (defined($disabled{ec2m}));
 
     # bn-586 is the only one implementing bn_*_part_words
-    $config{cflags}.=" -DOPENSSL_BN_ASM_PART_WORDS" if ($target{bn_obj} =~ /bn-586/);
-    $config{cflags}.=" -DOPENSSL_IA32_SSE2" if (!$no_sse2 && $target{bn_obj} =~ /86/);
+    $config{cflags}.=" -DOPENSSL_BN_ASM_PART_WORDS" if ($target{bn_asm_src} =~ /bn-586/);
+    $config{cflags}.=" -DOPENSSL_IA32_SSE2" if (!$no_sse2 && $target{bn_asm_src} =~ /86/);
 
-    $config{cflags}.=" -DOPENSSL_BN_ASM_MONT" if ($target{bn_obj} =~ /-mont/);
-    $config{cflags}.=" -DOPENSSL_BN_ASM_MONT5" if ($target{bn_obj} =~ /-mont5/);
-    $config{cflags}.=" -DOPENSSL_BN_ASM_GF2m" if ($target{bn_obj} =~ /-gf2m/);
+    $config{cflags}.=" -DOPENSSL_BN_ASM_MONT" if ($target{bn_asm_src} =~ /-mont/);
+    $config{cflags}.=" -DOPENSSL_BN_ASM_MONT5" if ($target{bn_asm_src} =~ /-mont5/);
+    $config{cflags}.=" -DOPENSSL_BN_ASM_GF2m" if ($target{bn_asm_src} =~ /-gf2m/);
 
     if ($config{fips}) {
        push @{$config{openssl_other_defines}}, "OPENSSL_FIPS";
     }
 
-    if ($target{sha1_obj} =~ /\.o$/) {
-       $config{cflags}.=" -DSHA1_ASM"   if ($target{sha1_obj} =~ /sx86/ || $target{sha1_obj} =~ /sha1/);
-       $config{cflags}.=" -DSHA256_ASM" if ($target{sha1_obj} =~ /sha256/);
-       $config{cflags}.=" -DSHA512_ASM" if ($target{sha1_obj} =~ /sha512/);
-       if ($target{sha1_obj} =~ /sse2/) {
-           if ($no_sse2) {
-               $target{sha1_obj} =~ s/\S*sse2\S+//;
-           } elsif ($config{cflags} !~ /OPENSSL_IA32_SSE2/) {
-               $config{cflags}.=" -DOPENSSL_IA32_SSE2";
-           }
-       }
+    if ($target{sha1_asm_src}) {
+       $config{cflags}.=" -DSHA1_ASM"   if ($target{sha1_asm_src} =~ /sx86/ || $target{sha1_asm_src} =~ /sha1/);
+       $config{cflags}.=" -DSHA256_ASM" if ($target{sha1_asm_src} =~ /sha256/);
+       $config{cflags}.=" -DSHA512_ASM" if ($target{sha1_asm_src} =~ /sha512/);
     }
-    if ($target{md5_obj} =~ /\.o$/) {
+    if ($target{md5_asm_src}) {
        $config{cflags}.=" -DMD5_ASM";
     }
-    $target{cast_obj}=$table{BASE}->{cast_obj} if (!$config{no_shared}); # CAST assembler is not PIC
-    if ($target{rmd160_obj} =~ /\.o$/) {
+    $target{cast_asm_src}=$table{BASE}->{cast_asm_src} if (!$config{no_shared}); # CAST assembler is not PIC
+    if ($target{rmd160_asm_src}) {
        $config{cflags}.=" -DRMD160_ASM";
     }
-    if ($target{aes_obj} =~ /\.o$/) {
-       $config{cflags}.=" -DAES_ASM" if ($target{aes_obj} =~ m/\baes-/);;
-       # aes-ctr.o is not a real file, only indication that assembler
+    if ($target{aes_asm_src}) {
+       $config{cflags}.=" -DAES_ASM" if ($target{aes_asm_src} =~ m/\baes-/);;
+       # aes-ctr.fake is not a real file, only indication that assembler
        # module implements AES_ctr32_encrypt...
-       $config{cflags}.=" -DAES_CTR_ASM" if ($target{aes_obj} =~ s/\s*aes-ctr\.o//);
-       # aes-xts.o indicates presence of AES_xts_[en|de]crypt...
-       $config{cflags}.=" -DAES_XTS_ASM" if ($target{aes_obj} =~ s/\s*aes-xts\.o//);
-       $target{aes_obj} =~ s/\s*(vpaes|aesni)-x86\.o//g if ($no_sse2);
-       $config{cflags}.=" -DVPAES_ASM" if ($target{aes_obj} =~ m/vpaes/);
-       $config{cflags}.=" -DBSAES_ASM" if ($target{aes_obj} =~ m/bsaes/);
+       $config{cflags}.=" -DAES_CTR_ASM" if ($target{aes_asm_src} =~ s/\s*aes-ctr\.fake//);
+       # aes-xts.fake indicates presence of AES_xts_[en|de]crypt...
+       $config{cflags}.=" -DAES_XTS_ASM" if ($target{aes_asm_src} =~ s/\s*aes-xts\.fake//);
+       $target{aes_asm_src} =~ s/\s*(vpaes|aesni)-x86\.s//g if ($no_sse2);
+       $config{cflags}.=" -DVPAES_ASM" if ($target{aes_asm_src} =~ m/vpaes/);
+       $config{cflags}.=" -DBSAES_ASM" if ($target{aes_asm_src} =~ m/bsaes/);
     }
-    if ($target{wp_obj} =~ /mmx/) {
+    if ($target{wp_asm_src} =~ /mmx/) {
         if ($config{processor} eq "386") {
-           $target{wp_obj}=$table{BASE}->{wp_obj};
+           $target{wp_asm_src}=$table{BASE}->{wp_asm_src};
        } elsif (!$disabled{"whirlpool"}) {
            $config{cflags}.=" -DWHIRLPOOL_ASM";
        }
     }
-    if ($target{modes_obj} =~ /ghash-/) {
+    if ($target{modes_asm_src} =~ /ghash-/) {
        $config{cflags}.=" -DGHASH_ASM";
     }
-    if ($target{ec_obj} =~ /ecp_nistz256/) {
+    if ($target{ec_asm_src} =~ /ecp_nistz256/) {
        $config{cflags}.=" -DECP_NISTZ256_ASM";
     }
-    if ($target{poly1305_obj} =~ /\.o$/) {
+    if ($target{poly1305_asm_src} ne "") {
        $config{cflags}.=" -DPOLY1305_ASM";
     }
 }
@@ -1144,6 +1146,375 @@ if ($strict_warnings)
                }
        }
 
+# If we use the unified build, collect information from build.info files
+my %unified_info = ();
+
+if ($target{build_scheme}->[0] eq "unified") {
+    use lib catdir(dirname(__FILE__),"util");
+    use with_fallback qw(Text::Template);
+
+    # Helpers to produce clean paths with no /../ in the middle and so on.
+    sub int_absolutedir {
+        my $dir = shift;
+
+        # Required, because realpath only works properly with existing dirs
+        make_path($dir);
+
+        my $res = realpath($dir);
+        return $res;
+    }
+
+    sub cleandir {
+        my $dir = shift;
+        my $base = shift || ".";
+
+        my $res = abs2rel(int_absolutedir($dir), rel2abs($base));
+        #print STDERR "DEBUG[cleandir]: $dir , $base => $res\n";
+        return $res;
+    }
+
+    sub cleanfile {
+        my $file = shift;
+        my $base = shift || ".";
+        my $d = dirname($file);
+        my $f = basename($file);
+
+        my $res = abs2rel(catfile(int_absolutedir($d), $f), rel2abs($base));
+        #print STDERR "DEBUG[cleanfile]: $d , $f => $res\n";
+        return $res;
+    }
+
+    my @build_infos = ( [ ".", "build.info" ] );
+    foreach (@{$config{dirs}}) {
+        push @build_infos, [ $_, "build.info" ]
+            if (-f catfile($srcdir, $_, "build.info"));
+    }
+    foreach (@{$config{sdirs}}) {
+        push @build_infos, [ catdir("crypto", $_), "build.info" ]
+            if (-f catfile($srcdir, "crypto", $_, "build.info"));
+    }
+    foreach (@{$config{engdirs}}) {
+        push @build_infos, [ catdir("engines", $_), "build.info" ]
+            if (-f catfile($srcdir, "engines", $_, "build.info"));
+    }
+
+    foreach (@build_infos) {
+        my $sourced = catdir($srcdir, $_->[0]);
+        my $buildd = catdir($blddir, $_->[0]);
+
+        make_path($buildd);
+
+        my $f = $_->[1];
+        # The basic things we're trying to build
+        my @programs = ();
+        my @libraries = ();
+        my @engines = ();
+        my @scripts = ();
+        my @extra = ();
+        my @intermediates = ();
+        my @rawlines = ();
+
+        my %ordinals = ();
+        my %sources = ();
+        my %includes = ();
+        my %depends = ();
+        my %renames = ();
+        my %sharednames = ();
+
+        my $template = Text::Template->new(TYPE => 'FILE',
+                                           SOURCE => catfile($sourced, $f));
+        die "Something went wrong with $sourced/$f: $!\n" unless $template;
+        my @text =
+            split /^/m,
+            $template->fill_in(HASH => { config => \%config,
+                                         target => \%target,
+                                         builddir => abs2rel($buildd, $blddir),
+                                         sourcedir => abs2rel($sourced, $blddir),
+                                         buildtop => abs2rel($blddir, $blddir),
+                                         sourcetop => abs2rel($srcdir, $blddir) },
+                               DELIMITERS => [ "{-", "-}" ]);
+
+        # The top item of this stack has the following values
+        # -2 positive already run and we found ELSE (following ELSIF should fail)
+        # -1 positive already run (skip until ENDIF)
+        # 0 negatives so far (if we're at a condition, check it)
+        # 1 last was positive (don't skip lines until next ELSE, ELSIF or ENDIF)
+        # 2 positive ELSE (following ELSIF should fail)
+        my @skip = ();
+        collect_information(
+            collect_from_array([ @text ],
+                               qr/\\$/ => sub { my $l1 = shift; my $l2 = shift;
+                                                $l1 =~ s/\\$//; $l1.$l2 }),
+            # Info we're looking for
+            qr/^\s*IF\[((?:\\.|[^\\\]])*)\]\s*$/
+            => sub { push @skip, !! $1; },
+            qr/^\s*ELSIF\[((?:\\.|[^\\\]])*)\]\s*$/
+            => sub { die "ELSIF out of scope" if ! @skip;
+                     die "ELSIF following ELSE" if abs($skip[$#skip]) == 2;
+                     $skip[$#skip] = -1 if $skip[$#skip] != 0;
+                     $skip[$#skip] = !! $1
+                         if $skip[$#skip] == 0; },
+            qr/^\s*ELSE\s*$/
+            => sub { die "ELSE out of scope" if ! @skip;
+                     $skip[$#skip] = -2 if $skip[$#skip] != 0;
+                     $skip[$#skip] = 2 if $skip[$#skip] == 0; },
+            qr/^\s*ENDIF\s*$/
+            => sub { die "ENDIF out of scope" if ! @skip;
+                     pop @skip; },
+            qr/^\s*PROGRAMS\s*=\s*(.*)\s*$/
+            => sub { push @programs, split(/\s+/, $1)
+                         if !@skip || $skip[$#skip] > 0 },
+            qr/^\s*LIBS\s*=\s*(.*)\s*$/
+            => sub { push @libraries, split(/\s+/, $1)
+                         if !@skip || $skip[$#skip] > 0 },
+            qr/^\s*ENGINES\s*=\s*(.*)\s*$/
+            => sub { push @engines, split(/\s+/, $1)
+                         if !@skip || $skip[$#skip] > 0 },
+            qr/^\s*SCRIPTS\s*=\s*(.*)\s*$/
+            => sub { push @scripts, split(/\s+/, $1)
+                         if !@skip || $skip[$#skip] > 0 },
+            qr/^\s*EXTRA\s*=\s*(.*)\s*$/
+            => sub { push @extra, split(/\s+/, $1)
+                         if !@skip || $skip[$#skip] > 0 },
+
+            qr/^\s*ORDINALS\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/,
+            => sub { push @{$ordinals{$1}}, split(/\s+/, $2)
+                         if !@skip || $skip[$#skip] > 0 },
+            qr/^\s*SOURCE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
+            => sub { push @{$sources{$1}}, split(/\s+/, $2)
+                         if !@skip || $skip[$#skip] > 0 },
+            qr/^\s*INCLUDE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
+            => sub { push @{$includes{$1}}, split(/\s+/, $2)
+                         if !@skip || $skip[$#skip] > 0 },
+            qr/^\s*DEPEND\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
+            => sub { push @{$depends{$1}}, split(/\s+/, $2)
+                         if !@skip || $skip[$#skip] > 0 },
+            qr/^\s*RENAME\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
+            => sub { push @{$renames{$1}}, split(/\s+/, $2)
+                         if !@skip || $skip[$#skip] > 0 },
+            qr/^\s*SHARED_NAME\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
+            => sub { push @{$sharednames{$1}}, split(/\s+/, $2)
+                         if !@skip || $skip[$#skip] > 0 },
+            qr/^\s*BEGINRAW\[((?:\\.|[^\\\]])+)\]\s*$/
+            => sub {
+                my $lineiterator = shift;
+                my $target_kind = $1;
+                while (defined $lineiterator->()) {
+                    chomp;
+                    if (/^\s*ENDRAW\[((?:\\.|[^\\\]])+)\]\s*$/) {
+                        die "ENDRAW doesn't match BEGINRAW"
+                            if $1 ne $target_kind;
+                        last;
+                    }
+                    next if @skip && $skip[$#skip] <= 0;
+                    push @rawlines,  $_
+                        if ($target_kind eq $target{build_file}
+                            || $target_kind eq $target{build_file}."(".$target{build_scheme}->[1].")");
+                }
+            },
+            qr/^(?:#.*|\s*)$/ => sub { },
+            "OTHERWISE" => sub { die "Something wrong with this line:\n$_\nat $sourced/$f" }
+            );
+        die "runaway IF?" if (@skip);
+
+        foreach (keys %renames) {
+            die "$_ renamed to more than one thing: "
+                ,join(" ", @{$renames{$_}}),"\n"
+                if scalar @{$renames{$_}} > 1;
+            my $dest = cleanfile(catfile($buildd, $_), $blddir);
+            my $to = cleanfile(catfile($buildd, $renames{$_}->[0]), $blddir);
+            die "$dest renamed to more than one thing: "
+                ,$unified_info{rename}->{$dest}, $to
+                unless !defined($unified_info{rename}->{$dest})
+                or $unified_info{rename}->{$dest} eq $to;
+            $unified_info{rename}->{$dest} = $to;
+        }
+
+        foreach (@programs) {
+            my $program = cleanfile(catfile($buildd, $_), $blddir);
+            if ($unified_info{rename}->{$program}) {
+                $program = $unified_info{rename}->{$program};
+            }
+            $unified_info{programs}->{$program} = 1;
+        }
+
+        foreach (@libraries) {
+            my $library = cleanfile(catfile($buildd, $_), $blddir);
+            if ($unified_info{rename}->{$library}) {
+                $library = $unified_info{rename}->{$library};
+            }
+            $unified_info{libraries}->{$library} = 1;
+        }
+
+        die <<"EOF" if $config{no_shared} && scalar @engines;
+ENGINES can only be used if configured with 'shared'.
+This is usually a fault in a build.info file.
+EOF
+        foreach (@engines) {
+            my $library = cleanfile(catfile($buildd, $_), $blddir);
+            if ($unified_info{rename}->{$library}) {
+                $library = $unified_info{rename}->{$library};
+            }
+            $unified_info{engines}->{$library} = 1;
+        }
+
+        foreach (@scripts) {
+            my $script = cleanfile(catfile($buildd, $_), $blddir);
+            if ($unified_info{rename}->{$script}) {
+                $script = $unified_info{rename}->{$script};
+            }
+            $unified_info{scripts}->{$script} = 1;
+        }
+
+        foreach (@extra) {
+            my $extra = cleanfile(catfile($buildd, $_), $blddir);
+            $unified_info{extra}->{$extra} = 1;
+        }
+
+        push @{$unified_info{rawlines}}, @rawlines;
+
+        if (!$config{no_shared}) {
+            # Check sharednames.
+            foreach (keys %sharednames) {
+                my $dest = cleanfile(catfile($buildd, $_), $blddir);
+                if ($unified_info{rename}->{$dest}) {
+                    $dest = $unified_info{rename}->{$dest};
+                }
+                die "shared_name for $dest with multiple values: "
+                    ,join(" ", @{$sharednames{$_}}),"\n"
+                    if scalar @{$sharednames{$_}} > 1;
+                my $to = cleanfile(catfile($buildd, $sharednames{$_}->[0]),
+                                   $blddir);
+                die "shared_name found for a library $dest that isn't defined\n"
+                    unless $unified_info{libraries}->{$dest};
+                die "shared_name for $dest with multiple values: "
+                    ,$unified_info{sharednames}->{$dest}, ", ", $to
+                    unless !defined($unified_info{sharednames}->{$dest})
+                    or $unified_info{sharednames}->{$dest} eq $to;
+                $unified_info{sharednames}->{$dest} = $to;
+            }
+
+            # Additionally, we set up sharednames for libraries that don't
+            # have any, as themselves.
+            foreach (keys %{$unified_info{libraries}}) {
+                if (!defined $unified_info{sharednames}->{$_}) {
+                    $unified_info{sharednames}->{$_} = $_
+                }
+            }
+        }
+
+        foreach (keys %ordinals) {
+            my $dest = $_;
+            my $ddest = cleanfile(catfile($buildd, $_), $blddir);
+            if ($unified_info{rename}->{$ddest}) {
+                $ddest = $unified_info{rename}->{$ddest};
+            }
+            foreach (@{$ordinals{$dest}}) {
+                my %known_ordinals =
+                    (
+                     crypto =>
+                     cleanfile(catfile($sourced, "util", "libeay.num"), $blddir),
+                     ssl =>
+                     cleanfile(catfile($sourced, "util", "ssleay.num"), $blddir)
+                    );
+                my $o = $known_ordinals{$_};
+                die "Ordinals for $ddest defined more than once\n"
+                    if $unified_info{ordinals}->{$ddest};
+                $unified_info{ordinals}->{$ddest} = [ $_, $o ];
+            }
+        }
+
+        foreach (keys %sources) {
+            my $dest = $_;
+            my $ddest = cleanfile(catfile($buildd, $_), $blddir);
+            if ($unified_info{rename}->{$ddest}) {
+                $ddest = $unified_info{rename}->{$ddest};
+            }
+            foreach (@{$sources{$dest}}) {
+                my $s = cleanfile(catfile($sourced, $_), $blddir);
+
+                # If it isn't in the source tree, we assume it's generated
+                # in the build tree
+                if (! -f $s) {
+                    $s = cleanfile(catfile($buildd, $_), $blddir);
+                }
+                # We recognise C and asm files
+                if ($s =~ /\.[csS]\b$/) {
+                    (my $o = $_) =~ s/\.[csS]\b$/.o/;
+                    $o = cleanfile(catfile($buildd, $o), $blddir);
+                    $unified_info{sources}->{$ddest}->{$o} = 1;
+                    $unified_info{sources}->{$o}->{$s} = 1;
+                } else {
+                    $unified_info{sources}->{$ddest}->{$s} = 1;
+                }
+            }
+        }
+
+        foreach (keys %depends) {
+            my $dest = $_;
+            my $ddest = cleanfile(catfile($buildd, $_), $blddir);
+            if ($unified_info{rename}->{$ddest}) {
+                $ddest = $unified_info{rename}->{$ddest};
+            }
+            foreach (@{$depends{$dest}}) {
+                my $d = cleanfile(catfile($sourced, $_), $blddir);
+
+                # If it isn't found in the source, let's assume it's generated
+                # and that the Makefile template has the lines
+                if (! -f $d) {
+                    $d = cleanfile(catfile($buildd, $_), $blddir);
+                }
+                # Take note if the file to depend on is being renamed
+                if ($unified_info{rename}->{$d}) {
+                    $d = $unified_info{rename}->{$d};
+                }
+                $unified_info{depends}->{$ddest}->{$d} = 1;
+                # If we depend on a header file, let's make sure it
+                # can get included
+                if ($d =~ /\.h$/) {
+                    my $i = dirname($d);
+                    push @{$unified_info{includes}->{$ddest}}, $i
+                        unless grep { $_ eq $i } @{$unified_info{includes}->{$ddest}};
+                }
+            }
+        }
+
+        foreach (keys %includes) {
+            my $dest = $_;
+            my $ddest = cleanfile(catfile($buildd, $_), $blddir);
+            if ($unified_info{rename}->{$ddest}) {
+                $ddest = $unified_info{rename}->{$ddest};
+            }
+            foreach (@{$includes{$dest}}) {
+                my $i = cleandir(catdir($sourced, $_), $blddir);
+                push @{$unified_info{includes}->{$ddest}}, $i
+                    unless grep { $_ eq $i } @{$unified_info{includes}->{$ddest}};
+            }
+        }
+    }
+
+    ### Make unified_info a bit more efficient
+    # One level structures
+    foreach (("programs", "libraries", "engines", "scripts", "extra")) {
+        $unified_info{$_} = [ sort keys %{$unified_info{$_}} ];
+    }
+    # Two level structures
+    foreach my $l1 (("sources", "ldadd", "depends")) {
+        foreach my $l2 (sort keys %{$unified_info{$l1}}) {
+            $unified_info{$l1}->{$l2} =
+                [ sort keys %{$unified_info{$l1}->{$l2}} ];
+        }
+    }
+}
+
+# For the schemes that need it, we provide the old *_obj configs
+# from the *_asm_obj ones
+foreach (grep /_asm_src$/, keys %target) {
+    my $src = $_;
+    (my $obj = $_) =~ s/_asm_src$/_obj/;
+    ($target{$obj} = $target{$src}) =~ s/\.[csS]\b/.o/g;
+}
+
 # Write down our configuration where it fits #########################
 
 open(OUT,">configdata.pm") || die "unable to create configdata.pm: $!\n";
@@ -1156,7 +1527,7 @@ use warnings;
 use Exporter;
 #use vars qw(\@ISA \@EXPORT);
 our \@ISA = qw(Exporter);
-our \@EXPORT = qw(\%config \%target %withargs);
+our \@EXPORT = qw(\%config \%target %withargs %unified_info);
 
 EOF
 print OUT "our %config = (\n";
@@ -1215,10 +1586,60 @@ foreach (sort keys %withargs) {
 print OUT <<"EOF";
 );
 
-1;
 EOF
+if ($target{build_scheme}->[0] eq "unified") {
+    my $recurse;
+    $recurse = sub {
+        my $indent = shift;
+        foreach (@_) {
+            if (ref $_ eq "ARRAY") {
+                print OUT " "x$indent, "[\n";
+                foreach (@$_) {
+                    $recurse->($indent + 4, $_);
+                }
+                print OUT " "x$indent, "],\n";
+            } elsif (ref $_ eq "HASH") {
+                my %h = %$_;
+                print OUT " "x$indent, "{\n";
+                foreach (sort keys %h) {
+                    if (ref $h{$_} eq "") {
+                        print OUT " "x($indent + 4), quotify("perl", $_), " => ", quotify("perl", $h{$_}), ",\n";
+                    } else {
+                        print OUT " "x($indent + 4), quotify("perl", $_), " =>\n";
+                        $recurse->($indent + 8, $h{$_});
+                    }
+                }
+                print OUT " "x$indent, "},\n";
+            } else {
+                print OUT " "x$indent, quotify("perl", $_), ",\n";
+            }
+        }
+    };
+    print OUT "our %unified_info = (\n";
+    foreach (sort keys %unified_info) {
+        if (ref $unified_info{$_} eq "") {
+            print OUT " "x4, quotify("perl", $_), " => ", quotify("perl", $unified_info{$_}), ",\n";
+        } else {
+            print OUT " "x4, quotify("perl", $_), " =>\n";
+            $recurse->(8, $unified_info{$_});
+        }
+    }
+    print OUT <<"EOF";
+);
+
+EOF
+}
+print OUT "1;\n";
 close(OUT);
 
+die <<"EOF" if $target{build_scheme}->[0] ne "unified" && $srcdir ne $blddir;
+
+***** Trying building anywhere else than in the source tree will not
+***** work for target $config{target}.  To make it possible, it needs
+***** to use the "unified" build scheme.
+
+EOF
+
 print "IsMK1MF       =", ($target{build_scheme}->[0] eq "mk1mf" ? "yes" : "no"), "\n";
 print "CC            =$target{cc}\n";
 print "CFLAG         =$config{cflags}\n";
@@ -1252,48 +1673,61 @@ print "THIRTY_TWO_BIT mode\n" if $config{b32};
 print "BN_LLONG mode\n" if $config{bn_ll};
 print "RC4 uses $config{rc4_int}\n" if $config{rc4_int} != $def_int;
 
-run_dofile("Makefile.in","Makefile");
-
-run_dofile("util/domd.in", "util/domd");
-chmod 0755, "util/domd";
-
-run_dofile("include/openssl/opensslconf.h.in", "include/openssl/opensslconf.h");
+make_path(catdir($blddir, "include/openssl"));
+run_dofile(catfile($blddir, "include/openssl/opensslconf.h"),
+           catfile($srcdir, "include/openssl/opensslconf.h.in"));
 
+make_path(catdir($blddir, "crypto/include/internal"));
 foreach my $alg ( 'bn' ) {
-    run_dofile("crypto/include/internal/${alg}_conf.h.in",
-              "crypto/include/internal/${alg}_conf.h");
+    run_dofile(catfile($blddir, "crypto/include/internal/${alg}_conf.h"),
+               catfile($srcdir, "crypto/include/internal/${alg}_conf.h.in"));
 }
 
-# Copy all Makefile.in to Makefile (except top-level)
-use File::Find;
-use IO::File;
-find(
-    {
-        preprocess => sub {
-            grep(!/^\./, @_);
-        },
-        wanted => sub {
-            return if ($_ ne "Makefile.in" || $File::Find::dir eq ".");
-            my $in = IO::File->new($_, "r") or
-                die sprintf "Error reading Makefile.in in %s: !$\n",
-                $File::Find::dir;
-            my $out = IO::File->new("Makefile", "w") or
-                die sprintf "Error writing Makefile in %s: !$\n",
-                $File::Find::dir;
-            print $out "# Generated from $_, do not edit\n";
-            while (my $line = <$in>) { print $out $line }
-            $in->close() or
-                die sprintf "Error reading Makefile.in in %s: !$\n",
-                $File::Find::dir;
-            $out->close() or
-                die sprintf "Error writing Makefile in %s: !$\n",
-                $File::Find::dir;
+###
+### When the old "unixmake" scheme goes away, so does this function
+###
+sub build_Makefile {
+    run_dofile("Makefile","Makefile.in");
+
+    # Copy all Makefile.in to Makefile (except top-level)
+    use File::Find;
+    use IO::File;
+    find(
+        {
+            preprocess => sub {
+                grep(!/^\./, @_);
+            },
+            wanted => sub {
+                return if ($_ ne "Makefile.in" || $File::Find::dir eq ".");
+                my $in = IO::File->new($_, "r") or
+                    die sprintf "Error reading Makefile.in in %s: !$\n",
+                    $File::Find::dir;
+                my $out = IO::File->new("Makefile", "w") or
+                    die sprintf "Error writing Makefile in %s: !$\n",
+                    $File::Find::dir;
+                print $out "# Generated from $_, do not edit\n";
+                while (my $line = <$in>) { print $out $line }
+                $in->close() or
+                    die sprintf "Error reading Makefile.in in %s: !$\n",
+                    $File::Find::dir;
+                $out->close() or
+                    die sprintf "Error writing Makefile in %s: !$\n",
+                    $File::Find::dir;
+            },
         },
-    },
-    ".");
+        ".");
+}
 
 my %builders = (
+    unified => sub {
+        die "unified build currently does nothing";
+    },
     unixmake => sub {
+        build_Makefile();
+
+        run_dofile("util/domd", "util/domd.in");
+        chmod 0755, "util/domd";
+
        my $make_command = "$make PERL=\'$config{perl}\'";
        my $make_targets = "";
        $make_targets .= " depend" if $config{depflags} ne $default_depflags && $make_depend;
@@ -1304,6 +1738,9 @@ my %builders = (
         }
     },
     mk1mf => sub {
+        # The only reason we do this is to have something to build MINFO from
+        build_Makefile();
+
        open (OUT,">crypto/buildinf.h") || die "Can't open buildinf.h";
        printf OUT <<"EOF";
 #ifndef MK1MF_BUILD
@@ -1633,13 +2070,17 @@ sub usage
 
 sub run_dofile()
 {
-    my $in = shift;
     my $out = shift;
+    my @templates = @_;
 
     unlink $out || warn "Can't remove $out, $!"
         if -f $out;
-    die "Can't open $in, $!" unless -f $in;
-    system("$config{perl} -I. -Mconfigdata util/dofile.pl -o\"Configure\" $in > $out.new");
+    foreach (@templates) {
+        die "Can't open $_, $!" unless -f $_;
+    }
+    my $cmd = "$config{perl} \"-I.\" \"-Mconfigdata\" $dofile -o\"Configure\" \"".join("\" \"",@templates)."\" > \"$out.new\"";
+    #print STDERR "DEBUG[run_dofile]: \$cmd = $cmd\n";
+    system($cmd);
     exit 1 if $? != 0;
     rename("$out.new", $out) || die "Can't rename $out.new, $!";
 }
@@ -1748,34 +2189,87 @@ sub quotify {
     map { $processor->($_); } @_;
 }
 
-# collect_information($filename, $line_continue, $regexp => $CODEref, ...)
-# $filename is the file to read.
-# $line_continue is either undef (which is a noop), or two arguments, where
-# the first is a regexp detecting a line continuation ending, and the
-# following argument is a CODEref that takes care of concatenating two
-# lines.
+# collect_from_file($filename, $line_concat_cond_re, $line_concat)
+# $filename is a file name to read from
+# $line_concat_cond_re is a regexp detecting a line continuation ending
+# $line_concat is a CODEref that takes care of concatenating two lines
+sub collect_from_file {
+    my $filename = shift;
+    my $line_concat_cond_re = shift;
+    my $line_concat = shift;
+
+    open my $fh, $filename || die "unable to read $filename: $!\n";
+    return sub {
+        my $saved_line = "";
+        $_ = "";
+        while (<$fh>) {
+            chomp;
+            if (defined $line_concat) {
+                $_ = $line_concat->($saved_line, $_);
+                $saved_line = "";
+            }
+            if (defined $line_concat_cond_re && /$line_concat_cond_re/) {
+                $saved_line = $_;
+                next;
+            }
+            return $_;
+        }
+        die "$filename ending with continuation line\n" if $_;
+        close $fh;
+        return undef;
+    }
+}
+
+# collect_from_array($array, $line_concat_cond_re, $line_concat)
+# $array is an ARRAYref of lines
+# $line_concat_cond_re is a regexp detecting a line continuation ending
+# $line_concat is a CODEref that takes care of concatenating two lines
+sub collect_from_array {
+    my $array = shift;
+    my $line_concat_cond_re = shift;
+    my $line_concat = shift;
+    my @array = (@$array);
+
+    return sub {
+        my $saved_line = "";
+        $_ = "";
+        while (defined($_ = shift @array)) {
+            chomp;
+            if (defined $line_concat) {
+                $_ = $line_concat->($saved_line, $_);
+                $saved_line = "";
+            }
+            if (defined $line_concat_cond_re && /$line_concat_cond_re/) {
+                $saved_line = $_;
+                next;
+            }
+            return $_;
+        }
+        die "input text ending with continuation line\n" if $_;
+        return undef;
+    }
+}
+
+# collect_information($lineiterator, $line_continue, $regexp => $CODEref, ...)
+# $lineiterator is a CODEref that delivers one line at a time.
 # All following arguments are regex/CODEref pairs, where the regexp detects a
 # line and the CODEref does something with the result of the regexp.
 sub collect_information {
-    my $filename = shift;
-    my $line_continue_re = shift;
-    my $line_concat = defined($line_continue_re) ? shift : undef;
+    my $lineiterator = shift;
     my %collectors = @_;
 
-    my $saved_line = "";
-    open IN, $filename || die "unable to read $filename: $!\n";
-    while(<IN>) {
-       chomp;
-       if (defined $line_concat) {
-           $_ = $line_concat->($saved_line, $_);
-       }
-       if (defined $line_continue_re && /$line_continue_re/) {
-           $saved_line = $_;
-           next;
-       }
-       foreach my $re (keys %collectors) {
-           if (/$re/) { $collectors{$re}->() };
-       }
+    while(defined($_ = $lineiterator->())) {
+        chomp;
+        my $found = 0;
+        foreach my $re (keys %collectors) {
+            if ($re ne "OTHERWISE" && /$re/) {
+                $collectors{$re}->($lineiterator);
+                $found = 1;
+            };
+        }
+        if ($collectors{"OTHERWISE"}) {
+            $collectors{"OTHERWISE"}->($lineiterator, $_)
+                unless $found || !defined $collectors{"OTHERWISE"};
+        }
     }
-    close IN;
 }
diff --git a/config b/config
index 9f15553..a70e3a2 100755 (executable)
--- a/config
+++ b/config
@@ -23,6 +23,7 @@
 SUFFIX=""
 TEST="false"
 EXE=""
+THERE=`dirname $0`
 
 # pick up any command line args to config
 for i
@@ -476,7 +477,7 @@ case "$GUESSOS" in
        ;;
   mips4-sgi-irix64)
        echo "WARNING! If you wish to build 64-bit library, then you have to"
-       echo "         invoke './Configure irix64-mips4-$CC' *manually*."
+       echo "         invoke '$THERE/Configure irix64-mips4-$CC' *manually*."
        if [ "$TEST" = "false" -a -t 1 ]; then
          echo "         You have about 5 seconds to press Ctrl-C to abort."
          (trap "stty `stty -g`" 2 0; stty -icanon min 0 time 50; read waste) <&1
@@ -495,7 +496,7 @@ case "$GUESSOS" in
        ISA64=`(sysctl -n hw.optional.64bitops) 2>/dev/null`
        if [ "$ISA64" = "1" -a -z "$KERNEL_BITS" ]; then
            echo "WARNING! If you wish to build 64-bit library, then you have to"
-           echo "         invoke './Configure darwin64-ppc-cc' *manually*."
+           echo "         invoke '$THERE/Configure darwin64-ppc-cc' *manually*."
            if [ "$TEST" = "false" -a -t 1 ]; then
              echo "         You have about 5 seconds to press Ctrl-C to abort."
              (trap "stty `stty -g`" 2 0; stty -icanon min 0 time 50; read waste) <&1
@@ -510,7 +511,7 @@ case "$GUESSOS" in
        ISA64=`(sysctl -n hw.optional.x86_64) 2>/dev/null`
        if [ "$ISA64" = "1" -a -z "$KERNEL_BITS" ]; then
            echo "WARNING! If you wish to build 64-bit library, then you have to"
-           echo "         invoke './Configure darwin64-x86_64-cc $options' *manually*."
+           echo "         invoke '$THERE/Configure darwin64-x86_64-cc $options' *manually*."
            if [ "$TEST" = "false" -a -t 1 ]; then
              echo "         You have about 5 seconds to press Ctrl-C to abort."
              # The stty technique used elsewhere doesn't work on
@@ -548,7 +549,7 @@ case "$GUESSOS" in
   ppc64-*-linux2)
        if [ -z "$KERNEL_BITS" ]; then
            echo "WARNING! If you wish to build 64-bit library, then you have to"
-           echo "         invoke './Configure linux-ppc64' *manually*."
+           echo "         invoke '$THERE/Configure linux-ppc64' *manually*."
            if [ "$TEST" = "false" -a -t 1 ]; then
                echo "         You have about 5 seconds to press Ctrl-C to abort."
                (trap "stty `stty -g`" 2 0; stty -icanon min 0 time 50; read waste) <&1
@@ -565,7 +566,7 @@ case "$GUESSOS" in
   ppc-*-linux2) OUT="linux-ppc" ;;
   mips64*-*-linux2)
        echo "WARNING! If you wish to build 64-bit library, then you have to"
-       echo "         invoke './Configure linux64-mips64' *manually*."
+       echo "         invoke '$THERE/Configure linux64-mips64' *manually*."
        if [ "$TEST" = "false" -a -t 1 ]; then
            echo "         You have about 5 seconds to press Ctrl-C to abort."
            (trap "stty `stty -g`" 2 0; stty -icanon min 0 time 50; read waste) <&1
@@ -582,7 +583,7 @@ case "$GUESSOS" in
   sparc64-*-linux2)
        echo "WARNING! If you *know* that your GNU C supports 64-bit/V9 ABI"
        echo "         and wish to build 64-bit library, then you have to"
-       echo "         invoke './Configure linux64-sparcv9' *manually*."
+       echo "         invoke '$THERE/Configure linux64-sparcv9' *manually*."
        if [ "$TEST" = "false" -a -t 1 ]; then
          echo "          You have about 5 seconds to press Ctrl-C to abort."
          (trap "stty `stty -g`" 2 0; stty -icanon min 0 time 50; read waste) <&1
@@ -659,7 +660,7 @@ case "$GUESSOS" in
        if [ "$ISA64" != "" -a "$KERNEL_BITS" = "" ]; then
            if [ "$CC" = "cc" -a $CCVER -ge 50 ]; then
                echo "WARNING! If you wish to build 64-bit library, then you have to"
-               echo "         invoke './Configure solaris64-sparcv9-cc' *manually*."
+               echo "         invoke '$THERE/Configure solaris64-sparcv9-cc' *manually*."
                if [ "$TEST" = "false" -a -t 1 ]; then
                  echo "         You have about 5 seconds to press Ctrl-C to abort."
                  (trap "stty `stty -g`" 2 0; stty -icanon min 0 time 50; read waste) <&1
@@ -671,7 +672,7 @@ case "$GUESSOS" in
                # and therefore switch over to 64-bit. <appro>
                OUT="solaris64-sparcv9-gcc"
                echo "WARNING! If you wish to build 32-bit library, then you have to"
-               echo "         invoke './Configure solaris-sparcv9-gcc' *manually*."
+               echo "         invoke '$THERE/Configure solaris-sparcv9-gcc' *manually*."
                if [ "$TEST" = "false" -a -t 1 ]; then
                  echo "         You have about 5 seconds to press Ctrl-C to abort."
                  (trap "stty `stty -g`" 2 0; stty -icanon min 0 time 50; read waste) <&1
@@ -679,7 +680,7 @@ case "$GUESSOS" in
            elif [ "$GCC_ARCH" = "-m32" ]; then
                echo "NOTICE! If you *know* that your GNU C supports 64-bit/V9 ABI"
                echo "        and wish to build 64-bit library, then you have to"
-               echo "        invoke './Configure solaris64-sparcv9-gcc' *manually*."
+               echo "        invoke '$THERE/Configure solaris64-sparcv9-gcc' *manually*."
                if [ "$TEST" = "false" -a -t 1 ]; then
                  echo "         You have about 5 seconds to press Ctrl-C to abort."
                  (trap "stty `stty -g`" 2 0; stty -icanon min 0 time 50; read waste) <&1
@@ -760,7 +761,7 @@ case "$GUESSOS" in
             OUT=${OUT:-"hpux-parisc2-${CC}"}
             if [ $KERNEL_BITS -eq 64 -a "$CC" = "cc" ]; then
                echo "WARNING! If you wish to build 64-bit library then you have to"
-               echo "         invoke './Configure hpux64-parisc2-cc' *manually*."
+               echo "         invoke '$THERE/Configure hpux64-parisc2-cc' *manually*."
                if [ "$TEST" = "false" -a -t 1 ]; then
                  echo "         You have about 5 seconds to press Ctrl-C to abort."
                  (trap "stty `stty -g`" 2 0; stty -icanon min 0 time 50; read waste) <&1
@@ -792,7 +793,7 @@ case "$GUESSOS" in
            OUT="aix-cc"
            if [ $KERNEL_BITS -eq 64 ]; then
                echo "WARNING! If you wish to build 64-bit kit, then you have to"
-               echo "         invoke './Configure aix64-cc' *manually*."
+               echo "         invoke '$THERE/Configure aix64-cc' *manually*."
                if [ "$TEST" = "false" -a -t 1 ]; then
                    echo "         You have ~5 seconds to press Ctrl-C to abort."
                    (trap "stty `stty -g`" 2 0; stty -icanon min 0 time 50; read waste) <&1
@@ -859,7 +860,7 @@ esac
 
 for i in aes bf camellia cast des dh dsa ec hmac idea md2 md5 mdc2 rc2 rc4 rc5 ripemd rsa seed sha
 do
-  if [ ! -d crypto/$i ]
+  if [ ! -d $THERE/crypto/$i ]
   then
     options="$options no-$i"
   fi
@@ -898,21 +899,21 @@ fi
 # compiler for the platform ... in which case we add it on
 # the end ... otherwise we leave it off
 
-$PERL ./Configure LIST | grep "$OUT-$CC" > /dev/null
+$PERL $THERE/Configure LIST | grep "$OUT-$CC" > /dev/null
 if [ $? = "0" ]; then
   OUT="$OUT-$CC"
 fi
 
 OUT="$OUT"
 
-$PERL ./Configure LIST | grep "$OUT" > /dev/null
+$PERL $THERE/Configure LIST | grep "$OUT" > /dev/null
 if [ $? = "0" ]; then
   echo Configuring for $OUT
 
   if [ "$TEST" = "true" ]; then
-    echo $PERL ./Configure $OUT $options
+    echo $PERL $THERE/Configure $OUT $options
   else
-    $PERL ./Configure $OUT $options
+    $PERL $THERE/Configure $OUT $options
   fi
 else
   echo "This system ($OUT) is not supported. See file INSTALL for details."
index ebae393..897580f 100644 (file)
@@ -158,4 +158,8 @@ depend:
 clean:
        rm -f *.s *.o *.obj lib tags core .pure .nfs* *.old *.bak fluff
 
+# Different flavours of make disagree on where output goes
+.c.o:
+       $(CC) $(CFLAGS) -c $< -o $@
+
 # DO NOT DELETE THIS LINE -- make depend depends on it.