Skip to content

Commit

Permalink
Merge changes I0e6d4b02,I36990c3f into ndk-release-r17
Browse files Browse the repository at this point in the history
* changes:
  Fix case of APP_WRAP_SH being empty.
  Add wrap.sh support, install default ASAN wrap.sh.
  • Loading branch information
Treehugger Robot authored and Gerrit Code Review committed Feb 21, 2018
2 parents 6dfe181 + f336f22 commit b4c2758
Show file tree
Hide file tree
Showing 30 changed files with 308 additions and 0 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,20 @@ NDK
of a local development build.
* `ANDROID_NDK_BETA`: The beta version of the NDK. This is 0 for a stable
release.
* Added support for `APP_WRAP_SH` to ndk-build.
* This variable points to a shell script (relative to your Android.mk) that
will be installed as a [wrap.sh] file in your APK.
* Available in both an ABI-generic form (`APP_WRAP_SH`), which will install
a single script for every ABI, and an ABI-specific form
(`APP_WRAP_SH_arm64-v8a`, etc) to allow for per-ABI customization of the
wrap.sh script.
* ndk-build now installs sanitizer runtime libraries to your out directory for
inclusion in your APK. Coupled with [wrap.sh], this removes the requirement
of rooting your device to use sanitizers. See [Issue 540].
* When using ASAN, ndk-build will install a wrap.sh file to set up ASAN for
your app if you have not specified your own wrap.sh. If you have specified
your own wrap.sh, you can add ASAN support to it as described
[here](https://github.com/google/sanitizers/wiki/AddressSanitizerOnAndroidO).

[wrap.sh]: https://developer.android.com/ndk/guides/wrap-script.html
[Issue 540]: https://github.com/android-ndk/ndk/issues/540
Expand Down
33 changes: 33 additions & 0 deletions build/core/add-application.mk
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,39 @@ ifneq ($(filter $(APP_STL),gnustl_static gnustl_shared stlport_static stlport_sh
information.)
endif

# wrap.sh files can be specified in the user's Application.mk in either an
# ABI-generic (APP_WRAP_SH) or ABI-specific (APP_WRAP_SH_x86, etc) fashion.
# These two approaches cannot be combined; if any ABI-specific wrap.sh files are
# specified then it is an error to also specify an ABI-generic one.
#
# After this block, only the ABI-specific values should be checked; if there is
# an ABI-generic script specified the ABI-specific variables will be populated
# with the generic script.
NDK_NO_USER_WRAP_SH := true
ifneq ($(APP_WRAP_SH),)
NDK_NO_USER_WRAP_SH := false
endif

NDK_HAVE_ABI_SPECIFIC_WRAP_SH := false
$(foreach _abi,$(NDK_ALL_ABIS),\
$(if $(APP_WRAP_SH_$(_abi)),\
$(eval NDK_HAVE_ABI_SPECIFIC_WRAP_SH := true)))

ifeq ($(NDK_HAVE_ABI_SPECIFIC_WRAP_SH),true)
# It is an error to have both ABI-specific and ABI-generic wrap.sh files
# specified.
ifneq ($(APP_WRAP_SH),)
$(call __ndk_error,Found both ABI-specific and ABI-generic APP_WRAP_SH \
directives. Must use either all ABI-specific or only ABI-generic.)
endif
NDK_NO_USER_WRAP_SH := false
else
# If we have no ABI-specific wrap.sh files but we *do* have an ABI-generic
# one, install the generic one for all ABIs.
$(foreach _abi,$(NDK_ALL_ABIS),\
$(eval APP_WRAP_SH_$(_abi) := $(APP_WRAP_SH)))
endif

$(if $(call get,$(_map),defined),\
$(call __ndk_info,Weird, the application $(_app) is already defined by $(call get,$(_map),defined))\
$(call __ndk_error,Aborting)\
Expand Down
8 changes: 8 additions & 0 deletions build/core/definitions.mk
Original file line number Diff line number Diff line change
Expand Up @@ -1339,6 +1339,14 @@ NDK_APP_VARS_OPTIONAL := \
APP_SHORT_COMMANDS \
APP_STL \
APP_THIN_ARCHIVE \
APP_WRAP_SH \

# NDK_ALL_ABIS is not configured yet.
NDK_APP_VARS_OPTIONAL += \
APP_WRAP_SH_armeabi-v7a \
APP_WRAP_SH_arm64-v8a \
APP_WRAP_SH_x86 \
APP_WRAP_SH_x86_64 \

# the list of all variables that may appear in an Application.mk file
# or defined by the build scripts.
Expand Down
29 changes: 29 additions & 0 deletions build/core/install_wrap_sh.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#
# Copyright (C) 2018 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

# Generates rules to install wrap.sh files to the app's out directory.

NDK_WRAP_SH := $(NDK_APP_DST_DIR)/wrap.sh
$(call generate-file-dir,$(NDK_WRAP_SH))

installed_modules: $(NDK_WRAP_SH)

WRAP_SH_SRC := $(call local-source-file-path,$(NDK_APP_WRAP_SH_$(TARGET_ARCH_ABI)))

$(NDK_WRAP_SH): PRIVATE_ABI := $(TARGET_ARCH_ABI)
$(NDK_WRAP_SH): $(WRAP_SH_SRC) clean-installed-binaries
$(call host-echo-build-step,$(PRIVATE_ABI),wrap.sh "$(call pretty-dir,$@)")
$(hide) $(call host-install,$<,$@)
9 changes: 9 additions & 0 deletions build/core/sanitizers.mk
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,12 @@ include $(BUILD_SYSTEM)/install_sanitizer.mk
NDK_SANITIZER_NAME := ASAN
NDK_SANITIZER_FSANITIZE_ARGS := address
include $(BUILD_SYSTEM)/install_sanitizer.mk

# If the user has not specified their own wrap.sh and is using ASAN, install a
# default ASAN wrap.sh for them.
ifneq (,$(filter address,$(NDK_SANITIZERS)))
ifeq ($(NDK_NO_USER_WRAP_SH),true)
NDK_APP_WRAP_SH_$(TARGET_ARCH_ABI) := \
$(NDK_ROOT)/wrap.sh/asan.$(TARGET_ARCH_ABI).sh
endif
endif
4 changes: 4 additions & 0 deletions build/core/setup-toolchain.mk
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,10 @@ include $(NDK_APP_BUILD_SCRIPT)
# -fsanitize in its ldflags.
include $(BUILD_SYSTEM)/sanitizers.mk

ifneq ($(NDK_APP_WRAP_SH_$(TARGET_ARCH_ABI)),)
include $(BUILD_SYSTEM)/install_wrap_sh.mk
endif

$(call ndk-stl-add-dependencies,$(NDK_APP_STL))

# recompute all dependencies between modules
Expand Down
11 changes: 11 additions & 0 deletions checkbuild.py
Original file line number Diff line number Diff line change
Expand Up @@ -1487,6 +1487,16 @@ def validate_notice(self, _install_base):
pass


class WrapSh(ndk.builds.PackageModule):
name = 'wrap.sh'
path = 'wrap.sh'
src = build_support.ndk_path('wrap.sh')

def validate_notice(self, _install_base):
# No license needed for meta.
pass


class SourceProperties(ndk.builds.Module):
name = 'source.properties'
path = 'source.properties'
Expand Down Expand Up @@ -1606,6 +1616,7 @@ def get_modules_to_build(module_names, arches):
Sysroot(),
SystemStl(),
Vulkan(),
WrapSh(),
]


Expand Down
Empty file added tests/build/wrap_sh/__init__.py
Empty file.
6 changes: 6 additions & 0 deletions tests/build/wrap_sh/project/jni/Android.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := foo
LOCAL_SRC_FILES := foo.cpp
include $(BUILD_SHARED_LIBRARY)
4 changes: 4 additions & 0 deletions tests/build/wrap_sh/project/jni/Application.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
APP_WRAP_SH_armeabi-v7a := armeabi-v7a.sh
APP_WRAP_SH_arm64-v8a := arm64-v8a.sh
APP_WRAP_SH_x86:= x86.sh
APP_WRAP_SH_x86_64:= x86_64.sh
1 change: 1 addition & 0 deletions tests/build/wrap_sh/project/jni/arm64-v8a.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
arm64-v8a
1 change: 1 addition & 0 deletions tests/build/wrap_sh/project/jni/armeabi-v7a.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
armeabi-v7a
1 change: 1 addition & 0 deletions tests/build/wrap_sh/project/jni/foo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
void foo() {}
1 change: 1 addition & 0 deletions tests/build/wrap_sh/project/jni/x86.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
x86
1 change: 1 addition & 0 deletions tests/build/wrap_sh/project/jni/x86_64.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
x86_64
54 changes: 54 additions & 0 deletions tests/build/wrap_sh/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#
# Copyright (C) 2018 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
"""Check for correct link order from ndk-build.
"""
import os
import subprocess
import sys
import textwrap


def run_test(ndk_path, abi, platform, toolchain, build_flags):
"""Checks that the proper wrap.sh scripts were installed."""
ndk_build = os.path.join(ndk_path, 'ndk-build')
if sys.platform == 'win32':
ndk_build += '.cmd'
project_path = 'project'
ndk_args = build_flags + [
'APP_ABI=' + abi,
'APP_PLATFORM=android-{}'.format(platform),
'NDK_TOOLCHAIN_VERSION=' + toolchain,
]
proc = subprocess.Popen([ndk_build, '-C', project_path] + ndk_args,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
out, _ = proc.communicate()
out = out.decode('utf-8')
if proc.returncode != 0:
return proc.returncode == 0, out

wrap_sh = os.path.join(project_path, 'libs', abi, 'wrap.sh')
if not os.path.exists(wrap_sh):
return False, '{} does not exist'.format(wrap_sh)

with open(wrap_sh) as wrap_sh_file:
contents = wrap_sh_file.read().strip()
if contents != abi:
return False, textwrap.dedent("""\
wrap.sh file had wrong contents:
Expected: {}
Actual: {}""".format(abi, contents))

return True, ''
Empty file.
6 changes: 6 additions & 0 deletions tests/build/wrap_sh_generic/project/jni/Android.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := foo
LOCAL_SRC_FILES := foo.cpp
include $(BUILD_SHARED_LIBRARY)
1 change: 1 addition & 0 deletions tests/build/wrap_sh_generic/project/jni/Application.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
APP_WRAP_SH := wrap.sh
1 change: 1 addition & 0 deletions tests/build/wrap_sh_generic/project/jni/foo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
void foo() {}
1 change: 1 addition & 0 deletions tests/build/wrap_sh_generic/project/jni/wrap.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
generic
54 changes: 54 additions & 0 deletions tests/build/wrap_sh_generic/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#
# Copyright (C) 2018 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
"""Check for correct link order from ndk-build.
"""
import os
import subprocess
import sys
import textwrap


def run_test(ndk_path, abi, platform, toolchain, build_flags):
"""Checks that the proper wrap.sh scripts were installed."""
ndk_build = os.path.join(ndk_path, 'ndk-build')
if sys.platform == 'win32':
ndk_build += '.cmd'
project_path = 'project'
ndk_args = build_flags + [
'APP_ABI=' + abi,
'APP_PLATFORM=android-{}'.format(platform),
'NDK_TOOLCHAIN_VERSION=' + toolchain,
]
proc = subprocess.Popen([ndk_build, '-C', project_path] + ndk_args,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
out, _ = proc.communicate()
out = out.decode('utf-8')
if proc.returncode != 0:
return proc.returncode == 0, out

wrap_sh = os.path.join(project_path, 'libs', abi, 'wrap.sh')
if not os.path.exists(wrap_sh):
return False, '{} does not exist'.format(wrap_sh)

with open(wrap_sh) as wrap_sh_file:
contents = wrap_sh_file.read().strip()
if contents != 'generic':
return False, textwrap.dedent("""\
wrap.sh file had wrong contents:
Expected: generic
Actual: {}""".format(abi, contents))

return True, ''
Empty file.
6 changes: 6 additions & 0 deletions tests/build/wrap_sh_none/project/jni/Android.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := foo
LOCAL_SRC_FILES := foo.cpp
include $(BUILD_SHARED_LIBRARY)
1 change: 1 addition & 0 deletions tests/build/wrap_sh_none/project/jni/foo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
void foo() {}
44 changes: 44 additions & 0 deletions tests/build/wrap_sh_none/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#
# Copyright (C) 2018 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
"""Check for correct link order from ndk-build.
"""
import os
import subprocess
import sys


def run_test(ndk_path, abi, platform, toolchain, build_flags):
"""Checks that the proper wrap.sh scripts were installed."""
ndk_build = os.path.join(ndk_path, 'ndk-build')
if sys.platform == 'win32':
ndk_build += '.cmd'
project_path = 'project'
ndk_args = build_flags + [
'APP_ABI=' + abi,
'APP_PLATFORM=android-{}'.format(platform),
'NDK_TOOLCHAIN_VERSION=' + toolchain,
]
proc = subprocess.Popen([ndk_build, '-C', project_path] + ndk_args,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
out, _ = proc.communicate()
out = out.decode('utf-8')
if proc.returncode != 0:
return proc.returncode == 0, out

wrap_sh = os.path.join(project_path, 'libs', abi, 'wrap.sh')
if os.path.exists(wrap_sh):
return False, '{} should not exist'.format(wrap_sh)
return True, ''
5 changes: 5 additions & 0 deletions wrap.sh/asan.arm64-v8a.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/system/bin/sh
HERE="$(cd "$(dirname "$0")" && pwd)"
export ASAN_OPTIONS=log_to_syslog=false,allow_user_segv_handler=1
export LD_PRELOAD=$HERE/libclang_rt.asan-aarch64-android.so
"$@"
5 changes: 5 additions & 0 deletions wrap.sh/asan.armeabi-v7a.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/system/bin/sh
HERE="$(cd "$(dirname "$0")" && pwd)"
export ASAN_OPTIONS=log_to_syslog=false,allow_user_segv_handler=1
export LD_PRELOAD=$HERE/libclang_rt.asan-arm-android.so
"$@"
5 changes: 5 additions & 0 deletions wrap.sh/asan.x86.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/system/bin/sh
HERE="$(cd "$(dirname "$0")" && pwd)"
export ASAN_OPTIONS=log_to_syslog=false,allow_user_segv_handler=1
export LD_PRELOAD=$HERE/libclang_rt.asan-i686-android.so
"$@"
5 changes: 5 additions & 0 deletions wrap.sh/asan.x86_64.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/system/bin/sh
HERE="$(cd "$(dirname "$0")" && pwd)"
export ASAN_OPTIONS=log_to_syslog=false,allow_user_segv_handler=1
export LD_PRELOAD=$HERE/libclang_rt.asan-x86_64-android.so
"$@"

0 comments on commit b4c2758

Please sign in to comment.