From 7628fa7a088a63b8085fffe99e4270df976a1daa Mon Sep 17 00:00:00 2001 From: "Yann E. MORIN\"" Date: Sun, 30 Aug 2009 00:30:45 +0200 Subject: overview: fix table of content, fix the hacker's way table of content: add missing entry the hacker's way: no need to "make install" diff --git a/docs/overview.txt b/docs/overview.txt index 740ac0a..ed45d63 100644 --- a/docs/overview.txt +++ b/docs/overview.txt @@ -24,6 +24,7 @@ Running crosstool-NG Stopping and restarting a build Testing all toolchains at once Overriding the number of // jobs + Note on // jobs Using the toolchain Toolchain types Internals @@ -145,7 +146,6 @@ If you go the hacker's way, then the usage is a bit different, although very simple: ./configure --local make - make install Now, *do not* remove crosstool-NG sources. They are needed to run crosstool-NG! Stay in the directory holding the sources, and run: -- cgit v0.10.2-6-g49f6 From 8f051d8ef6a9bc03da3c68da518021a6b222c176 Mon Sep 17 00:00:00 2001 From: "Yann E. MORIN\"" Date: Sat, 29 Aug 2009 18:27:47 +0200 Subject: tool wrapper: add initial wrapper coded in C Add an initial wrapper: - find the realpath of the tool being called - add the '.' in front of the tool name - add the '/lib' dir to the base dir of the tool - set and export LD_LIBRARY_PATH - execve the real tool diff --git a/scripts/wrapper.c b/scripts/wrapper.c new file mode 100644 index 0000000..dbbcdd9 --- /dev/null +++ b/scripts/wrapper.c @@ -0,0 +1,128 @@ +#include +#include +#include +#include +#include +#include +#include +#include + + +/* Needed for execve */ +extern char **environ; + +int main( int argc, + char** argv ) +{ + char *fullname; /* 'fullname' is used to store the absolute path to the + tool being executed; it serves as a base to compute + the realname of that tool, and the directory holding + our runtime libraries */ + char *realname; /* 'realname' is the real name of the tool, that is what + the wrapper is currently impersonating */ + char *basedir; /* 'libdir' contains our runtime libraries */ + + char *lastslash; /* Temporary variables now */ + char *ldlibpath; + size_t len; + int execve_ret; + + /* In case we have a relative or absolute pathname (ie. contains a slash), + * then realpath wll work. But if the tool was found in the PATH, realpath + * won't work, and we'll have to search ourselves. + * This if{}else{} block allocates memory for fullname. */ + if( strchr( argv[0], '/' ) ) { + fullname = (char*) malloc( PATH_MAX * sizeof(char) ); + if( ! realpath( argv[0], fullname ) ) { + perror( "tool wrapper" ); + exit( 1 ); + } + } else { + char *path; + char *mypath; + char *colon; + char *testname; + struct stat st; + + fullname = NULL; + colon = mypath = path = strdup( getenv( "PATH" ) ); + while( colon ) { + colon = strchr( mypath, ':' ); + if( colon ) { + *colon = '\0'; + } + testname = strdup( mypath ); + testname = (char*) realloc( testname, strlen( testname ) + + strlen( argv[0] ) + + 2 * sizeof(char) ); + memset( testname + strlen( testname ), + 0, + strlen( argv[0] ) + 2 * sizeof(char) ); + strcat( testname, "/" ); + strcat( testname, argv[0] ); + if( stat( testname, &st ) == 0 ) { + /* OK, exists. Is it a regular file, or a + * symlink, which the current user may execute? */ + if( S_ISREG( st.st_mode ) && ! access( testname, X_OK || R_OK ) ) { + fullname = strdup( testname ); + break; + } + } + free( testname ); + mypath = colon + 1; + } + free( path ); + if( ! fullname ) { + fprintf( stderr, "tool wrapper: %s: command not found\n", argv[0] ); + exit( 1 ); + } + } + + /* Duplicate my own name to add the 'dot' to tool name */ + realname = strdup( fullname ); + realname = (char*) realloc( realname, strlen( realname) + 2 * sizeof(char) ); + realname[ strlen( realname ) + 1 ] = '\0'; + + /* Add the dot after the last '/' */ + lastslash = strrchr( realname, '/' ); + memmove( lastslash + 1, lastslash, strlen( lastslash ) ); + *( lastslash + 1 ) = '.'; + + /* Compute the basedir of the tool */ + basedir = strdup( fullname ); + lastslash = strrchr( basedir, '/' ); + *lastslash = '\0'; + lastslash = strrchr( basedir, '/' ); + *lastslash = '\0'; + + /* Append '/lib' */ + len = strlen( basedir ); + basedir = (char*) realloc( basedir, len + 5 ); + *( basedir + len ) = '\0'; + strcat( basedir, "/lib" ); + + /* Now add the directory with our runtime libraries to the + front of the library search path, LD_LIBRARY_PATH */ + ldlibpath = getenv( "LD_LIBRARY_PATH" ); + if( ldlibpath ) { + basedir = (char*) realloc( basedir, strlen( basedir ) + + strlen( ldlibpath ) + + 2 * sizeof(char) ); + strcat( basedir, ":" ); + strcat( basedir, ldlibpath ); + } + + if( setenv( "LD_LIBRARY_PATH", basedir, 1 ) ) { + errno = ENOMEM; + perror( "tool wrapper" ); + exit( 1 ); + } + + /* Execute the real tool, now */ + execve_ret = execve( realname, argv, environ ); + + /* In case something went wrong above, print a + diagnostic message, and exit with error code 1 */ + perror( "tool wrapper" ); + return 1; +} -- cgit v0.10.2-6-g49f6 From d811941c9a8222476995fac6805ca0ee188dad1e Mon Sep 17 00:00:00 2001 From: "Yann E. MORIN\"" Date: Sun, 30 Aug 2009 00:27:12 +0200 Subject: config: choose whether to use the shell or the C wrapper Offer a config choice on whether to isntall the script wrapper, or the compiled C wrapper. Update docs/overview.txt accordingly. diff --git a/config/toolchain.in b/config/toolchain.in index ffa4f3e..0aae112 100644 --- a/config/toolchain.in +++ b/config/toolchain.in @@ -296,4 +296,42 @@ config TARGET_SUFFIX endif # CROSS_NATIVE || CANADIAN +# Kept as a separate if block, even if it could go into the above block, +# because it seems better. No real reason, only that it seems right... +if CANADIAN + +comment "Host specifics" + +choice + bool + prompt "| Install tools wrapper as:" + default TOOLS_WRAPPER_SHELL + +config TOOLS_WRAPPER_SCRIPT + bool + prompt "shell script" + help + If your host has a shell, then you should say 'Y' here, to use + a (very very simple) shell script as wrapper. + + See docs/overview.txt, section "Tools wrapper". + +config TOOLS_WRAPPER_EXEC + bool + prompt "executable" + help + If your host lacks a shell, then you should say 'Y' here, to use + an executable. + + See docs/overview.txt, section "Tools wrapper". + +endchoice + +config TOOLS_WRAPPER + string + default "script" if TOOLS_WRAPPER_SCRIPT + default "exec" if TOOLS_WRAPPER_EXEC + +endif # CROSS_NATIVE || CANADIAN + endmenu diff --git a/docs/overview.txt b/docs/overview.txt index ed45d63..1176352 100644 --- a/docs/overview.txt +++ b/docs/overview.txt @@ -25,6 +25,7 @@ Running crosstool-NG Testing all toolchains at once Overriding the number of // jobs Note on // jobs + Tools wrapper Using the toolchain Toolchain types Internals @@ -382,6 +383,52 @@ in parallel (there is not much to gain). When speaking of // jobs, we are refering to the number of // jobs when making the *components*. That is, we speak of the number of // jobs used to build gcc, glibc, and so on... +Tools wrapper | +--------------+ + +Starting with gcc-4.3 come two new dependencies: GMP and MPFR. With gcc-4.4, +come three new ones: GMP, PPL and CLooG/ppl. These are libraries that enable +advanced features to gcc. Additionally, some of the libraries can be used by +binutils and gdb. Unfortunately, not all systems on which crosstool-NG runs +have all of those libraries. And for those that do, the versions of those +libraries may be older than the version required by gcc. + +This is why crosstool-NG builds its own set of libraries as part of the +toolchain. + +The libraries are built as shared libraries, because building them as static +libraries has some short-comings. This poses no problem at build time, as +crosstool-NG correctly points gcc (and binutiols and gdb) to the correct +place where our own version of the libraries are installed. But it poses +a problem when gcc et al. are run: the place where the libraries are is most +probably not known to the host dynamic linker. Still worse, if the host system +has its own versions, then ld.so would load the wrong library! + +So we have to force the dynamic linker to load the correct version. We do this +by using the LD_LIBRARY_PATH variable, that informs the dynamic linker where +to look for shared libraries prior to searching its standard places. But we +can't impose that burden on all the system (because it'd be a nightmare to +configure, and because two tolchains on the same system may use different +versions of the libraries); so we have to do it on a per-toolchain basis. + +So we rename all binaries of the toolchain (by adding a dot '.' as their first +character), and add a small program, the so-called "tools wrapper", that +correctly sets LD_LIBRARY_PATH prior to running the real tool. + +First, the wrapper was written as a POSIX-compliant shell script. That shell +script is very simple, if not trivial, and works great. The only drawback is +that it does not work on host systems that lack a shell, for example the +MingW32 environment. To solve the issue, the wrapper has been re-written in C, +and compiled at build time. This C wrapper is much more complex than the shell +script, and although it sems to be working, it's been only lightly tested. +Some of the expected short-comings with this C wrapper are; + - multi-byte file names may not be handled correctly + - it's really big for what it does + +So, the default wrapper installed with your toolchain is the shell script. +If you know that your system is missing a shell, then you shall use the C +wrapper (and report back whether it works, or does not work, for you). + _______________________ / diff --git a/scripts/build/internals.sh b/scripts/build/internals.sh index a920c50..cf869a1 100644 --- a/scripts/build/internals.sh +++ b/scripts/build/internals.sh @@ -46,9 +46,25 @@ do_finish() { CT_DoLog EXTRA "Installing toolchain wrappers" CT_Pushd "${CT_PREFIX_DIR}/bin" - # Copy the wrapper - CT_DoExecLog DEBUG install -m 0755 "${CT_LIB_DIR}/scripts/wrapper.in" \ - ".${CT_TARGET}-wrapper" + # Install the wrapper + case "${CT_TOOLS_WRAPPER}" in + script) + CT_DoExecLog DEBUG install \ + -m 0755 \ + "${CT_LIB_DIR}/scripts/wrapper.in" \ + ".${CT_TARGET}-wrapper" + ;; + exec) + _t="-s" + if [ "${CT_DEBUG_CT}" = "y" ]; then + _t="" # If debugging crosstool-NG, don't strip the wrapper + fi + CT_DoExecLog "${HOST_CC}" \ + -Wall -Wextra -Wunreachable-code -Werror \ + -O3 -static ${_t} \ + -o ".${CT_TARGET}-wrapper" + ;; + esac # Replace every tools with the wrapper # Do it unconditionally, even for those tools that happen to be shell -- cgit v0.10.2-6-g49f6