123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619 |
- Design document for the unified scheme data
- ===========================================
- How are things connected?
- -------------------------
- The unified scheme takes all its data from the build.info files seen
- throughout the source tree. These files hold the minimum information
- needed to build end product files from diverse sources. See the
- section on build.info files below.
- From the information in build.info files, Configure builds up an
- information database as a hash table called %unified_info, which is
- stored in configdata.pm, found at the top of the build tree (which may
- or may not be the same as the source tree).
- Configurations/common.tmpl uses the data from %unified_info to
- generate the rules for building end product files as well as
- intermediary files with the help of a few functions found in the
- build-file templates. See the section on build-file templates further
- down for more information.
- build.info files
- ----------------
- As mentioned earlier, build.info files are meant to hold the minimum
- information needed to build output files, and therefore only (with a
- few possible exceptions [1]) have information about end products (such
- as scripts, library files and programs) and source files (such as C
- files, C header files, assembler files, etc). Intermediate files such
- as object files are rarely directly referred to in build.info files (and
- when they are, it's always with the file name extension .o), they are
- inferred by Configure. By the same rule of minimalism, end product
- file name extensions (such as .so, .a, .exe, etc) are never mentioned
- in build.info. Their file name extensions will be inferred by the
- build-file templates, adapted for the platform they are meant for (see
- sections on %unified_info and build-file templates further down).
- The variables PROGRAMS, LIBS, ENGINES and SCRIPTS are used to declare
- end products. There are variants for them with '_NO_INST' as suffix
- (PROGRAM_NO_INST etc) to specify end products that shouldn't get
- installed.
- The variables SOURCE, DEPEND, INCLUDE and DEFINE are indexed by a
- produced file, and their values are the source used to produce that
- particular produced file, extra dependencies, include directories
- needed, or C macros to be defined.
- All their values in all the build.info throughout the source tree are
- collected together and form a set of programs, libraries, engines and
- scripts to be produced, source files, dependencies, etc etc etc.
- Let's have a pretend example, a very limited contraption of OpenSSL,
- composed of the program 'apps/openssl', the libraries 'libssl' and
- 'libcrypto', an engine 'engines/ossltest' and their sources and
- dependencies.
- # build.info
- LIBS=libcrypto libssl
- INCLUDE[libcrypto]=include
- INCLUDE[libssl]=include
- DEPEND[libssl]=libcrypto
- This is the top directory build.info file, and it tells us that two
- libraries are to be built, the include directory 'include/' shall be
- used throughout when building anything that will end up in each
- library, and that the library 'libssl' depend on the library
- 'libcrypto' to function properly.
- # apps/build.info
- PROGRAMS=openssl
- SOURCE[openssl]=openssl.c
- INCLUDE[openssl]=.. ../include
- DEPEND[openssl]=../libssl
- This is the build.info file in 'apps/', one may notice that all file
- paths mentioned are relative to the directory the build.info file is
- located in. This one tells us that there's a program to be built
- called 'apps/openssl' (the file name extension will depend on the
- platform and is therefore not mentioned in the build.info file). It's
- built from one source file, 'apps/openssl.c', and building it requires
- the use of '.' and 'include' include directories (both are declared
- from the point of view of the 'apps/' directory), and that the program
- depends on the library 'libssl' to function properly.
- # crypto/build.info
- LIBS=../libcrypto
- SOURCE[../libcrypto]=aes.c evp.c cversion.c
- DEPEND[cversion.o]=buildinf.h
-
- GENERATE[buildinf.h]=../util/mkbuildinf.pl "$(CC) $(CFLAGS)" "$(PLATFORM)"
- DEPEND[buildinf.h]=../Makefile
- DEPEND[../util/mkbuildinf.pl]=../util/Foo.pm
- This is the build.info file in 'crypto', and it tells us a little more
- about what's needed to produce 'libcrypto'. LIBS is used again to
- declare that 'libcrypto' is to be produced. This declaration is
- really unnecessary as it's already mentioned in the top build.info
- file, but can make the info file easier to understand. This is to
- show that duplicate information isn't an issue.
- This build.info file informs us that 'libcrypto' is built from a few
- source files, 'crypto/aes.c', 'crypto/evp.c' and 'crypto/cversion.c'.
- It also shows us that building the object file inferred from
- 'crypto/cversion.c' depends on 'crypto/buildinf.h'. Finally, it
- also shows the possibility to declare how some files are generated
- using some script, in this case a perl script, and how such scripts
- can be declared to depend on other files, in this case a perl module.
- Two things are worth an extra note:
- 'DEPEND[cversion.o]' mentions an object file. DEPEND indexes is the
- only location where it's valid to mention them
- Lines in 'BEGINRAW'..'ENDRAW' sections must always mention files as
- seen from the top directory, no exception.
- # ssl/build.info
- LIBS=../libssl
- SOURCE[../libssl]=tls.c
- This is the build.info file in 'ssl/', and it tells us that the
- library 'libssl' is built from the source file 'ssl/tls.c'.
- # engines/build.info
- ENGINES=dasync
- SOURCE[dasync]=e_dasync.c
- DEPEND[dasync]=../libcrypto
- INCLUDE[dasync]=../include
- ENGINES_NO_INST=ossltest
- SOURCE[ossltest]=e_ossltest.c
- DEPEND[ossltest]=../libcrypto.a
- INCLUDE[ossltest]=../include
- This is the build.info file in 'engines/', telling us that two engines
- called 'engines/dasync' and 'engines/ossltest' shall be built, that
- dasync's source is 'engines/e_dasync.c' and ossltest's source is
- 'engines/e_ossltest.c' and that the include directory 'include/' may
- be used when building anything that will be part of these engines.
- Also, both engines depend on the library 'libcrypto' to function
- properly. ossltest is explicitly linked with the static variant of
- the library 'libcrypto'. Finally, only dasync is being installed, as
- ossltest is only for internal testing.
- When Configure digests these build.info files, the accumulated
- information comes down to this:
- LIBS=libcrypto libssl
- SOURCE[libcrypto]=crypto/aes.c crypto/evp.c crypto/cversion.c
- DEPEND[crypto/cversion.o]=crypto/buildinf.h
- INCLUDE[libcrypto]=include
- SOURCE[libssl]=ssl/tls.c
- INCLUDE[libssl]=include
- DEPEND[libssl]=libcrypto
-
- PROGRAMS=apps/openssl
- SOURCE[apps/openssl]=apps/openssl.c
- INCLUDE[apps/openssl]=. include
- DEPEND[apps/openssl]=libssl
- ENGINES=engines/dasync
- SOURCE[engines/dasync]=engines/e_dasync.c
- DEPEND[engines/dasync]=libcrypto
- INCLUDE[engines/dasync]=include
- ENGINES_NO_INST=engines/ossltest
- SOURCE[engines/ossltest]=engines/e_ossltest.c
- DEPEND[engines/ossltest]=libcrypto.a
- INCLUDE[engines/ossltest]=include
-
- GENERATE[crypto/buildinf.h]=util/mkbuildinf.pl "$(CC) $(CFLAGS)" "$(PLATFORM)"
- DEPEND[crypto/buildinf.h]=Makefile
- DEPEND[util/mkbuildinf.pl]=util/Foo.pm
- A few notes worth mentioning:
- LIBS may be used to declare routine libraries only.
- PROGRAMS may be used to declare programs only.
- ENGINES may be used to declare engines only.
- The indexes for SOURCE must only be end product files, such as
- libraries, programs or engines. The values of SOURCE variables must
- only be source files (possibly generated).
- INCLUDE and DEPEND shows a relationship between different files
- (usually produced files) or between files and directories, such as a
- program depending on a library, or between an object file and some
- extra source file.
- When Configure processes the build.info files, it will take it as
- truth without question, and will therefore perform very few checks.
- If the build tree is separate from the source tree, it will assume
- that all built files and up in the build directory and that all source
- files are to be found in the source tree, if they can be found there.
- Configure will assume that source files that can't be found in the
- source tree (such as 'crypto/bildinf.h' in the example above) are
- generated and will be found in the build tree.
- The %unified_info database
- --------------------------
- The information in all the build.info get digested by Configure and
- collected into the %unified_info database, divided into the following
- indexes:
- depends => a hash table containing 'file' => [ 'dependency' ... ]
- pairs. These are directly inferred from the DEPEND
- variables in build.info files.
- engines => a list of engines. These are directly inferred from
- the ENGINES variable in build.info files.
- generate => a hash table containing 'file' => [ 'generator' ... ]
- pairs. These are directly inferred from the GENERATE
- variables in build.info files.
- includes => a hash table containing 'file' => [ 'include' ... ]
- pairs. These are directly inferred from the INCLUDE
- variables in build.info files.
- install => a hash table containing 'type' => [ 'file' ... ] pairs.
- The types are 'programs', 'libraries', 'engines' and
- 'scripts', and the array of files list the files of
- that type that should be installed.
- libraries => a list of libraries. These are directly inferred from
- the LIBS variable in build.info files.
- programs => a list of programs. These are directly inferred from
- the PROGRAMS variable in build.info files.
- rawlines => a list of build-file lines. These are a direct copy of
- the BEGINRAW..ENDRAW lines in build.info files. Note:
- only the BEGINRAW..ENDRAW section for the current
- platform are copied, the rest are ignored.
- scripts => a list of scripts. There are directly inferred from
- the SCRIPTS variable in build.info files.
- sources => a hash table containing 'file' => [ 'sourcefile' ... ]
- pairs. These are indirectly inferred from the SOURCE
- variables in build.info files. Object files are
- mentioned in this hash table, with source files from
- SOURCE variables, and AS source files for programs and
- libraries.
- shared_sources =>
- a hash table just like 'sources', but only as source
- files (object files) for building shared libraries.
- As an example, here is how the build.info files example from the
- section above would be digested into a %unified_info table:
- our %unified_info = (
- "depends" =>
- {
- "apps/openssl" =>
- [
- "libssl",
- ],
- "crypto/buildinf.h" =>
- [
- "Makefile",
- ],
- "crypto/cversion.o" =>
- [
- "crypto/buildinf.h",
- ],
- "engines/dasync" =>
- [
- "libcrypto",
- ],
- "engines/ossltest" =>
- [
- "libcrypto.a",
- ],
- "libssl" =>
- [
- "libcrypto",
- ],
- "util/mkbuildinf.pl" =>
- [
- "util/Foo.pm",
- ],
- },
- "engines" =>
- [
- "engines/dasync",
- "engines/ossltest",
- ],
- "generate" =>
- {
- "crypto/buildinf.h" =>
- [
- "util/mkbuildinf.pl",
- "\"\$(CC)",
- "\$(CFLAGS)\"",
- "\"$(PLATFORM)\"",
- ],
- },
- "includes" =>
- {
- "apps/openssl" =>
- [
- ".",
- "include",
- ],
- "engines/ossltest" =>
- [
- "include"
- ],
- "libcrypto" =>
- [
- "include",
- ],
- "libssl" =>
- [
- "include",
- ],
- "util/mkbuildinf.pl" =>
- [
- "util",
- ],
- }
- "install" =>
- {
- "engines" =>
- [
- "engines/dasync",
- ],
- "libraries" =>
- [
- "libcrypto",
- "libssl",
- ],
- "programs" =>
- [
- "apps/openssl",
- ],
- },
- "libraries" =>
- [
- "libcrypto",
- "libssl",
- ],
- "programs" =>
- [
- "apps/openssl",
- ],
- "rawlines" =>
- [
- ],
- "sources" =>
- {
- "apps/openssl" =>
- [
- "apps/openssl.o",
- ],
- "apps/openssl.o" =>
- [
- "apps/openssl.c",
- ],
- "crypto/aes.o" =>
- [
- "crypto/aes.c",
- ],
- "crypto/cversion.o" =>
- [
- "crypto/cversion.c",
- ],
- "crypto/evp.o" =>
- [
- "crypto/evp.c",
- ],
- "engines/e_dasync.o" =>
- [
- "engines/e_dasync.c",
- ],
- "engines/dasync" =>
- [
- "engines/e_dasync.o",
- ],
- "engines/e_ossltest.o" =>
- [
- "engines/e_ossltest.c",
- ],
- "engines/ossltest" =>
- [
- "engines/e_ossltest.o",
- ],
- "libcrypto" =>
- [
- "crypto/aes.c",
- "crypto/cversion.c",
- "crypto/evp.c",
- ],
- "libssl" =>
- [
- "ssl/tls.c",
- ],
- "ssl/tls.o" =>
- [
- "ssl/tls.c",
- ],
- },
- );
- As can be seen, everything in %unified_info is fairly simple suggest
- of information. Still, it tells us that to build all programs, we
- must build 'apps/openssl', and to build the latter, we will need to
- build all its sources ('apps/openssl.o' in this case) and all the
- other things it depends on (such as 'libssl'). All those dependencies
- need to be built as well, using the same logic, so to build 'libssl',
- we need to build 'ssl/tls.o' as well as 'libcrypto', and to build the
- latter...
- Build-file templates
- --------------------
- Build-file templates are essentially build-files (such as Makefile on
- Unix) with perl code fragments mixed in. Those perl code fragment
- will generate all the configuration dependent data, including all the
- rules needed to build end product files and intermediary files alike.
- At a minimum, there must be a perl code fragment that defines a set of
- functions that are used to generates specific build-file rules, to
- build static libraries from object files, to build shared libraries
- from static libraries, to programs from object files and libraries,
- etc.
- generatesrc - function that produces build file lines to generate
- a source file from some input.
- It's called like this:
- generatesrc(src => "PATH/TO/tobegenerated",
- generator => [ "generatingfile", ... ]
- generator_incs => [ "INCL/PATH", ... ]
- generator_deps => [ "dep1", ... ]
- incs => [ "INCL/PATH", ... ],
- deps => [ "dep1", ... ],
- intent => one of "libs", "dso", "bin" );
- 'src' has the name of the file to be generated.
- 'generator' is the command or part of command to
- generate the file, of which the first item is
- expected to be the file to generate from.
- generatesrc() is expected to analyse and figure out
- exactly how to apply that file and how to capture
- the result. 'generator_incs' and 'generator_deps'
- are include directories and files that the generator
- file itself depends on. 'incs' and 'deps' are
- include directories and files that are used if $(CC)
- is used as an intermediary step when generating the
- end product (the file indicated by 'src'). 'intent'
- indicates what the generated file is going to be
- used for.
- src2obj - function that produces build file lines to build an
- object file from source files and associated data.
- It's called like this:
- src2obj(obj => "PATH/TO/objectfile",
- srcs => [ "PATH/TO/sourcefile", ... ],
- deps => [ "dep1", ... ],
- incs => [ "INCL/PATH", ... ]
- intent => one of "lib", "dso", "bin" );
- 'obj' has the intended object file with '.o'
- extension, src2obj() is expected to change it to
- something more suitable for the platform.
- 'srcs' has the list of source files to build the
- object file, with the first item being the source
- file that directly corresponds to the object file.
- 'deps' is a list of explicit dependencies. 'incs'
- is a list of include file directories. Finally,
- 'intent' indicates what this object file is going
- to be used for.
- obj2lib - function that produces build file lines to build a
- static library file ("libfoo.a" in Unix terms) from
- object files.
- called like this:
- obj2lib(lib => "PATH/TO/libfile",
- objs => [ "PATH/TO/objectfile", ... ]);
- 'lib' has the intended library file name *without*
- extension, obj2lib is expected to add that. 'objs'
- has the list of object files to build this library.
- libobj2shlib - backward compatibility function that's used the
- same way as obj2shlib (described next), and was
- expected to build the shared library from the
- corresponding static library when that was suitable.
- NOTE: building a shared library from a static
- library is now DEPRECATED, as they no longer share
- object files. Attempting to do this will fail.
- obj2shlib - function that produces build file lines to build a
- shareable object library file ("libfoo.so" in Unix
- terms) from the corresponding object files.
- called like this:
- obj2shlib(shlib => "PATH/TO/shlibfile",
- lib => "PATH/TO/libfile",
- objs => [ "PATH/TO/objectfile", ... ],
- deps => [ "PATH/TO/otherlibfile", ... ]);
- 'lib' has the base (static) library file name
- *without* extension. This is useful in case
- supporting files are needed (such as import
- libraries on Windows).
- 'shlib' has the corresponding shared library name
- *without* extension. 'deps' has the list of other
- libraries (also *without* extension) this library
- needs to be linked with. 'objs' has the list of
- object files to build this library.
- obj2dso - function that produces build file lines to build a
- dynamic shared object file from object files.
- called like this:
- obj2dso(lib => "PATH/TO/libfile",
- objs => [ "PATH/TO/objectfile", ... ],
- deps => [ "PATH/TO/otherlibfile",
- ... ]);
- This is almost the same as obj2shlib, but the
- intent is to build a shareable library that can be
- loaded in runtime (a "plugin"...).
- obj2bin - function that produces build file lines to build an
- executable file from object files.
- called like this:
- obj2bin(bin => "PATH/TO/binfile",
- objs => [ "PATH/TO/objectfile", ... ],
- deps => [ "PATH/TO/libfile", ... ]);
- 'bin' has the intended executable file name
- *without* extension, obj2bin is expected to add
- that. 'objs' has the list of object files to build
- this library. 'deps' has the list of library files
- (also *without* extension) that the programs needs
- to be linked with.
- in2script - function that produces build file lines to build a
- script file from some input.
- called like this:
- in2script(script => "PATH/TO/scriptfile",
- sources => [ "PATH/TO/infile", ... ]);
- 'script' has the intended script file name.
- 'sources' has the list of source files to build the
- resulting script from.
- Along with the build-file templates is the driving engine
- Configurations/common.tmpl, which looks through all the information in
- %unified_info and generates all the rulesets to build libraries,
- programs and all intermediate files, using the rule generating
- functions defined in the build-file template.
- As an example with the smaller build.info set we've seen as an
- example, producing the rules to build 'libcrypto' would result in the
- following calls:
- # Note: obj2shlib will only be called if shared libraries are
- # to be produced.
- # Note 2: obj2shlib must convert the '.o' extension to whatever
- # is suitable on the local platform.
- obj2shlib(shlib => "libcrypto",
- objs => [ "crypto/aes.o", "crypto/evp.o", "crypto/cversion.o" ],
- deps => [ ]);
- obj2lib(lib => "libcrypto"
- objs => [ "crypto/aes.o", "crypto/evp.o", "crypto/cversion.o" ]);
- src2obj(obj => "crypto/aes.o"
- srcs => [ "crypto/aes.c" ],
- deps => [ ],
- incs => [ "include" ],
- intent => "lib");
- src2obj(obj => "crypto/evp.o"
- srcs => [ "crypto/evp.c" ],
- deps => [ ],
- incs => [ "include" ],
- intent => "lib");
- src2obj(obj => "crypto/cversion.o"
- srcs => [ "crypto/cversion.c" ],
- deps => [ "crypto/buildinf.h" ],
- incs => [ "include" ],
- intent => "lib");
- generatesrc(src => "crypto/buildinf.h",
- generator => [ "util/mkbuildinf.pl", "\"$(CC)",
- "$(CFLAGS)\"", "\"$(PLATFORM)\"" ],
- generator_incs => [ "util" ],
- generator_deps => [ "util/Foo.pm" ],
- incs => [ ],
- deps => [ ],
- intent => "lib");
- The returned strings from all those calls are then concatenated
- together and written to the resulting build-file.
|