• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (C) 2009-2010 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#      http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14#
15
16# Initialization of the NDK build system. This file is included by
17# several build scripts.
18#
19
20# Disable GNU Make implicit rules
21
22# this turns off the suffix rules built into make
23.SUFFIXES:
24
25# this turns off the RCS / SCCS implicit rules of GNU Make
26% : RCS/%,v
27% : RCS/%
28% : %,v
29% : s.%
30% : SCCS/s.%
31
32# If a rule fails, delete $@.
33.DELETE_ON_ERROR:
34
35
36# Define NDK_LOG in your environment to display log traces when
37# using the build scripts. See also the definition of ndk_log below.
38#
39NDK_LOG := $(strip $(NDK_LOG))
40
41# Check that we have at least GNU Make 3.81
42# We do this by detecting whether 'lastword' is supported
43#
44MAKE_TEST := $(lastword a b c d e f)
45ifneq ($(MAKE_TEST),f)
46    $(error Android NDK: GNU Make version $(MAKE_VERSION) is too low (should be >= 3.81))
47endif
48ifdef NDK_LOG
49    $(info Android NDK: GNU Make version $(MAKE_VERSION) detected)
50endif
51
52# NDK_ROOT *must* be defined and point to the root of the NDK installation
53NDK_ROOT := $(strip $(NDK_ROOT))
54ifndef NDK_ROOT
55    $(error ERROR while including init.mk: NDK_ROOT must be defined !)
56endif
57ifneq ($(words $(NDK_ROOT)),1)
58    $(info,The Android NDK installation path contains spaces: '$(NDK_ROOT)')
59    $(error,Please fix the problem by reinstalling to a different location.)
60endif
61
62# ====================================================================
63#
64# Define a few useful variables and functions.
65# More stuff will follow in definitions.mk.
66#
67# ====================================================================
68
69# Used to output warnings and error from the library, it's possible to
70# disable any warnings or errors by overriding these definitions
71# manually or by setting NDK_NO_WARNINGS or NDK_NO_ERRORS
72
73__ndk_name    := Android NDK
74__ndk_info     = $(info $(__ndk_name): $1 $2 $3 $4 $5)
75__ndk_warning  = $(warning $(__ndk_name): $1 $2 $3 $4 $5)
76__ndk_error    = $(error $(__ndk_name): $1 $2 $3 $4 $5)
77
78ifdef NDK_NO_WARNINGS
79__ndk_warning :=
80endif
81ifdef NDK_NO_ERRORS
82__ndk_error :=
83endif
84
85# -----------------------------------------------------------------------------
86# Function : ndk_log
87# Arguments: 1: text to print when NDK_LOG is defined
88# Returns  : None
89# Usage    : $(call ndk_log,<some text>)
90# -----------------------------------------------------------------------------
91ifdef NDK_LOG
92ndk_log = $(info $(__ndk_name): $1)
93else
94ndk_log :=
95endif
96
97# ====================================================================
98#
99# Host system auto-detection.
100#
101# ====================================================================
102
103#
104# Determine host system and architecture from the environment
105#
106HOST_OS := $(strip $(HOST_OS))
107ifndef HOST_OS
108    # On all modern variants of Windows (including Cygwin and Wine)
109    # the OS environment variable is defined to 'Windows_NT'
110    #
111    # The value of PROCESSOR_ARCHITECTURE will be x86 or AMD64
112    #
113    ifeq ($(OS),Windows_NT)
114        HOST_OS := windows
115    else
116        # For other systems, use the `uname` output
117        UNAME := $(shell uname -s)
118        ifneq (,$(findstring Linux,$(UNAME)))
119            HOST_OS := linux
120        endif
121        ifneq (,$(findstring Darwin,$(UNAME)))
122            HOST_OS := darwin
123        endif
124        # We should not be there, but just in case !
125        ifneq (,$(findstring CYGWIN,$(UNAME)))
126            HOST_OS := windows
127        endif
128        ifeq ($(HOST_OS),)
129            $(call __ndk_info,Unable to determine HOST_OS from uname -s: $(UNAME))
130            $(call __ndk_info,Please define HOST_OS in your environment.)
131            $(call __ndk_error,Aborting.)
132        endif
133    endif
134    $(call ndk_log,Host OS was auto-detected: $(HOST_OS))
135else
136    $(call ndk_log,Host OS from environment: $(HOST_OS))
137endif
138
139# For all systems, we will have HOST_OS_BASE defined as
140# $(HOST_OS), except on Cygwin where we will have:
141#
142#  HOST_OS      == cygwin
143#  HOST_OS_BASE == windows
144#
145# Trying to detect that we're running from Cygwin is tricky
146# because we can't use $(OSTYPE): It's a Bash shell variable
147# that is not exported to sub-processes, and isn't defined by
148# other shells (for those with really weird setups).
149#
150# Instead, we assume that a program named /bin/uname.exe
151# that can be invoked and returns a valid value corresponds
152# to a Cygwin installation.
153#
154HOST_OS_BASE := $(HOST_OS)
155
156ifeq ($(HOST_OS),windows)
157    ifneq (,$(strip $(wildcard /bin/uname.exe)))
158        $(call ndk_log,Found /bin/uname.exe on Windows host, checking for Cygwin)
159        # NOTE: The 2>NUL here is for the case where we're running inside the
160        #       native Windows shell. On cygwin, this will create an empty NUL file
161        #       that we're going to remove later (see below).
162        UNAME := $(shell /bin/uname.exe -s 2>NUL)
163        $(call ndk_log,uname -s returned: $(UNAME))
164        ifneq (,$(filter CYGWIN%,$(UNAME)))
165            $(call ndk_log,Cygwin detected: $(shell uname -a))
166            HOST_OS := cygwin
167            DUMMY := $(shell rm -f NUL) # Cleaning up
168        else
169            ifneq (,$(filter MINGW32%,$(UNAME)))
170                $(call ndk_log,MSys detected: $(shell uname -a))
171                HOST_OS := cygwin
172            else
173                $(call ndk_log,Cygwin *not* detected!)
174            endif
175        endif
176    endif
177endif
178
179ifneq ($(HOST_OS),$(HOST_OS_BASE))
180    $(call ndk_log, Host operating system detected: $(HOST_OS), base OS: $(HOST_OS_BASE))
181else
182    $(call ndk_log, Host operating system detected: $(HOST_OS))
183endif
184
185HOST_ARCH := $(strip $(HOST_ARCH))
186ifndef HOST_ARCH
187    ifeq ($(HOST_OS_BASE),windows)
188        HOST_ARCH := $(PROCESSOR_ARCHITECTURE)
189        ifeq ($(HOST_ARCH),AMD64)
190            HOST_ARCH := x86
191        endif
192    else # HOST_OS_BASE != windows
193        UNAME := $(shell uname -m)
194        ifneq (,$(findstring 86,$(UNAME)))
195            HOST_ARCH := x86
196        endif
197        # We should probably should not care at all
198        ifneq (,$(findstring Power,$(UNAME)))
199            HOST_ARCH := ppc
200        endif
201        ifeq ($(HOST_ARCH),)
202            $(call __ndk_info,Unsupported host architecture: $(UNAME))
203            $(call __ndk_error,Aborting)
204        endif
205    endif # HOST_OS_BASE != windows
206    $(call ndk_log,Host CPU was auto-detected: $(HOST_ARCH))
207else
208    $(call ndk_log,Host CPU from environment: $(HOST_ARCH))
209endif
210
211HOST_TAG := $(HOST_OS_BASE)-$(HOST_ARCH)
212
213# The directory separator used on this host
214HOST_DIRSEP := :
215ifeq ($(HOST_OS),windows)
216  HOST_DIRSEP := ;
217endif
218
219# The host executable extension
220HOST_EXEEXT :=
221ifeq ($(HOST_OS),windows)
222  HOST_EXEEXT := .exe
223endif
224
225# If we are on Windows, we need to check that we are not running
226# Cygwin 1.5, which is deprecated and won't run our toolchain
227# binaries properly.
228#
229ifeq ($(HOST_TAG),windows-x86)
230    ifeq ($(HOST_OS),cygwin)
231        # On cygwin, 'uname -r' returns something like 1.5.23(0.225/5/3)
232        # We recognize 1.5. as the prefix to look for then.
233        CYGWIN_VERSION := $(shell uname -r)
234        ifneq ($(filter XX1.5.%,XX$(CYGWIN_VERSION)),)
235            $(call __ndk_info,You seem to be running Cygwin 1.5, which is not supported.)
236            $(call __ndk_info,Please upgrade to Cygwin 1.7 or higher.)
237            $(call __ndk_error,Aborting.)
238        endif
239    endif
240    # special-case the host-tag
241    HOST_TAG := windows
242endif
243
244$(call ndk_log,HOST_TAG set to $(HOST_TAG))
245
246# Check for NDK-specific versions of our host tools
247HOST_PREBUILT := $(strip $(wildcard $(NDK_ROOT)/prebuilt/$(HOST_TAG)/bin))
248ifdef HOST_PREBUILT
249    $(call ndk_log,Host tools prebuilt directory: $(HOST_PREBUILT))
250    # The windows prebuilt binaries are for ndk-build.cmd
251    # On cygwin, we must use the Cygwin version of these tools instead.
252    ifneq ($(HOST_OS),cygwin)
253        HOST_AWK := $(wildcard $(HOST_PREBUILT)/awk$(HOST_EXEEXT))
254        HOST_SED  := $(wildcard $(HOST_PREBUILT)/sed$(HOST_EXEEXT))
255        HOST_MAKE := $(wildcard $(HOST_PREBUILT)/make$(HOST_EXEEXT))
256    endif
257else
258    $(call ndk_log,Host tols prebuilt directory not found, using system tools)
259endif
260
261HOST_ECHO := $(strip $(HOST_ECHO))
262ifndef HOST_ECHO
263    HOST_ECHO := $(strip $(wildcard $(NDK_ROOT)/prebuilt/$(HOST_TAG)/bin/echo$(HOST_EXEEXT)))
264endif
265ifndef HOST_ECHO
266    HOST_ECHO := echo
267endif
268$(call ndk_log,Host 'echo' tool: $(HOST_ECHO))
269
270#
271# Verify that the 'awk' tool has the features we need.
272# Both Nawk and Gawk do.
273#
274HOST_AWK := $(strip $(HOST_AWK))
275ifndef HOST_AWK
276    HOST_AWK := awk
277endif
278$(call ndk_log,Host 'awk' tool: $(HOST_AWK))
279
280# Location of all awk scripts we use
281BUILD_AWK := $(NDK_ROOT)/build/awk
282
283AWK_TEST := $(shell $(HOST_AWK) -f $(BUILD_AWK)/check-awk.awk)
284$(call ndk_log,Host 'awk' test returned: $(AWK_TEST))
285ifneq ($(AWK_TEST),Pass)
286    $(call __ndk_info,Host 'awk' tool is outdated. Please define HOST_AWK to point to Gawk or Nawk !)
287    $(call __ndk_error,Aborting.)
288endif
289
290#
291# On Cygwin, define the 'cygwin-to-host-path' function here depending on the
292# environment. The rules are the following:
293#
294# 1/ If "cygpath' is not in your path, do not use it at all. It looks like
295#    this allows to build with the NDK from MSys without problems.
296#
297# 2/ Since invoking 'cygpath -m' from GNU Make for each source file is
298#    _very_ slow, try to generate a Make function that performs the mapping
299#    from cygwin to host paths through simple substitutions.
300#
301# 3/ In case we fail horribly, allow the user to define NDK_USE_CYGPATH to '1'
302#    in order to use 'cygpath -m' nonetheless. This is only a backup plan in
303#    case our automatic substitution function doesn't work (only likely if you
304#    have a very weird cygwin setup).
305#
306# The function for 2/ is generated by an awk script. It's really a series
307# of nested patsubst calls, that look like:
308#
309#     cygwin-to-host-path = $(patsubst /cygdrive/c/%,c:/%,\
310#                             $(patsusbt /cygdrive/d/%,d:/%, \
311#                              $1)
312#
313# except that the actual definition is built from the list of mounted
314# drives as reported by "mount" and deals with drive letter cases (i.e.
315# '/cygdrive/c' and '/cygdrive/C')
316#
317ifeq ($(HOST_OS),cygwin)
318    CYGPATH := $(strip $(HOST_CYGPATH))
319    ifndef CYGPATH
320        $(call ndk_log, Probing for 'cygpath' program)
321        CYGPATH := $(strip $(shell which cygpath 2>/dev/null))
322        ifndef CYGPATH
323            $(call ndk_log, 'cygpath' was *not* found in your path)
324        else
325            $(call ndk_log, 'cygpath' found as: $(CYGPATH))
326        endif
327    endif
328    ifndef CYGPATH
329        cygwin-to-host-path = $1
330    else
331        ifeq ($(NDK_USE_CYGPATH),1)
332            $(call ndk_log, Forced usage of 'cygpath -m' through NDK_USE_CYGPATH=1)
333            cygwin-to-host-path = $(strip $(shell $(CYGPATH) -m $1))
334        else
335            # Call an awk script to generate a Makefile fragment used to define a function
336            WINDOWS_HOST_PATH_FRAGMENT := $(shell mount | $(HOST_AWK) -f $(BUILD_AWK)/gen-windows-host-path.awk)
337            ifeq ($(NDK_LOG),1)
338                $(info Using cygwin substitution rules:)
339                $(eval $(shell mount | $(HOST_AWK) -f $(BUILD_AWK)/gen-windows-host-path.awk -vVERBOSE=1))
340            endif
341            $(eval cygwin-to-host-path = $(WINDOWS_HOST_PATH_FRAGMENT))
342        endif
343    endif
344endif # HOST_OS == cygwin
345
346# The location of the build system files
347BUILD_SYSTEM := $(NDK_ROOT)/build/core
348
349# Include common definitions
350include $(BUILD_SYSTEM)/definitions.mk
351
352# ====================================================================
353#
354# Read all toolchain-specific configuration files.
355#
356# Each toolchain must have a corresponding config.mk file located
357# in build/toolchains/<name>/ that will be included here.
358#
359# Each one of these files should define the following variables:
360#   TOOLCHAIN_NAME   toolchain name (e.g. arm-linux-androideabi-4.4.3)
361#   TOOLCHAIN_ABIS   list of target ABIs supported by the toolchain.
362#
363# Then, it should include $(ADD_TOOLCHAIN) which will perform
364# book-keeping for the build system.
365#
366# ====================================================================
367
368# the build script to include in each toolchain config.mk
369ADD_TOOLCHAIN := $(BUILD_SYSTEM)/add-toolchain.mk
370
371# the list of all toolchains in this NDK
372NDK_ALL_TOOLCHAINS :=
373NDK_ALL_ABIS       :=
374NDK_ALL_ARCHS      :=
375
376TOOLCHAIN_CONFIGS := $(wildcard $(NDK_ROOT)/toolchains/*/config.mk)
377$(foreach _config_mk,$(TOOLCHAIN_CONFIGS),\
378  $(eval include $(BUILD_SYSTEM)/add-toolchain.mk)\
379)
380
381NDK_ALL_TOOLCHAINS   := $(sort $(NDK_ALL_TOOLCHAINS))
382NDK_ALL_ABIS         := $(sort $(NDK_ALL_ABIS))
383NDK_ALL_ARCHS        := $(sort $(NDK_ALL_ARCHS))
384
385# Check that each ABI has a single architecture definition
386$(foreach _abi,$(strip $(NDK_ALL_ABIS)),\
387  $(if $(filter-out 1,$(words $(NDK_ABI.$(_abi).arch))),\
388    $(call __ndk_info,INTERNAL ERROR: The $(_abi) ABI should have exactly one architecture definitions. Found: '$(NDK_ABI.$(_abi).arch)')\
389    $(call __ndk_error,Aborting...)\
390  )\
391)
392
393# Allow the user to define NDK_TOOLCHAIN to a custom toolchain name.
394# This is normally used when the NDK release comes with several toolchains
395# for the same architecture (generally for backwards-compatibility).
396#
397NDK_TOOLCHAIN := $(strip $(NDK_TOOLCHAIN))
398ifdef NDK_TOOLCHAIN
399    # check that the toolchain name is supported
400    $(if $(filter-out $(NDK_ALL_TOOLCHAINS),$(NDK_TOOLCHAIN)),\
401      $(call __ndk_info,NDK_TOOLCHAIN is defined to the unsupported value $(NDK_TOOLCHAIN)) \
402      $(call __ndk_info,Please use one of the following values: $(NDK_ALL_TOOLCHAINS))\
403      $(call __ndk_error,Aborting)\
404    ,)
405    $(call ndk_log, Using specific toolchain $(NDK_TOOLCHAIN))
406endif
407
408$(call ndk_log, This NDK supports the following target architectures and ABIS:)
409$(foreach arch,$(NDK_ALL_ARCHS),\
410    $(call ndk_log, $(space)$(space)$(arch): $(NDK_ARCH.$(arch).abis))\
411)
412$(call ndk_log, This NDK supports the following toolchains and target ABIs:)
413$(foreach tc,$(NDK_ALL_TOOLCHAINS),\
414    $(call ndk_log, $(space)$(space)$(tc):  $(NDK_TOOLCHAIN.$(tc).abis))\
415)
416
417# ====================================================================
418#
419# Read all platform-specific configuration files.
420#
421# Each platform must be located in build/platforms/android-<apilevel>
422# where <apilevel> corresponds to an API level number, with:
423#   3 -> Android 1.5
424#   4 -> next platform release
425#
426# ====================================================================
427
428# The platform files were moved in the Android source tree from
429# $TOP/ndk/build/platforms to $TOP/development/ndk/platforms. However,
430# the official NDK release packages still place them under the old
431# location for now, so deal with this here
432#
433NDK_PLATFORMS_ROOT := $(strip $(NDK_PLATFORMS_ROOT))
434ifndef NDK_PLATFORMS_ROOT
435    NDK_PLATFORMS_ROOT := $(strip $(wildcard $(NDK_ROOT)/platforms))
436    ifndef NDK_PLATFORMS_ROOT
437        NDK_PLATFORMS_ROOT := $(strip $(wildcard $(NDK_ROOT)/build/platforms))
438    endif
439
440    ifndef NDK_PLATFORMS_ROOT
441        $(call __ndk_info,Could not find platform files (headers and libraries))
442        $(if $(strip $(wildcard $(NDK_ROOT)/RELEASE.TXT)),\
443            $(call __ndk_info,Please define NDK_PLATFORMS_ROOT to point to a valid directory.)\
444        ,\
445            $(call __ndk_info,Please run build/tools/build-platforms.sh to build the corresponding directory.)\
446        )
447        $(call __ndk_error,Aborting)
448    endif
449
450    $(call ndk_log,Found platform root directory: $(NDK_PLATFORMS_ROOT))
451endif
452ifeq ($(strip $(wildcard $(NDK_PLATFORMS_ROOT)/android-*)),)
453    $(call __ndk_info,Your NDK_PLATFORMS_ROOT points to an invalid directory)
454    $(call __ndk_info,Current value: $(NDK_PLATFORMS_ROOT))
455    $(call __ndk_error,Aborting)
456endif
457
458NDK_ALL_PLATFORMS := $(strip $(notdir $(wildcard $(NDK_PLATFORMS_ROOT)/android-*)))
459$(call ndk_log,Found supported platforms: $(NDK_ALL_PLATFORMS))
460
461$(foreach _platform,$(NDK_ALL_PLATFORMS),\
462  $(eval include $(BUILD_SYSTEM)/add-platform.mk)\
463)
464
465# we're going to find the maximum platform number of the form android-<number>
466# ignore others, which could correspond to special and experimental cases
467NDK_ALL_PLATFORM_LEVELS := $(filter android-%,$(NDK_ALL_PLATFORMS))
468NDK_ALL_PLATFORM_LEVELS := $(patsubst android-%,%,$(NDK_ALL_PLATFORM_LEVELS))
469$(call ndk_log,Found stable platform levels: $(NDK_ALL_PLATFORM_LEVELS))
470
471NDK_MAX_PLATFORM_LEVEL := 3
472$(foreach level,$(NDK_ALL_PLATFORM_LEVELS),\
473  $(eval NDK_MAX_PLATFORM_LEVEL := $$(call max,$$(NDK_MAX_PLATFORM_LEVEL),$$(level)))\
474)
475$(call ndk_log,Found max platform level: $(NDK_MAX_PLATFORM_LEVEL))
476
477