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 # 39 NDK_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 # 44 MAKE_TEST := $(lastword a b c d e f) 45 ifneq ($(MAKE_TEST),f) 46 $(error Android NDK: GNU Make version $(MAKE_VERSION) is too low (should be >= 3.81)) 47 endif 48 ifdef NDK_LOG 49 $(info Android NDK: GNU Make version $(MAKE_VERSION) detected) 50 endif 51 52 # NDK_ROOT *must* be defined and point to the root of the NDK installation 53 NDK_ROOT := $(strip $(NDK_ROOT)) 54 ifndef NDK_ROOT 55 $(error ERROR while including init.mk: NDK_ROOT must be defined !) 56 endif 57 ifneq ($(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.) 60 endif 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 78 ifdef NDK_NO_WARNINGS 79 __ndk_warning := 80 endif 81 ifdef NDK_NO_ERRORS 82 __ndk_error := 83 endif 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 # ----------------------------------------------------------------------------- 91 ifdef NDK_LOG 92 ndk_log = $(info $(__ndk_name): $1) 93 else 94 ndk_log := 95 endif 96 97 # ==================================================================== 98 # 99 # Host system auto-detection. 100 # 101 # ==================================================================== 102 103 # 104 # Determine host system and architecture from the environment 105 # 106 HOST_OS := $(strip $(HOST_OS)) 107 ifndef 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)) 135 else 136 $(call ndk_log,Host OS from environment: $(HOST_OS)) 137 endif 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 # 154 HOST_OS_BASE := $(HOST_OS) 155 156 ifeq ($(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 177 endif 178 179 ifneq ($(HOST_OS),$(HOST_OS_BASE)) 180 $(call ndk_log, Host operating system detected: $(HOST_OS), base OS: $(HOST_OS_BASE)) 181 else 182 $(call ndk_log, Host operating system detected: $(HOST_OS)) 183 endif 184 185 HOST_ARCH := $(strip $(HOST_ARCH)) 186 ifndef 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)) 207 else 208 $(call ndk_log,Host CPU from environment: $(HOST_ARCH)) 209 endif 210 211 HOST_TAG := $(HOST_OS_BASE)-$(HOST_ARCH) 212 213 # The directory separator used on this host 214 HOST_DIRSEP := : 215 ifeq ($(HOST_OS),windows) 216 HOST_DIRSEP := ; 217 endif 218 219 # The host executable extension 220 HOST_EXEEXT := 221 ifeq ($(HOST_OS),windows) 222 HOST_EXEEXT := .exe 223 endif 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 # 229 ifeq ($(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 242 endif 243 244 $(call ndk_log,HOST_TAG set to $(HOST_TAG)) 245 246 # Check for NDK-specific versions of our host tools 247 HOST_PREBUILT := $(strip $(wildcard $(NDK_ROOT)/prebuilt/$(HOST_TAG)/bin)) 248 ifdef 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 257 else 258 $(call ndk_log,Host tools prebuilt directory not found, using system tools) 259 endif 260 261 HOST_ECHO := $(strip $(HOST_ECHO)) 262 ifndef HOST_ECHO 263 # Special case, on Cygwin, always use the host echo, not our prebuilt one 264 # which adds \r\n at the end of lines. 265 ifneq ($(HOST_OS),cygwin) 266 HOST_ECHO := $(strip $(wildcard $(NDK_ROOT)/prebuilt/$(HOST_TAG)/bin/echo$(HOST_EXEEXT))) 267 endif 268 endif 269 ifndef HOST_ECHO 270 HOST_ECHO := echo 271 endif 272 $(call ndk_log,Host 'echo' tool: $(HOST_ECHO)) 273 274 # Define HOST_ECHO_N to perform the equivalent of 'echo -n' on all platforms. 275 ifeq ($(HOST_OS),windows) 276 # Our custom toolbox echo binary supports -n. 277 HOST_ECHO_N := $(HOST_ECHO) -n 278 else 279 # On Posix, just use bare printf. 280 HOST_ECHO_N := printf %s 281 endif 282 $(call ndk_log,Host 'echo -n' tool: $(HOST_ECHO_N)) 283 284 HOST_CMP := $(strip $(HOST_CMP)) 285 ifndef HOST_CMP 286 HOST_CMP := $(strip $(wildcard $(NDK_ROOT)/prebuilt/$(HOST_TAG)/bin/cmp$(HOST_EXEEXT))) 287 endif 288 ifndef HOST_CMP 289 HOST_CMP := cmp 290 endif 291 $(call ndk_log,Host 'cmp' tool: $(HOST_CMP)) 292 293 # 294 # Verify that the 'awk' tool has the features we need. 295 # Both Nawk and Gawk do. 296 # 297 HOST_AWK := $(strip $(HOST_AWK)) 298 ifndef HOST_AWK 299 HOST_AWK := awk 300 endif 301 $(call ndk_log,Host 'awk' tool: $(HOST_AWK)) 302 303 # Location of all awk scripts we use 304 BUILD_AWK := $(NDK_ROOT)/build/awk 305 306 AWK_TEST := $(shell $(HOST_AWK) -f $(BUILD_AWK)/check-awk.awk) 307 $(call ndk_log,Host 'awk' test returned: $(AWK_TEST)) 308 ifneq ($(AWK_TEST),Pass) 309 $(call __ndk_info,Host 'awk' tool is outdated. Please define HOST_AWK to point to Gawk or Nawk !) 310 $(call __ndk_error,Aborting.) 311 endif 312 313 # 314 # On Cygwin, define the 'cygwin-to-host-path' function here depending on the 315 # environment. The rules are the following: 316 # 317 # 1/ If "cygpath' is not in your path, do not use it at all. It looks like 318 # this allows to build with the NDK from MSys without problems. 319 # 320 # 2/ Since invoking 'cygpath -m' from GNU Make for each source file is 321 # _very_ slow, try to generate a Make function that performs the mapping 322 # from cygwin to host paths through simple substitutions. 323 # 324 # 3/ In case we fail horribly, allow the user to define NDK_USE_CYGPATH to '1' 325 # in order to use 'cygpath -m' nonetheless. This is only a backup plan in 326 # case our automatic substitution function doesn't work (only likely if you 327 # have a very weird cygwin setup). 328 # 329 # The function for 2/ is generated by an awk script. It's really a series 330 # of nested patsubst calls, that look like: 331 # 332 # cygwin-to-host-path = $(patsubst /cygdrive/c/%,c:/%,\ 333 # $(patsusbt /cygdrive/d/%,d:/%, \ 334 # $1) 335 # 336 # except that the actual definition is built from the list of mounted 337 # drives as reported by "mount" and deals with drive letter cases (i.e. 338 # '/cygdrive/c' and '/cygdrive/C') 339 # 340 ifeq ($(HOST_OS),cygwin) 341 CYGPATH := $(strip $(HOST_CYGPATH)) 342 ifndef CYGPATH 343 $(call ndk_log, Probing for 'cygpath' program) 344 CYGPATH := $(strip $(shell which cygpath 2>/dev/null)) 345 ifndef CYGPATH 346 $(call ndk_log, 'cygpath' was *not* found in your path) 347 else 348 $(call ndk_log, 'cygpath' found as: $(CYGPATH)) 349 endif 350 endif 351 ifndef CYGPATH 352 cygwin-to-host-path = $1 353 else 354 ifeq ($(NDK_USE_CYGPATH),1) 355 $(call ndk_log, Forced usage of 'cygpath -m' through NDK_USE_CYGPATH=1) 356 cygwin-to-host-path = $(strip $(shell $(CYGPATH) -m $1)) 357 else 358 # Call an awk script to generate a Makefile fragment used to define a function 359 WINDOWS_HOST_PATH_FRAGMENT := $(shell mount | $(HOST_AWK) -f $(BUILD_AWK)/gen-windows-host-path.awk) 360 ifeq ($(NDK_LOG),1) 361 $(info Using cygwin substitution rules:) 362 $(eval $(shell mount | $(HOST_AWK) -f $(BUILD_AWK)/gen-windows-host-path.awk -vVERBOSE=1)) 363 endif 364 $(eval cygwin-to-host-path = $(WINDOWS_HOST_PATH_FRAGMENT)) 365 endif 366 endif 367 endif # HOST_OS == cygwin 368 369 # The location of the build system files 370 BUILD_SYSTEM := $(NDK_ROOT)/build/core 371 372 # Include common definitions 373 include $(BUILD_SYSTEM)/definitions.mk 374 375 # ==================================================================== 376 # 377 # Read all toolchain-specific configuration files. 378 # 379 # Each toolchain must have a corresponding config.mk file located 380 # in build/toolchains/<name>/ that will be included here. 381 # 382 # Each one of these files should define the following variables: 383 # TOOLCHAIN_NAME toolchain name (e.g. arm-linux-androideabi-4.4.3) 384 # TOOLCHAIN_ABIS list of target ABIs supported by the toolchain. 385 # 386 # Then, it should include $(ADD_TOOLCHAIN) which will perform 387 # book-keeping for the build system. 388 # 389 # ==================================================================== 390 391 # the build script to include in each toolchain config.mk 392 ADD_TOOLCHAIN := $(BUILD_SYSTEM)/add-toolchain.mk 393 394 # the list of all toolchains in this NDK 395 NDK_ALL_TOOLCHAINS := 396 NDK_ALL_ABIS := 397 NDK_ALL_ARCHS := 398 399 TOOLCHAIN_CONFIGS := $(wildcard $(NDK_ROOT)/toolchains/*/config.mk) 400 $(foreach _config_mk,$(TOOLCHAIN_CONFIGS),\ 401 $(eval include $(BUILD_SYSTEM)/add-toolchain.mk)\ 402 ) 403 404 NDK_ALL_TOOLCHAINS := $(sort $(NDK_ALL_TOOLCHAINS)) 405 NDK_ALL_ABIS := $(sort $(NDK_ALL_ABIS)) 406 NDK_ALL_ARCHS := $(sort $(NDK_ALL_ARCHS)) 407 408 # Check that each ABI has a single architecture definition 409 $(foreach _abi,$(strip $(NDK_ALL_ABIS)),\ 410 $(if $(filter-out 1,$(words $(NDK_ABI.$(_abi).arch))),\ 411 $(call __ndk_info,INTERNAL ERROR: The $(_abi) ABI should have exactly one architecture definitions. Found: '$(NDK_ABI.$(_abi).arch)')\ 412 $(call __ndk_error,Aborting...)\ 413 )\ 414 ) 415 416 # Allow the user to define NDK_TOOLCHAIN to a custom toolchain name. 417 # This is normally used when the NDK release comes with several toolchains 418 # for the same architecture (generally for backwards-compatibility). 419 # 420 NDK_TOOLCHAIN := $(strip $(NDK_TOOLCHAIN)) 421 ifdef NDK_TOOLCHAIN 422 # check that the toolchain name is supported 423 $(if $(filter-out $(NDK_ALL_TOOLCHAINS),$(NDK_TOOLCHAIN)),\ 424 $(call __ndk_info,NDK_TOOLCHAIN is defined to the unsupported value $(NDK_TOOLCHAIN)) \ 425 $(call __ndk_info,Please use one of the following values: $(NDK_ALL_TOOLCHAINS))\ 426 $(call __ndk_error,Aborting)\ 427 ,) 428 $(call ndk_log, Using specific toolchain $(NDK_TOOLCHAIN)) 429 endif 430 431 # Allow the user to define NDK_TOOLCHAIN_VERSION to override the toolchain 432 # version number. Unlike NDK_TOOLCHAIN, this only changes the suffix of 433 # the toolchain path we're using. 434 # 435 # For example, if GCC 4.6 is the default, defining NDK_TOOLCHAIN_VERSION=4.4.3 436 # will ensure that ndk-build uses the following toolchains, depending on 437 # the target architecture: 438 # 439 # arm -> arm-linux-androideabi-4.4.3 440 # x86 -> x86-android-linux-4.4.3 441 # mips -> mipsel-linux-android-4.4.3 442 # 443 # This is used in setup-toolchain.mk 444 # 445 NDK_TOOLCHAIN_VERSION := $(strip $(NDK_TOOLCHAIN_VERSION)) 446 447 448 $(call ndk_log, This NDK supports the following target architectures and ABIS:) 449 $(foreach arch,$(NDK_ALL_ARCHS),\ 450 $(call ndk_log, $(space)$(space)$(arch): $(NDK_ARCH.$(arch).abis))\ 451 ) 452 $(call ndk_log, This NDK supports the following toolchains and target ABIs:) 453 $(foreach tc,$(NDK_ALL_TOOLCHAINS),\ 454 $(call ndk_log, $(space)$(space)$(tc): $(NDK_TOOLCHAIN.$(tc).abis))\ 455 ) 456 457 # ==================================================================== 458 # 459 # Read all platform-specific configuration files. 460 # 461 # Each platform must be located in build/platforms/android-<apilevel> 462 # where <apilevel> corresponds to an API level number, with: 463 # 3 -> Android 1.5 464 # 4 -> next platform release 465 # 466 # ==================================================================== 467 468 # The platform files were moved in the Android source tree from 469 # $TOP/ndk/build/platforms to $TOP/development/ndk/platforms. However, 470 # the official NDK release packages still place them under the old 471 # location for now, so deal with this here 472 # 473 NDK_PLATFORMS_ROOT := $(strip $(NDK_PLATFORMS_ROOT)) 474 ifndef NDK_PLATFORMS_ROOT 475 NDK_PLATFORMS_ROOT := $(strip $(wildcard $(NDK_ROOT)/platforms)) 476 ifndef NDK_PLATFORMS_ROOT 477 NDK_PLATFORMS_ROOT := $(strip $(wildcard $(NDK_ROOT)/build/platforms)) 478 endif 479 480 ifndef NDK_PLATFORMS_ROOT 481 $(call __ndk_info,Could not find platform files (headers and libraries)) 482 $(if $(strip $(wildcard $(NDK_ROOT)/RELEASE.TXT)),\ 483 $(call __ndk_info,Please define NDK_PLATFORMS_ROOT to point to a valid directory.)\ 484 ,\ 485 $(call __ndk_info,Please run build/tools/build-platforms.sh to build the corresponding directory.)\ 486 ) 487 $(call __ndk_error,Aborting) 488 endif 489 490 $(call ndk_log,Found platform root directory: $(NDK_PLATFORMS_ROOT)) 491 endif 492 ifeq ($(strip $(wildcard $(NDK_PLATFORMS_ROOT)/android-*)),) 493 $(call __ndk_info,Your NDK_PLATFORMS_ROOT points to an invalid directory) 494 $(call __ndk_info,Current value: $(NDK_PLATFORMS_ROOT)) 495 $(call __ndk_error,Aborting) 496 endif 497 498 NDK_ALL_PLATFORMS := $(strip $(notdir $(wildcard $(NDK_PLATFORMS_ROOT)/android-*))) 499 $(call ndk_log,Found supported platforms: $(NDK_ALL_PLATFORMS)) 500 501 $(foreach _platform,$(NDK_ALL_PLATFORMS),\ 502 $(eval include $(BUILD_SYSTEM)/add-platform.mk)\ 503 ) 504 505 # we're going to find the maximum platform number of the form android-<number> 506 # ignore others, which could correspond to special and experimental cases 507 NDK_ALL_PLATFORM_LEVELS := $(filter android-%,$(NDK_ALL_PLATFORMS)) 508 NDK_ALL_PLATFORM_LEVELS := $(patsubst android-%,%,$(NDK_ALL_PLATFORM_LEVELS)) 509 $(call ndk_log,Found stable platform levels: $(NDK_ALL_PLATFORM_LEVELS)) 510 511 NDK_MAX_PLATFORM_LEVEL := 3 512 $(foreach level,$(NDK_ALL_PLATFORM_LEVELS),\ 513 $(eval NDK_MAX_PLATFORM_LEVEL := $$(call max,$$(NDK_MAX_PLATFORM_LEVEL),$$(level)))\ 514 ) 515 $(call ndk_log,Found max platform level: $(NDK_MAX_PLATFORM_LEVEL)) 516 517