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