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