Merge the C wrapper.
1.1 --- a/config/toolchain.in Fri Aug 28 12:09:04 2009 +0200
1.2 +++ b/config/toolchain.in Sun Aug 30 00:35:58 2009 +0200
1.3 @@ -296,4 +296,42 @@
1.4
1.5 endif # CROSS_NATIVE || CANADIAN
1.6
1.7 +# Kept as a separate if block, even if it could go into the above block,
1.8 +# because it seems better. No real reason, only that it seems right...
1.9 +if CANADIAN
1.10 +
1.11 +comment "Host specifics"
1.12 +
1.13 +choice
1.14 + bool
1.15 + prompt "| Install tools wrapper as:"
1.16 + default TOOLS_WRAPPER_SHELL
1.17 +
1.18 +config TOOLS_WRAPPER_SCRIPT
1.19 + bool
1.20 + prompt "shell script"
1.21 + help
1.22 + If your host has a shell, then you should say 'Y' here, to use
1.23 + a (very very simple) shell script as wrapper.
1.24 +
1.25 + See docs/overview.txt, section "Tools wrapper".
1.26 +
1.27 +config TOOLS_WRAPPER_EXEC
1.28 + bool
1.29 + prompt "executable"
1.30 + help
1.31 + If your host lacks a shell, then you should say 'Y' here, to use
1.32 + an executable.
1.33 +
1.34 + See docs/overview.txt, section "Tools wrapper".
1.35 +
1.36 +endchoice
1.37 +
1.38 +config TOOLS_WRAPPER
1.39 + string
1.40 + default "script" if TOOLS_WRAPPER_SCRIPT
1.41 + default "exec" if TOOLS_WRAPPER_EXEC
1.42 +
1.43 +endif # CROSS_NATIVE || CANADIAN
1.44 +
1.45 endmenu
2.1 --- a/docs/overview.txt Fri Aug 28 12:09:04 2009 +0200
2.2 +++ b/docs/overview.txt Sun Aug 30 00:35:58 2009 +0200
2.3 @@ -24,6 +24,8 @@
2.4 Stopping and restarting a build
2.5 Testing all toolchains at once
2.6 Overriding the number of // jobs
2.7 + Note on // jobs
2.8 + Tools wrapper
2.9 Using the toolchain
2.10 Toolchain types
2.11 Internals
2.12 @@ -145,7 +147,6 @@
2.13 simple:
2.14 ./configure --local
2.15 make
2.16 - make install
2.17
2.18 Now, *do not* remove crosstool-NG sources. They are needed to run crosstool-NG!
2.19 Stay in the directory holding the sources, and run:
2.20 @@ -382,6 +383,52 @@
2.21 refering to the number of // jobs when making the *components*. That is, we
2.22 speak of the number of // jobs used to build gcc, glibc, and so on...
2.23
2.24 +Tools wrapper |
2.25 +--------------+
2.26 +
2.27 +Starting with gcc-4.3 come two new dependencies: GMP and MPFR. With gcc-4.4,
2.28 +come three new ones: GMP, PPL and CLooG/ppl. These are libraries that enable
2.29 +advanced features to gcc. Additionally, some of the libraries can be used by
2.30 +binutils and gdb. Unfortunately, not all systems on which crosstool-NG runs
2.31 +have all of those libraries. And for those that do, the versions of those
2.32 +libraries may be older than the version required by gcc.
2.33 +
2.34 +This is why crosstool-NG builds its own set of libraries as part of the
2.35 +toolchain.
2.36 +
2.37 +The libraries are built as shared libraries, because building them as static
2.38 +libraries has some short-comings. This poses no problem at build time, as
2.39 +crosstool-NG correctly points gcc (and binutiols and gdb) to the correct
2.40 +place where our own version of the libraries are installed. But it poses
2.41 +a problem when gcc et al. are run: the place where the libraries are is most
2.42 +probably not known to the host dynamic linker. Still worse, if the host system
2.43 +has its own versions, then ld.so would load the wrong library!
2.44 +
2.45 +So we have to force the dynamic linker to load the correct version. We do this
2.46 +by using the LD_LIBRARY_PATH variable, that informs the dynamic linker where
2.47 +to look for shared libraries prior to searching its standard places. But we
2.48 +can't impose that burden on all the system (because it'd be a nightmare to
2.49 +configure, and because two tolchains on the same system may use different
2.50 +versions of the libraries); so we have to do it on a per-toolchain basis.
2.51 +
2.52 +So we rename all binaries of the toolchain (by adding a dot '.' as their first
2.53 +character), and add a small program, the so-called "tools wrapper", that
2.54 +correctly sets LD_LIBRARY_PATH prior to running the real tool.
2.55 +
2.56 +First, the wrapper was written as a POSIX-compliant shell script. That shell
2.57 +script is very simple, if not trivial, and works great. The only drawback is
2.58 +that it does not work on host systems that lack a shell, for example the
2.59 +MingW32 environment. To solve the issue, the wrapper has been re-written in C,
2.60 +and compiled at build time. This C wrapper is much more complex than the shell
2.61 +script, and although it sems to be working, it's been only lightly tested.
2.62 +Some of the expected short-comings with this C wrapper are;
2.63 + - multi-byte file names may not be handled correctly
2.64 + - it's really big for what it does
2.65 +
2.66 +So, the default wrapper installed with your toolchain is the shell script.
2.67 +If you know that your system is missing a shell, then you shall use the C
2.68 +wrapper (and report back whether it works, or does not work, for you).
2.69 +
2.70
2.71 _______________________
2.72 /
3.1 --- a/scripts/build/internals.sh Fri Aug 28 12:09:04 2009 +0200
3.2 +++ b/scripts/build/internals.sh Sun Aug 30 00:35:58 2009 +0200
3.3 @@ -46,9 +46,25 @@
3.4 CT_DoLog EXTRA "Installing toolchain wrappers"
3.5 CT_Pushd "${CT_PREFIX_DIR}/bin"
3.6
3.7 - # Copy the wrapper
3.8 - CT_DoExecLog DEBUG install -m 0755 "${CT_LIB_DIR}/scripts/wrapper.in" \
3.9 - ".${CT_TARGET}-wrapper"
3.10 + # Install the wrapper
3.11 + case "${CT_TOOLS_WRAPPER}" in
3.12 + script)
3.13 + CT_DoExecLog DEBUG install \
3.14 + -m 0755 \
3.15 + "${CT_LIB_DIR}/scripts/wrapper.in" \
3.16 + ".${CT_TARGET}-wrapper"
3.17 + ;;
3.18 + exec)
3.19 + _t="-s"
3.20 + if [ "${CT_DEBUG_CT}" = "y" ]; then
3.21 + _t="" # If debugging crosstool-NG, don't strip the wrapper
3.22 + fi
3.23 + CT_DoExecLog "${HOST_CC}" \
3.24 + -Wall -Wextra -Wunreachable-code -Werror \
3.25 + -O3 -static ${_t} \
3.26 + -o ".${CT_TARGET}-wrapper"
3.27 + ;;
3.28 + esac
3.29
3.30 # Replace every tools with the wrapper
3.31 # Do it unconditionally, even for those tools that happen to be shell
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/scripts/wrapper.c Sun Aug 30 00:35:58 2009 +0200
4.3 @@ -0,0 +1,128 @@
4.4 +#include <limits.h>
4.5 +#include <stdlib.h>
4.6 +#include <stdio.h>
4.7 +#include <string.h>
4.8 +#include <sys/types.h>
4.9 +#include <sys/stat.h>
4.10 +#include <unistd.h>
4.11 +#include <errno.h>
4.12 +
4.13 +
4.14 +/* Needed for execve */
4.15 +extern char **environ;
4.16 +
4.17 +int main( int argc,
4.18 + char** argv )
4.19 +{
4.20 + char *fullname; /* 'fullname' is used to store the absolute path to the
4.21 + tool being executed; it serves as a base to compute
4.22 + the realname of that tool, and the directory holding
4.23 + our runtime libraries */
4.24 + char *realname; /* 'realname' is the real name of the tool, that is what
4.25 + the wrapper is currently impersonating */
4.26 + char *basedir; /* 'libdir' contains our runtime libraries */
4.27 +
4.28 + char *lastslash; /* Temporary variables now */
4.29 + char *ldlibpath;
4.30 + size_t len;
4.31 + int execve_ret;
4.32 +
4.33 + /* In case we have a relative or absolute pathname (ie. contains a slash),
4.34 + * then realpath wll work. But if the tool was found in the PATH, realpath
4.35 + * won't work, and we'll have to search ourselves.
4.36 + * This if{}else{} block allocates memory for fullname. */
4.37 + if( strchr( argv[0], '/' ) ) {
4.38 + fullname = (char*) malloc( PATH_MAX * sizeof(char) );
4.39 + if( ! realpath( argv[0], fullname ) ) {
4.40 + perror( "tool wrapper" );
4.41 + exit( 1 );
4.42 + }
4.43 + } else {
4.44 + char *path;
4.45 + char *mypath;
4.46 + char *colon;
4.47 + char *testname;
4.48 + struct stat st;
4.49 +
4.50 + fullname = NULL;
4.51 + colon = mypath = path = strdup( getenv( "PATH" ) );
4.52 + while( colon ) {
4.53 + colon = strchr( mypath, ':' );
4.54 + if( colon ) {
4.55 + *colon = '\0';
4.56 + }
4.57 + testname = strdup( mypath );
4.58 + testname = (char*) realloc( testname, strlen( testname )
4.59 + + strlen( argv[0] )
4.60 + + 2 * sizeof(char) );
4.61 + memset( testname + strlen( testname ),
4.62 + 0,
4.63 + strlen( argv[0] ) + 2 * sizeof(char) );
4.64 + strcat( testname, "/" );
4.65 + strcat( testname, argv[0] );
4.66 + if( stat( testname, &st ) == 0 ) {
4.67 + /* OK, exists. Is it a regular file, or a
4.68 + * symlink, which the current user may execute? */
4.69 + if( S_ISREG( st.st_mode ) && ! access( testname, X_OK || R_OK ) ) {
4.70 + fullname = strdup( testname );
4.71 + break;
4.72 + }
4.73 + }
4.74 + free( testname );
4.75 + mypath = colon + 1;
4.76 + }
4.77 + free( path );
4.78 + if( ! fullname ) {
4.79 + fprintf( stderr, "tool wrapper: %s: command not found\n", argv[0] );
4.80 + exit( 1 );
4.81 + }
4.82 + }
4.83 +
4.84 + /* Duplicate my own name to add the 'dot' to tool name */
4.85 + realname = strdup( fullname );
4.86 + realname = (char*) realloc( realname, strlen( realname) + 2 * sizeof(char) );
4.87 + realname[ strlen( realname ) + 1 ] = '\0';
4.88 +
4.89 + /* Add the dot after the last '/' */
4.90 + lastslash = strrchr( realname, '/' );
4.91 + memmove( lastslash + 1, lastslash, strlen( lastslash ) );
4.92 + *( lastslash + 1 ) = '.';
4.93 +
4.94 + /* Compute the basedir of the tool */
4.95 + basedir = strdup( fullname );
4.96 + lastslash = strrchr( basedir, '/' );
4.97 + *lastslash = '\0';
4.98 + lastslash = strrchr( basedir, '/' );
4.99 + *lastslash = '\0';
4.100 +
4.101 + /* Append '/lib' */
4.102 + len = strlen( basedir );
4.103 + basedir = (char*) realloc( basedir, len + 5 );
4.104 + *( basedir + len ) = '\0';
4.105 + strcat( basedir, "/lib" );
4.106 +
4.107 + /* Now add the directory with our runtime libraries to the
4.108 + front of the library search path, LD_LIBRARY_PATH */
4.109 + ldlibpath = getenv( "LD_LIBRARY_PATH" );
4.110 + if( ldlibpath ) {
4.111 + basedir = (char*) realloc( basedir, strlen( basedir )
4.112 + + strlen( ldlibpath )
4.113 + + 2 * sizeof(char) );
4.114 + strcat( basedir, ":" );
4.115 + strcat( basedir, ldlibpath );
4.116 + }
4.117 +
4.118 + if( setenv( "LD_LIBRARY_PATH", basedir, 1 ) ) {
4.119 + errno = ENOMEM;
4.120 + perror( "tool wrapper" );
4.121 + exit( 1 );
4.122 + }
4.123 +
4.124 + /* Execute the real tool, now */
4.125 + execve_ret = execve( realname, argv, environ );
4.126 +
4.127 + /* In case something went wrong above, print a
4.128 + diagnostic message, and exit with error code 1 */
4.129 + perror( "tool wrapper" );
4.130 + return 1;
4.131 +}