NSLU2-Linux
view · edit · print · history

GentooSlug.DistccCrossCompileFixupScript History

Hide minor edits - Show changes to markup

July 09, 2006, at 09:32 AM by Kevin Harris --
Changed line 4 from:
  1. fixup_distcc.sh by Kevin Harris (kpharris at sourceforge dot net) 20060709
to:
  1. fixup_distcc.sh by Kevin Harris (kpharris at users dot sourceforge dot net) 20060709
July 09, 2006, at 09:28 AM by Kevin Harris -- distcc symlink fixup (creation) script for distributed cross compiles
Added lines 1-217:
#!/bin/sh

# fixup_distcc.sh by Kevin Harris (kpharris at sourceforge dot net) 20060709
#
# Create links (normally to fix an existing distcc install) so distributed
# cross compiles are executed with the proper compiler.
#
# This was originally intended to be a simple script, but use on several
# platforms and oddly named cross compilers forced this to be somewhat more
# complex.
#
# Normally, you'd just compile something with 'gcc'.  If distcc invokes the
# remote compiler as 'gcc', it will have undesired effects.


set -u
set -e

distcc_binary_location=
gcc_arch_string=
compiler_suffix=
target_directory=

locate_distcc()
{
	if which distcc >/dev/null 2>&1; then
		distcc_binary_location=`which distcc`
		echo "Your distcc is located in ${distcc_binary_location} ..."
	else
		echo "Where is your distcc?  It does not seem to be in your path." >&2
		return 1
	fi
}

determine_gcc_arch()
{
	if gcc -v 2>&1 | grep -q target=; then
		gcc_arch_string=`gcc -v 2>&1 | grep 'target=' | sed 's/.*--target=\([^ ]*\).*/\1/g'`
	elif gcc -v 2>&1 | grep -q host=; then
		gcc_arch_string=`gcc -v 2>&1 | grep 'host=' | sed 's/.*--host=\([^ ]*\).*/\1/g'`
	else
		echo "I can't guess your gcc arch.  Fix this script." >&2
		return 1
	fi

	echo "Your gcc target appears to be ${gcc_arch_string} ..."
}

verify_arch_and_suffix()
{
	if ${gcc_arch_string}-gcc${compiler_suffix} --version >/dev/null 2>&1; then
		echo "${gcc_arch_string}-gcc${compiler_suffix} seems to work."
	else
		echo "Cannot execute ${gcc_arch_string}-gcc${compiler_suffix} --version" >&2
		echo "Does your compiler need a suffix?" >&2
		exit 1
	fi
}

setup_distcc_links()
{
	# This function creates:
	# * A wrapper script to ensure distcc is invoked with the full name to the
	#   compiler (otherwise a distributed cross compile would not function
	#   properly).
	# * Links for <arch>-{gcc,g++} to the distcc binary.
	# * Links for <arch>-{cc,c++}, cc, c++, gcc, and g++ to the wrapper script.
	if [ ! -d ${target_directory} ]; then
		echo "WARNING: ${target_directory} does not exist.  Creating." >&2
		mkdir -p ${target_directory}
	fi

	echo "Creating compiler wrapper script in ${target_directory} ..."
	wrapper_script=${target_directory}/${gcc_arch_string}-wrapper
	wrapper_cc_line=""
	cat > ${wrapper_script} <<EOF
#!/bin/sh
if [ "\${0%-wrapper}" != "\$0" ]; then
	echo "This script (\$0) must be executed through a symlink." >&2
	exit 1
fi

# This case statement will execute the arch specific gcc or g++.

# Note that it does execute gcc for "cc" and g++ for "c++".  This is
# intentional, as some installations of gcc do not seem to create the
# <arch>-{cc,c++} executables.
case \${0%-wrapper} in
 	*gcc | *cc | *gcc${compiler_suffix} | *cc${compiler_suffix})
 		exec ${target_directory}/${gcc_arch_string}-gcc${compiler_suffix} "\$@"
 		;;
 	*g++ | *c++ | *g++${compiler_suffix} | *c++${compiler_suffix})
 		exec ${target_directory}/${gcc_arch_string}-g++${compiler_suffix} "\$@"
 		;;
	*)
		echo "Cannot wrap unknown compiler \${0%-wrapper}" >&2
		exit 1
		;;
