1# Copyright (C) 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# This file is designed to be called from the 'ndk-build' script
17# or similar wrapper tool.
18#
19
20# Detect the NDK installation path by processing this Makefile's location.
21# This assumes we are located under $NDK_ROOT/build/core/main.mk
22#
23NDK_ROOT := $(dir $(lastword $(MAKEFILE_LIST)))
24NDK_ROOT := $(strip $(NDK_ROOT:%build/core/=%))
25NDK_ROOT := $(subst \,/,$(NDK_ROOT))
26NDK_ROOT := $(NDK_ROOT:%/=%)
27ifeq ($(NDK_ROOT),)
28    # for the case when we're invoked from the NDK install path
29    NDK_ROOT := .
30endif
31ifeq ($(NDK_LOG),1)
32    $(info Android NDK: NDK installation path auto-detected: '$(NDK_ROOT)')
33endif
34ifneq ($(words $(NDK_ROOT)),1)
35    $(info Android NDK: You NDK installation path contains spaces.)
36    $(info Android NDK: Please re-install to a different location to fix the issue !)
37    $(error Aborting.)
38endif
39
40include $(NDK_ROOT)/build/core/init.mk
41
42# ====================================================================
43#
44# If NDK_PROJECT_PATH is not defined, find the application's project
45# path by looking at the manifest file in the current directory or
46# any of its parents. If none is found, try again with 'jni/Android.mk'
47#
48# Note that we first look at the current directory to avoid using
49# absolute NDK_PROJECT_PATH values. This reduces the length of all
50# source, object and binary paths that are passed to build commands.
51#
52# It turns out that some people use ndk-build to generate static
53# libraries without a full Android project tree.
54#
55# If NDK_PROJECT_PATH=null, ndk-build make no attempt to look for it, but does
56# need the following variables depending on NDK_PROJECT_PATH to be explicitly
57# specified (from the default, if any):
58#
59#   NDK_OUT
60#   NDK_LIBS_OUT
61#   APP_BUILD_SCRIPT
62#   NDK_DEBUG (optional, default to 0)
63#   Other APP_* used to be in Application.mk
64#
65# This behavior may be useful in an integrated build system.
66#
67# ====================================================================
68
69ifeq ($(HOST_OS),windows)
70# On Windows, defining host-dir-parent is a bit more tricky because the
71# GNU Make $(dir ...) function doesn't return an empty string when it
72# reaches the top of the directory tree, and we want to enforce this to
73# avoid infinite loops.
74#
75#   $(dir C:)     -> C:       (empty expected)
76#   $(dir C:/)    -> C:/      (empty expected)
77#   $(dir C:\)    -> C:\      (empty expected)
78#   $(dir C:/foo) -> C:/      (correct)
79#   $(dir C:\foo) -> C:\      (correct)
80#
81host-dir-parent = $(patsubst %/,%,$(strip \
82    $(eval __host_dir_node := $(patsubst %/,%,$(subst \,/,$1)))\
83    $(eval __host_dir_parent := $(dir $(__host_dir_node)))\
84    $(filter-out $1,$(__host_dir_parent))\
85    ))
86else
87host-dir-parent = $(patsubst %/,%,$(dir $1))
88endif
89
90find-project-dir = $(strip $(call find-project-dir-inner,$(abspath $1),$2))
91
92find-project-dir-inner = \
93    $(eval __found_project_path := )\
94    $(eval __find_project_path := $1)\
95    $(eval __find_project_file := $2)\
96    $(call find-project-dir-inner-2)\
97    $(__found_project_path)
98
99find-project-dir-inner-2 = \
100    $(call ndk_log,Looking for $(__find_project_file) in $(__find_project_path))\
101    $(eval __find_project_manifest := $(strip $(wildcard $(__find_project_path)/$(__find_project_file))))\
102    $(if $(__find_project_manifest),\
103        $(call ndk_log,    Found it !)\
104        $(eval __found_project_path := $(__find_project_path))\
105        ,\
106        $(eval __find_project_parent := $(call host-dir-parent,$(__find_project_path)))\
107        $(if $(__find_project_parent),\
108            $(eval __find_project_path := $(__find_project_parent))\
109            $(call find-project-dir-inner-2)\
110        )\
111    )
112
113NDK_PROJECT_PATH := $(strip $(NDK_PROJECT_PATH))
114APP_PROJECT_PATH := $(strip $(APP_PROJECT_PATH))
115
116ifneq (,$(APP_PROJECT_PATH))
117    ifeq (,$(NDK_PROJECT_PATH))
118        # If NDK_PROJECT_PATH isn't set and APP_PROJECT_PATH is present, use APP_PROJECT_PATH
119        $(call ndk_log,Use APP_PROJECT_PATH for NDK_PROJECT_PATH: $(APP_PROJECT_PATH))
120        NDK_PROJECT_PATH := $(APP_PROJECT_PATH)
121    else
122        # If both NDK_PROJECT_PATH and APP_PROJECT_PATH are present, check consistency
123        ifneq ($(NDK_PROJECT_PATH),$(APP_PROJECT_PATH))
124            $(call __ndk_info,WARNING: NDK_PROJECT_PATH and APP_PROJECT_PATH are both set but not equal literally)
125            $(call __ndk_info,  NDK_PROJECT_PATH = $(NDK_PROJECT_PATH))
126            $(call __ndk_info,  APP_PROJECT_PATH = $(APP_PROJECT_PATH))
127        endif
128    endif
129endif
130
131ifeq (null,$(NDK_PROJECT_PATH))
132
133$(call ndk_log,Make no attempt to look for NDK_PROJECT_PATH.)
134
135else
136
137# To keep paths as short as possible during the build, we first look if the
138# current directory is the top of our project path. If this is the case, we
139# will define NDK_PROJECT_PATH to simply '.'
140#
141# Otherwise, we will use find-project-dir which will first get the absolute
142# path of the current directory the climb back the hierarchy until we find
143# something. The result will always be a much longer definition for
144# NDK_PROJECT_PATH
145#
146ifndef NDK_PROJECT_PATH
147    ifneq (,$(strip $(wildcard AndroidManifest.xml)))
148        NDK_PROJECT_PATH := .
149    else
150        ifneq (,$(strip $(wildcard jni/Android.mk)))
151            NDK_PROJECT_PATH := .
152        endif
153    endif
154endif
155ifndef NDK_PROJECT_PATH
156    NDK_PROJECT_PATH := $(call find-project-dir,.,jni/Android.mk)
157endif
158ifndef NDK_PROJECT_PATH
159    NDK_PROJECT_PATH := $(call find-project-dir,.,AndroidManifest.xml)
160endif
161ifndef NDK_PROJECT_PATH
162    $(call __ndk_info,Could not find application project directory !)
163    $(call __ndk_info,Please define the NDK_PROJECT_PATH variable to point to it.)
164    $(call __ndk_error,Aborting)
165endif
166
167# Check that there are no spaces in the project path, or bad things will happen
168ifneq ($(words $(NDK_PROJECT_PATH)),1)
169    $(call __ndk_info,Your Android application project path contains spaces: '$(NDK_PROJECT_PATH)')
170    $(call __ndk_info,The Android NDK build cannot work here. Please move your project to a different location.)
171    $(call __ndk_error,Aborting.)
172endif
173
174$(call ndk_log,Found project path: $(NDK_PROJECT_PATH))
175
176NDK_APPLICATION_MK := $(strip $(wildcard $(NDK_PROJECT_PATH)/jni/Application.mk))
177
178endif # NDK_PROJECT_PATH == null
179
180ifndef NDK_APPLICATION_MK
181    NDK_APPLICATION_MK := $(NDK_ROOT)/build/core/default-application.mk
182endif
183
184
185# Place all generated intermediate files here
186NDK_APP_OUT := $(strip $(NDK_OUT))
187ifndef NDK_APP_OUT
188  ifeq (null,$(NDK_PROJECT_PATH))
189    $(call __ndk_info,NDK_PROJECT_PATH==null.  Please explicitly set NDK_OUT to directory for all generated intermediate files.)
190    $(call __ndk_error,Aborting.)
191  endif
192  NDK_APP_OUT := $(NDK_PROJECT_PATH)/obj
193endif
194$(call ndk_log,Ouput path for intermediate files: $(NDK_APP_OUT))
195
196# Place all generated library files here.  This is rarely changed since aapt expects the default libs/
197NDK_APP_LIBS_OUT := $(strip $(NDK_LIBS_OUT))
198ifndef NDK_APP_LIBS_OUT
199  ifeq (null,$(NDK_PROJECT_PATH))
200    $(call __ndk_info,NDK_PROJECT_PATH==null.  Please explicitly set NDK_LIBS_OUT to directory for generated library files.)
201    $(call __ndk_error,Aborting.)
202  endif
203  NDK_APP_LIBS_OUT := $(NDK_PROJECT_PATH)/libs
204endif
205$(call ndk_log,Ouput path for generated library files: $(NDK_APP_LIBS_OUT))
206
207# Fake an application named 'local'
208_app            := local
209_application_mk := $(NDK_APPLICATION_MK)
210NDK_APPS        := $(_app)
211
212include $(BUILD_SYSTEM)/add-application.mk
213
214# For cygwin, put generated dependency conversion script here
215# Do not define this variable for other host platforms
216#
217ifeq ($(HOST_OS),cygwin)
218NDK_DEPENDENCIES_CONVERTER := $(NDK_APP_OUT)/convert-dependencies.sh
219endif
220
221# If a goal is DUMP_xxx then we dump a variable xxx instead
222# of building anything
223#
224DUMP_VAR     := $(patsubst DUMP_%,%,$(filter DUMP_%,$(MAKECMDGOALS)))
225MAKECMDGOALS := $(filter-out DUMP_$(DUMP_VAR),$(MAKECMDGOALS))
226
227include $(BUILD_SYSTEM)/setup-imports.mk
228
229ifneq (,$(DUMP_VAR))
230
231# We only support a single DUMP_XXX goal at a time for now.
232ifneq ($(words $(DUMP_VAR)),1)
233    $(call __ndk_error,!!TOO-MANY-DUMP-VARIABLES!!)
234endif
235
236$(foreach _app,$(NDK_APPS),\
237  $(eval include $(BUILD_SYSTEM)/setup-app.mk)\
238)
239
240DUMP_$(DUMP_VAR):
241	@echo $($(DUMP_VAR))
242else
243    # Build it
244    include $(BUILD_SYSTEM)/build-all.mk
245endif
246