Commit 5cf36153 authored by David 'Digit' Turner's avatar David 'Digit' Turner
Browse files

Better host CPU detection for future 64-bit binaries

This patch improves the way we detect the host CPU architecture:

- It detects when we're running a 64-bit kernel with a 32-bit userland
  (and in this case, will default to using 32-bit binaries)

- It checks whether 64-bit binaries are available under
  $NDK/prebuilt/$HOST_TAG/bin/, and if not, it will default to
  32-bit binaries

- ndk-build: Ensure we use the prebuilt 'make' binary. This allows
  us to run the NDK on system where 'make' is not installed by default
  like Darwin without an XCode installation (another example is Windows
  but then ndk-build.cmd is used instead).

- ndk-build: Adds new log traces if NDK_LOG is defined to '1' or 'true'
  in either the environment or the command-line

- build/core/ndk-common.sh: this script is only used by the NDK development
  scripts under build/tools/. Update it to detect proper userland bitness.

Right now, we don't use/package 64-bit binaries yet, so this doesn't change
the NDK runtime, and only 32-bit programs will be used anyway.

NOTE: ndk-gdb was not modified yet to reflect this.

Change-Id: I3874a72398312dda61f63f337b20ce99075207b9
parent d27fd4be
......@@ -190,27 +190,9 @@ to_uppercase ()
echo $1 | tr "[:lower:]" "[:upper:]"
}
## Normalize OS and CPU
## First, we need to detect the HOST CPU, because proper HOST_ARCH detection
## requires platform-specific tricks.
##
HOST_ARCH=`uname -m`
case "$HOST_ARCH" in
i?86) HOST_ARCH=x86
;;
amd64) HOST_ARCH=x86_64
;;
powerpc) HOST_ARCH=ppc
;;
esac
log2 "HOST_ARCH=$HOST_ARCH"
# at this point, the supported values for CPU are:
# x86
# x86_64
# ppc
#
# other values may be possible but haven't been tested
#
HOST_EXE=""
HOST_OS=`uname -s`
case "$HOST_OS" in
......@@ -236,6 +218,49 @@ esac
log2 "HOST_OS=$HOST_OS"
log2 "HOST_EXE=$HOST_EXE"
## Now find the host architecture. This must correspond to the bitness of
## the binaries we're going to run with this NDK. Certain platforms allow
## you to use a 64-bit kernel with a 32-bit userland, and unfortunately
## commands like 'uname -m' only report the kernel bitness.
##
HOST_ARCH=`uname -m`
case "$HOST_ARCH" in
i?86) HOST_ARCH=x86
;;
amd64) HOST_ARCH=x86_64
;;
powerpc) HOST_ARCH=ppc
;;
esac
case "$HOST_OS-$HOST_ARCH" in
linux-x86_64|darwin-x86_64)
## On Linux or Darwin, a 64-bit kernel doesn't mean that the user-land
## is always 32-bit, so use "file" to determine the bitness of the shell
## that invoked us. The -L option is used to de-reference symlinks.
##
## Note that on Darwin, a single executable can contain both x86 and
## x86_64 machine code, so just look for x86_64 (darwin) or x86-64 (Linux)
## in the output.
##
file -L "$SHELL" | grep -q "x86[_-]64"
if [ $? != 0 ]; then
# $SHELL is not a 64-bit executable, so assume our userland is too.
log2 "Detected 32-bit userland on 64-bit kernel system!"
HOST_ARCH=x86
fi
;;
esac
log2 "HOST_ARCH=$HOST_ARCH"
# at this point, the supported values for HOST_ARCH are:
# x86
# x86_64
# ppc
#
# other values may be possible but haven't been tested
#
# at this point, the value of HOST_OS should be one of the following:
# linux
# darwin
......@@ -252,18 +277,21 @@ log2 "HOST_EXE=$HOST_EXE"
# linux-x86
# linux-x86_64
# darwin-x86
# darwin-x86_64
# darwin-ppc
# windows
# windows-x86_64
#
# other values are possible but were not tested.
#
compute_host_tag ()
{
case "$HOST_OS" in
windows|cygwin)
HOST_TAG=${HOST_OS}-${HOST_ARCH}
# Special case for windows-x86 => windows
case $HOST_TAG in
windows-x86|cygwin-x86)
HOST_TAG="windows"
;;
*) HOST_TAG="${HOST_OS}-${HOST_ARCH}"
esac
log2 "HOST_TAG=$HOST_TAG"
}
......@@ -322,11 +350,10 @@ force_32bit_binaries ()
#
disable_cygwin ()
{
if [ $OS = cygwin ] ; then
if [ $HOST_OS = cygwin ] ; then
log2 "Disabling cygwin binaries generation"
CFLAGS="$CFLAGS -mno-cygwin"
LDFLAGS="$LDFLAGS -mno-cygwin"
OS=windows
HOST_OS=windows
compute_host_tag
fi
......
......@@ -40,6 +40,90 @@
PROGDIR=`dirname $0`
PROGDIR=`cd $PROGDIR && pwd`
# If NDK_LOG is set to 1 or true in the environment, or the command-line
# then enable log messages below
if [ -z "$NDK_LOG" ]; then
NDK_LOG=0
fi
for opt; do
case $opt in
NDK_LOG=1|NDK_LOG=true)
NDK_LOG=1
;;
NDK_LOG=*)
NDK_LOG=0
;;
esac
done
if [ "$NDK_LOG" = "true" ]; then
NDK_LOG=1
fi
if [ "$NDK_LOG" = 1 ]; then
log () {
echo "$@"
}
else
log () {
: # nothing
}
fi
# Detect host operating system and architecture
# The 64-bit / 32-bit distinction gets tricky on Linux and Darwin because
# uname -m returns the kernel's bit size, and it's possible to run with
# a 64-bit kernel and a 32-bit userland.
#
HOST_OS=$(uname -s)
case $HOST_OS in
Darwin) HOST_OS=darwin;;
Linux) HOST_OS=linux;;
FreeBsd) HOST_OS=freebsd;;
CYGWIN*|*_NT-*) HOST_OS=cygwin;;
*) echo "ERROR: Unknown host operating system: $HOST_OS"
exit 1
esac
log "HOST_OS=$HOST_OS"
HOST_ARCH=$(uname -m)
case $HOST_ARCH in
i?86) HOST_ARCH=x86;;
x86_64|amd64) HOST_ARCH=x86_64;;
*) echo "ERROR: Unknown host CPU architecture: $HOST_ARCH"
exit 1
esac
log "HOST_ARCH=$HOST_ARCH"
# Detect 32-bit userland on 64-bit kernels
HOST_TAG="$HOST_OS-$HOST_ARCH"
case $HOST_TAG in
linux-x86_64|darwin-x86_64)
# we look for x86_64 or x86-64 in the output of 'file' for our shell
# the -L flag is used to dereference symlinks, just in case.
file -L "$SHELL" | grep -q "x86[_-]64"
if [ $? != 0 ]; then
HOST_ARCH=x86
HOST_TAG=$HOST_OS-x86
log "HOST_ARCH=$HOST_ARCH (32-bit userland detected)"
fi
;;
windows-x86) # Special case windows-x86 -> windows
HOST_TAG=windows
esac
# Check that we have 64-bit binaries on 64-bit system, otherwise fallback
# on 32-bit ones. This gives us more freedom in packaging the NDK.
if [ $HOST_ARCH = x86_64 -a ! -d $PROGDIR/prebuilt/$HOST_TAG ]; then
HOST_TAG=$HOST_OS-x86
if [ $HOST_TAG = windows-x86 ]; then
HOST_TAG=windows
fi
log "HOST_TAG=$HOST_TAG (no 64-bit prebuilt binaries detected)"
else
log "HOST_TAG=$HOST_TAG"
fi
# If GNUMAKE is defined, check that it points to a valid file
if [ -n "$GNUMAKE" ] ; then
ABS_GNUMAKE=`which $GNUMAKE 2> /dev/null`
......@@ -49,19 +133,30 @@ if [ -n "$GNUMAKE" ] ; then
exit 1
fi
GNUMAKE="$ABS_GNUMAKE"
log "GNUMAKE=$GNUMAKE (from environment variable)"
else
# Otherwise, use 'make' and check that it is available
GNUMAKE=`which make 2> /dev/null`
if [ $? != 0 ] ; then
echo "ERROR: Cannot find 'make' program. Please install Cygwin make package"
echo "or define the GNUMAKE variable to point to it."
exit 1
# Otherwise use the prebuilt version for our host tag, if it exists
# Note: we intentionally do not provide prebuilt make binaries for Cygwin
# or MSys.
GNUMAKE=$PROGDIR/prebuilt/$HOST_TAG/bin/make
if [ ! -f "$GNUMAKE" ]; then
# Otherwise, use 'make' and check that it is available
GNUMAKE=`which make 2> /dev/null`
if [ $? != 0 ] ; then
echo "ERROR: Cannot find 'make' program. Please install Cygwin make package"
echo "or define the GNUMAKE variable to point to it."
exit 1
fi
log "GNUMAKE=$GNUMAKE (system path)"
else
log "GNUMAKE=$GNUMAKE (NDK prebuilt)"
fi
fi
# On Windows, when running under cygwin, check that we are
# invoking a cygwin-compatible GNU Make binary. It is unfortunately
# common for app developers to have another non-cygwin compatible
# common for app developers to have another non cygwin-compatible
# 'make' program in their PATH.
#
if [ "$OSTYPE" = "cygwin" ] ; then
GNUMAKE=`cygpath -u $GNUMAKE`
......@@ -84,6 +179,7 @@ if [ "$OSTYPE" = "cygwin" ] ; then
echo ""
exit 1
fi
log "Cygwin-compatible GNU make detected"
fi
$GNUMAKE -f $PROGDIR/build/core/build-local.mk "$@"
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment