aboutsummaryrefslogtreecommitdiff
path: root/ndk-build
blob: 62d6dc8c4779d69dbfbd16fdefc7800469561aab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
#!/bin/sh
#
# Copyright (C) 2010 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#  This shell script is a wrapper to launch the NDK build from the
#  command-line inside an application project path.
#
#  Typical usage is:
#
#     cd $PROJECT_PATH
#     ndk-build
#
#  Assuming that the Android NDK root path is in your PATH. However,
#  you can also invoke it directly as:
#
#     $NDK_ROOT/ndk-build
#
#  This really is a tiny wrapper around GNU Make.
#

# Ensure we get the full path of this script's directory
# this is needed if the caller uses the -C <path> GNU Make
# option, as in:
#
#    cd ndk
#    ./ndk-build -C <project-path>
#
PROGDIR=`dirname $0`
PROGDIR=`cd $PROGDIR && pwd -P`

# Check if absolute NDK path contain space
#
case $PROGDIR in
    *\ *) echo "ERROR: NDK path cannot contain space"
          exit 1
        ;;
esac

# If NDK_LOG is set to 1 or true in the environment, or the command-line
# then enable log messages below
# Also normalize NDK_HOST_32BIT and NDK_ANALYZE to 1 or 0
if [ -z "$NDK_LOG" ]; then
  NDK_LOG=0
fi

if [ -z "$NDK_HOST_32BIT" ]; then
  NDK_HOST_32BIT=0
fi

if [ -z "$NDK_ANALYZE" ]; then
  NDK_ANALYZE=0
fi

PROJECT_PATH=
PROJECT_PATH_NEXT=
for opt; do
    if [ -z "$PROJECT_PATH" -a "$PROJECT_PATH_NEXT" = "yes" ] ; then
        PROJECT_PATH=$opt
        PROJECT_PATH_NEXT=
    else
        case $opt in
          NDK_LOG=1|NDK_LOG=true)
            NDK_LOG=1
            ;;
          NDK_LOG=*)
            NDK_LOG=0
            ;;
          NDK_HOST_32BIT=1|NDK_HOST_32BIT=true)
            NDK_HOST_32BIT=1
            ;;
          NDK_HOST_32BIT=*)
            NDK_HOST_32BIT=0
            ;;
          NDK_ANALYZE=1|NDK_ANALYZE=true)
            NDK_ANALYZE=1
            ;;
          NDK_ANALYZE=*)
            NDK_ANALYZE=0
            ;;
          NDK_TOOLCHAIN_VERSION=*)
            NDK_TOOLCHAIN_VERSION=${opt#NDK_TOOLCHAIN_VERSION=}
            ;;
          APP_ABI=*)
            APP_ABI=${opt#APP_ABI=}
            ;;
          -C)
            PROJECT_PATH_NEXT="yes"
            ;;
        esac
    fi
done

if [ "$NDK_LOG" = "true" ]; then
  NDK_LOG=1
fi

if [ "$NDK_HOST_32BIT" = "true" ]; then
  NDK_HOST_32BIT=1
fi

if [ "$NDK_ANALYZE" = "true" ]; then
  NDK_ANALYZE=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
      log "HOST_ARCH=$HOST_ARCH (32-bit userland detected)"
    fi
    ;;
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.
LOG_MESSAGE=
if [ $HOST_ARCH = x86_64 ]; then
  if [ ! -d $PROGDIR/prebuilt/$HOST_TAG ]; then
    HOST_ARCH=x86
    LOG_MESSAGE="(no 64-bit prebuilt binaries detected)"
  fi

  if [ "$NDK_HOST_32BIT" = "1" ]; then
    HOST_ARCH=x86
    LOG_MESSAGE="(force 32-bit host toolchain)"
  fi
fi

HOST_TAG=$HOST_OS-$HOST_ARCH
# Special case windows-x86 -> windows
if [ $HOST_TAG = windows-x86 ]; then
  HOST_TAG=windows
fi
log "HOST_TAG=$HOST_TAG $LOG_MESSAGE"

# If GNUMAKE is defined, check that it points to a valid file
if [ -n "$GNUMAKE" ] ; then
    ABS_GNUMAKE=`which $GNUMAKE 2> /dev/null`
    if [ $? != 0 ] ; then
        echo "ERROR: Your GNUMAKE variable is defined to an invalid name: $GNUMAKE"
        echo "Please fix it to point to a valid make executable (e.g. /usr/bin/make)"
        exit 1
    fi
    GNUMAKE="$ABS_GNUMAKE"
    log "GNUMAKE=$GNUMAKE (from environment variable)"
else
    # 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
# 'make' program in their PATH.
#
if [ "$OSTYPE" = "cygwin" ] ; then
    GNUMAKE=`cygpath -u $GNUMAKE`
    PROGDIR_MIXED=`cygpath -m $PROGDIR`
    CYGWIN_GNUMAKE=`$GNUMAKE -f "$PROGDIR_MIXED/build/core/check-cygwin-make.mk" 2>&1`
    if [ $? != 0 ] ; then
        echo "ERROR: You are using a non-Cygwin compatible Make program."
        echo "Currently using: `cygpath -m $GNUMAKE`"
        echo ""
        echo "To solve the issue, follow these steps:"
        echo ""
        echo "1. Ensure that the Cygwin 'make' package is installed."
        echo "   NOTE: You will need GNU Make 3.81 or later!"
        echo ""
        echo "2. Define the GNUMAKE environment variable to point to it, as in:"
        echo ""
        echo "     export GNUMAKE=/usr/bin/make"
        echo ""
        echo "3. Call 'ndk-build' again."
        echo ""
        exit 1
    fi
    log "Cygwin-compatible GNU make detected"
fi

if [ "$NDK_ANALYZE" = 1 ]; then
    . $PROGDIR/build/tools/dev-defaults.sh  # for DEFAULT_LLVM_VERSION

    # Find perl.  If HOST_PERL is defined, check that it points to a valid file
    HOST_PERL_LIB=
    if [ -n "$HOST_PERL" ] ; then
        ABS_PERL=`which $HOST_PERL 2> /dev/null`
        if [ $? != 0 ] ; then
            echo "ERROR: Your HOST_PERL variable is defined to an invalid name: $HOST_PERL"
            echo "Please fix it to point to a valid perl executable (e.g. /usr/bin/perl)"
            exit 1
        fi
        HOST_PERL="$ABS_PERL"
        log "HOST_PERL=$HOST_PERL (from environment variable)"
    else
        # Otherwise use the prebuilt version for our host tag
        HOST_PERL="$PROGDIR/prebuilt/$HOST_TAG/bin/perl"
        if [ ! -f "$HOST_PERL" ]; then
            # Otherwise, use 'perl' and check that it is available
            HOST_PERL=`which perl 2> /dev/null`
            if [ $? != 0 ] ; then
                echo "ERROR: Cannot find 'perl' program. Please install perl package"
                echo "or define the HOST_PERL variable to point to it."
                exit 1
            fi
            log "HOST_PERL=$HOST_PERL (system path)"
        else
            HOST_PERL_LIB="$PROGDIR/prebuilt/$HOST_TAG/lib/perl5"
            log "HOST_PERL=$HOST_PERL (NDK prebuilt)"
        fi
    fi

    # Return flags send in env. or command line which are enough to retrive APP_ABI and TOOLCHAIN_PREFIX later
    gen_flags ()
    {
        local FLAGS=

        if [ -n "$PROJECT_PATH" ] ; then
            FLAGS=$FLAGS" -C $PROJECT_PATH"
        fi
        if [ -n "$APP_ABI" ] ; then
            FLAGS=$FLAGS" APP_ABI=$APP_ABI"
        fi
        if [ -n "$NDK_HOST_32BIT" ] ; then
            FLAGS=$FLAGS" NDK_HOST_32BIT=$NDK_HOST_32BIT"
        fi
        if [ -n "$NDK_TOOLCHAIN_VERSION" ] ; then
            FLAGS=$FLAGS" NDK_TOOLCHAIN_VERSION=$NDK_TOOLCHAIN_VERSION"
        fi
        echo "$FLAGS"
    }

    get_build_var ()
    {
        local VAR=$1
        local FLAGS=`gen_flags`
        $GNUMAKE --no-print-dir -f $PROGDIR/build/core/build-local.mk $FLAGS DUMP_${VAR} | tail -1
    }

    get_build_var_for_abi ()
    {
        local VAR=$1
        local ABI=$2
        local FLAGS=`gen_flags`
        $GNUMAKE --no-print-dir -f $PROGDIR/build/core/build-local.mk $FLAGS DUMP_${VAR} APP_ABI=${ABI} | tail -1
    }

    APP_ABIS=`get_build_var APP_ABI`
    for ABI in $APP_ABIS; do
        TOOLCHAIN_PREFIX=`get_build_var_for_abi TOOLCHAIN_PREFIX $ABI`
        PERL5LIB="$HOST_PERL_LIB" "$HOST_PERL" $PROGDIR/prebuilt/common/scan-build/scan-build \
            --use-analyzer $PROGDIR/toolchains/llvm-${DEFAULT_LLVM_VERSION}/prebuilt/$HOST_TAG/bin/${ABI}/analyzer \
            --use-cc ${TOOLCHAIN_PREFIX}gcc \
            --use-c++ ${TOOLCHAIN_PREFIX}g++ \
            --status-bugs \
            $GNUMAKE -f $PROGDIR/build/core/build-local.mk "$@" APP_ABI=$ABI
    done
else
    $GNUMAKE -f $PROGDIR/build/core/build-local.mk "$@"
fi