esac
EOF

	chmod +x ${wrapper_script}

	# These lists must be space (not tab) separated.  They are only here for readability.
	compiler_list="cc gcc c++ g++"
	distcc_compilers="gcc g++"
	needs_distcc_link()
	{
		distcc_protect_list=" ${distcc_compilers} "
		if [ "${distcc_protect_list% $1 *}" != "${distcc_protect_list}" ]; then
			return 0 # Yes, this entry is in the distcc list.
		else
			return 1
		fi
	}

	echo "Installing symlinks in ${target_directory} ..."
	for compiler in ${compiler_list}; do
		for prefix in "" ${gcc_arch_string}-; do
			for suffix in "" ${compiler_suffix}; do
				compiler_name=${prefix}${compiler}${suffix}
				rm -f ${target_directory}/${compiler_name}
				protect_list=" ${distcc_compilers} "
				# <arch>-{gcc,g++} must be links to distcc and not the wrapper.
				if [ -n "${prefix}" ] && needs_distcc_link ${compiler}; then
					echo "Creating distcc link for ${compiler_name} ..."
					ln -s ${distcc_binary_location} ${target_directory}/${compiler_name}
				else
					echo "Creating wrapper link for ${compiler_name} ..."
					ln -s ${wrapper_script} ${target_directory}/${compiler_name}
				fi
			done
		done
	done

	echo
	echo "###############################################################################"
	echo "To use distcc, add your chosen directory (${target_directory})"
	echo "to the front of your \$PATH (after ccache, if you are using it)."
	echo "###############################################################################"
}

usage()
{
	echo "Usage: $0 [-s <suffix>] [-a <arch string>] -d <target_directory>"
	echo "  -d: *REQUIRED* Specifies the target directory for the generated symlinks."
	echo "      For gentoo users this would normally be /usr/lib/distcc/bin"
	echo "  -s: Specifies a suffix to be appended to the compiler names"
	echo "  -a: Specifies an architecture string to use, overriding what would be"
	echo "      automatically determined by running gcc."
	echo "  -h: Display this help"
}

process_command_line()
{
	verify_args()
	{
		if [ $# -lt 3 ]; then
			echo "Argument required for $1 option $2" >&2
			exit 1
		fi
	}
	while [ $# -gt 0 ]; do
		case $1 in
			-s)
				 verify_args "compiler suffix" "$@"
				 compiler_suffix=$2
				 shift
				 ;;
			-d)
				 verify_args "target directory" "$@"
				 target_directory=$2
				 shift
				 ;;
			-a)
				 verify_args "architecture string" "$@"
				 gcc_arch_string=$2
				 shift
				 ;;
			-h)
				 usage
				 exit 0
				 ;;
			--)
				 ;;
			*)
				 echo "Invalid option: $1" >&2
				 usage >&2
				 exit 1
				 ;;
		esac
		shift
	done
	if [ x${target_directory:+set} != xset ]; then
		echo "No target directory specified." >&2
		usage >&2
		exit 1
	fi
}

main()
{
	process_command_line "$@"
	if [ x${gcc_arch_string:+set} = xset ]; then
		echo "Not guessing the gcc architecture string.  Using specified value: ${gcc_arch_string}"
	else
		determine_gcc_arch
	fi
	verify_arch_and_suffix
	locate_distcc
	setup_distcc_links
}

main "$@"

view · edit · print · history · Last edited by Kevin Harris.
Originally by Kevin Harris.
Page last modified on July 09, 2006, at 09:32 AM